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 14 static struct device isa_bus = { 15 .init_name = "isa" 16 }; 17 18 struct 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 26 static 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 39 static 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 49 static 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 59 static 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 67 static 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 77 static 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 87 static 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 97 static void isa_dev_release(struct device *dev) 98 { 99 kfree(to_isa_dev(dev)); 100 } 101 102 void 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 } 113 EXPORT_SYMBOL_GPL(isa_unregister_driver); 114 115 int 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 } 169 EXPORT_SYMBOL_GPL(isa_register_driver); 170 171 static 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 184 postcore_initcall(isa_bus_init); 185