Shutdown U-Boot before starting an OS
Some devices, especially the ones doing DMA should be disabled before giving control to an OS. We take the simple approach here: Just shutdown the devices in the reverse order they were activated. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
This commit is contained in:
parent
36ae69a2dc
commit
0b5a776c1e
|
@ -141,6 +141,8 @@ int cleanup_before_linux (void)
|
|||
{
|
||||
int i;
|
||||
|
||||
shutdown_uboot();
|
||||
|
||||
/* flush I/D-cache */
|
||||
i = 0;
|
||||
asm ("mcr p15, 0, %0, c7, c7, 0": :"r" (i));
|
||||
|
|
|
@ -156,3 +156,13 @@ void hang (void)
|
|||
puts ("### ERROR ### Please RESET the board ###\n");
|
||||
for (;;);
|
||||
}
|
||||
|
||||
/* Everything needed to cleanly shutdown U-Boot.
|
||||
* Should be called before starting an OS to get
|
||||
* the devices into a clean state
|
||||
*/
|
||||
void shutdown_uboot(void)
|
||||
{
|
||||
devices_shutdown();
|
||||
}
|
||||
|
||||
|
|
|
@ -131,6 +131,7 @@ int parse_area_spec(const char *str, ulong *start, ulong *size);
|
|||
unsigned long strtoul_suffix(const char *str, char **endp, int base);
|
||||
|
||||
void start_uboot(void);
|
||||
void shutdown_uboot(void);
|
||||
|
||||
int arch_execute(unsigned long address, int argc, char *argv[]);
|
||||
|
||||
|
|
|
@ -103,6 +103,7 @@ struct device_d {
|
|||
struct list_head list; /* The list of all devices */
|
||||
struct list_head children; /* our children */
|
||||
struct list_head sibling;
|
||||
struct list_head active; /* The list of all devices which have a driver */
|
||||
|
||||
struct device_d *parent; /* our parent, NULL if not present */
|
||||
|
||||
|
@ -128,7 +129,7 @@ struct driver_d {
|
|||
int (*probe) (struct device_d *);
|
||||
|
||||
/*! Called if an instance of a device is gone. */
|
||||
int (*remove)(struct device_d *);
|
||||
void (*remove)(struct device_d *);
|
||||
|
||||
/*! Called in response of reading from this device. Required */
|
||||
ssize_t (*read) (struct device_d*, void* buf, size_t count, ulong offset, ulong flags);
|
||||
|
@ -245,6 +246,11 @@ int mem_memmap(struct device_d *dev, void **map, int flags);
|
|||
/* Use this if you have nothing to do in your drivers probe function */
|
||||
int dummy_probe(struct device_d *);
|
||||
|
||||
/* Iterate over all activated devices (i.e. the ones with drivers and shut
|
||||
* them down.
|
||||
*/
|
||||
void devices_shutdown(void);
|
||||
|
||||
int generic_memmap_ro(struct device_d *dev, void **map, int flags);
|
||||
int generic_memmap_rw(struct device_d *dev, void **map, int flags);
|
||||
|
||||
|
|
14
lib/driver.c
14
lib/driver.c
|
@ -40,6 +40,8 @@ EXPORT_SYMBOL(device_list);
|
|||
LIST_HEAD(driver_list);
|
||||
EXPORT_SYMBOL(driver_list);
|
||||
|
||||
static LIST_HEAD(active);
|
||||
|
||||
struct device_d *get_device_by_id(const char *id)
|
||||
{
|
||||
struct device_d *dev;
|
||||
|
@ -77,6 +79,8 @@ static int match(struct driver_d *drv, struct device_d *dev)
|
|||
|
||||
dev->driver = drv;
|
||||
|
||||
list_add(&dev->active, &active);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -326,6 +330,16 @@ const char *dev_id(const struct device_d *dev)
|
|||
return buf;
|
||||
}
|
||||
|
||||
void devices_shutdown(void)
|
||||
{
|
||||
struct device_d *dev;
|
||||
|
||||
list_for_each_entry(dev, &active, active) {
|
||||
if (dev->driver->remove)
|
||||
dev->driver->remove(dev);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CMD_DEVINFO
|
||||
|
||||
static int do_devinfo ( cmd_tbl_t *cmdtp, int argc, char *argv[])
|
||||
|
|
Loading…
Reference in New Issue