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