前言
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的代码时,会发现更有意思的东西:
- ?
- ?
- ?*??@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?systemn");??
- ????else??
- ????????pr_emerg("Restarting?system?with?command?'%s'n",?cmd);??
- ????kmsg_dump(KMSG_DUMP_RESTART);??
- ????machine_restart(cmd);??
- }??
在kernel_restart中,又调用了kernel_restart_prepare方法:
device_shutdown在drivers/base/core.c中实现:
?
?????????*?prevent?it?from?being?freed?because?parent's?
?????????*?lock?is?to?be?held?
?????????*/??
????????parent?=?get_device(dev->parent);??
????????get_device(dev);??
?????????
?????????*?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)?{??
??????????????
????????????????dev_info(dev,?"shutdownn");??
????????????dev->bus->shutdown(dev);??
????????}?else?if?(dev->driver?&&?dev->driver->shutdown)?{??
????????????dev->driver->shutdown(dev);??
????????}??
????????device_unlock(dev);??
????????????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方法,如果存在该方法,则会调用之.
于是,32M spi flash的reset方法喷薄而出.
解决办法
转到drivers/mtd/devices/m25p80.c
修改如下代码:
?
};??
总结
通过注册设备的shutdown方法,让我们有机会在系统重启的时刻,做一些deinit的操作.通过此种方法来复位spi flash,优雅而简洁.
(编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|