Revert "platform/chrome: cros_typec_switch: Add ACPI Kconfig dep"
[platform/kernel/linux-starfive.git] / drivers / platform / chrome / cros_typec_switch.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright 2022 Google LLC
4  *
5  * This driver provides the ability to configure Type C muxes and retimers which are controlled by
6  * the Chrome OS EC.
7  */
8
9 #include <linux/acpi.h>
10 #include <linux/module.h>
11 #include <linux/platform_data/cros_ec_commands.h>
12 #include <linux/platform_device.h>
13 #include <linux/usb/typec_retimer.h>
14
15 #define DRV_NAME "cros-typec-switch"
16
17 /* Handles and other relevant data required for each port's switches. */
18 struct cros_typec_port {
19         int port_num;
20         struct typec_retimer *retimer;
21         struct cros_typec_switch_data *sdata;
22 };
23
24 /* Driver-specific data. */
25 struct cros_typec_switch_data {
26         struct device *dev;
27         struct cros_ec_device *ec;
28         struct cros_typec_port *ports[EC_USB_PD_MAX_PORTS];
29 };
30
31 static int cros_typec_retimer_set(struct typec_retimer *retimer, struct typec_retimer_state *state)
32 {
33         return 0;
34 }
35
36 static void cros_typec_unregister_switches(struct cros_typec_switch_data *sdata)
37 {
38         int i;
39
40         for (i = 0; i < EC_USB_PD_MAX_PORTS; i++) {
41                 if (!sdata->ports[i])
42                         continue;
43                 typec_retimer_unregister(sdata->ports[i]->retimer);
44         }
45 }
46
47 static int cros_typec_register_retimer(struct cros_typec_port *port, struct fwnode_handle *fwnode)
48 {
49         struct typec_retimer_desc retimer_desc = {
50                 .fwnode = fwnode,
51                 .drvdata = port,
52                 .name = fwnode_get_name(fwnode),
53                 .set = cros_typec_retimer_set,
54         };
55
56         port->retimer = typec_retimer_register(port->sdata->dev, &retimer_desc);
57         if (IS_ERR(port->retimer))
58                 return PTR_ERR(port->retimer);
59
60         return 0;
61 }
62
63 static int cros_typec_register_switches(struct cros_typec_switch_data *sdata)
64 {
65         struct cros_typec_port *port = NULL;
66         struct device *dev = sdata->dev;
67         struct fwnode_handle *fwnode;
68         struct acpi_device *adev;
69         unsigned long long index;
70         int ret = 0;
71         int nports;
72
73         nports = device_get_child_node_count(dev);
74         if (nports == 0) {
75                 dev_err(dev, "No switch devices found.\n");
76                 return -ENODEV;
77         }
78
79         device_for_each_child_node(dev, fwnode) {
80                 port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL);
81                 if (!port) {
82                         ret = -ENOMEM;
83                         goto err_switch;
84                 }
85
86                 adev = to_acpi_device_node(fwnode);
87                 if (!adev) {
88                         dev_err(fwnode->dev, "Couldn't get ACPI device handle\n");
89                         ret = -ENODEV;
90                         goto err_switch;
91                 }
92
93                 ret = acpi_evaluate_integer(adev->handle, "_ADR", NULL, &index);
94                 if (ACPI_FAILURE(ret)) {
95                         dev_err(fwnode->dev, "_ADR wasn't evaluated\n");
96                         ret = -ENODATA;
97                         goto err_switch;
98                 }
99
100                 if (index < 0 || index >= EC_USB_PD_MAX_PORTS) {
101                         dev_err(fwnode->dev, "Invalid port index number: %llu", index);
102                         ret = -EINVAL;
103                         goto err_switch;
104                 }
105                 port->sdata = sdata;
106                 port->port_num = index;
107                 sdata->ports[index] = port;
108
109                 ret = cros_typec_register_retimer(port, fwnode);
110                 if (ret) {
111                         dev_err(dev, "Retimer switch register failed\n");
112                         goto err_switch;
113                 }
114
115                 dev_dbg(dev, "Retimer switch registered for index %llu\n", index);
116         }
117
118         return 0;
119 err_switch:
120         cros_typec_unregister_switches(sdata);
121         return ret;
122 }
123
124 static int cros_typec_switch_probe(struct platform_device *pdev)
125 {
126         struct device *dev = &pdev->dev;
127         struct cros_typec_switch_data *sdata;
128
129         sdata = devm_kzalloc(dev, sizeof(*sdata), GFP_KERNEL);
130         if (!sdata)
131                 return -ENOMEM;
132
133         sdata->dev = dev;
134         sdata->ec = dev_get_drvdata(pdev->dev.parent);
135
136         platform_set_drvdata(pdev, sdata);
137
138         return cros_typec_register_switches(sdata);
139 }
140
141 static int cros_typec_switch_remove(struct platform_device *pdev)
142 {
143         struct cros_typec_switch_data *sdata = platform_get_drvdata(pdev);
144
145         cros_typec_unregister_switches(sdata);
146         return 0;
147 }
148
149 #ifdef CONFIG_ACPI
150 static const struct acpi_device_id cros_typec_switch_acpi_id[] = {
151         { "GOOG001A", 0 },
152         {}
153 };
154 MODULE_DEVICE_TABLE(acpi, cros_typec_switch_acpi_id);
155 #endif
156
157 static struct platform_driver cros_typec_switch_driver = {
158         .driver = {
159                 .name = DRV_NAME,
160                 .acpi_match_table = ACPI_PTR(cros_typec_switch_acpi_id),
161         },
162         .probe = cros_typec_switch_probe,
163         .remove = cros_typec_switch_remove,
164 };
165
166 module_platform_driver(cros_typec_switch_driver);
167
168 MODULE_AUTHOR("Prashant Malani <pmalani@chromium.org>");
169 MODULE_DESCRIPTION("Chrome OS EC Type C Switch control");
170 MODULE_LICENSE("GPL");