]> git.neil.brown.name Git - history.git/commitdiff
Convert acorn expansion card probing code to the Linux device model.
authorRussell King <rmk@flint.arm.linux.org.uk>
Sun, 13 Oct 2002 14:35:29 +0000 (15:35 +0100)
committerRussell King <rmk@flint.arm.linux.org.uk>
Sun, 13 Oct 2002 14:35:29 +0000 (15:35 +0100)
Provide LDM-based driver registration/removal interface for drivers
to use.  We make the old device discovery code ignore devices
claimed via the LDM framework.  However, the LDM framework ignores
devices that may be in use by the old device discovery code.  This
is fine since the only devices that will still use the old discovery
code will be SCSI drivers.

Currently, we don't provide a useful dev.name entry.

arch/arm/kernel/ecard.c
include/asm-arm/ecard.h

index 4a4d89003ecc29a709fd004527d555f9f5a4efae..4cb68c31b86ed625e1a0255da4732d433c4803fa 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/slab.h>
 #include <linux/proc_fs.h>
 #include <linux/notifier.h>
+#include <linux/device.h>
 #include <linux/init.h>
 
 #include <asm/dma.h>
@@ -48,6 +49,7 @@
 #include <asm/pgalloc.h>
 #include <asm/mmu_context.h>
 #include <asm/mach/irq.h>
+#include <asm/tlbflush.h>
 
 #ifndef CONFIG_ARCH_RPC
 #define HAVE_EXPMASK
@@ -92,6 +94,8 @@ ecard_loader_reset(volatile unsigned char *pa, loader_t loader);
 asmlinkage extern int
 ecard_loader_read(int off, volatile unsigned char *pa, loader_t loader);
 
+static const struct ecard_id *
+ecard_match_device(const struct ecard_id *ids, struct expansion_card *ec);
 
 static inline unsigned short
 ecard_getu16(unsigned char *v)
@@ -969,6 +973,14 @@ ecard_probe(int slot, card_type_t type)
 
        *ecp = ec;
        slot_to_expcard[slot] = ec;
+
+       snprintf(ec->dev.bus_id, sizeof(ec->dev.bus_id), "ecard%d", slot);
+       strcpy(ec->dev.name, "fixme!");
+       ec->dev.parent = NULL;
+       ec->dev.bus    = &ecard_bus_type;
+
+       device_register(&ec->dev);
+
        return 0;
 
 nodev:
@@ -995,22 +1007,17 @@ ecard_t *ecard_find(int cid, const card_ids *cids)
                if (finding_pos->claimed)
                        continue;
 
+               if (finding_pos->dev.driver)
+                       continue;
+
                if (!cids) {
                        if ((finding_pos->cid.id ^ cid) == 0)
                                break;
                } else {
-                       unsigned int manufacturer, product;
-                       int i;
-
-                       manufacturer = finding_pos->cid.manufacturer;
-                       product = finding_pos->cid.product;
-
-                       for (i = 0; cids[i].manufacturer != 65535; i++)
-                               if (manufacturer == cids[i].manufacturer &&
-                                   product == cids[i].product)
-                                       break;
+                       const struct ecard_id *id;
 
-                       if (cids[i].manufacturer != 65535)
+                       id = ecard_match_device(cids, finding_pos);
+                       if (id)
                                break;
                }
        }
@@ -1023,7 +1030,7 @@ ecard_t *ecard_find(int cid, const card_ids *cids)
  * Locate all hardware - interrupt management and
  * actual cards.
  */
-void __init ecard_init(void)
+static int __init ecard_init(void)
 {
        int slot, irqhw;
 
@@ -1053,11 +1060,96 @@ void __init ecard_init(void)
                                irqhw ? ecard_irqexp_handler : ecard_irq_handler);
 
        ecard_proc_init();
+
+       return 0;
 }
 
 subsys_initcall(ecard_init);
 
