Use Linux kernel list for drivers and devices instead of handmade
list.
This commit is contained in:
parent
29fc9471f5
commit
eadf71abc7
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
20
fs/devfs.c
20
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;
|
||||
|
|
|
@ -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
|
||||
|
|
194
lib/driver.c
194
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)
|
||||
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[] =
|
||||
|
|
Loading…
Reference in New Issue