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 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 57 static 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 65 static 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 75 static 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 85 static 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 95 static void isa_dev_release(struct device *dev) 96 { 97 kfree(to_isa_dev(dev)); 98 } 99 100 void 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 } 111 EXPORT_SYMBOL_GPL(isa_unregister_driver); 112 113 int 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 isa_dev->next = isa_driver->devices; 153 isa_driver->devices = &isa_dev->dev; 154 } 155 156 if (!error && !isa_driver->devices) 157 error = -ENODEV; 158 159 if (error) 160 isa_unregister_driver(isa_driver); 161 162 return error; 163 } 164 EXPORT_SYMBOL_GPL(isa_register_driver); 165 166 static int __init isa_bus_init(void) 167 { 168 int error; 169 170 error = bus_register(&isa_bus_type); 171 if (!error) { 172 error = device_register(&isa_bus); 173 if (error) 174 bus_unregister(&isa_bus_type); 175 } 176 return error; 177 } 178 179 postcore_initcall(isa_bus_init); 180