linux/drivers/platform/chrome/cros_ec_typec.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright 2020 Google LLC
   4 *
   5 * This driver provides the ability to view and manage Type C ports through the
   6 * Chrome OS EC.
   7 */
   8
   9#include <linux/acpi.h>
  10#include <linux/list.h>
  11#include <linux/module.h>
  12#include <linux/of.h>
  13#include <linux/platform_data/cros_ec_commands.h>
  14#include <linux/platform_data/cros_ec_proto.h>
  15#include <linux/platform_data/cros_usbpd_notify.h>
  16#include <linux/platform_device.h>
  17#include <linux/usb/pd.h>
  18#include <linux/usb/pd_vdo.h>
  19#include <linux/usb/typec.h>
  20#include <linux/usb/typec_altmode.h>
  21#include <linux/usb/typec_dp.h>
  22#include <linux/usb/typec_mux.h>
  23#include <linux/usb/typec_tbt.h>
  24#include <linux/usb/role.h>
  25
  26#define DRV_NAME "cros-ec-typec"
  27
  28/* Supported alt modes. */
  29enum {
  30        CROS_EC_ALTMODE_DP = 0,
  31        CROS_EC_ALTMODE_TBT,
  32        CROS_EC_ALTMODE_MAX,
  33};
  34
  35/* Container for altmode pointer nodes. */
  36struct cros_typec_altmode_node {
  37        struct typec_altmode *amode;
  38        struct list_head list;
  39};
  40
  41/* Per port data. */
  42struct cros_typec_port {
  43        struct typec_port *port;
  44        /* Initial capabilities for the port. */
  45        struct typec_capability caps;
  46        struct typec_partner *partner;
  47        struct typec_cable *cable;
  48        /* SOP' plug. */
  49        struct typec_plug *plug;
  50        /* Port partner PD identity info. */
  51        struct usb_pd_identity p_identity;
  52        /* Port cable PD identity info. */
  53        struct usb_pd_identity c_identity;
  54        struct typec_switch *ori_sw;
  55        struct typec_mux *mux;
  56        struct usb_role_switch *role_sw;
  57
  58        /* Variables keeping track of switch state. */
  59        struct typec_mux_state state;
  60        uint8_t mux_flags;
  61        uint8_t role;
  62
  63        /* Port alt modes. */
  64        struct typec_altmode p_altmode[CROS_EC_ALTMODE_MAX];
  65
  66        /* Flag indicating that PD partner discovery data parsing is completed. */
  67        bool sop_disc_done;
  68        bool sop_prime_disc_done;
  69        struct ec_response_typec_discovery *disc_data;
  70        struct list_head partner_mode_list;
  71        struct list_head plug_mode_list;
  72};
  73
  74/* Platform-specific data for the Chrome OS EC Type C controller. */
  75struct cros_typec_data {
  76        struct device *dev;
  77        struct cros_ec_device *ec;
  78        int num_ports;
  79        unsigned int pd_ctrl_ver;
  80        /* Array of ports, indexed by port number. */
  81        struct cros_typec_port *ports[EC_USB_PD_MAX_PORTS];
  82        struct notifier_block nb;
  83        struct work_struct port_work;
  84        bool typec_cmd_supported;
  85        bool needs_mux_ack;
  86};
  87
  88static int cros_typec_parse_port_props(struct typec_capability *cap,
  89                                       struct fwnode_handle *fwnode,
  90                                       struct device *dev)
  91{
  92        const char *buf;
  93        int ret;
  94
  95        memset(cap, 0, sizeof(*cap));
  96        ret = fwnode_property_read_string(fwnode, "power-role", &buf);
  97        if (ret) {
  98                dev_err(dev, "power-role not found: %d\n", ret);
  99                return ret;
 100        }
 101
 102        ret = typec_find_port_power_role(buf);
 103        if (ret < 0)
 104                return ret;
 105        cap->type = ret;
 106
 107        ret = fwnode_property_read_string(fwnode, "data-role", &buf);
 108        if (ret) {
 109                dev_err(dev, "data-role not found: %d\n", ret);
 110                return ret;
 111        }
 112
 113        ret = typec_find_port_data_role(buf);
 114        if (ret < 0)
 115                return ret;
 116        cap->data = ret;
 117
 118        /* Try-power-role is optional. */
 119        ret = fwnode_property_read_string(fwnode, "try-power-role", &buf);
 120        if (ret) {
 121                dev_warn(dev, "try-power-role not found: %d\n", ret);
 122                cap->prefer_role = TYPEC_NO_PREFERRED_ROLE;
 123        } else {
 124                ret = typec_find_power_role(buf);
 125                if (ret < 0)
 126                        return ret;
 127                cap->prefer_role = ret;
 128        }
 129
 130        cap->fwnode = fwnode;
 131
 132        return 0;
 133}
 134
 135static int cros_typec_get_switch_handles(struct cros_typec_port *port,
 136                                         struct fwnode_handle *fwnode,
 137                                         struct device *dev)
 138{
 139        port->mux = fwnode_typec_mux_get(fwnode, NULL);
 140        if (IS_ERR(port->mux)) {
 141                dev_dbg(dev, "Mux handle not found.\n");
 142                goto mux_err;
 143        }
 144
 145        port->ori_sw = fwnode_typec_switch_get(fwnode);
 146        if (IS_ERR(port->ori_sw)) {
 147                dev_dbg(dev, "Orientation switch handle not found.\n");
 148                goto ori_sw_err;
 149        }
 150
 151        port->role_sw = fwnode_usb_role_switch_get(fwnode);
 152        if (IS_ERR(port->role_sw)) {
 153                dev_dbg(dev, "USB role switch handle not found.\n");
 154                goto role_sw_err;
 155        }
 156
 157        return 0;
 158
 159role_sw_err:
 160        usb_role_switch_put(port->role_sw);
 161ori_sw_err:
 162        typec_switch_put(port->ori_sw);
 163mux_err:
 164        typec_mux_put(port->mux);
 165
 166        return -ENODEV;
 167}
 168
 169static int cros_typec_add_partner(struct cros_typec_data *typec, int port_num,
 170                                  bool pd_en)
 171{
 172        struct cros_typec_port *port = typec->ports[port_num];
 173        struct typec_partner_desc p_desc = {
 174                .usb_pd = pd_en,
 175        };
 176        int ret = 0;
 177
 178        /*
 179         * Fill an initial PD identity, which will then be updated with info
 180         * from the EC.
 181         */
 182        p_desc.identity = &port->p_identity;
 183
 184        port->partner = typec_register_partner(port->port, &p_desc);
 185        if (IS_ERR(port->partner)) {
 186                ret = PTR_ERR(port->partner);
 187                port->partner = NULL;
 188        }
 189
 190        return ret;
 191}
 192
 193static void cros_typec_unregister_altmodes(struct cros_typec_data *typec, int port_num,
 194                                           bool is_partner)
 195{
 196        struct cros_typec_port *port = typec->ports[port_num];
 197        struct cros_typec_altmode_node *node, *tmp;
 198        struct list_head *head;
 199
 200        head = is_partner ? &port->partner_mode_list : &port->plug_mode_list;
 201        list_for_each_entry_safe(node, tmp, head, list) {
 202                list_del(&node->list);
 203                typec_unregister_altmode(node->amode);
 204                devm_kfree(typec->dev, node);
 205        }
 206}
 207
 208static int cros_typec_usb_disconnect_state(struct cros_typec_port *port)
 209{
 210        port->state.alt = NULL;
 211        port->state.mode = TYPEC_STATE_USB;
 212        port->state.data = NULL;
 213
 214        usb_role_switch_set_role(port->role_sw, USB_ROLE_NONE);
 215        typec_switch_set(port->ori_sw, TYPEC_ORIENTATION_NONE);
 216
 217        return typec_mux_set(port->mux, &port->state);
 218}
 219
 220static void cros_typec_remove_partner(struct cros_typec_data *typec,
 221                                      int port_num)
 222{
 223        struct cros_typec_port *port = typec->ports[port_num];
 224
 225        if (!port->partner)
 226                return;
 227
 228        cros_typec_unregister_altmodes(typec, port_num, true);
 229
 230        cros_typec_usb_disconnect_state(port);
 231        port->mux_flags = USB_PD_MUX_NONE;
 232
 233        typec_unregister_partner(port->partner);
 234        port->partner = NULL;
 235        memset(&port->p_identity, 0, sizeof(port->p_identity));
 236        port->sop_disc_done = false;
 237}
 238
 239static void cros_typec_remove_cable(struct cros_typec_data *typec,
 240                                    int port_num)
 241{
 242        struct cros_typec_port *port = typec->ports[port_num];
 243
 244        if (!port->cable)
 245                return;
 246
 247        cros_typec_unregister_altmodes(typec, port_num, false);
 248
 249        typec_unregister_plug(port->plug);
 250        port->plug = NULL;
 251        typec_unregister_cable(port->cable);
 252        port->cable = NULL;
 253        memset(&port->c_identity, 0, sizeof(port->c_identity));
 254        port->sop_prime_disc_done = false;
 255}
 256
 257static void cros_unregister_ports(struct cros_typec_data *typec)
 258{
 259        int i;
 260
 261        for (i = 0; i < typec->num_ports; i++) {
 262                if (!typec->ports[i])
 263                        continue;
 264
 265                cros_typec_remove_partner(typec, i);
 266                cros_typec_remove_cable(typec, i);
 267
 268                usb_role_switch_put(typec->ports[i]->role_sw);
 269                typec_switch_put(typec->ports[i]->ori_sw);
 270                typec_mux_put(typec->ports[i]->mux);
 271                typec_unregister_port(typec->ports[i]->port);
 272        }
 273}
 274
 275/*
 276 * Fake the alt mode structs until we actually start registering Type C port
 277 * and partner alt modes.
 278 */
 279static void cros_typec_register_port_altmodes(struct cros_typec_data *typec,
 280                                              int port_num)
 281{
 282        struct cros_typec_port *port = typec->ports[port_num];
 283
 284        /* All PD capable CrOS devices are assumed to support DP altmode. */
 285        port->p_altmode[CROS_EC_ALTMODE_DP].svid = USB_TYPEC_DP_SID;
 286        port->p_altmode[CROS_EC_ALTMODE_DP].mode = USB_TYPEC_DP_MODE;
 287
 288        /*
 289         * Register TBT compatibility alt mode. The EC will not enter the mode
 290         * if it doesn't support it, so it's safe to register it unconditionally
 291         * here for now.
 292         */
 293        port->p_altmode[CROS_EC_ALTMODE_TBT].svid = USB_TYPEC_TBT_SID;
 294        port->p_altmode[CROS_EC_ALTMODE_TBT].mode = TYPEC_ANY_MODE;
 295
 296        port->state.alt = NULL;
 297        port->state.mode = TYPEC_STATE_USB;
 298        port->state.data = NULL;
 299}
 300
 301static int cros_typec_init_ports(struct cros_typec_data *typec)
 302{
 303        struct device *dev = typec->dev;
 304        struct typec_capability *cap;
 305        struct fwnode_handle *fwnode;
 306        struct cros_typec_port *cros_port;
 307        const char *port_prop;
 308        int ret;
 309        int nports;
 310        u32 port_num = 0;
 311
 312        nports = device_get_child_node_count(dev);
 313        if (nports == 0) {
 314                dev_err(dev, "No port entries found.\n");
 315                return -ENODEV;
 316        }
 317
 318        if (nports > typec->num_ports) {
 319                dev_err(dev, "More ports listed than can be supported.\n");
 320                return -EINVAL;
 321        }
 322
 323        /* DT uses "reg" to specify port number. */
 324        port_prop = dev->of_node ? "reg" : "port-number";
 325        device_for_each_child_node(dev, fwnode) {
 326                if (fwnode_property_read_u32(fwnode, port_prop, &port_num)) {
 327                        ret = -EINVAL;
 328                        dev_err(dev, "No port-number for port, aborting.\n");
 329                        goto unregister_ports;
 330                }
 331
 332                if (port_num >= typec->num_ports) {
 333                        dev_err(dev, "Invalid port number.\n");
 334                        ret = -EINVAL;
 335                        goto unregister_ports;
 336                }
 337
 338                dev_dbg(dev, "Registering port %d\n", port_num);
 339
 340                cros_port = devm_kzalloc(dev, sizeof(*cros_port), GFP_KERNEL);
 341                if (!cros_port) {
 342                        ret = -ENOMEM;
 343                        goto unregister_ports;
 344                }
 345
 346                typec->ports[port_num] = cros_port;
 347                cap = &cros_port->caps;
 348
 349                ret = cros_typec_parse_port_props(cap, fwnode, dev);
 350                if (ret < 0)
 351                        goto unregister_ports;
 352
 353                cros_port->port = typec_register_port(dev, cap);
 354                if (IS_ERR(cros_port->port)) {
 355                        dev_err(dev, "Failed to register port %d\n", port_num);
 356                        ret = PTR_ERR(cros_port->port);
 357                        goto unregister_ports;
 358                }
 359
 360                ret = cros_typec_get_switch_handles(cros_port, fwnode, dev);
 361                if (ret)
 362                        dev_dbg(dev, "No switch control for port %d\n",
 363                                port_num);
 364
 365                cros_typec_register_port_altmodes(typec, port_num);
 366
 367                cros_port->disc_data = devm_kzalloc(dev, EC_PROTO2_MAX_RESPONSE_SIZE, GFP_KERNEL);
 368                if (!cros_port->disc_data) {
 369                        ret = -ENOMEM;
 370                        goto unregister_ports;
 371                }
 372
 373                INIT_LIST_HEAD(&cros_port->partner_mode_list);
 374                INIT_LIST_HEAD(&cros_port->plug_mode_list);
 375        }
 376
 377        return 0;
 378
 379unregister_ports:
 380        cros_unregister_ports(typec);
 381        return ret;
 382}
 383
 384static int cros_typec_usb_safe_state(struct cros_typec_port *port)
 385{
 386        port->state.mode = TYPEC_STATE_SAFE;
 387
 388        return typec_mux_set(port->mux, &port->state);
 389}
 390
 391/*
 392 * Spoof the VDOs that were likely communicated by the partner for TBT alt
 393 * mode.
 394 */
 395static int cros_typec_enable_tbt(struct cros_typec_data *typec,
 396                                 int port_num,
 397                                 struct ec_response_usb_pd_control_v2 *pd_ctrl)
 398{
 399        struct cros_typec_port *port = typec->ports[port_num];
 400        struct typec_thunderbolt_data data;
 401        int ret;
 402
 403        if (typec->pd_ctrl_ver < 2) {
 404                dev_err(typec->dev,
 405                        "PD_CTRL version too old: %d\n", typec->pd_ctrl_ver);
 406                return -ENOTSUPP;
 407        }
 408
 409        /* Device Discover Mode VDO */
 410        data.device_mode = TBT_MODE;
 411
 412        if (pd_ctrl->control_flags & USB_PD_CTRL_TBT_LEGACY_ADAPTER)
 413                data.device_mode = TBT_SET_ADAPTER(TBT_ADAPTER_TBT3);
 414
 415        /* Cable Discover Mode VDO */
 416        data.cable_mode = TBT_MODE;
 417        data.cable_mode |= TBT_SET_CABLE_SPEED(pd_ctrl->cable_speed);
 418
 419        if (pd_ctrl->control_flags & USB_PD_CTRL_OPTICAL_CABLE)
 420                data.cable_mode |= TBT_CABLE_OPTICAL;
 421
 422        if (pd_ctrl->control_flags & USB_PD_CTRL_ACTIVE_LINK_UNIDIR)
 423                data.cable_mode |= TBT_CABLE_LINK_TRAINING;
 424
 425        data.cable_mode |= TBT_SET_CABLE_ROUNDED(pd_ctrl->cable_gen);
 426
 427        /* Enter Mode VDO */
 428        data.enter_vdo = TBT_SET_CABLE_SPEED(pd_ctrl->cable_speed);
 429
 430        if (pd_ctrl->control_flags & USB_PD_CTRL_ACTIVE_CABLE)
 431                data.enter_vdo |= TBT_ENTER_MODE_ACTIVE_CABLE;
 432
 433        if (!port->state.alt) {
 434                port->state.alt = &port->p_altmode[CROS_EC_ALTMODE_TBT];
 435                ret = cros_typec_usb_safe_state(port);
 436                if (ret)
 437                        return ret;
 438        }
 439
 440        port->state.data = &data;
 441        port->state.mode = TYPEC_TBT_MODE;
 442
 443        return typec_mux_set(port->mux, &port->state);
 444}
 445
 446/* Spoof the VDOs that were likely communicated by the partner. */
 447static int cros_typec_enable_dp(struct cros_typec_data *typec,
 448                                int port_num,
 449                                struct ec_response_usb_pd_control_v2 *pd_ctrl)
 450{
 451        struct cros_typec_port *port = typec->ports[port_num];
 452        struct typec_displayport_data dp_data;
 453        int ret;
 454
 455        if (typec->pd_ctrl_ver < 2) {
 456                dev_err(typec->dev,
 457                        "PD_CTRL version too old: %d\n", typec->pd_ctrl_ver);
 458                return -ENOTSUPP;
 459        }
 460
 461        if (!pd_ctrl->dp_mode) {
 462                dev_err(typec->dev, "No valid DP mode provided.\n");
 463                return -EINVAL;
 464        }
 465
 466        /* Status VDO. */
 467        dp_data.status = DP_STATUS_ENABLED;
 468        if (port->mux_flags & USB_PD_MUX_HPD_IRQ)
 469                dp_data.status |= DP_STATUS_IRQ_HPD;
 470        if (port->mux_flags & USB_PD_MUX_HPD_LVL)
 471                dp_data.status |= DP_STATUS_HPD_STATE;
 472
 473        /* Configuration VDO. */
 474        dp_data.conf = DP_CONF_SET_PIN_ASSIGN(pd_ctrl->dp_mode);
 475        if (!port->state.alt) {
 476                port->state.alt = &port->p_altmode[CROS_EC_ALTMODE_DP];
 477                ret = cros_typec_usb_safe_state(port);
 478                if (ret)
 479                        return ret;
 480        }
 481
 482        port->state.data = &dp_data;
 483        port->state.mode = TYPEC_MODAL_STATE(ffs(pd_ctrl->dp_mode));
 484
 485        return typec_mux_set(port->mux, &port->state);
 486}
 487
 488static int cros_typec_enable_usb4(struct cros_typec_data *typec,
 489                                  int port_num,
 490                                  struct ec_response_usb_pd_control_v2 *pd_ctrl)
 491{
 492        struct cros_typec_port *port = typec->ports[port_num];
 493        struct enter_usb_data data;
 494
 495        data.eudo = EUDO_USB_MODE_USB4 << EUDO_USB_MODE_SHIFT;
 496
 497        /* Cable Speed */
 498        data.eudo |= pd_ctrl->cable_speed << EUDO_CABLE_SPEED_SHIFT;
 499
 500        /* Cable Type */
 501        if (pd_ctrl->control_flags & USB_PD_CTRL_OPTICAL_CABLE)
 502                data.eudo |= EUDO_CABLE_TYPE_OPTICAL << EUDO_CABLE_TYPE_SHIFT;
 503        else if (pd_ctrl->control_flags & USB_PD_CTRL_ACTIVE_CABLE)
 504                data.eudo |= EUDO_CABLE_TYPE_RE_TIMER << EUDO_CABLE_TYPE_SHIFT;
 505
 506        data.active_link_training = !!(pd_ctrl->control_flags &
 507                                       USB_PD_CTRL_ACTIVE_LINK_UNIDIR);
 508
 509        port->state.alt = NULL;
 510        port->state.data = &data;
 511        port->state.mode = TYPEC_MODE_USB4;
 512
 513        return typec_mux_set(port->mux, &port->state);
 514}
 515
 516static int cros_typec_configure_mux(struct cros_typec_data *typec, int port_num,
 517                                struct ec_response_usb_pd_control_v2 *pd_ctrl)
 518{
 519        struct cros_typec_port *port = typec->ports[port_num];
 520        struct ec_response_usb_pd_mux_info resp;
 521        struct ec_params_usb_pd_mux_info req = {
 522                .port = port_num,
 523        };
 524        struct ec_params_usb_pd_mux_ack mux_ack;
 525        enum typec_orientation orientation;
 526        int ret;
 527
 528        ret = cros_ec_command(typec->ec, 0, EC_CMD_USB_PD_MUX_INFO,
 529                              &req, sizeof(req), &resp, sizeof(resp));
 530        if (ret < 0) {
 531                dev_warn(typec->dev, "Failed to get mux info for port: %d, err = %d\n",
 532                         port_num, ret);
 533                return ret;
 534        }
 535
 536        /* No change needs to be made, let's exit early. */
 537        if (port->mux_flags == resp.flags && port->role == pd_ctrl->role)
 538                return 0;
 539
 540        port->mux_flags = resp.flags;
 541        port->role = pd_ctrl->role;
 542
 543        if (port->mux_flags == USB_PD_MUX_NONE) {
 544                ret = cros_typec_usb_disconnect_state(port);
 545                goto mux_ack;
 546        }
 547
 548        if (port->mux_flags & USB_PD_MUX_POLARITY_INVERTED)
 549                orientation = TYPEC_ORIENTATION_REVERSE;
 550        else
 551                orientation = TYPEC_ORIENTATION_NORMAL;
 552
 553        ret = typec_switch_set(port->ori_sw, orientation);
 554        if (ret)
 555                return ret;
 556
 557        ret = usb_role_switch_set_role(typec->ports[port_num]->role_sw,
 558                                        pd_ctrl->role & PD_CTRL_RESP_ROLE_DATA
 559                                        ? USB_ROLE_HOST : USB_ROLE_DEVICE);
 560        if (ret)
 561                return ret;
 562
 563        if (port->mux_flags & USB_PD_MUX_USB4_ENABLED) {
 564                ret = cros_typec_enable_usb4(typec, port_num, pd_ctrl);
 565        } else if (port->mux_flags & USB_PD_MUX_TBT_COMPAT_ENABLED) {
 566                ret = cros_typec_enable_tbt(typec, port_num, pd_ctrl);
 567        } else if (port->mux_flags & USB_PD_MUX_DP_ENABLED) {
 568                ret = cros_typec_enable_dp(typec, port_num, pd_ctrl);
 569        } else if (port->mux_flags & USB_PD_MUX_SAFE_MODE) {
 570                ret = cros_typec_usb_safe_state(port);
 571        } else if (port->mux_flags & USB_PD_MUX_USB_ENABLED) {
 572                port->state.alt = NULL;
 573                port->state.mode = TYPEC_STATE_USB;
 574                ret = typec_mux_set(port->mux, &port->state);
 575        } else {
 576                dev_dbg(typec->dev,
 577                        "Unrecognized mode requested, mux flags: %x\n",
 578                        port->mux_flags);
 579        }
 580
 581mux_ack:
 582        if (!typec->needs_mux_ack)
 583                return ret;
 584
 585        /* Sending Acknowledgment to EC */
 586        mux_ack.port = port_num;
 587
 588        if (cros_ec_command(typec->ec, 0, EC_CMD_USB_PD_MUX_ACK, &mux_ack,
 589                            sizeof(mux_ack), NULL, 0) < 0)
 590                dev_warn(typec->dev,
 591                         "Failed to send Mux ACK to EC for port: %d\n",
 592                         port_num);
 593
 594        return ret;
 595}
 596
 597static void cros_typec_set_port_params_v0(struct cros_typec_data *typec,
 598                int port_num, struct ec_response_usb_pd_control *resp)
 599{
 600        struct typec_port *port = typec->ports[port_num]->port;
 601        enum typec_orientation polarity;
 602
 603        if (!resp->enabled)
 604                polarity = TYPEC_ORIENTATION_NONE;
 605        else if (!resp->polarity)
 606                polarity = TYPEC_ORIENTATION_NORMAL;
 607        else
 608                polarity = TYPEC_ORIENTATION_REVERSE;
 609
 610        typec_set_pwr_role(port, resp->role ? TYPEC_SOURCE : TYPEC_SINK);
 611        typec_set_orientation(port, polarity);
 612}
 613
 614static void cros_typec_set_port_params_v1(struct cros_typec_data *typec,
 615                int port_num, struct ec_response_usb_pd_control_v1 *resp)
 616{
 617        struct typec_port *port = typec->ports[port_num]->port;
 618        enum typec_orientation polarity;
 619        bool pd_en;
 620        int ret;
 621
 622        if (!(resp->enabled & PD_CTRL_RESP_ENABLED_CONNECTED))
 623                polarity = TYPEC_ORIENTATION_NONE;
 624        else if (!resp->polarity)
 625                polarity = TYPEC_ORIENTATION_NORMAL;
 626        else
 627                polarity = TYPEC_ORIENTATION_REVERSE;
 628        typec_set_orientation(port, polarity);
 629        typec_set_data_role(port, resp->role & PD_CTRL_RESP_ROLE_DATA ?
 630                        TYPEC_HOST : TYPEC_DEVICE);
 631        typec_set_pwr_role(port, resp->role & PD_CTRL_RESP_ROLE_POWER ?
 632                        TYPEC_SOURCE : TYPEC_SINK);
 633        typec_set_vconn_role(port, resp->role & PD_CTRL_RESP_ROLE_VCONN ?
 634                        TYPEC_SOURCE : TYPEC_SINK);
 635
 636        /* Register/remove partners when a connect/disconnect occurs. */
 637        if (resp->enabled & PD_CTRL_RESP_ENABLED_CONNECTED) {
 638                if (typec->ports[port_num]->partner)
 639                        return;
 640
 641                pd_en = resp->enabled & PD_CTRL_RESP_ENABLED_PD_CAPABLE;
 642                ret = cros_typec_add_partner(typec, port_num, pd_en);
 643                if (ret)
 644                        dev_warn(typec->dev,
 645                                 "Failed to register partner on port: %d\n",
 646                                 port_num);
 647        } else {
 648                cros_typec_remove_partner(typec, port_num);
 649                cros_typec_remove_cable(typec, port_num);
 650        }
 651}
 652
 653/*
 654 * Helper function to register partner/plug altmodes.
 655 */
 656static int cros_typec_register_altmodes(struct cros_typec_data *typec, int port_num,
 657                                        bool is_partner)
 658{
 659        struct cros_typec_port *port = typec->ports[port_num];
 660        struct ec_response_typec_discovery *sop_disc = port->disc_data;
 661        struct cros_typec_altmode_node *node;
 662        struct typec_altmode_desc desc;
 663        struct typec_altmode *amode;
 664        int num_altmodes = 0;
 665        int ret = 0;
 666        int i, j;
 667
 668        for (i = 0; i < sop_disc->svid_count; i++) {
 669                for (j = 0; j < sop_disc->svids[i].mode_count; j++) {
 670                        memset(&desc, 0, sizeof(desc));
 671                        desc.svid = sop_disc->svids[i].svid;
 672                        desc.mode = j;
 673                        desc.vdo = sop_disc->svids[i].mode_vdo[j];
 674
 675                        if (is_partner)
 676                                amode = typec_partner_register_altmode(port->partner, &desc);
 677                        else
 678                                amode = typec_plug_register_altmode(port->plug, &desc);
 679
 680                        if (IS_ERR(amode)) {
 681                                ret = PTR_ERR(amode);
 682                                goto err_cleanup;
 683                        }
 684
 685                        /* If no memory is available we should unregister and exit. */
 686                        node = devm_kzalloc(typec->dev, sizeof(*node), GFP_KERNEL);
 687                        if (!node) {
 688                                ret = -ENOMEM;
 689                                typec_unregister_altmode(amode);
 690                                goto err_cleanup;
 691                        }
 692
 693                        node->amode = amode;
 694
 695                        if (is_partner)
 696                                list_add_tail(&node->list, &port->partner_mode_list);
 697                        else
 698                                list_add_tail(&node->list, &port->plug_mode_list);
 699                        num_altmodes++;
 700                }
 701        }
 702
 703        if (is_partner)
 704                ret = typec_partner_set_num_altmodes(port->partner, num_altmodes);
 705        else
 706                ret = typec_plug_set_num_altmodes(port->plug, num_altmodes);
 707
 708        if (ret < 0) {
 709                dev_err(typec->dev, "Unable to set %s num_altmodes for port: %d\n",
 710                        is_partner ? "partner" : "plug", port_num);
 711                goto err_cleanup;
 712        }
 713
 714        return 0;
 715
 716err_cleanup:
 717        cros_typec_unregister_altmodes(typec, port_num, is_partner);
 718        return ret;
 719}
 720
 721/*
 722 * Parse the PD identity data from the EC PD discovery responses and copy that to the supplied
 723 * PD identity struct.
 724 */
 725static void cros_typec_parse_pd_identity(struct usb_pd_identity *id,
 726                                         struct ec_response_typec_discovery *disc)
 727{
 728        int i;
 729
 730        /* First, update the PD identity VDOs for the partner. */
 731        if (disc->identity_count > 0)
 732                id->id_header = disc->discovery_vdo[0];
 733        if (disc->identity_count > 1)
 734                id->cert_stat = disc->discovery_vdo[1];
 735        if (disc->identity_count > 2)
 736                id->product = disc->discovery_vdo[2];
 737
 738        /* Copy the remaining identity VDOs till a maximum of 6. */
 739        for (i = 3; i < disc->identity_count && i < VDO_MAX_OBJECTS; i++)
 740                id->vdo[i - 3] = disc->discovery_vdo[i];
 741}
 742
 743static int cros_typec_handle_sop_prime_disc(struct cros_typec_data *typec, int port_num, u16 pd_revision)
 744{
 745        struct cros_typec_port *port = typec->ports[port_num];
 746        struct ec_response_typec_discovery *disc = port->disc_data;
 747        struct typec_cable_desc c_desc = {};
 748        struct typec_plug_desc p_desc;
 749        struct ec_params_typec_discovery req = {
 750                .port = port_num,
 751                .partner_type = TYPEC_PARTNER_SOP_PRIME,
 752        };
 753        u32 cable_plug_type;
 754        int ret = 0;
 755
 756        memset(disc, 0, EC_PROTO2_MAX_RESPONSE_SIZE);
 757        ret = cros_ec_command(typec->ec, 0, EC_CMD_TYPEC_DISCOVERY, &req, sizeof(req),
 758                              disc, EC_PROTO2_MAX_RESPONSE_SIZE);
 759        if (ret < 0) {
 760                dev_err(typec->dev, "Failed to get SOP' discovery data for port: %d\n", port_num);
 761                goto sop_prime_disc_exit;
 762        }
 763
 764        /* Parse the PD identity data, even if only 0s were returned. */
 765        cros_typec_parse_pd_identity(&port->c_identity, disc);
 766
 767        if (disc->identity_count != 0) {
 768                cable_plug_type = VDO_TYPEC_CABLE_TYPE(port->c_identity.vdo[0]);
 769                switch (cable_plug_type) {
 770                case CABLE_ATYPE:
 771                        c_desc.type = USB_PLUG_TYPE_A;
 772                        break;
 773                case CABLE_BTYPE:
 774                        c_desc.type = USB_PLUG_TYPE_B;
 775                        break;
 776                case CABLE_CTYPE:
 777                        c_desc.type = USB_PLUG_TYPE_C;
 778                        break;
 779                case CABLE_CAPTIVE:
 780                        c_desc.type = USB_PLUG_CAPTIVE;
 781                        break;
 782                default:
 783                        c_desc.type = USB_PLUG_NONE;
 784                }
 785                c_desc.active = PD_IDH_PTYPE(port->c_identity.id_header) == IDH_PTYPE_ACABLE;
 786        }
 787
 788        c_desc.identity = &port->c_identity;
 789        c_desc.pd_revision = pd_revision;
 790
 791        port->cable = typec_register_cable(port->port, &c_desc);
 792        if (IS_ERR(port->cable)) {
 793                ret = PTR_ERR(port->cable);
 794                port->cable = NULL;
 795                goto sop_prime_disc_exit;
 796        }
 797
 798        p_desc.index = TYPEC_PLUG_SOP_P;
 799        port->plug = typec_register_plug(port->cable, &p_desc);
 800        if (IS_ERR(port->plug)) {
 801                ret = PTR_ERR(port->plug);
 802                port->plug = NULL;
 803                goto sop_prime_disc_exit;
 804        }
 805
 806        ret = cros_typec_register_altmodes(typec, port_num, false);
 807        if (ret < 0) {
 808                dev_err(typec->dev, "Failed to register plug altmodes, port: %d\n", port_num);
 809                goto sop_prime_disc_exit;
 810        }
 811
 812        return 0;
 813
 814sop_prime_disc_exit:
 815        cros_typec_remove_cable(typec, port_num);
 816        return ret;
 817}
 818
 819static int cros_typec_handle_sop_disc(struct cros_typec_data *typec, int port_num, u16 pd_revision)
 820{
 821        struct cros_typec_port *port = typec->ports[port_num];
 822        struct ec_response_typec_discovery *sop_disc = port->disc_data;
 823        struct ec_params_typec_discovery req = {
 824                .port = port_num,
 825                .partner_type = TYPEC_PARTNER_SOP,
 826        };
 827        int ret = 0;
 828
 829        if (!port->partner) {
 830                dev_err(typec->dev,
 831                        "SOP Discovery received without partner registered, port: %d\n",
 832                        port_num);
 833                ret = -EINVAL;
 834                goto disc_exit;
 835        }
 836
 837        typec_partner_set_pd_revision(port->partner, pd_revision);
 838
 839        memset(sop_disc, 0, EC_PROTO2_MAX_RESPONSE_SIZE);
 840        ret = cros_ec_command(typec->ec, 0, EC_CMD_TYPEC_DISCOVERY, &req, sizeof(req),
 841                              sop_disc, EC_PROTO2_MAX_RESPONSE_SIZE);
 842        if (ret < 0) {
 843                dev_err(typec->dev, "Failed to get SOP discovery data for port: %d\n", port_num);
 844                goto disc_exit;
 845        }
 846
 847        cros_typec_parse_pd_identity(&port->p_identity, sop_disc);
 848
 849        ret = typec_partner_set_identity(port->partner);
 850        if (ret < 0) {
 851                dev_err(typec->dev, "Failed to update partner PD identity, port: %d\n", port_num);
 852                goto disc_exit;
 853        }
 854
 855        ret = cros_typec_register_altmodes(typec, port_num, true);
 856        if (ret < 0) {
 857                dev_err(typec->dev, "Failed to register partner altmodes, port: %d\n", port_num);
 858                goto disc_exit;
 859        }
 860
 861disc_exit:
 862        return ret;
 863}
 864
 865static int cros_typec_send_clear_event(struct cros_typec_data *typec, int port_num, u32 events_mask)
 866{
 867        struct ec_params_typec_control req = {
 868                .port = port_num,
 869                .command = TYPEC_CONTROL_COMMAND_CLEAR_EVENTS,
 870                .clear_events_mask = events_mask,
 871        };
 872
 873        return cros_ec_command(typec->ec, 0, EC_CMD_TYPEC_CONTROL, &req,
 874                               sizeof(req), NULL, 0);
 875}
 876
 877static void cros_typec_handle_status(struct cros_typec_data *typec, int port_num)
 878{
 879        struct ec_response_typec_status resp;
 880        struct ec_params_typec_status req = {
 881                .port = port_num,
 882        };
 883        int ret;
 884
 885        ret = cros_ec_command(typec->ec, 0, EC_CMD_TYPEC_STATUS, &req, sizeof(req),
 886                              &resp, sizeof(resp));
 887        if (ret < 0) {
 888                dev_warn(typec->dev, "EC_CMD_TYPEC_STATUS failed for port: %d\n", port_num);
 889                return;
 890        }
 891
 892        /* If we got a hard reset, unregister everything and return. */
 893        if (resp.events & PD_STATUS_EVENT_HARD_RESET) {
 894                cros_typec_remove_partner(typec, port_num);
 895                cros_typec_remove_cable(typec, port_num);
 896
 897                ret = cros_typec_send_clear_event(typec, port_num,
 898                                                  PD_STATUS_EVENT_HARD_RESET);
 899                if (ret < 0)
 900                        dev_warn(typec->dev,
 901                                 "Failed hard reset event clear, port: %d\n", port_num);
 902                return;
 903        }
 904
 905        /* Handle any events appropriately. */
 906        if (resp.events & PD_STATUS_EVENT_SOP_DISC_DONE && !typec->ports[port_num]->sop_disc_done) {
 907                u16 sop_revision;
 908
 909                /* Convert BCD to the format preferred by the TypeC framework */
 910                sop_revision = (le16_to_cpu(resp.sop_revision) & 0xff00) >> 4;
 911                ret = cros_typec_handle_sop_disc(typec, port_num, sop_revision);
 912                if (ret < 0)
 913                        dev_err(typec->dev, "Couldn't parse SOP Disc data, port: %d\n", port_num);
 914                else {
 915                        typec->ports[port_num]->sop_disc_done = true;
 916                        ret = cros_typec_send_clear_event(typec, port_num,
 917                                                          PD_STATUS_EVENT_SOP_DISC_DONE);
 918                        if (ret < 0)
 919                                dev_warn(typec->dev,
 920                                         "Failed SOP Disc event clear, port: %d\n", port_num);
 921                }
 922                if (resp.sop_connected)
 923                        typec_set_pwr_opmode(typec->ports[port_num]->port, TYPEC_PWR_MODE_PD);
 924        }
 925
 926        if (resp.events & PD_STATUS_EVENT_SOP_PRIME_DISC_DONE &&
 927            !typec->ports[port_num]->sop_prime_disc_done) {
 928                u16 sop_prime_revision;
 929
 930                /* Convert BCD to the format preferred by the TypeC framework */
 931                sop_prime_revision = (le16_to_cpu(resp.sop_prime_revision) & 0xff00) >> 4;
 932                ret = cros_typec_handle_sop_prime_disc(typec, port_num, sop_prime_revision);
 933                if (ret < 0)
 934                        dev_err(typec->dev, "Couldn't parse SOP' Disc data, port: %d\n", port_num);
 935                else {
 936                        typec->ports[port_num]->sop_prime_disc_done = true;
 937                        ret = cros_typec_send_clear_event(typec, port_num,
 938                                                          PD_STATUS_EVENT_SOP_PRIME_DISC_DONE);
 939                        if (ret < 0)
 940                                dev_warn(typec->dev,
 941                                         "Failed SOP Disc event clear, port: %d\n", port_num);
 942                }
 943        }
 944}
 945
 946static int cros_typec_port_update(struct cros_typec_data *typec, int port_num)
 947{
 948        struct ec_params_usb_pd_control req;
 949        struct ec_response_usb_pd_control_v2 resp;
 950        int ret;
 951
 952        if (port_num < 0 || port_num >= typec->num_ports) {
 953                dev_err(typec->dev, "cannot get status for invalid port %d\n",
 954                        port_num);
 955                return -EINVAL;
 956        }
 957
 958        req.port = port_num;
 959        req.role = USB_PD_CTRL_ROLE_NO_CHANGE;
 960        req.mux = USB_PD_CTRL_MUX_NO_CHANGE;
 961        req.swap = USB_PD_CTRL_SWAP_NONE;
 962
 963        ret = cros_ec_command(typec->ec, typec->pd_ctrl_ver,
 964                              EC_CMD_USB_PD_CONTROL, &req, sizeof(req),
 965                              &resp, sizeof(resp));
 966        if (ret < 0)
 967                return ret;
 968
 969        /* Update the switches if they exist, according to requested state */
 970        ret = cros_typec_configure_mux(typec, port_num, &resp);
 971        if (ret)
 972                dev_warn(typec->dev, "Configure muxes failed, err = %d\n", ret);
 973
 974        dev_dbg(typec->dev, "Enabled %d: 0x%hhx\n", port_num, resp.enabled);
 975        dev_dbg(typec->dev, "Role %d: 0x%hhx\n", port_num, resp.role);
 976        dev_dbg(typec->dev, "Polarity %d: 0x%hhx\n", port_num, resp.polarity);
 977        dev_dbg(typec->dev, "State %d: %s\n", port_num, resp.state);
 978
 979        if (typec->pd_ctrl_ver != 0)
 980                cros_typec_set_port_params_v1(typec, port_num,
 981                        (struct ec_response_usb_pd_control_v1 *)&resp);
 982        else
 983                cros_typec_set_port_params_v0(typec, port_num,
 984                        (struct ec_response_usb_pd_control *) &resp);
 985
 986        if (typec->typec_cmd_supported)
 987                cros_typec_handle_status(typec, port_num);
 988
 989        return 0;
 990}
 991
 992static int cros_typec_get_cmd_version(struct cros_typec_data *typec)
 993{
 994        struct ec_params_get_cmd_versions_v1 req_v1;
 995        struct ec_response_get_cmd_versions resp;
 996        int ret;
 997
 998        /* We're interested in the PD control command version. */
 999        req_v1.cmd = EC_CMD_USB_PD_CONTROL;
1000        ret = cros_ec_command(typec->ec, 1, EC_CMD_GET_CMD_VERSIONS,
1001                              &req_v1, sizeof(req_v1), &resp,
1002                                    sizeof(resp));
1003        if (ret < 0)
1004                return ret;
1005
1006        if (resp.version_mask & EC_VER_MASK(2))
1007                typec->pd_ctrl_ver = 2;
1008        else if (resp.version_mask & EC_VER_MASK(1))
1009                typec->pd_ctrl_ver = 1;
1010        else
1011                typec->pd_ctrl_ver = 0;
1012
1013        dev_dbg(typec->dev, "PD Control has version mask 0x%02x\n",
1014                typec->pd_ctrl_ver & 0xff);
1015
1016        return 0;
1017}
1018
1019static void cros_typec_port_work(struct work_struct *work)
1020{
1021        struct cros_typec_data *typec = container_of(work, struct cros_typec_data, port_work);
1022        int ret, i;
1023
1024        for (i = 0; i < typec->num_ports; i++) {
1025                ret = cros_typec_port_update(typec, i);
1026                if (ret < 0)
1027                        dev_warn(typec->dev, "Update failed for port: %d\n", i);
1028        }
1029}
1030
1031static int cros_ec_typec_event(struct notifier_block *nb,
1032                               unsigned long host_event, void *_notify)
1033{
1034        struct cros_typec_data *typec = container_of(nb, struct cros_typec_data, nb);
1035
1036        flush_work(&typec->port_work);
1037        schedule_work(&typec->port_work);
1038
1039        return NOTIFY_OK;
1040}
1041
1042#ifdef CONFIG_ACPI
1043static const struct acpi_device_id cros_typec_acpi_id[] = {
1044        { "GOOG0014", 0 },
1045        {}
1046};
1047MODULE_DEVICE_TABLE(acpi, cros_typec_acpi_id);
1048#endif
1049
1050#ifdef CONFIG_OF
1051static const struct of_device_id cros_typec_of_match[] = {
1052        { .compatible = "google,cros-ec-typec", },
1053        {}
1054};
1055MODULE_DEVICE_TABLE(of, cros_typec_of_match);
1056#endif
1057
1058static int cros_typec_probe(struct platform_device *pdev)
1059{
1060        struct cros_ec_dev *ec_dev = NULL;
1061        struct device *dev = &pdev->dev;
1062        struct cros_typec_data *typec;
1063        struct ec_response_usb_pd_ports resp;
1064        int ret, i;
1065
1066        typec = devm_kzalloc(dev, sizeof(*typec), GFP_KERNEL);
1067        if (!typec)
1068                return -ENOMEM;
1069
1070        typec->dev = dev;
1071
1072        typec->ec = dev_get_drvdata(pdev->dev.parent);
1073        if (!typec->ec) {
1074                dev_err(dev, "couldn't find parent EC device\n");
1075                return -ENODEV;
1076        }
1077
1078        platform_set_drvdata(pdev, typec);
1079
1080        ret = cros_typec_get_cmd_version(typec);
1081        if (ret < 0) {
1082                dev_err(dev, "failed to get PD command version info\n");
1083                return ret;
1084        }
1085
1086        ec_dev = dev_get_drvdata(&typec->ec->ec->dev);
1087        if (!ec_dev)
1088                return -EPROBE_DEFER;
1089
1090        typec->typec_cmd_supported = cros_ec_check_features(ec_dev, EC_FEATURE_TYPEC_CMD);
1091        typec->needs_mux_ack = cros_ec_check_features(ec_dev, EC_FEATURE_TYPEC_MUX_REQUIRE_AP_ACK);
1092
1093        ret = cros_ec_command(typec->ec, 0, EC_CMD_USB_PD_PORTS, NULL, 0,
1094                              &resp, sizeof(resp));
1095        if (ret < 0)
1096                return ret;
1097
1098        typec->num_ports = resp.num_ports;
1099        if (typec->num_ports > EC_USB_PD_MAX_PORTS) {
1100                dev_warn(typec->dev,
1101                         "Too many ports reported: %d, limiting to max: %d\n",
1102                         typec->num_ports, EC_USB_PD_MAX_PORTS);
1103                typec->num_ports = EC_USB_PD_MAX_PORTS;
1104        }
1105
1106        ret = cros_typec_init_ports(typec);
1107        if (ret < 0)
1108                return ret;
1109
1110        INIT_WORK(&typec->port_work, cros_typec_port_work);
1111
1112        /*
1113         * Safe to call port update here, since we haven't registered the
1114         * PD notifier yet.
1115         */
1116        for (i = 0; i < typec->num_ports; i++) {
1117                ret = cros_typec_port_update(typec, i);
1118                if (ret < 0)
1119                        goto unregister_ports;
1120        }
1121
1122        typec->nb.notifier_call = cros_ec_typec_event;
1123        ret = cros_usbpd_register_notify(&typec->nb);
1124        if (ret < 0)
1125                goto unregister_ports;
1126
1127        return 0;
1128
1129unregister_ports:
1130        cros_unregister_ports(typec);
1131        return ret;
1132}
1133
1134static int __maybe_unused cros_typec_suspend(struct device *dev)
1135{
1136        struct cros_typec_data *typec = dev_get_drvdata(dev);
1137
1138        cancel_work_sync(&typec->port_work);
1139
1140        return 0;
1141}
1142
1143static int __maybe_unused cros_typec_resume(struct device *dev)
1144{
1145        struct cros_typec_data *typec = dev_get_drvdata(dev);
1146
1147        /* Refresh port state. */
1148        schedule_work(&typec->port_work);
1149
1150        return 0;
1151}
1152
1153static const struct dev_pm_ops cros_typec_pm_ops = {
1154        SET_SYSTEM_SLEEP_PM_OPS(cros_typec_suspend, cros_typec_resume)
1155};
1156
1157static struct platform_driver cros_typec_driver = {
1158        .driver = {
1159                .name = DRV_NAME,
1160                .acpi_match_table = ACPI_PTR(cros_typec_acpi_id),
1161                .of_match_table = of_match_ptr(cros_typec_of_match),
1162                .pm = &cros_typec_pm_ops,
1163        },
1164        .probe = cros_typec_probe,
1165};
1166
1167module_platform_driver(cros_typec_driver);
1168
1169MODULE_AUTHOR("Prashant Malani <pmalani@chromium.org>");
1170MODULE_DESCRIPTION("Chrome OS EC Type C control");
1171MODULE_LICENSE("GPL");
1172