isa.c (3862B)
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 void 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 isa_driver->remove(dev, to_isa_dev(dev)->id); 55} 56 57static void isa_bus_shutdown(struct device *dev) 58{ 59 struct isa_driver *isa_driver = dev->platform_data; 60 61 if (isa_driver && isa_driver->shutdown) 62 isa_driver->shutdown(dev, to_isa_dev(dev)->id); 63} 64 65static int isa_bus_suspend(struct device *dev, pm_message_t state) 66{ 67 struct isa_driver *isa_driver = dev->platform_data; 68 69 if (isa_driver && isa_driver->suspend) 70 return isa_driver->suspend(dev, to_isa_dev(dev)->id, state); 71 72 return 0; 73} 74 75static int isa_bus_resume(struct device *dev) 76{ 77 struct isa_driver *isa_driver = dev->platform_data; 78 79 if (isa_driver && isa_driver->resume) 80 return isa_driver->resume(dev, to_isa_dev(dev)->id); 81 82 return 0; 83} 84 85static struct bus_type isa_bus_type = { 86 .name = "isa", 87 .match = isa_bus_match, 88 .probe = isa_bus_probe, 89 .remove = isa_bus_remove, 90 .shutdown = isa_bus_shutdown, 91 .suspend = isa_bus_suspend, 92 .resume = isa_bus_resume 93}; 94 95static void isa_dev_release(struct device *dev) 96{ 97 kfree(to_isa_dev(dev)); 98} 99 100void isa_unregister_driver(struct isa_driver *isa_driver) 101{ 102 struct device *dev = isa_driver->devices; 103 104 while (dev) { 105 struct device *tmp = to_isa_dev(dev)->next; 106 device_unregister(dev); 107 dev = tmp; 108 } 109 driver_unregister(&isa_driver->driver); 110} 111EXPORT_SYMBOL_GPL(isa_unregister_driver); 112 113int isa_register_driver(struct isa_driver *isa_driver, unsigned int ndev) 114{ 115 int error; 116 unsigned int id; 117 118 isa_driver->driver.bus = &isa_bus_type; 119 isa_driver->devices = NULL; 120 121 error = driver_register(&isa_driver->driver); 122 if (error) 123 return error; 124 125 for (id = 0; id < ndev; id++) { 126 struct isa_dev *isa_dev; 127 128 isa_dev = kzalloc(sizeof *isa_dev, GFP_KERNEL); 129 if (!isa_dev) { 130 error = -ENOMEM; 131 break; 132 } 133 134 isa_dev->dev.parent = &isa_bus; 135 isa_dev->dev.bus = &isa_bus_type; 136 137 dev_set_name(&isa_dev->dev, "%s.%u", 138 isa_driver->driver.name, id); 139 isa_dev->dev.platform_data = isa_driver; 140 isa_dev->dev.release = isa_dev_release; 141 isa_dev->id = id; 142 143 isa_dev->dev.coherent_dma_mask = DMA_BIT_MASK(24); 144 isa_dev->dev.dma_mask = &isa_dev->dev.coherent_dma_mask; 145 146 error = device_register(&isa_dev->dev); 147 if (error) { 148 put_device(&isa_dev->dev); 149 break; 150 } 151 152 if (isa_dev->dev.platform_data) { 153 isa_dev->next = isa_driver->devices; 154 isa_driver->devices = &isa_dev->dev; 155 } else 156 device_unregister(&isa_dev->dev); 157 } 158 159 if (!error && !isa_driver->devices) 160 error = -ENODEV; 161 162 if (error) 163 isa_unregister_driver(isa_driver); 164 165 return error; 166} 167EXPORT_SYMBOL_GPL(isa_register_driver); 168 169static int __init isa_bus_init(void) 170{ 171 int error; 172 173 error = bus_register(&isa_bus_type); 174 if (!error) { 175 error = device_register(&isa_bus); 176 if (error) 177 bus_unregister(&isa_bus_type); 178 } 179 return error; 180} 181 182postcore_initcall(isa_bus_init);