linux 支持32M SPI Flash(W25Q256) — 兼谈设备驱动中的shutdown方法
来源:互联网 发布:特朗普蔡英文通话 知乎 编辑:程序博客网 时间:2024/05/22 03:49
前言
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");elsepr_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_shutdown在drivers/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) manfeeldev_info(dev, "shutdown\n");dev->bus->shutdown(dev);} else if (dev->driver && dev->driver->shutdown) {//if (initcall_debug) manfeeldev_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方法,如果存在该方法,则会调用之.
于是,32M spi flash的reset方法喷薄而出.
解决办法
转到drivers/mtd/devices/m25p80.c
修改如下代码:
static int m25p_remove(struct spi_device *spi){struct m25p*flash = spi_get_drvdata(spi);// manfeel note: add spi flash reset codeflash->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. */return mtd_device_unregister(&flash->mtd);}static struct spi_driver m25p80_driver = {.driver = {.name= "m25p80",.owner= THIS_MODULE,},.id_table= m25p_ids,.probe= m25p_probe,.remove= m25p_remove,// manfeel, add shutdown method to reset spi flash.shutdown = m25p_remove,/* 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,优雅而简洁.
0 0
- linux 支持32M SPI Flash(W25Q256) — 兼谈设备驱动中的shutdown方法
- 让MT7620完美支持32M SPI Flash(W25Q256) — 兼谈设备驱动中的shutdown方法
- 让MT7620完美支持32M SPI Flash(W25Q256) — 兼谈设备驱动中的shutdown方法
- 让MT7620完美支持32M SPI Flash(W25Q256) — 兼谈设备驱动中的shutdown方法
- 让ambarella s2l 支持32M SPI Flash(W25Q256)
- MT7621完美支持32M SPI Flash(W25Q256) 修复 soft reset fail
- linux SPI 设备驱动
- Linux spi设备驱动
- Linux spi 设备驱动
- 三、Linux spi 设备驱动
- Linux SPI设备驱动框架
- S3C2440驱动篇—Linux平台设备驱动之SPI
- 63 linux内核的SPI设备驱动模型及应用程序调用SPI控制器的方法
- linux设备驱动程序之SPI nor flash
- Linux spi驱动分析(四)----SPI设备驱动(W25Q32BV)
- Linux spi驱动分析(四)----SPI设备驱动(W25Q32BV)
- Linux spi驱动分析(四)----SPI设备驱动(W25Q32BV)
- Linux spi驱动分析(四)----SPI设备驱动(W25Q32BV)
- 浅谈struts2之chain
- MySQL-给新建用户授权以允许远程登录数据库
- 欧拉计划 46
- mybatis入门基础(五)----动态SQL
- 课程设计
- linux 支持32M SPI Flash(W25Q256) — 兼谈设备驱动中的shutdown方法
- Word插入的分节符(下一页)自动变为分节符(连续)的解决办法
- ubuntu 16.04 启用root用户方法
- java基础之操作符
- Nginx的介绍和使用
- Python爬虫--访问互联网
- am335x w25Q256
- 关于#define与C的内存
- 搭建整合Struts2,Spring,Hibernate的Web开发框架