diff --git a/arch/arm/lib/armlinux.c b/arch/arm/lib/armlinux.c index c80a683..f4bb814 100644 --- a/arch/arm/lib/armlinux.c +++ b/arch/arm/lib/armlinux.c @@ -163,19 +163,16 @@ { struct device_d *dev = NULL; - while (1) { - dev = get_device_by_type(DEVICE_TYPE_DRAM, dev); + list_for_each_entry(dev, &device_list, list) { + if (dev->type == DEVICE_TYPE_DRAM) { + params->hdr.tag = ATAG_MEM; + params->hdr.size = tag_size (tag_mem32); - if (!dev) - return; + params->u.mem.start = dev->map_base; + params->u.mem.size = dev->size; - params->hdr.tag = ATAG_MEM; - params->hdr.size = tag_size (tag_mem32); - - params->u.mem.start = dev->map_base; - params->u.mem.size = dev->size; - - params = tag_next (params); + params = tag_next (params); + } } } #endif /* CONFIG_SETUP_MEMORY_TAGS */ diff --git a/board/phycore_pcm038/lowlevel_init.S b/board/phycore_pcm038/lowlevel_init.S index 17f3ad3..d12e4db 100644 --- a/board/phycore_pcm038/lowlevel_init.S +++ b/board/phycore_pcm038/lowlevel_init.S @@ -30,8 +30,9 @@ writel(0x04082008, SPCTL0) writel(0x33f00304, CSCR) - writel(0x33f00304 | CSCR_MPEN | CSCR_SPEN | CSCR_MCU_SEL | - CSCR_SP_SEL | CSCR_MPLL_RESTART | CSCR_SPLL_RESTART, + writel(0x33f00300 | CSCR_FPM_EN | CSCR_MPEN | CSCR_SPEN | CSCR_MCU_SEL | + CSCR_SP_SEL | CSCR_MPLL_RESTART | CSCR_SPLL_RESTART | + 0 , CSCR) /* add some delay here */ @@ -39,6 +40,11 @@ 1: subs r1, r1, #0x1 bne 1b + writel(0x33f00300 | CSCR_FPM_EN | CSCR_MPEN | CSCR_SPEN | CSCR_MCU_SEL | + CSCR_SP_SEL | CSCR_MPLL_RESTART | CSCR_SPLL_RESTART | + CSCR_ARM_SRC_MPLL, + CSCR) + writel(0x00070f08, GPCR) writel(0x130410c3, PCDR0) @@ -50,6 +56,9 @@ cmp pc, #0xc0000000 bhi 1f + mov pc,r10 + +1: /* * DDR on CSD0 */ @@ -81,5 +90,6 @@ mov r1, #0x0 strb r1, [r0] writel(0x82126080, 0xD8001000) -1: + mov pc,r10 + diff --git a/fs/devfs.c b/fs/devfs.c index cc8a9d0..10c2dfe 100644 --- a/fs/devfs.c +++ b/fs/devfs.c @@ -27,6 +27,7 @@ #include #include #include +#include #include static int devfs_read(struct device_d *_dev, FILE *f, void *buf, size_t size) @@ -92,11 +93,10 @@ { DIR *dir; - dir = malloc(sizeof(DIR)); - if (!dir) - return NULL; + dir = xzalloc(sizeof(DIR)); - dir->priv = get_first_device(); + if (!list_empty(&device_list)) + dir->priv = list_first_entry(&device_list, struct device_d, list); return dir; } @@ -105,12 +105,16 @@ { struct device_d *dev = dir->priv; - while (dev && (!strlen(dev->id) || !dev->driver)) - dev = dev->next; + if (!dev) + return NULL; - if (dev) { + list_for_each_entry_from(dev, &device_list, list) { + if (!*dev->id) + continue; + if (!dev->driver) + continue; strcpy(dir->d.d_name, dev->id); - dir->priv = dev->next; + dir->priv = list_entry(dev->list.next, struct device_d, list); return &dir->d; } return NULL; diff --git a/include/driver.h b/include/driver.h index 293a265..e1b344c 100644 --- a/include/driver.h +++ b/include/driver.h @@ -1,6 +1,8 @@ #ifndef DRIVER_H #define DRIVER_H +#include + #define MAX_DRIVER_NAME 16 #define DEVICE_TYPE_UNKNOWN 0 @@ -35,7 +37,7 @@ struct driver_d *driver; /* The driver for this device */ - struct device_d *next; + struct list_head list; unsigned long type; @@ -46,7 +48,7 @@ char name[MAX_DRIVER_NAME]; /* The name of this driver. Used to match to * the corresponding device. */ - struct driver_d *next; + struct list_head list; int (*probe) (struct device_d *); int (*remove)(struct device_d *); @@ -93,6 +95,12 @@ struct device_d *device_from_spec_str(const char *str, char **endp); char *deviceid_from_spec_str(const char *str, char **endp); +extern struct list_head device_list; +#define for_each_device(dev) list_for_each_entry(dev, &device_list, list) + +extern struct list_head driver_list; +#define for_each_driver(drv) list_for_each_entry(drv, &driver_list, list) + /* Find a driver with the given name. Currently the filesystem implementation * uses this to get the driver from the name the user specifies with the * mount command diff --git a/lib/driver.c b/lib/driver.c index 75ee912..f801007 100644 --- a/lib/driver.c +++ b/lib/driver.c @@ -27,35 +27,24 @@ #include #include #include +#include -static struct device_d *first_device = NULL; -static struct driver_d *first_driver = NULL; +LIST_HEAD(device_list); +EXPORT_SYMBOL(device_list); -struct device_d *get_first_device(void) +LIST_HEAD(driver_list); +EXPORT_SYMBOL(driver_list); + +struct device_d *get_device_by_id(const char *id) { - return first_device; -} + struct device_d *dev; -struct device_d *get_device_by_id(const char *_id) -{ - struct device_d *d; - char *id, *colon; - - /* FIXME: is this still needed? */ - id = strdup(_id); - if ((colon = strchr(id, ':'))) - *colon = 0; - - d = first_device; - - while(d) { - if(!strcmp(id, d->id)) - break; - d = d->next; + for_each_device(dev) { + if(!strcmp(id, dev->id)) + return dev; } - free(id); - return d; + return NULL; } int get_free_deviceid(char *id, char *id_template) @@ -89,9 +78,6 @@ int register_device(struct device_d *new_device) { struct driver_d *drv; - struct device_d *dev; - - dev = first_device; if(*new_device->id && get_device_by_id(new_device->id)) { printf("device %s already exists\n", new_device->id); @@ -99,23 +85,11 @@ } debug ("register_device: %s\n",new_device->name); - if(!dev) { - first_device = new_device; - dev = first_device; - } else { - while(dev->next) - dev = dev->next; - } + list_add_tail(&new_device->list, &device_list); - dev->next = new_device; - new_device->next = 0; - - drv = first_driver; - - while(drv) { + for_each_driver(drv) { if (!match(drv, new_device)) break; - drv = drv->next; } return 0; @@ -124,37 +98,25 @@ void unregister_device(struct device_d *old_dev) { - struct device_d *dev; - debug("unregister_device: %s:%s\n",old_dev->name, old_dev->id); - dev = first_device; + if (old_dev->driver) + old_dev->driver->remove(old_dev); - while (dev) { - if (dev->next == old_dev) { - if (old_dev->driver) - old_dev->driver->remove(old_dev); - dev->next = old_dev->next; - return; - } - dev = dev->next; - } + list_del(&old_dev->list); } EXPORT_SYMBOL(unregister_device); struct driver_d *get_driver_by_name(const char *name) { - struct driver_d *d; + struct driver_d *drv; - d = first_driver; - - while(d) { - if(!strcmp(name, d->name)) - break; - d = d->next; + for_each_driver(drv) { + if(!strcmp(name, drv->name)) + return drv; } - return d; + return NULL; } static void noinfo(struct device_d *dev) @@ -166,36 +128,21 @@ { } -int register_driver(struct driver_d *new_driver) +int register_driver(struct driver_d *drv) { - struct driver_d *drv; struct device_d *dev = NULL; - drv = first_driver; - debug("register_driver: %s\n",new_driver->name); - if(!drv) { - first_driver = new_driver; - drv = first_driver; - } else { - while(drv->next) - drv = drv->next; - } + list_add_tail(&drv->list, &driver_list); - drv->next = new_driver; - new_driver->next = 0; + if (!drv->info) + drv->info = noinfo; + if (!drv->shortinfo) + drv->shortinfo = noshortinfo; - if (!new_driver->info) - new_driver->info = noinfo; - if (!new_driver->shortinfo) - new_driver->shortinfo = noshortinfo; - - dev = first_device; - while (dev) { - match(new_driver, dev); - dev = dev->next; - } + for_each_device(dev) + match(drv, dev); return 0; } @@ -248,30 +195,6 @@ return get_device_by_id(name); } -/* Get devices from their type. - * If last is NULL the first device of this type is given. - * If last is not NULL, the next device of this type starting - * from last is given. - */ -struct device_d *get_device_by_type(ulong type, struct device_d *last) -{ - struct device_d *dev; - - if (!last) - dev = first_device; - else - dev = last->next; - - while (dev) { - if (dev->type == type) - return dev; - dev = dev->next; - } - - return NULL; -} -EXPORT_SYMBOL(get_device_by_type); - ssize_t dev_read(struct device_d *dev, void *buf, size_t count, unsigned long offset, ulong flags) { if (dev->driver->read) @@ -333,50 +256,47 @@ static int do_devinfo ( cmd_tbl_t *cmdtp, int argc, char *argv[]) { - struct device_d *dev = first_device; - struct driver_d *drv = first_driver; - struct param_d *param; + struct device_d *dev; + struct driver_d *drv; + struct param_d *param; - if (argc == 1) { - printf("devices:\n"); + if (argc == 1) { + printf("devices:\n"); - while(dev) { - printf("%10s: base=0x%08x size=0x%08x (driver %s)\n", - dev->id, dev->map_base, dev->size, + for_each_device(dev) { + printf("%10s: base=0x%08x size=0x%08x (driver %s)\n", + dev->id, dev->map_base, dev->size, dev->driver ? dev->driver->name : "none"); - dev = dev->next; - } + } - printf("drivers:\n"); - while(drv) { - printf("%10s\n",drv->name); - drv = drv->next; - } - } else { - struct device_d *dev = get_device_by_id(argv[1]); + printf("\ndrivers:\n"); + for_each_driver(drv) + printf("%10s\n",drv->name); + } else { + struct device_d *dev = get_device_by_id(argv[1]); - if (!dev) { - printf("no such device: %s\n",argv[1]); - return -1; - } + if (!dev) { + printf("no such device: %s\n",argv[1]); + return -1; + } - if (dev->driver) - dev->driver->info(dev); + if (dev->driver) + dev->driver->info(dev); - param = dev->param; + param = dev->param; - printf("%s\n", param ? + printf("%s\n", param ? "Parameters:" : "no parameters available"); - while (param) { + while (param) { printf("%16s = %s\n", param->name, param->value); - param = param->next; - } + param = param->next; + } - } + } - return 0; + return 0; } static __maybe_unused char cmd_devinfo_help[] =