Merge tag 'tag-chrome-platform-for-v5.9' of git://git.kernel.org/pub/scm/linux/kernel/git/chrome-platform/linux

Pull chrome platform updates from Benson Leung:
"cros_ec_typec:

- Add support for switch control and alternate modes to the Chrome EC
Type C port driver

- Add basic suspend/resume support

sensorhub:

- Fix timestamp overflow issue

- Fix legacy timestamp spreading on Nami systems

cros_ec_proto:

- After removing all users of, stop exporting cros_ec_cmd_xfer

- Check for missing EC_CMD_HOST_EVENT_GET_WAKE_MASK and ignore
wakeups on old ECs

misc:

- Documentation warning cleanup

- Fix double unlock issue in ishtp"

* tag 'tag-chrome-platform-for-v5.9' of git://git.kernel.org/pub/scm/linux/kernel/git/chrome-platform/linux: (21 commits)
platform/chrome: cros_ec_proto: check for missing EC_CMD_HOST_EVENT_GET_WAKE_MASK
platform/chrome: cros_ec_proto: ignore unnecessary wakeups on old ECs
platform/chrome: cros_ec_sensorhub: Simplify legacy timestamp spreading
platform/chrome: cros_ec_proto: Do not export cros_ec_cmd_xfer()
platform/chrome: cros_ec_typec: Unregister partner on error
platform/chrome: cros_ec_sensorhub: Fix EC timestamp overflow
platform/chrome: cros_ec_typec: Add PM support
platform/chrome: cros_ec_typec: Use workqueue for port update
platform/chrome: cros_ec_typec: Add a dependency on USB_ROLE_SWITCH
platform/chrome: cros_ec_ishtp: Fix a double-unlock issue
platform/chrome: cros_ec_rpmsg: Document missing struct parameters
platform/chrome: cros_ec_spi: Document missing function parameters
platform/chrome: cros_ec_typec: Add TBT compat support
platform/chrome: cros_ec: Add TBT pd_ctrl fields
platform/chrome: cros_ec_typec: Make configure_mux static
platform/chrome: cros_ec_typec: Support DP alt mode
platform/chrome: cros_ec_typec: Add USB mux control
platform/chrome: cros_ec_typec: Register PD CTRL cmd v2
platform/chrome: cros_ec: Update mux state bits
platform/chrome: cros_ec_typec: Register Type C switches
...

