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, spi_dev->chip_select); 143 144 smi->spi_devs[i] = spi_dev; 145 smi->spi_num++; 146 } 147 148 if (smi->spi_num < count) { 149 dev_dbg(dev, "Error finding driver, idx %d\n", i); 150 ret = -ENODEV; 151 goto error; 152 } 153 154 dev_info(dev, "Instantiated %d SPI devices.\n", smi->spi_num); 155 156 return 0; 157 error: 158 smi_devs_unregister(smi); 159 160 return ret; 161 } 162 163 /** 164 * smi_i2c_probe - Instantiate multiple I2C devices from inst array 165 * @pdev: Platform device 166 * @smi: Internal struct for Serial multi instantiate driver 167 * @inst_array: Array of instances to probe 168 * 169 * Returns the number of I2C devices instantiate, Zero if none is found or a negative error code. 170 */ 171 static int smi_i2c_probe(struct platform_device *pdev, struct smi *smi, 172 const struct smi_instance *inst_array) 173 { 174 struct i2c_board_info board_info = {}; 175 struct device *dev = &pdev->dev; 176 struct acpi_device *adev = ACPI_COMPANION(dev); 177 char name[32]; 178 int i, ret, count; 179 180 ret = i2c_acpi_client_count(adev); 181 if (ret < 0) 182 return ret; 183 if (!ret) 184 return -ENOENT; 185 186 count = ret; 187 188 smi->i2c_devs = devm_kcalloc(dev, count, sizeof(*smi->i2c_devs), GFP_KERNEL); 189 if (!smi->i2c_devs) 190 return -ENOMEM; 191 192 for (i = 0; i < count && inst_array[i].type; i++) { 193 memset(&board_info, 0, sizeof(board_info)); 194 strscpy(board_info.type, inst_array[i].type, I2C_NAME_SIZE); 195 snprintf(name, sizeof(name), "%s-%s.%d", dev_name(dev), inst_array[i].type, i); 196 board_info.dev_name = name; 197 198 ret = smi_get_irq(pdev, adev, &inst_array[i]); 199 if (ret < 0) 200 goto error; 201 board_info.irq = ret; 202 203 smi->i2c_devs[i] = i2c_acpi_new_device(dev, i, &board_info); 204 if (IS_ERR(smi->i2c_devs[i])) { 205 ret = dev_err_probe(dev, PTR_ERR(smi->i2c_devs[i]), 206 "Error creating i2c-client, idx %d\n", i); 207 goto error; 208 } 209 smi->i2c_num++; 210 } 211 if (smi->i2c_num < count) { 212 dev_dbg(dev, "Error finding driver, idx %d\n", i); 213 ret = -ENODEV; 214 goto error; 215 } 216 217 dev_info(dev, "Instantiated %d I2C devices.\n", smi->i2c_num); 218 219 return 0; 220 error: 221 smi_devs_unregister(smi); 222 223 return ret; 224 } 225 226 static int smi_probe(struct platform_device *pdev) 227 { 228 struct device *dev = &pdev->dev; 229 const struct smi_node *node; 230 struct smi *smi; 231 int ret; 232 233 node = device_get_match_data(dev); 234 if (!node) { 235 dev_dbg(dev, "Error ACPI match data is missing\n"); 236 return -ENODEV; 237 } 238 239 smi = devm_kzalloc(dev, sizeof(*smi), GFP_KERNEL); 240 if (!smi) 241 return -ENOMEM; 242 243 platform_set_drvdata(pdev, smi); 244 245 switch (node->bus_type) { 246 case SMI_I2C: 247 return smi_i2c_probe(pdev, smi, node->instances); 248 case SMI_SPI: 249 return smi_spi_probe(pdev, smi, node->instances); 250 case SMI_AUTO_DETECT: 251 /* 252 * For backwards-compatibility with the existing nodes I2C 253 * is checked first and if such entries are found ONLY I2C 254 * devices are created. Since some existing nodes that were 255 * already handled by this driver could also contain unrelated 256 * SpiSerialBus nodes that were previously ignored, and this 257 * preserves that behavior. 258 */ 259 ret = smi_i2c_probe(pdev, smi, node->instances); 260 if (ret != -ENOENT) 261 return ret; 262 return smi_spi_probe(pdev, smi, node->instances); 263 default: 264 return -EINVAL; 265 } 266 } 267 268 static int smi_remove(struct platform_device *pdev) 269 { 270 struct smi *smi = platform_get_drvdata(pdev); 271 272 smi_devs_unregister(smi); 273 274 return 0; 275 } 276 277 static const struct smi_node bsg1160_data = { 278 .instances = { 279 { "bmc150_accel", IRQ_RESOURCE_GPIO, 0 }, 280 { "bmc150_magn" }, 281 { "bmg160" }, 282 {} 283 }, 284 .bus_type = SMI_I2C, 285 }; 286 287 static const struct smi_node bsg2150_data = { 288 .instances = { 289 { "bmc150_accel", IRQ_RESOURCE_GPIO, 0 }, 290 { "bmc150_magn" }, 291 /* The resources describe a 3th client, but it is not really there. */ 292 { "bsg2150_dummy_dev" }, 293 {} 294 }, 295 .bus_type = SMI_I2C, 296 }; 297 298 static const struct smi_node int3515_data = { 299 .instances = { 300 { "tps6598x", IRQ_RESOURCE_APIC, 0 }, 301 { "tps6598x", IRQ_RESOURCE_APIC, 1 }, 302 { "tps6598x", IRQ_RESOURCE_APIC, 2 }, 303 { "tps6598x", IRQ_RESOURCE_APIC, 3 }, 304 {} 305 }, 306 .bus_type = SMI_I2C, 307 }; 308 309 static const struct smi_node cs35l41_hda = { 310 .instances = { 311 { "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 }, 312 { "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 }, 313 { "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 }, 314 { "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 }, 315 {} 316 }, 317 .bus_type = SMI_AUTO_DETECT, 318 }; 319 320 /* 321 * Note new device-ids must also be added to ignore_serial_bus_ids in 322 * drivers/acpi/scan.c: acpi_device_enumeration_by_parent(). 323 */ 324 static const struct acpi_device_id smi_acpi_ids[] = { 325 { "BSG1160", (unsigned long)&bsg1160_data }, 326 { "BSG2150", (unsigned long)&bsg2150_data }, 327 { "CSC3551", (unsigned long)&cs35l41_hda }, 328 { "INT3515", (unsigned long)&int3515_data }, 329 /* Non-conforming _HID for Cirrus Logic already released */ 330 { "CLSA0100", (unsigned long)&cs35l41_hda }, 331 { "CLSA0101", (unsigned long)&cs35l41_hda }, 332 { } 333 }; 334 MODULE_DEVICE_TABLE(acpi, smi_acpi_ids); 335 336 static struct platform_driver smi_driver = { 337 .driver = { 338 .name = "Serial bus multi instantiate pseudo device driver", 339 .acpi_match_table = smi_acpi_ids, 340 }, 341 .probe = smi_probe, 342 .remove = smi_remove, 343 }; 344 module_platform_driver(smi_driver); 345 346 MODULE_DESCRIPTION("Serial multi instantiate pseudo device driver"); 347 MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); 348 MODULE_LICENSE("GPL"); 349