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