linux/drivers/base/isa.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * ISA bus.
   4 */
   5
   6#include <linux/device.h>
   7#include <linux/kernel.h>
   8#include <linux/slab.h>
   9#include <linux/module.h>
  10#include <linux/init.h>
  11#include <linux/dma-mapping.h>
  12#include <linux/isa.h>
  13
  14static struct device isa_bus = {
  15        .init_name      = "isa"
  16};
  17
  18struct isa_dev {
  19        struct device dev;
  20        struct device *next;
  21        unsigned int id;
  22};
  23
  24#define to_isa_dev(x) container_of((x), struct isa_dev, dev)
  25
  26static int isa_bus_match(struct device *dev, struct device_driver *driver)
  27{
  28        struct isa_driver *isa_driver = to_isa_driver(driver);
  29
  30        if (dev->platform_data == isa_driver) {
  31                if (!isa_driver->match ||
  32                        isa_driver->match(dev, to_isa_dev(dev)->id))
  33                        return 1;
  34                dev->platform_data = NULL;
  35        }
  36        return 0;
  37}
  38
  39static int isa_bus_probe(struct device *dev)
  40{
  41        struct isa_driver *isa_driver = dev->platform_data;
  42
  43        if (isa_driver && isa_driver->probe)
  44                return isa_driver->probe(dev, to_isa_dev(dev)->id);
  45
  46        return 0;
  47}
  48
  49static int isa_bus_remove(struct device *dev)
  50{
  51        struct isa_driver *isa_driver = dev->platform_data;
  52
  53        if (isa_driver && isa_driver->remove)
  54                return isa_driver->remove(dev, to_isa_dev(dev)->id);
  55
  56        return 0;
  57}
  58
  59static void isa_bus_shutdown(struct device *dev)
  60{
  61        struct isa_driver *isa_driver = dev->platform_data;
  62
  63        if (isa_driver && isa_driver->shutdown)
  64                isa_driver->shutdown(dev, to_isa_dev(dev)->id);
  65}
  66
  67static int isa_bus_suspend(struct device *dev, pm_message_t state)
  68{
  69        struct isa_driver *isa_driver = dev->platform_data;
  70
  71        if (isa_driver && isa_driver->suspend)
  72                return isa_driver->suspend(dev, to_isa_dev(dev)->id, state);
  73
  74        return 0;
  75}
  76
  77static int isa_bus_resume(struct device *dev)
  78{
  79        struct isa_driver *isa_driver = dev->platform_data;
  80
  81        if (isa_driver && isa_driver->resume)
  82                return isa_driver->resume(dev, to_isa_dev(dev)->id);
  83
  84        return 0;
  85}
  86
  87static struct bus_type isa_bus_type = {
  88        .name           = "isa",
  89        .match          = isa_bus_match,
  90        .probe          = isa_bus_probe,
  91        .remove         = isa_bus_remove,
  92        .shutdown       = isa_bus_shutdown,
  93        .suspend        = isa_bus_suspend,
  94        .resume         = isa_bus_resume
  95};
  96
  97static void isa_dev_release(struct device *dev)
  98{
  99        kfree(to_isa_dev(dev));
 100}
 101
 102void isa_unregister_driver(struct isa_driver *isa_driver)
 103{
 104        struct device *dev = isa_driver->devices;
 105
 106        while (dev) {
 107                struct device *tmp = to_isa_dev(dev)->next;
 108                device_unregister(dev);
 109                dev = tmp;
 110        }
 111        driver_unregister(&isa_driver->driver);
 112}
 113EXPORT_SYMBOL_GPL(isa_unregister_driver);
 114
 115int isa_register_driver(struct isa_driver *isa_driver, unsigned int ndev)
 116{
 117        int error;
 118        unsigned int id;
 119
 120        isa_driver->driver.bus  = &isa_bus_type;
 121        isa_driver->devices     = NULL;
 122
 123        error = driver_register(&isa_driver->driver);
 124        if (error)
 125                return error;
 126
 127        for (id = 0; id < ndev; id++) {
 128                struct isa_dev *isa_dev;
 129
 130                isa_dev = kzalloc(sizeof *isa_dev, GFP_KERNEL);
 131                if (!isa_dev) {
 132                        error = -ENOMEM;
 133                        break;
 134                }
 135
 136                isa_dev->dev.parent     = &isa_bus;
 137                isa_dev->dev.bus        = &isa_bus_type;
 138
 139                dev_set_name(&isa_dev->dev, "%s.%u",
 140                             isa_driver->driver.name, id);
 141                isa_dev->dev.platform_data      = isa_driver;
 142                isa_dev->dev.release            = isa_dev_release;
 143                isa_dev->id                     = id;
 144
 145                isa_dev->dev.coherent_dma_mask = DMA_BIT_MASK(24);
 146                isa_dev->dev.dma_mask = &isa_dev->dev.coherent_dma_mask;
 147
 148                error = device_register(&isa_dev->dev);
 149                if (error) {
 150                        put_device(&isa_dev->dev);
 151                        break;
 152                }
 153
 154                if (isa_dev->dev.platform_data) {
 155                        isa_dev->next = isa_driver->devices;
 156                        isa_driver->devices = &isa_dev->dev;
 157                } else
 158                        device_unregister(&isa_dev->dev);
 159        }
 160
 161        if (!error && !isa_driver->devices)
 162                error = -ENODEV;
 163
 164        if (error)
 165                isa_unregister_driver(isa_driver);
 166
 167        return error;
 168}
 169EXPORT_SYMBOL_GPL(isa_register_driver);
 170
 171static int __init isa_bus_init(void)
 172{
 173        int error;
 174
 175        error = bus_register(&isa_bus_type);
 176        if (!error) {
 177                error = device_register(&isa_bus);
 178                if (error)
 179                        bus_unregister(&isa_bus_type);
 180        }
 181        return error;
 182}
 183
 184postcore_initcall(isa_bus_init);
 185