summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2007-10-11 20:20:36 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2007-10-11 20:20:36 +0200
commiteadf71abc77bf97cf5aa7dbe206f4778c4b2480d (patch)
treeb777f0f97d094c836300b11cc390ce10678dd417
parent29fc9471f5b0f18df699f8e47c5a1fbeb5398e9e (diff)
downloadbarebox-eadf71abc77bf97cf5aa7dbe206f4778c4b2480d.tar.gz
barebox-eadf71abc77bf97cf5aa7dbe206f4778c4b2480d.tar.xz
Use Linux kernel list for drivers and devices instead of handmade
list.
-rw-r--r--arch/arm/lib/armlinux.c19
-rw-r--r--board/phycore_pcm038/lowlevel_init.S16
-rw-r--r--fs/devfs.c20
-rw-r--r--include/driver.h12
-rw-r--r--lib/driver.c194
5 files changed, 100 insertions, 161 deletions
diff --git a/arch/arm/lib/armlinux.c b/arch/arm/lib/armlinux.c
index c80a6832df..f4bb814a60 100644
--- a/arch/arm/lib/armlinux.c
+++ b/arch/arm/lib/armlinux.c
@@ -163,19 +163,16 @@ static void setup_memory_tags (void)
{
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 17f3ad3bd8..d12e4db451 100644
--- a/board/phycore_pcm038/lowlevel_init.S
+++ b/board/phycore_pcm038/lowlevel_init.S
@@ -30,8 +30,9 @@ lowlevel_init:
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 @@ lowlevel_init:
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 @@ lowlevel_init:
cmp pc, #0xc0000000
bhi 1f
+ mov pc,r10
+
+1:
/*
* DDR on CSD0
*/
@@ -81,5 +90,6 @@ lowlevel_init:
mov r1, #0x0
strb r1, [r0]
writel(0x82126080, 0xD8001000)
-1:
+
mov pc,r10
+
diff --git a/fs/devfs.c b/fs/devfs.c
index cc8a9d0542..10c2dfeab6 100644
--- a/fs/devfs.c
+++ b/fs/devfs.c
@@ -27,6 +27,7 @@
#include <fs.h>
#include <command.h>
#include <errno.h>
+#include <xfuncs.h>
#include <linux/stat.h>
static int devfs_read(struct device_d *_dev, FILE *f, void *buf, size_t size)
@@ -92,11 +93,10 @@ static DIR* devfs_opendir(struct device_d *dev, const char *pathname)
{
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 @@ static struct dirent* devfs_readdir(struct device_d *_dev, DIR *dir)
{
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 293a265045..e1b344cfe3 100644
--- a/include/driver.h
+++ b/include/driver.h
@@ -1,6 +1,8 @@
#ifndef DRIVER_H
#define DRIVER_H
+#include <list.h>
+
#define MAX_DRIVER_NAME 16
#define DEVICE_TYPE_UNKNOWN 0
@@ -35,7 +37,7 @@ struct device_d {
struct driver_d *driver; /* The driver for this device */
- struct device_d *next;
+ struct list_head list;
unsigned long type;
@@ -46,7 +48,7 @@ struct driver_d {
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 @@ int get_free_deviceid(char *id, char *id_template);
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 75ee912a34..f801007406 100644
--- a/lib/driver.c
+++ b/lib/driver.c
@@ -27,35 +27,24 @@
#include <linux/ctype.h>
#include <errno.h>
#include <fs.h>
+#include <list.h>
-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)
-{
- return first_device;
-}
+LIST_HEAD(driver_list);
+EXPORT_SYMBOL(driver_list);
-struct device_d *get_device_by_id(const char *_id)
+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;
+ struct device_d *dev;
- 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 @@ static int match(struct driver_d *drv, struct device_d *dev)
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 @@ int register_device(struct device_d *new_device)
}
debug ("register_device: %s\n",new_device->name);
- if(!dev) {
- first_device = new_device;
- dev = first_device;
- } else {
- while(dev->next)
- dev = dev->next;
- }
-
- dev->next = new_device;
- new_device->next = 0;
+ list_add_tail(&new_device->list, &device_list);
- drv = first_driver;
-
- while(drv) {
+ for_each_driver(drv) {
if (!match(drv, new_device))
break;
- drv = drv->next;
}
return 0;
@@ -124,37 +98,25 @@ EXPORT_SYMBOL(register_device);
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;
-
- d = first_driver;
+ struct driver_d *drv;
- 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 @@ static void noshortinfo(struct device_d *dev)
{
}
-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 @@ struct device_d *device_from_spec_str(const char *str, char **endp)
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 @@ int dummy_probe(struct device_d *dev)
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[] =