1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Serial multi-instantiate driver, pseudo driver to instantiate multiple 4 * client devices from a single fwnode. 5 * 6 * Copyright 2018 Hans de Goede <hdegoede@redhat.com> 7 */ 8 9 #include <linux/acpi.h> 10 #include <linux/bits.h> 11 #include <linux/i2c.h> 12 #include <linux/interrupt.h> 13 #include <linux/kernel.h> 14 #include <linux/module.h> 15 #include <linux/platform_device.h> 16 #include <linux/property.h> 17 #include <linux/spi/spi.h> 18 #include <linux/types.h> 19 20 #define IRQ_RESOURCE_TYPE GENMASK(1, 0) 21 #define IRQ_RESOURCE_NONE 0 22 #define IRQ_RESOURCE_GPIO 1 23 #define IRQ_RESOURCE_APIC 2 24 25 enum smi_bus_type { 26 SMI_I2C, 27 SMI_SPI, 28 SMI_AUTO_DETECT, 29 }; 30 31 struct smi_instance { 32 const char *type; 33 unsigned int flags; 34 int irq_idx; 35 }; 36 37 struct smi_node { 38 enum smi_bus_type bus_type; 39 struct smi_instance instances[]; 40 }; 41 42 struct smi { 43 int i2c_num; 44 int spi_num; 45 struct i2c_client **i2c_devs; 46 struct spi_device **spi_devs; 47 }; 48 49 static int smi_get_irq(struct platform_device *pdev, struct acpi_device *adev, 50 const struct smi_instance *inst) 51 { 52 int ret; 53 54 switch (inst->flags & IRQ_RESOURCE_TYPE) { 55 case IRQ_RESOURCE_GPIO: 56 ret = acpi_dev_gpio_irq_get(adev, inst->irq_idx); 57 break; 58 case IRQ_RESOURCE_APIC: 59 ret = platform_get_irq(pdev, inst->irq_idx); 60 break; 61 default: 62 return 0; 63 } 64 if (ret < 0) 65 return dev_err_probe(&pdev->dev, ret, "Error requesting irq at index %d\n", 66 inst->irq_idx); 67 68 return ret; 69 } 70 71 static void smi_devs_unregister(struct smi *smi) 72 { 73 while (smi->i2c_num--) 74 i2c_unregister_device(smi->i2c_devs[smi->i2c_num]); 75 76 while (smi->spi_num--) 77 spi_unregister_device(smi->spi_devs[smi->spi_num]); 78 } 79 80 /** 81 * smi_spi_probe - Instantiate multiple SPI devices from inst array 82 * @pdev: Platform device 83 * @smi: Internal struct for Serial multi instantiate driver 84 * @inst_array: Array of instances to probe 85 * 86 * Returns the number of SPI devices instantiate, Zero if none is found or a negative error code. 87 */ 88 static int smi_spi_probe(struct platform_device *pdev, struct smi *smi, 89 const struct smi_instance *inst_array) 90 { 91 struct device *dev = &pdev->dev; 92 struct acpi_device *adev = ACPI_COMPANION(dev); 93 struct spi_controller *ctlr; 94 struct spi_device *spi_dev; 95 char name[50]; 96 int i, ret, count; 97 98 ret = acpi_spi_count_resources(adev); 99 if (ret < 0) 100 return ret; 101 if (!ret) 102 return -ENOENT; 103 104 count = ret; 105 106 smi->spi_devs = devm_kcalloc(dev, count, sizeof(*smi->spi_devs), GFP_KERNEL); 107 if (!smi->spi_devs) 108 return -ENOMEM; 109 110 for (i = 0; i < count && inst_array[i].type; i++) { 111 112 spi_dev = acpi_spi_device_alloc(NULL, adev, i); 113 if (IS_ERR(spi_dev)) { 114 ret = dev_err_probe(dev, PTR_ERR(spi_dev), "failed to allocate SPI device %s from ACPI\n", 115 dev_name(&adev->dev)); 116 goto error; 117 } 118 119 ctlr = spi_dev->controller; 120 121 strscpy(spi_dev->modalias, inst_array[i].type, sizeof(spi_dev->modalias)); 122 123 ret = smi_get_irq(pdev, adev, &inst_array[i]); 124 if (ret < 0) { 125 spi_dev_put(spi_dev); 126 goto error; 127 } 128 spi_dev->irq = ret; 129 130 snprintf(name, sizeof(name), "%s-%s-%s.%d", dev_name(&ctlr->dev), dev_name(dev), 131 inst_array[i].type, i); 132 spi_dev->dev.init_name = name; 133 134 ret = spi_add_device(spi_dev); 135 if (ret) { 136 dev_err_probe(&ctlr->dev, ret, "failed to add SPI device %s from ACPI\n", 137 dev_name(&adev->dev)); 138 spi_dev_put(spi_dev); 139 goto error; 140 } 141 142 dev_dbg(dev, "SPI device %s using chip select %u", name, 143 spi_get_chipselect(spi_dev, 0)); 144 145 smi->spi_devs[i] = spi_dev; 146 smi->spi_num++; 147 } 148 149 if (smi->spi_num < count) { 150 dev_dbg(dev, "Error finding driver, idx %d\n", i); 151 ret = -ENODEV; 152 goto error; 153 } 154 155 dev_info(dev, "Instantiated %d SPI devices.\n", smi->spi_num); 156 157 return 0; 158 error: 159 smi_devs_unregister(smi); 160 161 return ret; 162 } 163 164 /** 165 * smi_i2c_probe - Instantiate multiple I2C devices from inst array 166 * @pdev: Platform device 167 * @smi: Internal struct for Serial multi instantiate driver 168 * @inst_array: Array of instances to probe 169 * 170 * Returns the number of I2C devices instantiate, Zero if none is found or a negative error code. 171 */ 172 static int smi_i2c_probe(struct platform_device *pdev, struct smi *smi, 173 const struct smi_instance *inst_array) 174 { 175 struct i2c_board_info board_info = {}; 176 struct device *dev = &pdev->dev; 177 struct acpi_device *adev = ACPI_COMPANION(dev); 178 char name[32]; 179 int i, ret, count; 180 181 ret = i2c_acpi_client_count(adev); 182 if (ret < 0) 183 return ret; 184 if (!ret) 185 return -ENOENT; 186 187 count = ret; 188 189 smi->i2c_devs = devm_kcalloc(dev, count, sizeof(*smi->i2c_devs), GFP_KERNEL); 190 if (!smi->i2c_devs) 191 return -ENOMEM; 192 193 for (i = 0; i < count && inst_array[i].type; i++) { 194 memset(&board_info, 0, sizeof(board_info)); 195 strscpy(board_info.type, inst_array[i].type, I2C_NAME_SIZE); 196 snprintf(name, sizeof(name), "%s-%s.%d", dev_name(dev), inst_array[i].type, i); 197 board_info.dev_name = name; 198 199 ret = smi_get_irq(pdev, adev, &inst_array[i]); 200 if (ret < 0) 201 goto error; 202 board_info.irq = ret; 203 204 smi->i2c_devs[i] = i2c_acpi_new_device(dev, i, &board_info); 205 if (IS_ERR(smi->i2c_devs[i])) { 206 ret = dev_err_probe(dev, PTR_ERR(smi->i2c_devs[i]), 207 "Error creating i2c-client, idx %d\n", i); 208 goto error; 209 } 210 smi->i2c_num++; 211 } 212 if (smi->i2c_num < count) { 213 dev_dbg(dev, "Error finding driver, idx %d\n", i); 214 ret = -ENODEV; 215 goto error; 216 } 217 218 dev_info(dev, "Instantiated %d I2C devices.\n", smi->i2c_num); 219 220 return 0; 221 error: 222 smi_devs_unregister(smi); 223 224 return ret; 225 } 226 227 static int smi_probe(struct platform_device *pdev) 228 { 229 struct device *dev = &pdev->dev; 230 const struct smi_node *node; 231 struct smi *smi; 232 int ret; 233 234 node = device_get_match_data(dev); 235 if (!node) { 236 dev_dbg(dev, "Error ACPI match data is missing\n"); 237 return -ENODEV; 238 } 239 240 smi = devm_kzalloc(dev, sizeof(*smi), GFP_KERNEL); 241 if (!smi) 242 return -ENOMEM; 243 244 platform_set_drvdata(pdev, smi); 245 246 switch (node->bus_type) { 247 case SMI_I2C: 248 return smi_i2c_probe(pdev, smi, node->instances); 249 case SMI_SPI: 250 return smi_spi_probe(pdev, smi, node->instances); 251 case SMI_AUTO_DETECT: 252 /* 253 * For backwards-compatibility with the existing nodes I2C 254 * is checked first and if such entries are found ONLY I2C 255 * devices are created. Since some existing nodes that were 256 * already handled by this driver could also contain unrelated 257 * SpiSerialBus nodes that were previously ignored, and this 258 * preserves that behavior. 259 */ 260 ret = smi_i2c_probe(pdev, smi, node->instances); 261 if (ret != -ENOENT) 262 return ret; 263 return smi_spi_probe(pdev, smi, node->instances); 264 default: 265 return -EINVAL; 266 } 267 } 268 269 static void smi_remove(struct platform_device *pdev) 270 { 271 struct smi *smi = platform_get_drvdata(pdev); 272 273 smi_devs_unregister(smi); 274 } 275 276 static const struct smi_node bsg1160_data = { 277 .instances = { 278 { "bmc150_accel", IRQ_RESOURCE_GPIO, 0 }, 279 { "bmc150_magn" }, 280 { "bmg160" }, 281 {} 282 }, 283 .bus_type = SMI_I2C, 284 }; 285 286 static const struct smi_node bsg2150_data = { 287 .instances = { 288 { "bmc150_accel", IRQ_RESOURCE_GPIO, 0 }, 289 { "bmc150_magn" }, 290 /* The resources describe a 3th client, but it is not really there. */ 291 { "bsg2150_dummy_dev" }, 292 {} 293 }, 294 .bus_type = SMI_I2C, 295 }; 296 297 static const struct smi_node int3515_data = { 298 .instances = { 299 { "tps6598x", IRQ_RESOURCE_APIC, 0 }, 300 { "tps6598x", IRQ_RESOURCE_APIC, 1 }, 301 { "tps6598x", IRQ_RESOURCE_APIC, 2 }, 302 { "tps6598x", IRQ_RESOURCE_APIC, 3 }, 303 {} 304 }, 305 .bus_type = SMI_I2C, 306 }; 307 308 static const struct smi_node cs35l41_hda = { 309 .instances = { 310 { "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 }, 311 { "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 }, 312 { "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 }, 313 { "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 }, 314 {} 315 }, 316 .bus_type = SMI_AUTO_DETECT, 317 }; 318 319 /* 320 * Note new device-ids must also be added to ignore_serial_bus_ids in 321 * drivers/acpi/scan.c: acpi_device_enumeration_by_parent(). 322 */ 323 static const struct acpi_device_id smi_acpi_ids[] = { 324 { "BSG1160", (unsigned long)&bsg1160_data }, 325 { "BSG2150", (unsigned long)&bsg2150_data }, 326 { "CSC3551", (unsigned long)&cs35l41_hda }, 327 { "INT3515", (unsigned long)&int3515_data }, 328 /* Non-conforming _HID for Cirrus Logic already released */ 329 { "CLSA0100", (unsigned long)&cs35l41_hda }, 330 { "CLSA0101", (unsigned long)&cs35l41_hda }, 331 { } 332 }; 333 MODULE_DEVICE_TABLE(acpi, smi_acpi_ids); 334 335 static struct platform_driver smi_driver = { 336 .driver = { 337 .name = "Serial bus multi instantiate pseudo device driver", 338 .acpi_match_table = smi_acpi_ids, 339 }, 340 .probe = smi_probe, 341 .remove_new = smi_remove, 342 }; 343 module_platform_driver(smi_driver); 344 345 MODULE_DESCRIPTION("Serial multi instantiate pseudo device driver"); 346 MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); 347 MODULE_LICENSE("GPL"); 348