+/*
+ *     ECARD "bus"
+ */
+static const struct ecard_id *
+ecard_match_device(const struct ecard_id *ids, struct expansion_card *ec)
+{
+       int i;
+
+       for (i = 0; ids[i].manufacturer != 65535; i++)
+               if (ec->cid.manufacturer == ids[i].manufacturer &&
+                   ec->cid.product == ids[i].product)
+                       return ids + i;
+
+       return NULL;
+}
+
+static int ecard_drv_probe(struct device *dev)
+{
+       struct expansion_card *ec = ECARD_DEV(dev);
+       struct ecard_driver *drv = ECARD_DRV(dev->driver);
+       const struct ecard_id *id;
+
+       id = ecard_match_device(drv->id_table, ec);
+
+       return drv->probe(ec, id);
+}
+
+static int ecard_drv_remove(struct device *dev)
+{
+       struct expansion_card *ec = ECARD_DEV(dev);
+       struct ecard_driver *drv = ECARD_DRV(dev->driver);
+
+       drv->remove(ec);
+
+       return 0;
+}
+
+int ecard_register_driver(struct ecard_driver *drv)
+{
+       drv->drv.bus = &ecard_bus_type;
+       drv->drv.probe = ecard_drv_probe;
+       drv->drv.remove = ecard_drv_remove;
+
+       return driver_register(&drv->drv);
+}
+
+void ecard_remove_driver(struct ecard_driver *drv)
+{
+       remove_driver(&drv->drv);
+}
+
+static int ecard_match(struct device *_dev, struct device_driver *_drv)
+{
+       struct expansion_card *ec = ECARD_DEV(_dev);
+       struct ecard_driver *drv = ECARD_DRV(_drv);
+       int ret;
+
+       if (drv->id_table) {
+               ret = ecard_match_device(drv->id_table, ec) != NULL;
+       } else {
+               ret = ec->cid.id == drv->id;
+       }
+
+       return ret;
+}
+
+struct bus_type ecard_bus_type = {
+       .name   = "ecard",
+       .match  = ecard_match,
+};
+
+static int ecard_bus_init(void)
+{
+       return bus_register(&ecard_bus_type);
+}
+
+postcore_initcall(ecard_bus_init);
+
 EXPORT_SYMBOL(ecard_startfind);
 EXPORT_SYMBOL(ecard_find);
 EXPORT_SYMBOL(ecard_readchunk);
 EXPORT_SYMBOL(ecard_address);
+
+EXPORT_SYMBOL(ecard_register_driver);
+EXPORT_SYMBOL(ecard_remove_driver);
+
+EXPORT_SYMBOL(ecard_bus_type);
index fa0adbaeb12dc09fead339136c15a0f0a75378be..7c719a206399c14c291eac5a70bbda2fae59d877 100644 (file)
@@ -95,9 +95,10 @@ typedef enum {                               /* Speed for ECARD_IOC space    */
        ECARD_SYNC       = 3
 } card_speed_t;
 
-typedef struct  {                      /* Card ID structure            */
-       unsigned short manufacturer;
-       unsigned short product;
+typedef struct ecard_id {              /* Card ID structure            */
+       unsigned short  manufacturer;
+       unsigned short  product;
+       void            *data;
 } card_ids;
 
 struct in_ecid {                       /* Packed card ID information   */
@@ -132,6 +133,8 @@ typedef struct {                    /* Card handler routines        */
 struct expansion_card {
        struct expansion_card  *next;
 
+       struct device           dev;
+
        /* Public data */
        volatile unsigned char *irqaddr;        /* address of IRQ register      */
        volatile unsigned char *fiqaddr;        /* address of FIQ register      */
@@ -248,4 +251,24 @@ struct ex_chunk_dir {
 
 #endif
 
+extern struct bus_type ecard_bus_type;
+
+#define ECARD_DEV(_d)  container_of((_d), struct expansion_card, dev)
+
+struct ecard_driver {
+       int                     (*probe)(struct expansion_card *, const struct ecard_id *id);
+       void                    (*remove)(struct expansion_card *);
+       const struct ecard_id   *id_table;
+       unsigned int            id;
+       struct device_driver    drv;
+};
+
+#define ECARD_DRV(_d)  container_of((_d), struct ecard_driver, drv)
+
+#define ecard_set_drvdata(ec,data)     dev_set_drvdata(&(ec)->dev, (data))
+#define ecard_get_drvdata(ec)          dev_get_drvdata(&(ec)->dev)
+
+int ecard_register_driver(struct ecard_driver *);
+void ecard_remove_driver(struct ecard_driver *);
+
 #endif