15e63b2eaSLucas Tanure // SPDX-License-Identifier: GPL-2.0+
25e63b2eaSLucas Tanure /*
35e63b2eaSLucas Tanure * Serial multi-instantiate driver, pseudo driver to instantiate multiple
45e63b2eaSLucas Tanure * client devices from a single fwnode.
55e63b2eaSLucas Tanure *
65e63b2eaSLucas Tanure * Copyright 2018 Hans de Goede <hdegoede@redhat.com>
75e63b2eaSLucas Tanure */
85e63b2eaSLucas Tanure
95e63b2eaSLucas Tanure #include <linux/acpi.h>
105e63b2eaSLucas Tanure #include <linux/bits.h>
115e63b2eaSLucas Tanure #include <linux/i2c.h>
125e63b2eaSLucas Tanure #include <linux/interrupt.h>
135e63b2eaSLucas Tanure #include <linux/kernel.h>
145e63b2eaSLucas Tanure #include <linux/module.h>
155e63b2eaSLucas Tanure #include <linux/platform_device.h>
165e63b2eaSLucas Tanure #include <linux/property.h>
1768f201f9SStefan Binding #include <linux/spi/spi.h>
185e63b2eaSLucas Tanure #include <linux/types.h>
195e63b2eaSLucas Tanure
205e63b2eaSLucas Tanure #define IRQ_RESOURCE_TYPE GENMASK(1, 0)
215e63b2eaSLucas Tanure #define IRQ_RESOURCE_NONE 0
225e63b2eaSLucas Tanure #define IRQ_RESOURCE_GPIO 1
235e63b2eaSLucas Tanure #define IRQ_RESOURCE_APIC 2
24676b7c5eSDavid Xu #define IRQ_RESOURCE_AUTO 3
255e63b2eaSLucas Tanure
2668f201f9SStefan Binding enum smi_bus_type {
2768f201f9SStefan Binding SMI_I2C,
2868f201f9SStefan Binding SMI_SPI,
2968f201f9SStefan Binding SMI_AUTO_DETECT,
3068f201f9SStefan Binding };
3168f201f9SStefan Binding
325e63b2eaSLucas Tanure struct smi_instance {
335e63b2eaSLucas Tanure const char *type;
345e63b2eaSLucas Tanure unsigned int flags;
355e63b2eaSLucas Tanure int irq_idx;
365e63b2eaSLucas Tanure };
375e63b2eaSLucas Tanure
3868f201f9SStefan Binding struct smi_node {
3968f201f9SStefan Binding enum smi_bus_type bus_type;
4068f201f9SStefan Binding struct smi_instance instances[];
4168f201f9SStefan Binding };
4268f201f9SStefan Binding
435e63b2eaSLucas Tanure struct smi {
445e63b2eaSLucas Tanure int i2c_num;
4568f201f9SStefan Binding int spi_num;
4635a36cbbSLucas Tanure struct i2c_client **i2c_devs;
4768f201f9SStefan Binding struct spi_device **spi_devs;
485e63b2eaSLucas Tanure };
495e63b2eaSLucas Tanure
smi_get_irq(struct platform_device * pdev,struct acpi_device * adev,const struct smi_instance * inst)5035a36cbbSLucas Tanure static int smi_get_irq(struct platform_device *pdev, struct acpi_device *adev,
5135a36cbbSLucas Tanure const struct smi_instance *inst)
525e63b2eaSLucas Tanure {
5335a36cbbSLucas Tanure int ret;
545e63b2eaSLucas Tanure
5535a36cbbSLucas Tanure switch (inst->flags & IRQ_RESOURCE_TYPE) {
56676b7c5eSDavid Xu case IRQ_RESOURCE_AUTO:
57676b7c5eSDavid Xu ret = acpi_dev_gpio_irq_get(adev, inst->irq_idx);
58676b7c5eSDavid Xu if (ret > 0) {
59676b7c5eSDavid Xu dev_dbg(&pdev->dev, "Using gpio irq\n");
60676b7c5eSDavid Xu break;
61676b7c5eSDavid Xu }
62676b7c5eSDavid Xu ret = platform_get_irq(pdev, inst->irq_idx);
63676b7c5eSDavid Xu if (ret > 0) {
64676b7c5eSDavid Xu dev_dbg(&pdev->dev, "Using platform irq\n");
65676b7c5eSDavid Xu break;
66676b7c5eSDavid Xu }
67676b7c5eSDavid Xu break;
6835a36cbbSLucas Tanure case IRQ_RESOURCE_GPIO:
6935a36cbbSLucas Tanure ret = acpi_dev_gpio_irq_get(adev, inst->irq_idx);
7035a36cbbSLucas Tanure break;
7135a36cbbSLucas Tanure case IRQ_RESOURCE_APIC:
7235a36cbbSLucas Tanure ret = platform_get_irq(pdev, inst->irq_idx);
7335a36cbbSLucas Tanure break;
7435a36cbbSLucas Tanure default:
7535a36cbbSLucas Tanure return 0;
765e63b2eaSLucas Tanure }
7735a36cbbSLucas Tanure if (ret < 0)
7814a9aa99SAndy Shevchenko return dev_err_probe(&pdev->dev, ret, "Error requesting irq at index %d\n",
7914a9aa99SAndy Shevchenko inst->irq_idx);
805e63b2eaSLucas Tanure
8135a36cbbSLucas Tanure return ret;
8235a36cbbSLucas Tanure }
8335a36cbbSLucas Tanure
smi_devs_unregister(struct smi * smi)8435a36cbbSLucas Tanure static void smi_devs_unregister(struct smi *smi)
8535a36cbbSLucas Tanure {
86*3900c6abSRichard Fitzgerald #if IS_REACHABLE(CONFIG_I2C)
87ed7adc2bSAndy Shevchenko while (smi->i2c_num--)
88ed7adc2bSAndy Shevchenko i2c_unregister_device(smi->i2c_devs[smi->i2c_num]);
89*3900c6abSRichard Fitzgerald #endif
9068f201f9SStefan Binding
91*3900c6abSRichard Fitzgerald if (IS_REACHABLE(CONFIG_SPI)) {
92ed7adc2bSAndy Shevchenko while (smi->spi_num--)
93ed7adc2bSAndy Shevchenko spi_unregister_device(smi->spi_devs[smi->spi_num]);
9468f201f9SStefan Binding }
95*3900c6abSRichard Fitzgerald }
9668f201f9SStefan Binding
9768f201f9SStefan Binding /**
9868f201f9SStefan Binding * smi_spi_probe - Instantiate multiple SPI devices from inst array
9968f201f9SStefan Binding * @pdev: Platform device
10068f201f9SStefan Binding * @smi: Internal struct for Serial multi instantiate driver
10168f201f9SStefan Binding * @inst_array: Array of instances to probe
10268f201f9SStefan Binding *
10368f201f9SStefan Binding * Returns the number of SPI devices instantiate, Zero if none is found or a negative error code.
10468f201f9SStefan Binding */
smi_spi_probe(struct platform_device * pdev,struct smi * smi,const struct smi_instance * inst_array)1058b50c48dSAndy Shevchenko static int smi_spi_probe(struct platform_device *pdev, struct smi *smi,
10668f201f9SStefan Binding const struct smi_instance *inst_array)
10768f201f9SStefan Binding {
10868f201f9SStefan Binding struct device *dev = &pdev->dev;
1098b50c48dSAndy Shevchenko struct acpi_device *adev = ACPI_COMPANION(dev);
11068f201f9SStefan Binding struct spi_controller *ctlr;
11168f201f9SStefan Binding struct spi_device *spi_dev;
11268f201f9SStefan Binding char name[50];
11368f201f9SStefan Binding int i, ret, count;
11468f201f9SStefan Binding
11568f201f9SStefan Binding ret = acpi_spi_count_resources(adev);
11668f201f9SStefan Binding if (ret < 0)
11768f201f9SStefan Binding return ret;
118f3e13bbcSAndy Shevchenko if (!ret)
1192b5b2782SAndy Shevchenko return -ENOENT;
12068f201f9SStefan Binding
12168f201f9SStefan Binding count = ret;
12268f201f9SStefan Binding
12368f201f9SStefan Binding smi->spi_devs = devm_kcalloc(dev, count, sizeof(*smi->spi_devs), GFP_KERNEL);
12468f201f9SStefan Binding if (!smi->spi_devs)
12568f201f9SStefan Binding return -ENOMEM;
12668f201f9SStefan Binding
12768f201f9SStefan Binding for (i = 0; i < count && inst_array[i].type; i++) {
12868f201f9SStefan Binding
12968f201f9SStefan Binding spi_dev = acpi_spi_device_alloc(NULL, adev, i);
13068f201f9SStefan Binding if (IS_ERR(spi_dev)) {
13114a9aa99SAndy Shevchenko ret = dev_err_probe(dev, PTR_ERR(spi_dev), "failed to allocate SPI device %s from ACPI\n",
13214a9aa99SAndy Shevchenko dev_name(&adev->dev));
13368f201f9SStefan Binding goto error;
13468f201f9SStefan Binding }
13568f201f9SStefan Binding
13668f201f9SStefan Binding ctlr = spi_dev->controller;
13768f201f9SStefan Binding
1389a3291e9SAndy Shevchenko strscpy(spi_dev->modalias, inst_array[i].type);
13968f201f9SStefan Binding
14068f201f9SStefan Binding ret = smi_get_irq(pdev, adev, &inst_array[i]);
14168f201f9SStefan Binding if (ret < 0) {
14268f201f9SStefan Binding spi_dev_put(spi_dev);
14368f201f9SStefan Binding goto error;
14468f201f9SStefan Binding }
14568f201f9SStefan Binding spi_dev->irq = ret;
14668f201f9SStefan Binding
14768f201f9SStefan Binding snprintf(name, sizeof(name), "%s-%s-%s.%d", dev_name(&ctlr->dev), dev_name(dev),
14868f201f9SStefan Binding inst_array[i].type, i);
14968f201f9SStefan Binding spi_dev->dev.init_name = name;
15068f201f9SStefan Binding
15168f201f9SStefan Binding ret = spi_add_device(spi_dev);
15268f201f9SStefan Binding if (ret) {
15314a9aa99SAndy Shevchenko dev_err_probe(&ctlr->dev, ret, "failed to add SPI device %s from ACPI\n",
15414a9aa99SAndy Shevchenko dev_name(&adev->dev));
15568f201f9SStefan Binding spi_dev_put(spi_dev);
15668f201f9SStefan Binding goto error;
15768f201f9SStefan Binding }
15868f201f9SStefan Binding
159e20451f4SAmit Kumar Mahapatra via Alsa-devel dev_dbg(dev, "SPI device %s using chip select %u", name,
160e20451f4SAmit Kumar Mahapatra via Alsa-devel spi_get_chipselect(spi_dev, 0));
16168f201f9SStefan Binding
16268f201f9SStefan Binding smi->spi_devs[i] = spi_dev;
16368f201f9SStefan Binding smi->spi_num++;
16468f201f9SStefan Binding }
16568f201f9SStefan Binding
16668f201f9SStefan Binding if (smi->spi_num < count) {
16768f201f9SStefan Binding dev_dbg(dev, "Error finding driver, idx %d\n", i);
16868f201f9SStefan Binding ret = -ENODEV;
16968f201f9SStefan Binding goto error;
17068f201f9SStefan Binding }
17168f201f9SStefan Binding
17268f201f9SStefan Binding dev_info(dev, "Instantiated %d SPI devices.\n", smi->spi_num);
17368f201f9SStefan Binding
17468f201f9SStefan Binding return 0;
17568f201f9SStefan Binding error:
17668f201f9SStefan Binding smi_devs_unregister(smi);
17768f201f9SStefan Binding
17868f201f9SStefan Binding return ret;
17935a36cbbSLucas Tanure }
18035a36cbbSLucas Tanure
18135a36cbbSLucas Tanure /**
18235a36cbbSLucas Tanure * smi_i2c_probe - Instantiate multiple I2C devices from inst array
18335a36cbbSLucas Tanure * @pdev: Platform device
18435a36cbbSLucas Tanure * @smi: Internal struct for Serial multi instantiate driver
18535a36cbbSLucas Tanure * @inst_array: Array of instances to probe
18635a36cbbSLucas Tanure *
18735a36cbbSLucas Tanure * Returns the number of I2C devices instantiate, Zero if none is found or a negative error code.
18835a36cbbSLucas Tanure */
smi_i2c_probe(struct platform_device * pdev,struct smi * smi,const struct smi_instance * inst_array)1898b50c48dSAndy Shevchenko static int smi_i2c_probe(struct platform_device *pdev, struct smi *smi,
19035a36cbbSLucas Tanure const struct smi_instance *inst_array)
19135a36cbbSLucas Tanure {
19235a36cbbSLucas Tanure struct i2c_board_info board_info = {};
19335a36cbbSLucas Tanure struct device *dev = &pdev->dev;
1948b50c48dSAndy Shevchenko struct acpi_device *adev = ACPI_COMPANION(dev);
19535a36cbbSLucas Tanure char name[32];
19635a36cbbSLucas Tanure int i, ret, count;
19735a36cbbSLucas Tanure
1985e63b2eaSLucas Tanure ret = i2c_acpi_client_count(adev);
1995e63b2eaSLucas Tanure if (ret < 0)
2005e63b2eaSLucas Tanure return ret;
201f3e13bbcSAndy Shevchenko if (!ret)
2022b5b2782SAndy Shevchenko return -ENOENT;
2035e63b2eaSLucas Tanure
20435a36cbbSLucas Tanure count = ret;
20535a36cbbSLucas Tanure
20635a36cbbSLucas Tanure smi->i2c_devs = devm_kcalloc(dev, count, sizeof(*smi->i2c_devs), GFP_KERNEL);
20735a36cbbSLucas Tanure if (!smi->i2c_devs)
2085e63b2eaSLucas Tanure return -ENOMEM;
2095e63b2eaSLucas Tanure
21035a36cbbSLucas Tanure for (i = 0; i < count && inst_array[i].type; i++) {
2115e63b2eaSLucas Tanure memset(&board_info, 0, sizeof(board_info));
2129a3291e9SAndy Shevchenko strscpy(board_info.type, inst_array[i].type);
21335a36cbbSLucas Tanure snprintf(name, sizeof(name), "%s-%s.%d", dev_name(dev), inst_array[i].type, i);
2145e63b2eaSLucas Tanure board_info.dev_name = name;
21535a36cbbSLucas Tanure
21635a36cbbSLucas Tanure ret = smi_get_irq(pdev, adev, &inst_array[i]);
21735a36cbbSLucas Tanure if (ret < 0)
2185e63b2eaSLucas Tanure goto error;
2195e63b2eaSLucas Tanure board_info.irq = ret;
22035a36cbbSLucas Tanure
2215e63b2eaSLucas Tanure smi->i2c_devs[i] = i2c_acpi_new_device(dev, i, &board_info);
2225e63b2eaSLucas Tanure if (IS_ERR(smi->i2c_devs[i])) {
2235e63b2eaSLucas Tanure ret = dev_err_probe(dev, PTR_ERR(smi->i2c_devs[i]),
2245e63b2eaSLucas Tanure "Error creating i2c-client, idx %d\n", i);
2255e63b2eaSLucas Tanure goto error;
2265e63b2eaSLucas Tanure }
22735a36cbbSLucas Tanure smi->i2c_num++;
2285e63b2eaSLucas Tanure }
22935a36cbbSLucas Tanure if (smi->i2c_num < count) {
23035a36cbbSLucas Tanure dev_dbg(dev, "Error finding driver, idx %d\n", i);
2315e63b2eaSLucas Tanure ret = -ENODEV;
2325e63b2eaSLucas Tanure goto error;
2335e63b2eaSLucas Tanure }
2345e63b2eaSLucas Tanure
23535a36cbbSLucas Tanure dev_info(dev, "Instantiated %d I2C devices.\n", smi->i2c_num);
2365e63b2eaSLucas Tanure
23735a36cbbSLucas Tanure return 0;
2385e63b2eaSLucas Tanure error:
23935a36cbbSLucas Tanure smi_devs_unregister(smi);
2405e63b2eaSLucas Tanure
2415e63b2eaSLucas Tanure return ret;
2425e63b2eaSLucas Tanure }
2435e63b2eaSLucas Tanure
smi_probe(struct platform_device * pdev)24435a36cbbSLucas Tanure static int smi_probe(struct platform_device *pdev)
24535a36cbbSLucas Tanure {
24635a36cbbSLucas Tanure struct device *dev = &pdev->dev;
24768f201f9SStefan Binding const struct smi_node *node;
24835a36cbbSLucas Tanure struct smi *smi;
2492b5b2782SAndy Shevchenko int ret;
25035a36cbbSLucas Tanure
25168f201f9SStefan Binding node = device_get_match_data(dev);
25268f201f9SStefan Binding if (!node) {
25335a36cbbSLucas Tanure dev_dbg(dev, "Error ACPI match data is missing\n");
25435a36cbbSLucas Tanure return -ENODEV;
25535a36cbbSLucas Tanure }
25635a36cbbSLucas Tanure
25735a36cbbSLucas Tanure smi = devm_kzalloc(dev, sizeof(*smi), GFP_KERNEL);
25835a36cbbSLucas Tanure if (!smi)
25935a36cbbSLucas Tanure return -ENOMEM;
26035a36cbbSLucas Tanure
26135a36cbbSLucas Tanure platform_set_drvdata(pdev, smi);
26235a36cbbSLucas Tanure
26368f201f9SStefan Binding switch (node->bus_type) {
26468f201f9SStefan Binding case SMI_I2C:
265*3900c6abSRichard Fitzgerald if (IS_REACHABLE(CONFIG_I2C))
2668b50c48dSAndy Shevchenko return smi_i2c_probe(pdev, smi, node->instances);
267*3900c6abSRichard Fitzgerald
268*3900c6abSRichard Fitzgerald return -ENODEV;
26968f201f9SStefan Binding case SMI_SPI:
270*3900c6abSRichard Fitzgerald if (IS_REACHABLE(CONFIG_SPI))
2718b50c48dSAndy Shevchenko return smi_spi_probe(pdev, smi, node->instances);
272*3900c6abSRichard Fitzgerald
273*3900c6abSRichard Fitzgerald return -ENODEV;
27468f201f9SStefan Binding case SMI_AUTO_DETECT:
2752b5b2782SAndy Shevchenko /*
2762b5b2782SAndy Shevchenko * For backwards-compatibility with the existing nodes I2C
2772b5b2782SAndy Shevchenko * is checked first and if such entries are found ONLY I2C
2782b5b2782SAndy Shevchenko * devices are created. Since some existing nodes that were
2792b5b2782SAndy Shevchenko * already handled by this driver could also contain unrelated
2802b5b2782SAndy Shevchenko * SpiSerialBus nodes that were previously ignored, and this
2812b5b2782SAndy Shevchenko * preserves that behavior.
2822b5b2782SAndy Shevchenko */
283*3900c6abSRichard Fitzgerald if (IS_REACHABLE(CONFIG_I2C)) {
2848b50c48dSAndy Shevchenko ret = smi_i2c_probe(pdev, smi, node->instances);
2852b5b2782SAndy Shevchenko if (ret != -ENOENT)
2862b5b2782SAndy Shevchenko return ret;
287*3900c6abSRichard Fitzgerald }
288*3900c6abSRichard Fitzgerald
289*3900c6abSRichard Fitzgerald if (IS_REACHABLE(CONFIG_SPI))
2908b50c48dSAndy Shevchenko return smi_spi_probe(pdev, smi, node->instances);
291*3900c6abSRichard Fitzgerald
292*3900c6abSRichard Fitzgerald return -ENODEV;
29368f201f9SStefan Binding default:
29468f201f9SStefan Binding return -EINVAL;
29568f201f9SStefan Binding }
29635a36cbbSLucas Tanure }
29735a36cbbSLucas Tanure
smi_remove(struct platform_device * pdev)298143b3c1aSUwe Kleine-König static void smi_remove(struct platform_device *pdev)
2995e63b2eaSLucas Tanure {
3005e63b2eaSLucas Tanure struct smi *smi = platform_get_drvdata(pdev);
3015e63b2eaSLucas Tanure
30235a36cbbSLucas Tanure smi_devs_unregister(smi);
3035e63b2eaSLucas Tanure }
3045e63b2eaSLucas Tanure
30568f201f9SStefan Binding static const struct smi_node bsg1160_data = {
30668f201f9SStefan Binding .instances = {
3075e63b2eaSLucas Tanure { "bmc150_accel", IRQ_RESOURCE_GPIO, 0 },
3085e63b2eaSLucas Tanure { "bmc150_magn" },
3095e63b2eaSLucas Tanure { "bmg160" },
3105e63b2eaSLucas Tanure {}
31168f201f9SStefan Binding },
31268f201f9SStefan Binding .bus_type = SMI_I2C,
3135e63b2eaSLucas Tanure };
3145e63b2eaSLucas Tanure
31568f201f9SStefan Binding static const struct smi_node bsg2150_data = {
31668f201f9SStefan Binding .instances = {
3175e63b2eaSLucas Tanure { "bmc150_accel", IRQ_RESOURCE_GPIO, 0 },
3185e63b2eaSLucas Tanure { "bmc150_magn" },
3195e63b2eaSLucas Tanure /* The resources describe a 3th client, but it is not really there. */
3205e63b2eaSLucas Tanure { "bsg2150_dummy_dev" },
3215e63b2eaSLucas Tanure {}
32268f201f9SStefan Binding },
32368f201f9SStefan Binding .bus_type = SMI_I2C,
3245e63b2eaSLucas Tanure };
3255e63b2eaSLucas Tanure
32668f201f9SStefan Binding static const struct smi_node int3515_data = {
32768f201f9SStefan Binding .instances = {
3285e63b2eaSLucas Tanure { "tps6598x", IRQ_RESOURCE_APIC, 0 },
3295e63b2eaSLucas Tanure { "tps6598x", IRQ_RESOURCE_APIC, 1 },
3305e63b2eaSLucas Tanure { "tps6598x", IRQ_RESOURCE_APIC, 2 },
3315e63b2eaSLucas Tanure { "tps6598x", IRQ_RESOURCE_APIC, 3 },
3325e63b2eaSLucas Tanure {}
33368f201f9SStefan Binding },
33468f201f9SStefan Binding .bus_type = SMI_I2C,
3355e63b2eaSLucas Tanure };
3365e63b2eaSLucas Tanure
337d9c01c53SLucas Tanure static const struct smi_node cs35l41_hda = {
338d9c01c53SLucas Tanure .instances = {
339676b7c5eSDavid Xu { "cs35l41-hda", IRQ_RESOURCE_AUTO, 0 },
340676b7c5eSDavid Xu { "cs35l41-hda", IRQ_RESOURCE_AUTO, 0 },
341676b7c5eSDavid Xu { "cs35l41-hda", IRQ_RESOURCE_AUTO, 0 },
342676b7c5eSDavid Xu { "cs35l41-hda", IRQ_RESOURCE_AUTO, 0 },
343d9c01c53SLucas Tanure {}
344d9c01c53SLucas Tanure },
345d9c01c53SLucas Tanure .bus_type = SMI_AUTO_DETECT,
346d9c01c53SLucas Tanure };
347d9c01c53SLucas Tanure
3486fa9ba2dSSimon Trimmer static const struct smi_node cs35l54_hda = {
3496fa9ba2dSSimon Trimmer .instances = {
3506fa9ba2dSSimon Trimmer { "cs35l54-hda", IRQ_RESOURCE_AUTO, 0 },
3516fa9ba2dSSimon Trimmer { "cs35l54-hda", IRQ_RESOURCE_AUTO, 0 },
3526fa9ba2dSSimon Trimmer { "cs35l54-hda", IRQ_RESOURCE_AUTO, 0 },
3536fa9ba2dSSimon Trimmer { "cs35l54-hda", IRQ_RESOURCE_AUTO, 0 },
3546fa9ba2dSSimon Trimmer /* a 5th entry is an alias address, not a real device */
3556fa9ba2dSSimon Trimmer { "cs35l54-hda_dummy_dev" },
3566fa9ba2dSSimon Trimmer {}
3576fa9ba2dSSimon Trimmer },
3586fa9ba2dSSimon Trimmer .bus_type = SMI_AUTO_DETECT,
3596fa9ba2dSSimon Trimmer };
3606fa9ba2dSSimon Trimmer
3611cd0302bSSimon Trimmer static const struct smi_node cs35l56_hda = {
3621cd0302bSSimon Trimmer .instances = {
3631cd0302bSSimon Trimmer { "cs35l56-hda", IRQ_RESOURCE_AUTO, 0 },
3641cd0302bSSimon Trimmer { "cs35l56-hda", IRQ_RESOURCE_AUTO, 0 },
3651cd0302bSSimon Trimmer { "cs35l56-hda", IRQ_RESOURCE_AUTO, 0 },
3661cd0302bSSimon Trimmer { "cs35l56-hda", IRQ_RESOURCE_AUTO, 0 },
3671cd0302bSSimon Trimmer /* a 5th entry is an alias address, not a real device */
3681cd0302bSSimon Trimmer { "cs35l56-hda_dummy_dev" },
3691cd0302bSSimon Trimmer {}
3701cd0302bSSimon Trimmer },
3711cd0302bSSimon Trimmer .bus_type = SMI_AUTO_DETECT,
3721cd0302bSSimon Trimmer };
3731cd0302bSSimon Trimmer
3746fa9ba2dSSimon Trimmer static const struct smi_node cs35l57_hda = {
3756fa9ba2dSSimon Trimmer .instances = {
3766fa9ba2dSSimon Trimmer { "cs35l57-hda", IRQ_RESOURCE_AUTO, 0 },
3776fa9ba2dSSimon Trimmer { "cs35l57-hda", IRQ_RESOURCE_AUTO, 0 },
3786fa9ba2dSSimon Trimmer { "cs35l57-hda", IRQ_RESOURCE_AUTO, 0 },
3796fa9ba2dSSimon Trimmer { "cs35l57-hda", IRQ_RESOURCE_AUTO, 0 },
3806fa9ba2dSSimon Trimmer /* a 5th entry is an alias address, not a real device */
3816fa9ba2dSSimon Trimmer { "cs35l57-hda_dummy_dev" },
3826fa9ba2dSSimon Trimmer {}
3836fa9ba2dSSimon Trimmer },
3846fa9ba2dSSimon Trimmer .bus_type = SMI_AUTO_DETECT,
3856fa9ba2dSSimon Trimmer };
3866fa9ba2dSSimon Trimmer
3875e63b2eaSLucas Tanure /*
3885e63b2eaSLucas Tanure * Note new device-ids must also be added to ignore_serial_bus_ids in
3895e63b2eaSLucas Tanure * drivers/acpi/scan.c: acpi_device_enumeration_by_parent().
3905e63b2eaSLucas Tanure */
3915e63b2eaSLucas Tanure static const struct acpi_device_id smi_acpi_ids[] = {
39268f201f9SStefan Binding { "BSG1160", (unsigned long)&bsg1160_data },
39368f201f9SStefan Binding { "BSG2150", (unsigned long)&bsg2150_data },
394d9c01c53SLucas Tanure { "CSC3551", (unsigned long)&cs35l41_hda },
3956fa9ba2dSSimon Trimmer { "CSC3554", (unsigned long)&cs35l54_hda },
3961cd0302bSSimon Trimmer { "CSC3556", (unsigned long)&cs35l56_hda },
3976fa9ba2dSSimon Trimmer { "CSC3557", (unsigned long)&cs35l57_hda },
398e286044bSAndy Shevchenko { "INT3515", (unsigned long)&int3515_data },
399d9c01c53SLucas Tanure /* Non-conforming _HID for Cirrus Logic already released */
400d9c01c53SLucas Tanure { "CLSA0100", (unsigned long)&cs35l41_hda },
40188392a0dSLucas Tanure { "CLSA0101", (unsigned long)&cs35l41_hda },
4025e63b2eaSLucas Tanure { }
4035e63b2eaSLucas Tanure };
4045e63b2eaSLucas Tanure MODULE_DEVICE_TABLE(acpi, smi_acpi_ids);
4055e63b2eaSLucas Tanure
4065e63b2eaSLucas Tanure static struct platform_driver smi_driver = {
4075e63b2eaSLucas Tanure .driver = {
4085e63b2eaSLucas Tanure .name = "Serial bus multi instantiate pseudo device driver",
4095e63b2eaSLucas Tanure .acpi_match_table = smi_acpi_ids,
4105e63b2eaSLucas Tanure },
4115e63b2eaSLucas Tanure .probe = smi_probe,
412143b3c1aSUwe Kleine-König .remove_new = smi_remove,
4135e63b2eaSLucas Tanure };
4145e63b2eaSLucas Tanure module_platform_driver(smi_driver);
4155e63b2eaSLucas Tanure
4165e63b2eaSLucas Tanure MODULE_DESCRIPTION("Serial multi instantiate pseudo device driver");
4175e63b2eaSLucas Tanure MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
4185e63b2eaSLucas Tanure MODULE_LICENSE("GPL");
419