电子常识
本文主要是关于MT7621和QCA9558的相关介绍,并着重对MT7621和QCA9558进行详尽的对比分析。
MT7621 比9558 强多了。不是一个档次的。你可以上openwrt官网看看,我给你截了个图。你就很明了了。最后一栏越高越好。9558比MT7620A好一点。MT7621应该面对的竞争对手是BCM4708/4709或者高通的IPQ8064。但这只是MTK的愿望,7621的表现离这两款的差距还是有点大,所以后来出了个MT7623,但是芯片发布了一年多了,到现在市场还没出现一款消费级别的路由用此芯片,我估计还是MTK的老问题。
OpenWrt的最新kernel(3.18.23)已经能够支持32M SPI Flash的读写以及擦除操作。然而,可能是系统考虑不周,亦或是MT7621系统的BUG,在配置了W25Q256的MT7621开发板系统上,无法soft reset!经过查阅相关资料,发现,MT7621默认支持24bit(3byte)的spi地址模式,而要支持32M以上的spi flash,则必须切换到32bit(4byte)地址模式。在soft reset的时候,spi停留在了32bit模式,没有切换回默认的24bit模式,导致reset后,MT7621在默认的24bit模式,无法和32bit模式的spi通讯,系统死机。
在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_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) 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方法,如果存在该方法,则会调用之。
于是,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 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. */
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.。.
*/
};
关于MT7621和QCA9558的相关介绍就到这了,如有不足之处欢迎指正。
全部0条评论
快来发表一下你的评论吧 !