+485 -130
+1
drivers/platform/chrome/Kconfig
··· 218 218 tristate "ChromeOS EC Type-C Connector Control" 219 219 depends on MFD_CROS_EC_DEV && TYPEC 220 220 depends on CROS_USBPD_NOTIFY 221 + depends on USB_ROLE_SWITCH 221 222 default MFD_CROS_EC_DEV 222 223 help 223 224 If you say Y here, you get support for accessing Type C connector
+22 -2
drivers/platform/chrome/cros_ec_debugfs.c
··· 242 242 read_buf, p - read_buf); 243 243 } 244 244 245 + static bool cros_ec_uptime_is_supported(struct cros_ec_device *ec_dev) 246 + { 247 + struct { 248 + struct cros_ec_command cmd; 249 + struct ec_response_uptime_info resp; 250 + } __packed msg = {}; 251 + int ret; 252 + 253 + msg.cmd.command = EC_CMD_GET_UPTIME_INFO; 254 + msg.cmd.insize = sizeof(msg.resp); 255 + 256 + ret = cros_ec_cmd_xfer_status(ec_dev, &msg.cmd); 257 + if (ret == -EPROTO && msg.cmd.result == EC_RES_INVALID_COMMAND) 258 + return false; 259 + 260 + /* Other errors maybe a transient error, do not rule about support. */ 261 + return true; 262 + } 263 + 245 264 static ssize_t cros_ec_uptime_read(struct file *file, char __user *user_buf, 246 265 size_t count, loff_t *ppos) 247 266 { ··· 463 444 debugfs_create_file("pdinfo", 0444, debug_info->dir, debug_info, 464 445 &cros_ec_pdinfo_fops); 465 446 466 - debugfs_create_file("uptime", 0444, debug_info->dir, debug_info, 467 - &cros_ec_uptime_fops); 447 + if (cros_ec_uptime_is_supported(ec->ec_dev)) 448 + debugfs_create_file("uptime", 0444, debug_info->dir, debug_info, 449 + &cros_ec_uptime_fops); 468 450 469 451 debugfs_create_x32("last_resume_result", 0444, debug_info->dir, 470 452 &ec->ec_dev->last_resume_result);
+3 -1
drivers/platform/chrome/cros_ec_ishtp.c
··· 681 681 682 682 /* Register croc_ec_dev mfd */ 683 683 rv = cros_ec_dev_init(client_data); 684 - if (rv) 684 + if (rv) { 685 + down_write(&init_lock); 685 686 goto end_cros_ec_dev_init_error; 687 + } 686 688 687 689 return 0; 688 690
+33 -9
drivers/platform/chrome/cros_ec_proto.c
··· 208 208 msg->insize = sizeof(*r); 209 209 210 210 ret = send_command(ec_dev, msg); 211 + if (ret >= 0) { 212 + if (msg->result == EC_RES_INVALID_COMMAND) 213 + return -EOPNOTSUPP; 214 + if (msg->result != EC_RES_SUCCESS) 215 + return -EPROTO; 216 + } 211 217 if (ret > 0) { 212 218 r = (struct ec_response_host_event_mask *)msg->data; 213 219 *mask = r->mask; ··· 475 469 &ver_mask); 476 470 ec_dev->host_sleep_v1 = (ret >= 0 && (ver_mask & EC_VER_MASK(1))); 477 471 478 - /* 479 - * Get host event wake mask, assume all events are wake events 480 - * if unavailable. 481 - */ 472 + /* Get host event wake mask. */ 482 473 ret = cros_ec_get_host_event_wake_mask(ec_dev, proto_msg, 483 474 &ec_dev->host_event_wake_mask); 484 - if (ret < 0) 485 - ec_dev->host_event_wake_mask = U32_MAX; 475 + if (ret < 0) { 476 + /* 477 + * If the EC doesn't support EC_CMD_HOST_EVENT_GET_WAKE_MASK, 478 + * use a reasonable default. Note that we ignore various 479 + * battery, AC status, and power-state events, because (a) 480 + * those can be quite common (e.g., when sitting at full 481 + * charge, on AC) and (b) these are not actionable wake events; 482 + * if anything, we'd like to continue suspending (to save 483 + * power), not wake up. 484 + */ 485 + ec_dev->host_event_wake_mask = U32_MAX & 486 + ~(BIT(EC_HOST_EVENT_AC_DISCONNECTED) | 487 + BIT(EC_HOST_EVENT_BATTERY_LOW) | 488 + BIT(EC_HOST_EVENT_BATTERY_CRITICAL) | 489 + BIT(EC_HOST_EVENT_PD_MCU) | 490 + BIT(EC_HOST_EVENT_BATTERY_STATUS)); 491 + /* 492 + * Old ECs may not support this command. Complain about all 493 + * other errors. 494 + */ 495 + if (ret != -EOPNOTSUPP) 496 + dev_err(ec_dev->dev, 497 + "failed to retrieve wake mask: %d\n", ret); 498 + } 486 499 487 500 ret = 0; 488 501 ··· 521 496 * 522 497 * Return: 0 on success or negative error code. 523 498 */ 524 - int cros_ec_cmd_xfer(struct cros_ec_device *ec_dev, 525 - struct cros_ec_command *msg) 499 + static int cros_ec_cmd_xfer(struct cros_ec_device *ec_dev, 500 + struct cros_ec_command *msg) 526 501 { 527 502 int ret; 528 503 ··· 566 541 567 542 return ret; 568 543 } 569 - EXPORT_SYMBOL(cros_ec_cmd_xfer); 570 544 571 545 /** 572 546 * cros_ec_cmd_xfer_status() - Send a command to the ChromeOS EC.
+3
drivers/platform/chrome/cros_ec_rpmsg.c
··· 38 38 * @rpdev: rpmsg device we are connected to 39 39 * @xfer_ack: completion for host command transfer. 40 40 * @host_event_work: Work struct for pending host event. 41 + * @ept: The rpmsg endpoint of this channel. 42 + * @has_pending_host_event: Boolean used to check if there is a pending event. 43 + * @probe_done: Flag to indicate that probe is done. 41 44 */ 42 45 struct cros_ec_rpmsg { 43 46 struct rpmsg_device *rpdev;
+35 -65
drivers/platform/chrome/cros_ec_sensorhub_ring.c
··· 419 419 * Disable filtering since we might add more jitter 420 420 * if b is in a random point in time. 421 421 */ 422 - new_timestamp = fifo_timestamp - 423 - fifo_info->timestamp * 1000 + 424 - in->timestamp * 1000; 422 + new_timestamp = c - b * 1000 + a * 1000; 425 423 /* 426 424 * The timestamp can be stale if we had to use the fifo 427 425 * info timestamp. ··· 673 675 * cros_ec_sensor_ring_spread_add_legacy: Calculate proper timestamps then 674 676 * add to ringbuffer (legacy). 675 677 * 676 - * Note: This assumes we're running old firmware, where every sample's timestamp 677 - * is after the sample. Run if tight_timestamps == false. 678 - * 679 - * If there is a sample with a proper timestamp 678 + * Note: This assumes we're running old firmware, where timestamp 679 + * is inserted after its sample(s)e. There can be several samples between 680 + * timestamps, so several samples can have the same timestamp. 680 681 * 681 682 * timestamp | count 682 683 * ----------------- 683 - * older_unprocess_out --> TS1 | 1 684 - * TS1 | 2 685 - * out --> TS1 | 3 686 - * next_out --> TS2 | 684 + * 1st sample --> TS1 | 1 685 + * TS2 | 2 686 + * TS2 | 3 687 + * TS3 | 4 688 + * last_out --> 687 689 * 688 - * We spread time for the samples [older_unprocess_out .. out] 689 - * between TS1 and TS2: [TS1+1/4, TS1+2/4, TS1+3/4, TS2]. 690 690 * 691 - * If we reach the end of the samples, we compare with the 692 - * current timestamp: 691 + * We spread time for the samples using perod p = (current - TS1)/4. 692 + * between TS1 and TS2: [TS1+p/4, TS1+2p/4, TS1+3p/4, current_timestamp]. 693 693 * 694 - * older_unprocess_out --> TS1 | 1 695 - * TS1 | 2 696 - * out --> TS1 | 3 697 - * 698 - * We know have [TS1+1/3, TS1+2/3, current timestamp] 699 694 */ 700 695 static void 701 696 cros_ec_sensor_ring_spread_add_legacy(struct cros_ec_sensorhub *sensorhub, ··· 701 710 int i; 702 711 703 712 for_each_set_bit(i, &sensor_mask, sensorhub->sensor_num) { 704 - s64 older_timestamp; 705 713 s64 timestamp; 706 - struct cros_ec_sensors_ring_sample *older_unprocess_out = 707 - sensorhub->ring; 708 - struct cros_ec_sensors_ring_sample *next_out; 709 - int count = 1; 714 + int count = 0; 715 + s64 time_period; 710 716 711 - for (out = sensorhub->ring; out < last_out; out = next_out) { 712 - s64 time_period; 713 - 714 - next_out = out + 1; 717 + for (out = sensorhub->ring; out < last_out; out++) { 715 718 if (out->sensor_id != i) 716 719 continue; 717 720 718 721 /* Timestamp to start with */ 719 - older_timestamp = out->timestamp; 720 - 721 - /* Find next sample. */ 722 - while (next_out < last_out && next_out->sensor_id != i) 723 - next_out++; 724 - 725 - if (next_out >= last_out) { 726 - timestamp = current_timestamp; 727 - } else { 728 - timestamp = next_out->timestamp; 729 - if (timestamp == older_timestamp) { 730 - count++; 731 - continue; 732 - } 733 - } 734 - 735 - /* 736 - * The next sample has a new timestamp, spread the 737 - * unprocessed samples. 738 - */ 739 - if (next_out < last_out) 740 - count++; 741 - time_period = div_s64(timestamp - older_timestamp, 742 - count); 743 - 744 - for (; older_unprocess_out <= out; 745 - older_unprocess_out++) { 746 - if (older_unprocess_out->sensor_id != i) 747 - continue; 748 - older_timestamp += time_period; 749 - older_unprocess_out->timestamp = 750 - older_timestamp; 751 - } 722 + timestamp = out->timestamp; 723 + out++; 752 724 count = 1; 753 - /* The next_out sample has a valid timestamp, skip. */ 754 - next_out++; 755 - older_unprocess_out = next_out; 725 + break; 726 + } 727 + for (; out < last_out; out++) { 728 + /* Find last sample. */ 729 + if (out->sensor_id != i) 730 + continue; 731 + count++; 732 + } 733 + if (count == 0) 734 + continue; 735 + 736 + /* Spread uniformly between the first and last samples. */ 737 + time_period = div_s64(current_timestamp - timestamp, count); 738 + 739 + for (out = sensorhub->ring; out < last_out; out++) { 740 + if (out->sensor_id != i) 741 + continue; 742 + timestamp += time_period; 743 + out->timestamp = timestamp; 756 744 } 757 745 } 758 746
+4
drivers/platform/chrome/cros_ec_spi.c
··· 148 148 * receive_n_bytes - receive n bytes from the EC. 149 149 * 150 150 * Assumes buf is a pointer into the ec_dev->din buffer 151 + * 152 + * @ec_dev: ChromeOS EC device. 153 + * @buf: Pointer to the buffer receiving the data. 154 + * @n: Number of bytes received. 151 155 */ 152 156 static int receive_n_bytes(struct cros_ec_device *ec_dev, u8 *buf, int n) 153 157 {
+360 -41
drivers/platform/chrome/cros_ec_typec.c
··· 14 14 #include <linux/platform_data/cros_usbpd_notify.h> 15 15 #include <linux/platform_device.h> 16 16 #include <linux/usb/typec.h> 17 + #include <linux/usb/typec_altmode.h> 18 + #include <linux/usb/typec_dp.h> 19 + #include <linux/usb/typec_mux.h> 20 + #include <linux/usb/typec_tbt.h> 21 + #include <linux/usb/role.h> 17 22 18 23 #define DRV_NAME "cros-ec-typec" 24 + 25 + /* Supported alt modes. */ 26 + enum { 27 + CROS_EC_ALTMODE_DP = 0, 28 + CROS_EC_ALTMODE_TBT, 29 + CROS_EC_ALTMODE_MAX, 30 + }; 19 31 20 32 /* Per port data. */ 21 33 struct cros_typec_port { ··· 37 25 struct typec_partner *partner; 38 26 /* Port partner PD identity info. */ 39 27 struct usb_pd_identity p_identity; 28 + struct typec_switch *ori_sw; 29 + struct typec_mux *mux; 30 + struct usb_role_switch *role_sw; 31 + 32 + /* Variables keeping track of switch state. */ 33 + struct typec_mux_state state; 34 + uint8_t mux_flags; 35 + 36 + /* Port alt modes. */ 37 + struct typec_altmode p_altmode[CROS_EC_ALTMODE_MAX]; 40 38 }; 41 39 42 40 /* Platform-specific data for the Chrome OS EC Type C controller. */ ··· 54 32 struct device *dev; 55 33 struct cros_ec_device *ec; 56 34 int num_ports; 57 - unsigned int cmd_ver; 35 + unsigned int pd_ctrl_ver; 58 36 /* Array of ports, indexed by port number. */ 59 37 struct cros_typec_port *ports[EC_USB_PD_MAX_PORTS]; 60 38 struct notifier_block nb; 39 + struct work_struct port_work; 61 40 }; 62 41 63 42 static int cros_typec_parse_port_props(struct typec_capability *cap, ··· 107 84 return 0; 108 85 } 109 86 87 + static int cros_typec_get_switch_handles(struct cros_typec_port *port, 88 + struct fwnode_handle *fwnode, 89 + struct device *dev) 90 + { 91 + port->mux = fwnode_typec_mux_get(fwnode, NULL); 92 + if (IS_ERR(port->mux)) { 93 + dev_dbg(dev, "Mux handle not found.\n"); 94 + goto mux_err; 95 + } 96 + 97 + port->ori_sw = fwnode_typec_switch_get(fwnode); 98 + if (IS_ERR(port->ori_sw)) { 99 + dev_dbg(dev, "Orientation switch handle not found.\n"); 100 + goto ori_sw_err; 101 + } 102 + 103 + port->role_sw = fwnode_usb_role_switch_get(fwnode); 104 + if (IS_ERR(port->role_sw)) { 105 + dev_dbg(dev, "USB role switch handle not found.\n"); 106 + goto role_sw_err; 107 + } 108 + 109 + return 0; 110 + 111 + role_sw_err: 112 + usb_role_switch_put(port->role_sw); 113 + ori_sw_err: 114 + typec_switch_put(port->ori_sw); 115 + mux_err: 116 + typec_mux_put(port->mux); 117 + 118 + return -ENODEV; 119 + } 120 + 121 + static int cros_typec_add_partner(struct cros_typec_data *typec, int port_num, 122 + bool pd_en) 123 + { 124 + struct cros_typec_port *port = typec->ports[port_num]; 125 + struct typec_partner_desc p_desc = { 126 + .usb_pd = pd_en, 127 + }; 128 + int ret = 0; 129 + 130 + /* 131 + * Fill an initial PD identity, which will then be updated with info 132 + * from the EC. 133 + */ 134 + p_desc.identity = &port->p_identity; 135 + 136 + port->partner = typec_register_partner(port->port, &p_desc); 137 + if (IS_ERR(port->partner)) { 138 + ret = PTR_ERR(port->partner); 139 + port->partner = NULL; 140 + } 141 + 142 + return ret; 143 + } 144 + 145 + static void cros_typec_remove_partner(struct cros_typec_data *typec, 146 + int port_num) 147 + { 148 + struct cros_typec_port *port = typec->ports[port_num]; 149 + 150 + port->state.alt = NULL; 151 + port->state.mode = TYPEC_STATE_USB; 152 + port->state.data = NULL; 153 + 154 + usb_role_switch_set_role(port->role_sw, USB_ROLE_NONE); 155 + typec_switch_set(port->ori_sw, TYPEC_ORIENTATION_NONE); 156 + typec_mux_set(port->mux, &port->state); 157 + 158 + typec_unregister_partner(port->partner); 159 + port->partner = NULL; 160 + } 161 + 110 162 static void cros_unregister_ports(struct cros_typec_data *typec) 111 163 { 112 164 int i; ··· 189 91 for (i = 0; i < typec->num_ports; i++) { 190 92 if (!typec->ports[i]) 191 93 continue; 94 + cros_typec_remove_partner(typec, i); 95 + usb_role_switch_put(typec->ports[i]->role_sw); 96 + typec_switch_put(typec->ports[i]->ori_sw); 97 + typec_mux_put(typec->ports[i]->mux); 192 98 typec_unregister_port(typec->ports[i]->port); 193 99 } 100 + } 101 + 102 + /* 103 + * Fake the alt mode structs until we actually start registering Type C port 104 + * and partner alt modes. 105 + */ 106 + static void cros_typec_register_port_altmodes(struct cros_typec_data *typec, 107 + int port_num) 108 + { 109 + struct cros_typec_port *port = typec->ports[port_num]; 110 + 111 + /* All PD capable CrOS devices are assumed to support DP altmode. */ 112 + port->p_altmode[CROS_EC_ALTMODE_DP].svid = USB_TYPEC_DP_SID; 113 + port->p_altmode[CROS_EC_ALTMODE_DP].mode = USB_TYPEC_DP_MODE; 114 + 115 + /* 116 + * Register TBT compatibility alt mode. The EC will not enter the mode 117 + * if it doesn't support it, so it's safe to register it unconditionally 118 + * here for now. 119 + */ 120 + port->p_altmode[CROS_EC_ALTMODE_TBT].svid = USB_TYPEC_TBT_SID; 121 + port->p_altmode[CROS_EC_ALTMODE_TBT].mode = TYPEC_ANY_MODE; 122 + 123 + port->state.alt = NULL; 124 + port->state.mode = TYPEC_STATE_USB; 125 + port->state.data = NULL; 194 126 } 195 127 196 128 static int cros_typec_init_ports(struct cros_typec_data *typec) ··· 281 153 ret = PTR_ERR(cros_port->port); 282 154 goto unregister_ports; 283 155 } 156 + 157 + ret = cros_typec_get_switch_handles(cros_port, fwnode, dev); 158 + if (ret) 159 + dev_dbg(dev, "No switch control for port %d\n", 160 + port_num); 161 + 162 + cros_typec_register_port_altmodes(typec, port_num); 284 163 } 285 164 286 165 return 0; ··· 325 190 memcpy(indata, msg->data, insize); 326 191 327 192 kfree(msg); 328 - return ret; 329 - } 330 - 331 - static int cros_typec_add_partner(struct cros_typec_data *typec, int port_num, 332 - bool pd_en) 333 - { 334 - struct cros_typec_port *port = typec->ports[port_num]; 335 - struct typec_partner_desc p_desc = { 336 - .usb_pd = pd_en, 337 - }; 338 - int ret = 0; 339 - 340 - /* 341 - * Fill an initial PD identity, which will then be updated with info 342 - * from the EC. 343 - */ 344 - p_desc.identity = &port->p_identity; 345 - 346 - port->partner = typec_register_partner(port->port, &p_desc); 347 - if (IS_ERR(port->partner)) { 348 - ret = PTR_ERR(port->partner); 349 - port->partner = NULL; 350 - } 351 - 352 193 return ret; 353 194 } 354 195 ··· 381 270 } else { 382 271 if (!typec->ports[port_num]->partner) 383 272 return; 384 - 385 - typec_unregister_partner(typec->ports[port_num]->partner); 386 - typec->ports[port_num]->partner = NULL; 273 + cros_typec_remove_partner(typec, port_num); 387 274 } 275 + } 276 + 277 + static int cros_typec_get_mux_info(struct cros_typec_data *typec, int port_num, 278 + struct ec_response_usb_pd_mux_info *resp) 279 + { 280 + struct ec_params_usb_pd_mux_info req = { 281 + .port = port_num, 282 + }; 283 + 284 + return cros_typec_ec_command(typec, 0, EC_CMD_USB_PD_MUX_INFO, &req, 285 + sizeof(req), resp, sizeof(*resp)); 286 + } 287 + 288 + static int cros_typec_usb_safe_state(struct cros_typec_port *port) 289 + { 290 + port->state.mode = TYPEC_STATE_SAFE; 291 + 292 + return typec_mux_set(port->mux, &port->state); 293 + } 294 + 295 + /* 296 + * Spoof the VDOs that were likely communicated by the partner for TBT alt 297 + * mode. 298 + */ 299 + static int cros_typec_enable_tbt(struct cros_typec_data *typec, 300 + int port_num, 301 + struct ec_response_usb_pd_control_v2 *pd_ctrl) 302 + { 303 + struct cros_typec_port *port = typec->ports[port_num]; 304 + struct typec_thunderbolt_data data; 305 + int ret; 306 + 307 + if (typec->pd_ctrl_ver < 2) { 308 + dev_err(typec->dev, 309 + "PD_CTRL version too old: %d\n", typec->pd_ctrl_ver); 310 + return -ENOTSUPP; 311 + } 312 + 313 + /* Device Discover Mode VDO */ 314 + data.device_mode = TBT_MODE; 315 + 316 + if (pd_ctrl->control_flags & USB_PD_CTRL_TBT_LEGACY_ADAPTER) 317 + data.device_mode = TBT_SET_ADAPTER(TBT_ADAPTER_TBT3); 318 + 319 + /* Cable Discover Mode VDO */ 320 + data.cable_mode = TBT_MODE; 321 + data.cable_mode |= TBT_SET_CABLE_SPEED(pd_ctrl->cable_speed); 322 + 323 + if (pd_ctrl->control_flags & USB_PD_CTRL_OPTICAL_CABLE) 324 + data.cable_mode |= TBT_CABLE_OPTICAL; 325 + 326 + if (pd_ctrl->control_flags & USB_PD_CTRL_ACTIVE_LINK_UNIDIR) 327 + data.cable_mode |= TBT_CABLE_LINK_TRAINING; 328 + 329 + if (pd_ctrl->cable_gen) 330 + data.cable_mode |= TBT_CABLE_ROUNDED; 331 + 332 + /* Enter Mode VDO */ 333 + data.enter_vdo = TBT_SET_CABLE_SPEED(pd_ctrl->cable_speed); 334 + 335 + if (pd_ctrl->control_flags & USB_PD_CTRL_ACTIVE_CABLE) 336 + data.enter_vdo |= TBT_ENTER_MODE_ACTIVE_CABLE; 337 + 338 + if (!port->state.alt) { 339 + port->state.alt = &port->p_altmode[CROS_EC_ALTMODE_TBT]; 340 + ret = cros_typec_usb_safe_state(port); 341 + if (ret) 342 + return ret; 343 + } 344 + 345 + port->state.data = &data; 346 + port->state.mode = TYPEC_TBT_MODE; 347 + 348 + return typec_mux_set(port->mux, &port->state); 349 + } 350 + 351 + /* Spoof the VDOs that were likely communicated by the partner. */ 352 + static int cros_typec_enable_dp(struct cros_typec_data *typec, 353 + int port_num, 354 + struct ec_response_usb_pd_control_v2 *pd_ctrl) 355 + { 356 + struct cros_typec_port *port = typec->ports[port_num]; 357 + struct typec_displayport_data dp_data; 358 + int ret; 359 + 360 + if (typec->pd_ctrl_ver < 2) { 361 + dev_err(typec->dev, 362 + "PD_CTRL version too old: %d\n", typec->pd_ctrl_ver); 363 + return -ENOTSUPP; 364 + } 365 + 366 + /* Status VDO. */ 367 + dp_data.status = DP_STATUS_ENABLED; 368 + if (port->mux_flags & USB_PD_MUX_HPD_IRQ) 369 + dp_data.status |= DP_STATUS_IRQ_HPD; 370 + if (port->mux_flags & USB_PD_MUX_HPD_LVL) 371 + dp_data.status |= DP_STATUS_HPD_STATE; 372 + 373 + /* Configuration VDO. */ 374 + dp_data.conf = DP_CONF_SET_PIN_ASSIGN(pd_ctrl->dp_mode); 375 + if (!port->state.alt) { 376 + port->state.alt = &port->p_altmode[CROS_EC_ALTMODE_DP]; 377 + ret = cros_typec_usb_safe_state(port); 378 + if (ret) 379 + return ret; 380 + } 381 + 382 + port->state.data = &dp_data; 383 + port->state.mode = TYPEC_MODAL_STATE(ffs(pd_ctrl->dp_mode)); 384 + 385 + return typec_mux_set(port->mux, &port->state); 386 + } 387 + 388 + static int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num, 389 + uint8_t mux_flags, 390 + struct ec_response_usb_pd_control_v2 *pd_ctrl) 391 + { 392 + struct cros_typec_port *port = typec->ports[port_num]; 393 + enum typec_orientation orientation; 394 + int ret; 395 + 396 + if (!port->partner) 397 + return 0; 398 + 399 + if (mux_flags & USB_PD_MUX_POLARITY_INVERTED) 400 + orientation = TYPEC_ORIENTATION_REVERSE; 401 + else 402 + orientation = TYPEC_ORIENTATION_NORMAL; 403 + 404 + ret = typec_switch_set(port->ori_sw, orientation); 405 + if (ret) 406 + return ret; 407 + 408 + if (mux_flags & USB_PD_MUX_TBT_COMPAT_ENABLED) { 409 + ret = cros_typec_enable_tbt(typec, port_num, pd_ctrl); 410 + } else if (mux_flags & USB_PD_MUX_DP_ENABLED) { 411 + ret = cros_typec_enable_dp(typec, port_num, pd_ctrl); 412 + } else if (mux_flags & USB_PD_MUX_SAFE_MODE) { 413 + ret = cros_typec_usb_safe_state(port); 414 + } else if (mux_flags & USB_PD_MUX_USB_ENABLED) { 415 + port->state.alt = NULL; 416 + port->state.mode = TYPEC_STATE_USB; 417 + ret = typec_mux_set(port->mux, &port->state); 418 + } else { 419 + dev_info(typec->dev, 420 + "Unsupported mode requested, mux flags: %x\n", 421 + mux_flags); 422 + ret = -ENOTSUPP; 423 + } 424 + 425 + return ret; 388 426 } 389 427 390 428 static int cros_typec_port_update(struct cros_typec_data *typec, int port_num) 391 429 { 392 430 struct ec_params_usb_pd_control req; 393 - struct ec_response_usb_pd_control_v1 resp; 431 + struct ec_response_usb_pd_control_v2 resp; 432 + struct ec_response_usb_pd_mux_info mux_resp; 394 433 int ret; 395 434 396 435 if (port_num < 0 || port_num >= typec->num_ports) { ··· 554 293 req.mux = USB_PD_CTRL_MUX_NO_CHANGE; 555 294 req.swap = USB_PD_CTRL_SWAP_NONE; 556 295 557 - ret = cros_typec_ec_command(typec, typec->cmd_ver, 296 + ret = cros_typec_ec_command(typec, typec->pd_ctrl_ver, 558 297 EC_CMD_USB_PD_CONTROL, &req, sizeof(req), 559 298 &resp, sizeof(resp)); 560 299 if (ret < 0) ··· 565 304 dev_dbg(typec->dev, "Polarity %d: 0x%hhx\n", port_num, resp.polarity); 566 305 dev_dbg(typec->dev, "State %d: %s\n", port_num, resp.state); 567 306 568 - if (typec->cmd_ver == 1) 569 - cros_typec_set_port_params_v1(typec, port_num, &resp); 307 + if (typec->pd_ctrl_ver != 0) 308 + cros_typec_set_port_params_v1(typec, port_num, 309 + (struct ec_response_usb_pd_control_v1 *)&resp); 570 310 else 571 311 cros_typec_set_port_params_v0(typec, port_num, 572 312 (struct ec_response_usb_pd_control *) &resp); 573 313 574 - return 0; 314 + /* Update the switches if they exist, according to requested state */ 315 + ret = cros_typec_get_mux_info(typec, port_num, &mux_resp); 316 + if (ret < 0) { 317 + dev_warn(typec->dev, 318 + "Failed to get mux info for port: %d, err = %d\n", 319 + port_num, ret); 320 + return 0; 321 + } 322 + 323 + /* No change needs to be made, let's exit early. */ 324 + if (typec->ports[port_num]->mux_flags == mux_resp.flags) 325 + return 0; 326 + 327 + typec->ports[port_num]->mux_flags = mux_resp.flags; 328 + ret = cros_typec_configure_mux(typec, port_num, mux_resp.flags, &resp); 329 + if (ret) 330 + dev_warn(typec->dev, "Configure muxes failed, err = %d\n", ret); 331 + 332 + return usb_role_switch_set_role(typec->ports[port_num]->role_sw, 333 + !!(resp.role & PD_CTRL_RESP_ROLE_DATA)); 575 334 } 576 335 577 336 static int cros_typec_get_cmd_version(struct cros_typec_data *typec) ··· 608 327 if (ret < 0) 609 328 return ret; 610 329 611 - if (resp.version_mask & EC_VER_MASK(1)) 612 - typec->cmd_ver = 1; 330 + if (resp.version_mask & EC_VER_MASK(2)) 331 + typec->pd_ctrl_ver = 2; 332 + else if (resp.version_mask & EC_VER_MASK(1)) 333 + typec->pd_ctrl_ver = 1; 613 334 else 614 - typec->cmd_ver = 0; 335 + typec->pd_ctrl_ver = 0; 615 336 616 337 dev_dbg(typec->dev, "PD Control has version mask 0x%hhx\n", 617 - typec->cmd_ver); 338 + typec->pd_ctrl_ver); 618 339 619 340 return 0; 620 341 } 621 342 622 - static int cros_ec_typec_event(struct notifier_block *nb, 623 - unsigned long host_event, void *_notify) 343 + static void cros_typec_port_work(struct work_struct *work) 624 344 { 625 - struct cros_typec_data *typec = container_of(nb, struct cros_typec_data, 626 - nb); 345 + struct cros_typec_data *typec = container_of(work, struct cros_typec_data, port_work); 627 346 int ret, i; 628 347 629 348 for (i = 0; i < typec->num_ports; i++) { ··· 631 350 if (ret < 0) 632 351 dev_warn(typec->dev, "Update failed for port: %d\n", i); 633 352 } 353 + } 354 + 355 + static int cros_ec_typec_event(struct notifier_block *nb, 356 + unsigned long host_event, void *_notify) 357 + { 358 + struct cros_typec_data *typec = container_of(nb, struct cros_typec_data, nb); 359 + 360 + schedule_work(&typec->port_work); 634 361 635 362 return NOTIFY_OK; 636 363 } ··· 697 408 if (ret < 0) 698 409 return ret; 699 410 411 + INIT_WORK(&typec->port_work, cros_typec_port_work); 412 + 413 + /* 414 + * Safe to call port update here, since we haven't registered the 415 + * PD notifier yet. 416 + */ 700 417 for (i = 0; i < typec->num_ports; i++) { 701 418 ret = cros_typec_port_update(typec, i); 702 419 if (ret < 0) ··· 721 426 return ret; 722 427 } 723 428 429 + static int __maybe_unused cros_typec_suspend(struct device *dev) 430 + { 431 + struct cros_typec_data *typec = dev_get_drvdata(dev); 432 + 433 + cancel_work_sync(&typec->port_work); 434 + 435 + return 0; 436 + } 437 + 438 + static int __maybe_unused cros_typec_resume(struct device *dev) 439 + { 440 + struct cros_typec_data *typec = dev_get_drvdata(dev); 441 + 442 + /* Refresh port state. */ 443 + schedule_work(&typec->port_work); 444 + 445 + return 0; 446 + } 447 + 448 + static const struct dev_pm_ops cros_typec_pm_ops = { 449 + SET_SYSTEM_SLEEP_PM_OPS(cros_typec_suspend, cros_typec_resume) 450 + }; 451 + 724 452 static struct platform_driver cros_typec_driver = { 725 453 .driver = { 726 454 .name = DRV_NAME, 727 455 .acpi_match_table = ACPI_PTR(cros_typec_acpi_id), 728 456 .of_match_table = of_match_ptr(cros_typec_of_match), 457 + .pm = &cros_typec_pm_ops, 729 458 }, 730 459 .probe = cros_typec_probe, 731 460 };
+24 -9
include/linux/platform_data/cros_ec_commands.h
··· 4917 4917 #define USBC_PD_CC_UFP_ATTACHED 4 /* UFP attached to usbc */ 4918 4918 #define USBC_PD_CC_DFP_ATTACHED 5 /* DPF attached to usbc */ 4919 4919 4920 + /* Active/Passive Cable */ 4921 + #define USB_PD_CTRL_ACTIVE_CABLE BIT(0) 4922 + /* Optical/Non-optical cable */ 4923 + #define USB_PD_CTRL_OPTICAL_CABLE BIT(1) 4924 + /* 3rd Gen TBT device (or AMA)/2nd gen tbt Adapter */ 4925 + #define USB_PD_CTRL_TBT_LEGACY_ADAPTER BIT(2) 4926 + /* Active Link Uni-Direction */ 4927 + #define USB_PD_CTRL_ACTIVE_LINK_UNIDIR BIT(3) 4928 + 4920 4929 struct ec_response_usb_pd_control_v2 { 4921 4930 uint8_t enabled; 4922 4931 uint8_t role; 4923 4932 uint8_t polarity; 4924 4933 char state[32]; 4925 - uint8_t cc_state; /* USBC_PD_CC_*Encoded cc state */ 4926 - uint8_t dp_mode; /* Current DP pin mode (MODE_DP_PIN_[A-E]) */ 4927 - /* CL:1500994 Current cable type */ 4928 - uint8_t reserved_cable_type; 4934 + uint8_t cc_state; /* enum pd_cc_states representing cc state */ 4935 + uint8_t dp_mode; /* Current DP pin mode (MODE_DP_PIN_[A-E]) */ 4936 + uint8_t reserved; /* Reserved for future use */ 4937 + uint8_t control_flags; /* USB_PD_CTRL_*flags */ 4938 + uint8_t cable_speed; /* TBT_SS_* cable speed */ 4939 + uint8_t cable_gen; /* TBT_GEN3_* cable rounded support */ 4929 4940 } __ec_align1; 4930 4941 4931 4942 #define EC_CMD_USB_PD_PORTS 0x0102 ··· 5218 5207 } __ec_align1; 5219 5208 5220 5209 /* Flags representing mux state */ 5221 - #define USB_PD_MUX_USB_ENABLED BIT(0) /* USB connected */ 5222 - #define USB_PD_MUX_DP_ENABLED BIT(1) /* DP connected */ 5223 - #define USB_PD_MUX_POLARITY_INVERTED BIT(2) /* CC line Polarity inverted */ 5224 - #define USB_PD_MUX_HPD_IRQ BIT(3) /* HPD IRQ is asserted */ 5225 - #define USB_PD_MUX_HPD_LVL BIT(4) /* HPD level is asserted */ 5210 + #define USB_PD_MUX_NONE 0 /* Open switch */ 5211 + #define USB_PD_MUX_USB_ENABLED BIT(0) /* USB connected */ 5212 + #define USB_PD_MUX_DP_ENABLED BIT(1) /* DP connected */ 5213 + #define USB_PD_MUX_POLARITY_INVERTED BIT(2) /* CC line Polarity inverted */ 5214 + #define USB_PD_MUX_HPD_IRQ BIT(3) /* HPD IRQ is asserted */ 5215 + #define USB_PD_MUX_HPD_LVL BIT(4) /* HPD level is asserted */ 5216 + #define USB_PD_MUX_SAFE_MODE BIT(5) /* DP is in safe mode */ 5217 + #define USB_PD_MUX_TBT_COMPAT_ENABLED BIT(6) /* TBT compat enabled */ 5218 + #define USB_PD_MUX_USB4_ENABLED BIT(7) /* USB4 enabled */ 5226 5219 5227 5220 struct ec_response_usb_pd_mux_info { 5228 5221 uint8_t flags; /* USB_PD_MUX_*-encoded USB mux state */
-3
include/linux/platform_data/cros_ec_proto.h
··· 216 216 int cros_ec_check_result(struct cros_ec_device *ec_dev, 217 217 struct cros_ec_command *msg); 218 218 219 - int cros_ec_cmd_xfer(struct cros_ec_device *ec_dev, 220 - struct cros_ec_command *msg); 221 - 222 219 int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev, 223 220 struct cros_ec_command *msg); 224 221