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