ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

MT7620A 完美支持32M SPI Flash

2021-09-17 18:06:07  阅读:224  来源: 互联网

标签:MT7620A flash Flash list dev 32M spi shutdown device


MT7620A 完美支持32M SPI Flash

前言

基于在Openwrt19.07开源软件中修改。初步测试Openwrt21.02无此bug.

OpenWrt的最新kernel(3.14.28)已经能够支持32M SPI Flash的读写以及擦除操作.然而,可能是系统考虑不周,亦或是MT7620系统的BUG,在配置了W25Q256的MT7620开发板系统上,无法 soft reset!经过查阅相关资料,发现,MT7620默认支持24bit(3byte)的spi地址模式,而要支持32M以上的spi flash,则必须切换到32bit(4byte)地址模式.在soft reset的时候,spi停留在了32bit模式,没有切换回默认的24bit模式,导致reset后,MT7620在默认的24bit模式,无法和 32bit模式的spi通讯,系统死机.那么问题来了:如何在soft reset时刻,让spi flash切换回24bit模式呢?本文通过设备驱动中的一个shutdown方法来解决这个问题.

知识背景

在linux源代码kernel目录下,有一个reboot.c文件,里面暴露了一个register_reboot_notifier方法,可以让kernel中的代码有机会获得reboot的通知,当我们继续分析reboot.c的代码时,会发现更有意思的东西:

/**
 *    kernel_restart - reboot the system
 *    @cmd: pointer to buffer containing command to execute for restart
 *        or %NULL
 *
 *    Shutdown everything and perform a clean reboot.
 *    This is not safe to call in interrupt context.
 */
void kernel_restart(char *cmd)
{
    kernel_restart_prepare(cmd);
    migrate_to_reboot_cpu();
    syscore_shutdown();
    if (!cmd)
        pr_emerg("Restarting system\n");
    else
        pr_emerg("Restarting system with command '%s'\n", cmd);
    kmsg_dump(KMSG_DUMP_RESTART);
    machine_restart(cmd);
}

kernel_restart中,又调用了kernel_restart_prepare方法:

void kernel_restart_prepare(char *cmd)
{
    blocking_notifier_call_chain(&reboot_notifier_list, SYS_RESTART, cmd);
    system_state = SYSTEM_RESTART;
    usermodehelper_disable();
    device_shutdown();
}

device_shutdowndrivers/base/core.c中实现:

/**
 * device_shutdown - call ->shutdown() on each device to shutdown.
 */
void device_shutdown(void)
{
    struct device *dev, *parent;
    spin_lock(&devices_kset->list_lock);
    /*
     * Walk the devices list backward, shutting down each in turn.
     * Beware that device unplug events may also start pulling
     * devices offline, even as the system is shutting down.
     */
    while (!list_empty(&devices_kset->list)) {
        dev = list_entry(devices_kset->list.prev, struct device,
                kobj.entry);
        /*
         * hold reference count of device's parent to
         * prevent it from being freed because parent's
         * lock is to be held
         */
        parent = get_device(dev->parent);
        get_device(dev);
        /*
         * Make sure the device is off the kset list, in the
         * event that dev->*->shutdown() doesn't remove it.
         */
        list_del_init(&dev->kobj.entry);
        spin_unlock(&devices_kset->list_lock);
        /* hold lock to avoid race with probe/release */
        if (parent)
            device_lock(parent);
        device_lock(dev);
        /* Don't allow any more runtime suspends */
        pm_runtime_get_noresume(dev);
        pm_runtime_barrier(dev);
        // manfeel, add debug info
        //dev_info(dev,"search shutdown method...\n");
        
        if (dev->bus && dev->bus->shutdown) {
            //if (initcall_debug) manfeel
                dev_info(dev, "shutdown\n");
            dev->bus->shutdown(dev);
        } else if (dev->driver && dev->driver->shutdown) {
            //if (initcall_debug) manfeel
                dev_info(dev, "shutdown\n");
            dev->driver->shutdown(dev);
        }
        device_unlock(dev);
        if (parent)
            device_unlock(parent);
        put_device(dev);
        put_device(parent);
        spin_lock(&devices_kset->list_lock);
    }
    spin_unlock(&devices_kset->list_lock);
    async_synchronize_full();
}

通过阅读代码,我们不难发现,在device_shutdown中,枚举了设备的shutdown方法,如果存在该方法,则会调用之.

解决办法

转到drivers/mtd/devices/m25p80.c,所在目录为./build_dir/target-mipsel_24kec+dsp_uClibc-0.9.33.2/linux-ramips_mt7620a/linux-3.10.49/drivers/mtd/devices/m25p80.c

static void m25p_shutdown(struct spi_device *spi)
{
    struct m25p    *flash = spi_get_drvdata(spi);
    
    // manfeel note: add spi flash reset code
    flash->command[0] = 0x66;
    spi_write(flash->spi, flash->command, 1);
    flash->command[0] = 0x99;
    spi_write(flash->spi, flash->command, 1);
    
    /* Clean up MTD stuff. */
    mtd_device_unregister(&flash->mtd);   
}


static struct spi_driver m25p80_driver = {
    .driver = {
        .name    = "m25p80",
        .owner    = THIS_MODULE,   //此处是3.14.28版本中的样式,4.4.14版本内容已改
    },
    .id_table    = m25p_ids,
    .probe    = m25p_probe,
    .remove    = m25p_remove,
    
    // manfeel, add shutdown method to reset spi flash
    .shutdown = m25p_shutdown,

    /* REVISIT: many of these chips have deep power-down modes, which
     * should clearly be entered on suspend() to minimize power use.
     * And also when they're otherwise idle...
     */
};

通过注册设备的shutdown方法,让我们有机会在系统重启的时刻,做一些deinit的操作.通过此种方法来复位spi flash,优雅而简洁.

参考连接:https://blog.csdn.net/manfeel/article/details/43530817

标签:MT7620A,flash,Flash,list,dev,32M,spi,shutdown,device
来源: https://www.cnblogs.com/lionxy/p/15305725.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有