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