MT7620 Perfect support for 32M SPI Flash (w25q256)--Also on shutdown method in device driver

Source: Internet
Author: User
Preface

OpenWrt's newest kernel (3.14.28) has been able to support both read-write and erase operations for 32M SPI Flash. However, the system may be poorly considered or a bug in the MT7620 system, on the W25Q256 Development Board system configured MT7620, Unable to soft reset! after consulting the relevant data, found that the MT7620 default support 24bit (3byte) SPI address mode, and to support more than 32M of SPI Flash, you must switch to 32bit (4byte) address mode. At soft reset. , the SPI stays in the 32bit mode, does not switch back to the default 24bit mode, resulting in reset, MT7620 in the default 24bit mode, cannot and 32bit mode SPI communication, the system freezes. Then the question came: How to soft the reset moment, let the SPI Flash switch back to 24bit mode? This paper solves this problem by means of a shutdown method in device driver.


Background Knowledge

In the Linux source code kernel directory, there is a reboot.c file, which exposes a Register_reboot_notifier method, you can let kernel in the code to get reboot notification, When we continue to analyze Reboot.c's code, we find something more interesting:

/**
 *	kernel_restart-reboot the system
 *	@cmd: Pointer to buffer containing command-to-execute for Resta RT
 *		or%null
 *
 *	Shutdown Everything and perform a clean reboot.
 * This is the 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);
}
In Kernel_restart, the Kernel_restart_prepare method is called:

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 is implemented in DRIVERS/BASE/CORE.C:

/** * Device_shutdown-call->shutdown () on the device to shutdown.

	*/void Device_shutdown (void) {struct device *dev, *parent;
	Spin_lock (&devices_kset->list_lock);
	 /* * Walk the devices list backward, shutting down all in turn.
	 * Beware that device unplug events may also start pulling * devices offline, even as the system was shutting down. */while (!list_empty (&devices_kset->list)) {dev = list_entry (devices_kset->list.prev, struct device, KO

		Bj.entry); /* * Hold reference count of device's parent to * prevent it from being freed because parent's * lock is to be he
		LD */parent = Get_device (dev->parent);
		Get_device (Dev);
		 /* * Make sure the device was 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, "sh
			Utdown\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 (); }
By reading the code, it is not difficult to see that in Device_shutdown, the shutdown method of the device is enumerated, and if the method is present, it is called.

As a result, the Reset method of the 32M SPI Flash is gushing out.


Solutions

Go to Drivers/mtd/devices/m25p80.c

Modify the following code:

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 de EP Power-down modes, which
	 * should clearly is entered on suspend () to minimize power use.
	 * and also when they ' re otherwise idle ...
	 */
};


Summary

By registering the device's shutdown method, we have the opportunity to do some deinit operation at the time of the system reboot. This method resets the SPI flash in an elegant and concise manner.


Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.