hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/mfd/kempld-core.c
....@@ -1,17 +1,9 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Kontron PLD MFD core driver
34 *
45 * Copyright (c) 2010-2013 Kontron Europe GmbH
56 * Author: Michael Brunner <michael.brunner@kontron.com>
6
- *
7
- * This program is free software; you can redistribute it and/or modify
8
- * it under the terms of the GNU General Public License 2 as published
9
- * by the Free Software Foundation.
10
- *
11
- * This program is distributed in the hope that it will be useful,
12
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
- * GNU General Public License for more details.
157 */
168
179 #include <linux/platform_device.h>
....@@ -21,6 +13,7 @@
2113 #include <linux/dmi.h>
2214 #include <linux/io.h>
2315 #include <linux/delay.h>
16
+#include <linux/acpi.h>
2417
2518 #define MAX_ID_LEN 4
2619 static char force_device_id[MAX_ID_LEN + 1] = "";
....@@ -87,39 +80,31 @@
8780 KEMPLD_UART,
8881 };
8982
90
-static const struct mfd_cell kempld_devs[] = {
91
- [KEMPLD_I2C] = {
92
- .name = "kempld-i2c",
93
- },
94
- [KEMPLD_WDT] = {
95
- .name = "kempld-wdt",
96
- },
97
- [KEMPLD_GPIO] = {
98
- .name = "kempld-gpio",
99
- },
100
- [KEMPLD_UART] = {
101
- .name = "kempld-uart",
102
- },
83
+static const char *kempld_dev_names[] = {
84
+ [KEMPLD_I2C] = "kempld-i2c",
85
+ [KEMPLD_WDT] = "kempld-wdt",
86
+ [KEMPLD_GPIO] = "kempld-gpio",
87
+ [KEMPLD_UART] = "kempld-uart",
10388 };
10489
105
-#define KEMPLD_MAX_DEVS ARRAY_SIZE(kempld_devs)
90
+#define KEMPLD_MAX_DEVS ARRAY_SIZE(kempld_dev_names)
10691
10792 static int kempld_register_cells_generic(struct kempld_device_data *pld)
10893 {
109
- struct mfd_cell devs[KEMPLD_MAX_DEVS];
94
+ struct mfd_cell devs[KEMPLD_MAX_DEVS] = {};
11095 int i = 0;
11196
11297 if (pld->feature_mask & KEMPLD_FEATURE_BIT_I2C)
113
- devs[i++] = kempld_devs[KEMPLD_I2C];
98
+ devs[i++].name = kempld_dev_names[KEMPLD_I2C];
11499
115100 if (pld->feature_mask & KEMPLD_FEATURE_BIT_WATCHDOG)
116
- devs[i++] = kempld_devs[KEMPLD_WDT];
101
+ devs[i++].name = kempld_dev_names[KEMPLD_WDT];
117102
118103 if (pld->feature_mask & KEMPLD_FEATURE_BIT_GPIO)
119
- devs[i++] = kempld_devs[KEMPLD_GPIO];
104
+ devs[i++].name = kempld_dev_names[KEMPLD_GPIO];
120105
121106 if (pld->feature_mask & KEMPLD_FEATURE_MASK_UART)
122
- devs[i++] = kempld_devs[KEMPLD_UART];
107
+ devs[i++].name = kempld_dev_names[KEMPLD_UART];
123108
124109 return mfd_add_devices(pld->dev, -1, devs, i, NULL, 0, NULL);
125110 }
....@@ -140,6 +125,7 @@
140125 };
141126
142127 static struct platform_device *kempld_pdev;
128
+static bool kempld_acpi_mode;
143129
144130 static int kempld_create_platform_device(const struct dmi_system_id *id)
145131 {
....@@ -442,13 +428,93 @@
442428 return ret;
443429 }
444430
431
+#ifdef CONFIG_ACPI
432
+static int kempld_get_acpi_data(struct platform_device *pdev)
433
+{
434
+ struct list_head resource_list;
435
+ struct resource *resources;
436
+ struct resource_entry *rentry;
437
+ struct device *dev = &pdev->dev;
438
+ struct acpi_device *acpi_dev = ACPI_COMPANION(dev);
439
+ const struct kempld_platform_data *pdata;
440
+ int ret;
441
+ int count;
442
+
443
+ pdata = acpi_device_get_match_data(dev);
444
+ ret = platform_device_add_data(pdev, pdata,
445
+ sizeof(struct kempld_platform_data));
446
+ if (ret)
447
+ return ret;
448
+
449
+ INIT_LIST_HEAD(&resource_list);
450
+ ret = acpi_dev_get_resources(acpi_dev, &resource_list, NULL, NULL);
451
+ if (ret < 0)
452
+ goto out;
453
+
454
+ count = ret;
455
+
456
+ if (count == 0) {
457
+ ret = platform_device_add_resources(pdev, pdata->ioresource, 1);
458
+ goto out;
459
+ }
460
+
461
+ resources = devm_kcalloc(&acpi_dev->dev, count, sizeof(*resources),
462
+ GFP_KERNEL);
463
+ if (!resources) {
464
+ ret = -ENOMEM;
465
+ goto out;
466
+ }
467
+
468
+ count = 0;
469
+ list_for_each_entry(rentry, &resource_list, node) {
470
+ memcpy(&resources[count], rentry->res,
471
+ sizeof(*resources));
472
+ count++;
473
+ }
474
+ ret = platform_device_add_resources(pdev, resources, count);
475
+
476
+out:
477
+ acpi_dev_free_resource_list(&resource_list);
478
+
479
+ return ret;
480
+}
481
+#else
482
+static int kempld_get_acpi_data(struct platform_device *pdev)
483
+{
484
+ return -ENODEV;
485
+}
486
+#endif /* CONFIG_ACPI */
487
+
445488 static int kempld_probe(struct platform_device *pdev)
446489 {
447
- const struct kempld_platform_data *pdata =
448
- dev_get_platdata(&pdev->dev);
490
+ const struct kempld_platform_data *pdata;
449491 struct device *dev = &pdev->dev;
450492 struct kempld_device_data *pld;
451493 struct resource *ioport;
494
+ int ret;
495
+
496
+ if (kempld_pdev == NULL) {
497
+ /*
498
+ * No kempld_pdev device has been registered in kempld_init,
499
+ * so we seem to be probing an ACPI platform device.
500
+ */
501
+ ret = kempld_get_acpi_data(pdev);
502
+ if (ret)
503
+ return ret;
504
+
505
+ kempld_acpi_mode = true;
506
+ } else if (kempld_pdev != pdev) {
507
+ /*
508
+ * The platform device we are probing is not the one we
509
+ * registered in kempld_init using the DMI table, so this one
510
+ * comes from ACPI.
511
+ * As we can only probe one - abort here and use the DMI
512
+ * based one instead.
513
+ */
514
+ dev_notice(dev, "platform device exists - not using ACPI\n");
515
+ return -ENODEV;
516
+ }
517
+ pdata = dev_get_platdata(dev);
452518
453519 pld = devm_kzalloc(dev, sizeof(*pld), GFP_KERNEL);
454520 if (!pld)
....@@ -487,9 +553,19 @@
487553 return 0;
488554 }
489555
556
+#ifdef CONFIG_ACPI
557
+static const struct acpi_device_id kempld_acpi_table[] = {
558
+ { "KEM0001", (kernel_ulong_t)&kempld_platform_data_generic },
559
+ {}
560
+};
561
+MODULE_DEVICE_TABLE(acpi, kempld_acpi_table);
562
+#endif
563
+
490564 static struct platform_driver kempld_driver = {
491565 .driver = {
492566 .name = "kempld",
567
+ .acpi_match_table = ACPI_PTR(kempld_acpi_table),
568
+ .probe_type = PROBE_FORCE_SYNCHRONOUS,
493569 },
494570 .probe = kempld_probe,
495571 .remove = kempld_remove,
....@@ -808,6 +884,7 @@
808884 static int __init kempld_init(void)
809885 {
810886 const struct dmi_system_id *id;
887
+ int ret;
811888
812889 if (force_device_id[0]) {
813890 for (id = kempld_dmi_table;
....@@ -817,12 +894,24 @@
817894 break;
818895 if (id->matches[0].slot == DMI_NONE)
819896 return -ENODEV;
820
- } else {
821
- if (!dmi_check_system(kempld_dmi_table))
822
- return -ENODEV;
823897 }
824898
825
- return platform_driver_register(&kempld_driver);
899
+ ret = platform_driver_register(&kempld_driver);
900
+ if (ret)
901
+ return ret;
902
+
903
+ /*
904
+ * With synchronous probing the device should already be probed now.
905
+ * If no device id is forced and also no ACPI definition for the
906
+ * device was found, scan DMI table as fallback.
907
+ *
908
+ * If drivers_autoprobing is disabled and the device is found here,
909
+ * only that device can be bound manually later.
910
+ */
911
+ if (!kempld_pdev && !kempld_acpi_mode)
912
+ dmi_check_system(kempld_dmi_table);
913
+
914
+ return 0;
826915 }
827916
828917 static void __exit kempld_exit(void)