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 ChromeOS EC.
7  */
8 
9 #include <linux/acpi.h>
10 #include <linux/delay.h>
11 #include <linux/jiffies.h>
12 #include <linux/module.h>
13 #include <linux/platform_data/cros_ec_commands.h>
14 #include <linux/platform_data/cros_ec_proto.h>
15 #include <linux/platform_device.h>
16 #include <linux/usb/typec_altmode.h>
17 #include <linux/usb/typec_dp.h>
18 #include <linux/usb/typec_mux.h>
19 #include <linux/usb/typec_retimer.h>
20 
21 /* Handles and other relevant data required for each port's switches. */
22 struct cros_typec_port {
23 	int port_num;
24 	struct typec_mux_dev *mode_switch;
25 	struct typec_retimer *retimer;
26 	struct cros_typec_switch_data *sdata;
27 };
28 
29 /* Driver-specific data. */
30 struct cros_typec_switch_data {
31 	struct device *dev;
32 	struct cros_ec_device *ec;
33 	struct cros_typec_port *ports[EC_USB_PD_MAX_PORTS];
34 };
35 
36 static int cros_typec_cmd_mux_set(struct cros_typec_switch_data *sdata, int port_num, u8 index,
37 				  u8 state)
38 {
39 	struct ec_params_typec_control req = {
40 		.port = port_num,
41 		.command = TYPEC_CONTROL_COMMAND_USB_MUX_SET,
42 		.mux_params = {
43 			.mux_index = index,
44 			.mux_flags = state,
45 		},
46 	};
47 
48 	return cros_ec_cmd(sdata->ec, 0, EC_CMD_TYPEC_CONTROL, &req, sizeof(req), NULL, 0);
49 }
50 
51 static int cros_typec_get_mux_state(unsigned long mode, struct typec_altmode *alt)
52 {
53 	int ret = -EOPNOTSUPP;
54 
55 	if (mode == TYPEC_STATE_SAFE)
56 		ret = USB_PD_MUX_SAFE_MODE;
57 	else if (mode == TYPEC_STATE_USB)
58 		ret = USB_PD_MUX_USB_ENABLED;
59 	else if (alt && alt->svid == USB_TYPEC_DP_SID)
60 		ret = USB_PD_MUX_DP_ENABLED;
61 
62 	return ret;
63 }
64 
65 static int cros_typec_send_clear_event(struct cros_typec_switch_data *sdata, int port_num,
66 				       u32 events_mask)
67 {
68 	struct ec_params_typec_control req = {
69 		.port = port_num,
70 		.command = TYPEC_CONTROL_COMMAND_CLEAR_EVENTS,
71 		.clear_events_mask = events_mask,
72 	};
73 
74 	return cros_ec_cmd(sdata->ec, 0, EC_CMD_TYPEC_CONTROL, &req, sizeof(req), NULL, 0);
75 }
76 
77 static bool cros_typec_check_event(struct cros_typec_switch_data *sdata, int port_num, u32 mask)
78 {
79 	struct ec_response_typec_status resp;
80 	struct ec_params_typec_status req = {
81 		.port = port_num,
82 	};
83 	int ret;
84 
85 	ret = cros_ec_cmd(sdata->ec, 0, EC_CMD_TYPEC_STATUS, &req, sizeof(req),
86 			  &resp, sizeof(resp));
87 	if (ret < 0) {
88 		dev_warn(sdata->dev, "EC_CMD_TYPEC_STATUS failed for port: %d\n", port_num);
89 		return false;
90 	}
91 
92 	if (resp.events & mask)
93 		return true;
94 
95 	return false;
96 }
97 
98 /*
99  * The ChromeOS EC treats both mode-switches and retimers as "muxes" for the purposes of the
100  * host command API. This common function configures and verifies the retimer/mode-switch
101  * according to the provided setting.
102  */
103 static int cros_typec_configure_mux(struct cros_typec_switch_data *sdata, int port_num, int index,
104 				    unsigned long mode, struct typec_altmode *alt)
105 {
106 	unsigned long end;
107 	u32 event_mask;
108 	u8 mux_state;
109 	int ret;
110 
111 	ret = cros_typec_get_mux_state(mode, alt);
112 	if (ret < 0)
113 		return ret;
114 	mux_state = (u8)ret;
115 
116 	/* Clear any old mux set done event. */
117 	if (index == 0)
118 		event_mask = PD_STATUS_EVENT_MUX_0_SET_DONE;
119 	else
120 		event_mask = PD_STATUS_EVENT_MUX_1_SET_DONE;
121 
122 	ret = cros_typec_send_clear_event(sdata, port_num, event_mask);
123 	if (ret < 0)
124 		return ret;
125 
126 	/* Send the set command. */
127 	ret = cros_typec_cmd_mux_set(sdata, port_num, index, mux_state);
128 	if (ret < 0)
129 		return ret;
130 
131 	/* Check for the mux set done event. */
132 	end = jiffies + msecs_to_jiffies(1000);
133 	do {
134 		if (cros_typec_check_event(sdata, port_num, event_mask))
135 			return 0;
136 
137 		usleep_range(500, 1000);
138 	} while (time_before(jiffies, end));
139 
140 	dev_err(sdata->dev, "Timed out waiting for mux set done on index: %d, state: %d\n",
141 		index, mux_state);
142 
143 	return -ETIMEDOUT;
144 }
145 
146 static int cros_typec_mode_switch_set(struct typec_mux_dev *mode_switch,
147 				      struct typec_mux_state *state)
148 {
149 	struct cros_typec_port *port = typec_mux_get_drvdata(mode_switch);
150 
151 	/* Mode switches have index 0. */
152 	return cros_typec_configure_mux(port->sdata, port->port_num, 0, state->mode, state->alt);
153 }
154 
155 static int cros_typec_retimer_set(struct typec_retimer *retimer, struct typec_retimer_state *state)
156 {
157 	struct cros_typec_port *port = typec_retimer_get_drvdata(retimer);
158 
159 	/* Retimers have index 1. */
160 	return cros_typec_configure_mux(port->sdata, port->port_num, 1, state->mode, state->alt);
161 }
162 
163 static void cros_typec_unregister_switches(struct cros_typec_switch_data *sdata)
164 {
165 	int i;
166 
167 	for (i = 0; i < EC_USB_PD_MAX_PORTS; i++) {
168 		if (!sdata->ports[i])
169 			continue;
170 		typec_retimer_unregister(sdata->ports[i]->retimer);
171 		typec_mux_unregister(sdata->ports[i]->mode_switch);
172 	}
173 }
174 
175 static int cros_typec_register_mode_switch(struct cros_typec_port *port,
176 					   struct fwnode_handle *fwnode)
177 {
178 	struct typec_mux_desc mode_switch_desc = {
179 		.fwnode = fwnode,
180 		.drvdata = port,
181 		.name = fwnode_get_name(fwnode),
182 		.set = cros_typec_mode_switch_set,
183 	};
184 
185 	port->mode_switch = typec_mux_register(port->sdata->dev, &mode_switch_desc);
186 
187 	return PTR_ERR_OR_ZERO(port->mode_switch);
188 }
189 
190 static int cros_typec_register_retimer(struct cros_typec_port *port, struct fwnode_handle *fwnode)
191 {
192 	struct typec_retimer_desc retimer_desc = {
193 		.fwnode = fwnode,
194 		.drvdata = port,
195 		.name = fwnode_get_name(fwnode),
196 		.set = cros_typec_retimer_set,
197 	};
198 
199 	port->retimer = typec_retimer_register(port->sdata->dev, &retimer_desc);
200 
201 	return PTR_ERR_OR_ZERO(port->retimer);
202 }
203 
204 static int cros_typec_register_switches(struct cros_typec_switch_data *sdata)
205 {
206 	struct cros_typec_port *port;
207 	struct device *dev = sdata->dev;
208 	struct fwnode_handle *fwnode;
209 	struct acpi_device *adev;
210 	unsigned long long index;
211 	int nports, ret;
212 
213 	nports = device_get_child_node_count(dev);
214 	if (nports == 0) {
215 		dev_err(dev, "No switch devices found.\n");
216 		return -ENODEV;
217 	}
218 
219 	device_for_each_child_node(dev, fwnode) {
220 		port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL);
221 		if (!port) {
222 			ret = -ENOMEM;
223 			goto err_switch;
224 		}
225 
226 		adev = to_acpi_device_node(fwnode);
227 		if (!adev) {
228 			dev_err(fwnode->dev, "Couldn't get ACPI device handle\n");
229 			ret = -ENODEV;
230 			goto err_switch;
231 		}
232 
233 		ret = acpi_evaluate_integer(adev->handle, "_ADR", NULL, &index);
234 		if (ACPI_FAILURE(ret)) {
235 			dev_err(fwnode->dev, "_ADR wasn't evaluated\n");
236 			ret = -ENODATA;
237 			goto err_switch;
238 		}
239 
240 		if (index >= EC_USB_PD_MAX_PORTS) {
241 			dev_err(fwnode->dev, "Invalid port index number: %llu\n", index);
242 			ret = -EINVAL;
243 			goto err_switch;
244 		}
245 		port->sdata = sdata;
246 		port->port_num = index;
247 		sdata->ports[index] = port;
248 
249 		ret = cros_typec_register_retimer(port, fwnode);
250 		if (ret) {
251 			dev_err(dev, "Retimer switch register failed\n");
252 			goto err_switch;
253 		}
254 
255 		dev_dbg(dev, "Retimer switch registered for index %llu\n", index);
256 
257 		if (!device_property_present(fwnode->dev, "mode-switch"))
258 			continue;
259 
260 		ret = cros_typec_register_mode_switch(port, fwnode);
261 		if (ret) {
262 			dev_err(dev, "Mode switch register failed\n");
263 			goto err_switch;
264 		}
265 
266 		dev_dbg(dev, "Mode switch registered for index %llu\n", index);
267 	}
268 
269 	return 0;
270 err_switch:
271 	cros_typec_unregister_switches(sdata);
272 	return ret;
273 }
274 
275 static int cros_typec_switch_probe(struct platform_device *pdev)
276 {
277 	struct device *dev = &pdev->dev;
278 	struct cros_typec_switch_data *sdata;
279 
280 	sdata = devm_kzalloc(dev, sizeof(*sdata), GFP_KERNEL);
281 	if (!sdata)
282 		return -ENOMEM;
283 
284 	sdata->dev = dev;
285 	sdata->ec = dev_get_drvdata(pdev->dev.parent);
286 
287 	platform_set_drvdata(pdev, sdata);
288 
289 	return cros_typec_register_switches(sdata);
290 }
291 
292 static int cros_typec_switch_remove(struct platform_device *pdev)
293 {
294 	struct cros_typec_switch_data *sdata = platform_get_drvdata(pdev);
295 
296 	cros_typec_unregister_switches(sdata);
297 	return 0;
298 }
299 
300 #ifdef CONFIG_ACPI
301 static const struct acpi_device_id cros_typec_switch_acpi_id[] = {
302 	{ "GOOG001A", 0 },
303 	{}
304 };
305 MODULE_DEVICE_TABLE(acpi, cros_typec_switch_acpi_id);
306 #endif
307 
308 static struct platform_driver cros_typec_switch_driver = {
309 	.driver	= {
310 		.name = "cros-typec-switch",
311 		.acpi_match_table = ACPI_PTR(cros_typec_switch_acpi_id),
312 	},
313 	.probe = cros_typec_switch_probe,
314 	.remove = cros_typec_switch_remove,
315 };
316 
317 module_platform_driver(cros_typec_switch_driver);
318 
319 MODULE_AUTHOR("Prashant Malani <pmalani@chromium.org>");
320 MODULE_DESCRIPTION("ChromeOS EC Type-C Switch control");
321 MODULE_LICENSE("GPL");
322