9
0
Fork 0

Use Linux kernel list for drivers and devices instead of handmade

list.
This commit is contained in:
Sascha Hauer 2007-10-11 20:20:36 +02:00
parent 29fc9471f5
commit eadf71abc7
5 changed files with 100 additions and 161 deletions

View File

@ -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 */

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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)
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 @@ 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;
}
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 @@ 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;
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 @@ 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[] =