0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/acpi.h>
0010 #include <linux/bits.h>
0011 #include <linux/i2c.h>
0012 #include <linux/interrupt.h>
0013 #include <linux/kernel.h>
0014 #include <linux/module.h>
0015 #include <linux/platform_device.h>
0016 #include <linux/property.h>
0017 #include <linux/spi/spi.h>
0018 #include <linux/types.h>
0019
0020 #define IRQ_RESOURCE_TYPE GENMASK(1, 0)
0021 #define IRQ_RESOURCE_NONE 0
0022 #define IRQ_RESOURCE_GPIO 1
0023 #define IRQ_RESOURCE_APIC 2
0024
0025 enum smi_bus_type {
0026 SMI_I2C,
0027 SMI_SPI,
0028 SMI_AUTO_DETECT,
0029 };
0030
0031 struct smi_instance {
0032 const char *type;
0033 unsigned int flags;
0034 int irq_idx;
0035 };
0036
0037 struct smi_node {
0038 enum smi_bus_type bus_type;
0039 struct smi_instance instances[];
0040 };
0041
0042 struct smi {
0043 int i2c_num;
0044 int spi_num;
0045 struct i2c_client **i2c_devs;
0046 struct spi_device **spi_devs;
0047 };
0048
0049 static int smi_get_irq(struct platform_device *pdev, struct acpi_device *adev,
0050 const struct smi_instance *inst)
0051 {
0052 int ret;
0053
0054 switch (inst->flags & IRQ_RESOURCE_TYPE) {
0055 case IRQ_RESOURCE_GPIO:
0056 ret = acpi_dev_gpio_irq_get(adev, inst->irq_idx);
0057 break;
0058 case IRQ_RESOURCE_APIC:
0059 ret = platform_get_irq(pdev, inst->irq_idx);
0060 break;
0061 default:
0062 return 0;
0063 }
0064 if (ret < 0)
0065 return dev_err_probe(&pdev->dev, ret, "Error requesting irq at index %d\n",
0066 inst->irq_idx);
0067
0068 return ret;
0069 }
0070
0071 static void smi_devs_unregister(struct smi *smi)
0072 {
0073 while (smi->i2c_num--)
0074 i2c_unregister_device(smi->i2c_devs[smi->i2c_num]);
0075
0076 while (smi->spi_num--)
0077 spi_unregister_device(smi->spi_devs[smi->spi_num]);
0078 }
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088 static int smi_spi_probe(struct platform_device *pdev, struct smi *smi,
0089 const struct smi_instance *inst_array)
0090 {
0091 struct device *dev = &pdev->dev;
0092 struct acpi_device *adev = ACPI_COMPANION(dev);
0093 struct spi_controller *ctlr;
0094 struct spi_device *spi_dev;
0095 char name[50];
0096 int i, ret, count;
0097
0098 ret = acpi_spi_count_resources(adev);
0099 if (ret < 0)
0100 return ret;
0101 if (!ret)
0102 return -ENOENT;
0103
0104 count = ret;
0105
0106 smi->spi_devs = devm_kcalloc(dev, count, sizeof(*smi->spi_devs), GFP_KERNEL);
0107 if (!smi->spi_devs)
0108 return -ENOMEM;
0109
0110 for (i = 0; i < count && inst_array[i].type; i++) {
0111
0112 spi_dev = acpi_spi_device_alloc(NULL, adev, i);
0113 if (IS_ERR(spi_dev)) {
0114 ret = dev_err_probe(dev, PTR_ERR(spi_dev), "failed to allocate SPI device %s from ACPI\n",
0115 dev_name(&adev->dev));
0116 goto error;
0117 }
0118
0119 ctlr = spi_dev->controller;
0120
0121 strscpy(spi_dev->modalias, inst_array[i].type, sizeof(spi_dev->modalias));
0122
0123 ret = smi_get_irq(pdev, adev, &inst_array[i]);
0124 if (ret < 0) {
0125 spi_dev_put(spi_dev);
0126 goto error;
0127 }
0128 spi_dev->irq = ret;
0129
0130 snprintf(name, sizeof(name), "%s-%s-%s.%d", dev_name(&ctlr->dev), dev_name(dev),
0131 inst_array[i].type, i);
0132 spi_dev->dev.init_name = name;
0133
0134 ret = spi_add_device(spi_dev);
0135 if (ret) {
0136 dev_err_probe(&ctlr->dev, ret, "failed to add SPI device %s from ACPI\n",
0137 dev_name(&adev->dev));
0138 spi_dev_put(spi_dev);
0139 goto error;
0140 }
0141
0142 dev_dbg(dev, "SPI device %s using chip select %u", name, spi_dev->chip_select);
0143
0144 smi->spi_devs[i] = spi_dev;
0145 smi->spi_num++;
0146 }
0147
0148 if (smi->spi_num < count) {
0149 dev_dbg(dev, "Error finding driver, idx %d\n", i);
0150 ret = -ENODEV;
0151 goto error;
0152 }
0153
0154 dev_info(dev, "Instantiated %d SPI devices.\n", smi->spi_num);
0155
0156 return 0;
0157 error:
0158 smi_devs_unregister(smi);
0159
0160 return ret;
0161 }
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171 static int smi_i2c_probe(struct platform_device *pdev, struct smi *smi,
0172 const struct smi_instance *inst_array)
0173 {
0174 struct i2c_board_info board_info = {};
0175 struct device *dev = &pdev->dev;
0176 struct acpi_device *adev = ACPI_COMPANION(dev);
0177 char name[32];
0178 int i, ret, count;
0179
0180 ret = i2c_acpi_client_count(adev);
0181 if (ret < 0)
0182 return ret;
0183 if (!ret)
0184 return -ENOENT;
0185
0186 count = ret;
0187
0188 smi->i2c_devs = devm_kcalloc(dev, count, sizeof(*smi->i2c_devs), GFP_KERNEL);
0189 if (!smi->i2c_devs)
0190 return -ENOMEM;
0191
0192 for (i = 0; i < count && inst_array[i].type; i++) {
0193 memset(&board_info, 0, sizeof(board_info));
0194 strscpy(board_info.type, inst_array[i].type, I2C_NAME_SIZE);
0195 snprintf(name, sizeof(name), "%s-%s.%d", dev_name(dev), inst_array[i].type, i);
0196 board_info.dev_name = name;
0197
0198 ret = smi_get_irq(pdev, adev, &inst_array[i]);
0199 if (ret < 0)
0200 goto error;
0201 board_info.irq = ret;
0202
0203 smi->i2c_devs[i] = i2c_acpi_new_device(dev, i, &board_info);
0204 if (IS_ERR(smi->i2c_devs[i])) {
0205 ret = dev_err_probe(dev, PTR_ERR(smi->i2c_devs[i]),
0206 "Error creating i2c-client, idx %d\n", i);
0207 goto error;
0208 }
0209 smi->i2c_num++;
0210 }
0211 if (smi->i2c_num < count) {
0212 dev_dbg(dev, "Error finding driver, idx %d\n", i);
0213 ret = -ENODEV;
0214 goto error;
0215 }
0216
0217 dev_info(dev, "Instantiated %d I2C devices.\n", smi->i2c_num);
0218
0219 return 0;
0220 error:
0221 smi_devs_unregister(smi);
0222
0223 return ret;
0224 }
0225
0226 static int smi_probe(struct platform_device *pdev)
0227 {
0228 struct device *dev = &pdev->dev;
0229 const struct smi_node *node;
0230 struct smi *smi;
0231 int ret;
0232
0233 node = device_get_match_data(dev);
0234 if (!node) {
0235 dev_dbg(dev, "Error ACPI match data is missing\n");
0236 return -ENODEV;
0237 }
0238
0239 smi = devm_kzalloc(dev, sizeof(*smi), GFP_KERNEL);
0240 if (!smi)
0241 return -ENOMEM;
0242
0243 platform_set_drvdata(pdev, smi);
0244
0245 switch (node->bus_type) {
0246 case SMI_I2C:
0247 return smi_i2c_probe(pdev, smi, node->instances);
0248 case SMI_SPI:
0249 return smi_spi_probe(pdev, smi, node->instances);
0250 case SMI_AUTO_DETECT:
0251
0252
0253
0254
0255
0256
0257
0258
0259 ret = smi_i2c_probe(pdev, smi, node->instances);
0260 if (ret != -ENOENT)
0261 return ret;
0262 return smi_spi_probe(pdev, smi, node->instances);
0263 default:
0264 return -EINVAL;
0265 }
0266 }
0267
0268 static int smi_remove(struct platform_device *pdev)
0269 {
0270 struct smi *smi = platform_get_drvdata(pdev);
0271
0272 smi_devs_unregister(smi);
0273
0274 return 0;
0275 }
0276
0277 static const struct smi_node bsg1160_data = {
0278 .instances = {
0279 { "bmc150_accel", IRQ_RESOURCE_GPIO, 0 },
0280 { "bmc150_magn" },
0281 { "bmg160" },
0282 {}
0283 },
0284 .bus_type = SMI_I2C,
0285 };
0286
0287 static const struct smi_node bsg2150_data = {
0288 .instances = {
0289 { "bmc150_accel", IRQ_RESOURCE_GPIO, 0 },
0290 { "bmc150_magn" },
0291
0292 { "bsg2150_dummy_dev" },
0293 {}
0294 },
0295 .bus_type = SMI_I2C,
0296 };
0297
0298 static const struct smi_node int3515_data = {
0299 .instances = {
0300 { "tps6598x", IRQ_RESOURCE_APIC, 0 },
0301 { "tps6598x", IRQ_RESOURCE_APIC, 1 },
0302 { "tps6598x", IRQ_RESOURCE_APIC, 2 },
0303 { "tps6598x", IRQ_RESOURCE_APIC, 3 },
0304 {}
0305 },
0306 .bus_type = SMI_I2C,
0307 };
0308
0309 static const struct smi_node cs35l41_hda = {
0310 .instances = {
0311 { "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
0312 { "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
0313 { "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
0314 { "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
0315 {}
0316 },
0317 .bus_type = SMI_AUTO_DETECT,
0318 };
0319
0320
0321
0322
0323
0324 static const struct acpi_device_id smi_acpi_ids[] = {
0325 { "BSG1160", (unsigned long)&bsg1160_data },
0326 { "BSG2150", (unsigned long)&bsg2150_data },
0327 { "CSC3551", (unsigned long)&cs35l41_hda },
0328 { "INT3515", (unsigned long)&int3515_data },
0329
0330 { "CLSA0100", (unsigned long)&cs35l41_hda },
0331 { "CLSA0101", (unsigned long)&cs35l41_hda },
0332 { }
0333 };
0334 MODULE_DEVICE_TABLE(acpi, smi_acpi_ids);
0335
0336 static struct platform_driver smi_driver = {
0337 .driver = {
0338 .name = "Serial bus multi instantiate pseudo device driver",
0339 .acpi_match_table = smi_acpi_ids,
0340 },
0341 .probe = smi_probe,
0342 .remove = smi_remove,
0343 };
0344 module_platform_driver(smi_driver);
0345
0346 MODULE_DESCRIPTION("Serial multi instantiate pseudo device driver");
0347 MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
0348 MODULE_LICENSE("GPL");