Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Willsemi WUSB3801 Type-C port controller driver
0004  *
0005  * Copyright (C) 2022 Samuel Holland <samuel@sholland.org>
0006  */
0007 
0008 #include <linux/i2c.h>
0009 #include <linux/module.h>
0010 #include <linux/regmap.h>
0011 #include <linux/regulator/consumer.h>
0012 #include <linux/usb/typec.h>
0013 
0014 #define WUSB3801_REG_DEVICE_ID      0x01
0015 #define WUSB3801_REG_CTRL0      0x02
0016 #define WUSB3801_REG_INT        0x03
0017 #define WUSB3801_REG_STAT       0x04
0018 #define WUSB3801_REG_CTRL1      0x05
0019 #define WUSB3801_REG_TEST00     0x06
0020 #define WUSB3801_REG_TEST01     0x07
0021 #define WUSB3801_REG_TEST02     0x08
0022 #define WUSB3801_REG_TEST03     0x09
0023 #define WUSB3801_REG_TEST04     0x0a
0024 #define WUSB3801_REG_TEST05     0x0b
0025 #define WUSB3801_REG_TEST06     0x0c
0026 #define WUSB3801_REG_TEST07     0x0d
0027 #define WUSB3801_REG_TEST08     0x0e
0028 #define WUSB3801_REG_TEST09     0x0f
0029 #define WUSB3801_REG_TEST0A     0x10
0030 #define WUSB3801_REG_TEST0B     0x11
0031 #define WUSB3801_REG_TEST0C     0x12
0032 #define WUSB3801_REG_TEST0D     0x13
0033 #define WUSB3801_REG_TEST0E     0x14
0034 #define WUSB3801_REG_TEST0F     0x15
0035 #define WUSB3801_REG_TEST10     0x16
0036 #define WUSB3801_REG_TEST11     0x17
0037 #define WUSB3801_REG_TEST12     0x18
0038 
0039 #define WUSB3801_DEVICE_ID_VERSION_ID   GENMASK(7, 3)
0040 #define WUSB3801_DEVICE_ID_VENDOR_ID    GENMASK(2, 0)
0041 
0042 #define WUSB3801_CTRL0_DIS_ACC_SUPPORT  BIT(7)
0043 #define WUSB3801_CTRL0_TRY      GENMASK(6, 5)
0044 #define WUSB3801_CTRL0_TRY_NONE     (0x0 << 5)
0045 #define WUSB3801_CTRL0_TRY_SNK      (0x1 << 5)
0046 #define WUSB3801_CTRL0_TRY_SRC      (0x2 << 5)
0047 #define WUSB3801_CTRL0_CURRENT      GENMASK(4, 3) /* SRC */
0048 #define WUSB3801_CTRL0_CURRENT_DEFAULT  (0x0 << 3)
0049 #define WUSB3801_CTRL0_CURRENT_1_5A (0x1 << 3)
0050 #define WUSB3801_CTRL0_CURRENT_3_0A (0x2 << 3)
0051 #define WUSB3801_CTRL0_ROLE     GENMASK(2, 1)
0052 #define WUSB3801_CTRL0_ROLE_SNK     (0x0 << 1)
0053 #define WUSB3801_CTRL0_ROLE_SRC     (0x1 << 1)
0054 #define WUSB3801_CTRL0_ROLE_DRP     (0x2 << 1)
0055 #define WUSB3801_CTRL0_INT_MASK     BIT(0)
0056 
0057 #define WUSB3801_INT_ATTACHED       BIT(0)
0058 #define WUSB3801_INT_DETACHED       BIT(1)
0059 
0060 #define WUSB3801_STAT_VBUS_DETECTED BIT(7)
0061 #define WUSB3801_STAT_CURRENT       GENMASK(6, 5) /* SNK */
0062 #define WUSB3801_STAT_CURRENT_STANDBY   (0x0 << 5)
0063 #define WUSB3801_STAT_CURRENT_DEFAULT   (0x1 << 5)
0064 #define WUSB3801_STAT_CURRENT_1_5A  (0x2 << 5)
0065 #define WUSB3801_STAT_CURRENT_3_0A  (0x3 << 5)
0066 #define WUSB3801_STAT_PARTNER       GENMASK(4, 2)
0067 #define WUSB3801_STAT_PARTNER_STANDBY   (0x0 << 2)
0068 #define WUSB3801_STAT_PARTNER_SNK   (0x1 << 2)
0069 #define WUSB3801_STAT_PARTNER_SRC   (0x2 << 2)
0070 #define WUSB3801_STAT_PARTNER_AUDIO (0x3 << 2)
0071 #define WUSB3801_STAT_PARTNER_DEBUG (0x4 << 2)
0072 #define WUSB3801_STAT_ORIENTATION   GENMASK(1, 0)
0073 #define WUSB3801_STAT_ORIENTATION_NONE  (0x0 << 0)
0074 #define WUSB3801_STAT_ORIENTATION_CC1   (0x1 << 0)
0075 #define WUSB3801_STAT_ORIENTATION_CC2   (0x2 << 0)
0076 #define WUSB3801_STAT_ORIENTATION_BOTH  (0x3 << 0)
0077 
0078 #define WUSB3801_CTRL1_SM_RESET     BIT(0)
0079 
0080 #define WUSB3801_TEST01_VENDOR_SUB_ID   (BIT(8) | BIT(6))
0081 
0082 #define WUSB3801_TEST02_FORCE_ERR_RCY   BIT(8)
0083 
0084 #define WUSB3801_TEST0A_WAIT_VBUS   BIT(5)
0085 
0086 struct wusb3801 {
0087     struct typec_capability cap;
0088     struct device       *dev;
0089     struct typec_partner    *partner;
0090     struct typec_port   *port;
0091     struct regmap       *regmap;
0092     struct regulator    *vbus_supply;
0093     unsigned int        partner_type;
0094     enum typec_port_type    port_type;
0095     enum typec_pwr_opmode   pwr_opmode;
0096     bool            vbus_on;
0097 };
0098 
0099 static enum typec_role wusb3801_get_default_role(struct wusb3801 *wusb3801)
0100 {
0101     switch (wusb3801->port_type) {
0102     case TYPEC_PORT_SRC:
0103         return TYPEC_SOURCE;
0104     case TYPEC_PORT_SNK:
0105         return TYPEC_SINK;
0106     case TYPEC_PORT_DRP:
0107     default:
0108         if (wusb3801->cap.prefer_role == TYPEC_SOURCE)
0109             return TYPEC_SOURCE;
0110         return TYPEC_SINK;
0111     }
0112 }
0113 
0114 static int wusb3801_map_port_type(enum typec_port_type type)
0115 {
0116     switch (type) {
0117     case TYPEC_PORT_SRC:
0118         return WUSB3801_CTRL0_ROLE_SRC;
0119     case TYPEC_PORT_SNK:
0120         return WUSB3801_CTRL0_ROLE_SNK;
0121     case TYPEC_PORT_DRP:
0122     default:
0123         return WUSB3801_CTRL0_ROLE_DRP;
0124     }
0125 }
0126 
0127 static int wusb3801_map_pwr_opmode(enum typec_pwr_opmode mode)
0128 {
0129     switch (mode) {
0130     case TYPEC_PWR_MODE_USB:
0131     default:
0132         return WUSB3801_CTRL0_CURRENT_DEFAULT;
0133     case TYPEC_PWR_MODE_1_5A:
0134         return WUSB3801_CTRL0_CURRENT_1_5A;
0135     case TYPEC_PWR_MODE_3_0A:
0136         return WUSB3801_CTRL0_CURRENT_3_0A;
0137     }
0138 }
0139 
0140 static unsigned int wusb3801_map_try_role(int role)
0141 {
0142     switch (role) {
0143     case TYPEC_NO_PREFERRED_ROLE:
0144     default:
0145         return WUSB3801_CTRL0_TRY_NONE;
0146     case TYPEC_SINK:
0147         return WUSB3801_CTRL0_TRY_SNK;
0148     case TYPEC_SOURCE:
0149         return WUSB3801_CTRL0_TRY_SRC;
0150     }
0151 }
0152 
0153 static enum typec_orientation wusb3801_unmap_orientation(unsigned int status)
0154 {
0155     switch (status & WUSB3801_STAT_ORIENTATION) {
0156     case WUSB3801_STAT_ORIENTATION_NONE:
0157     case WUSB3801_STAT_ORIENTATION_BOTH:
0158     default:
0159         return TYPEC_ORIENTATION_NONE;
0160     case WUSB3801_STAT_ORIENTATION_CC1:
0161         return TYPEC_ORIENTATION_NORMAL;
0162     case WUSB3801_STAT_ORIENTATION_CC2:
0163         return TYPEC_ORIENTATION_REVERSE;
0164     }
0165 }
0166 
0167 static enum typec_pwr_opmode wusb3801_unmap_pwr_opmode(unsigned int status)
0168 {
0169     switch (status & WUSB3801_STAT_CURRENT) {
0170     case WUSB3801_STAT_CURRENT_STANDBY:
0171     case WUSB3801_STAT_CURRENT_DEFAULT:
0172     default:
0173         return TYPEC_PWR_MODE_USB;
0174     case WUSB3801_STAT_CURRENT_1_5A:
0175         return TYPEC_PWR_MODE_1_5A;
0176     case WUSB3801_STAT_CURRENT_3_0A:
0177         return TYPEC_PWR_MODE_3_0A;
0178     }
0179 }
0180 
0181 static int wusb3801_try_role(struct typec_port *port, int role)
0182 {
0183     struct wusb3801 *wusb3801 = typec_get_drvdata(port);
0184 
0185     return regmap_update_bits(wusb3801->regmap, WUSB3801_REG_CTRL0,
0186                   WUSB3801_CTRL0_TRY,
0187                   wusb3801_map_try_role(role));
0188 }
0189 
0190 static int wusb3801_port_type_set(struct typec_port *port,
0191                   enum typec_port_type type)
0192 {
0193     struct wusb3801 *wusb3801 = typec_get_drvdata(port);
0194     int ret;
0195 
0196     ret = regmap_update_bits(wusb3801->regmap, WUSB3801_REG_CTRL0,
0197                  WUSB3801_CTRL0_ROLE,
0198                  wusb3801_map_port_type(type));
0199     if (ret)
0200         return ret;
0201 
0202     wusb3801->port_type = type;
0203 
0204     return 0;
0205 }
0206 
0207 static const struct typec_operations wusb3801_typec_ops = {
0208     .try_role   = wusb3801_try_role,
0209     .port_type_set  = wusb3801_port_type_set,
0210 };
0211 
0212 static int wusb3801_hw_init(struct wusb3801 *wusb3801)
0213 {
0214     return regmap_write(wusb3801->regmap, WUSB3801_REG_CTRL0,
0215                 wusb3801_map_try_role(wusb3801->cap.prefer_role) |
0216                 wusb3801_map_pwr_opmode(wusb3801->pwr_opmode) |
0217                 wusb3801_map_port_type(wusb3801->port_type));
0218 }
0219 
0220 static void wusb3801_hw_update(struct wusb3801 *wusb3801)
0221 {
0222     struct typec_port *port = wusb3801->port;
0223     struct device *dev = wusb3801->dev;
0224     unsigned int partner_type, status;
0225     int ret;
0226 
0227     ret = regmap_read(wusb3801->regmap, WUSB3801_REG_STAT, &status);
0228     if (ret) {
0229         dev_warn(dev, "Failed to read port status: %d\n", ret);
0230         status = 0;
0231     }
0232     dev_dbg(dev, "status = 0x%02x\n", status);
0233 
0234     partner_type = status & WUSB3801_STAT_PARTNER;
0235 
0236     if (partner_type == WUSB3801_STAT_PARTNER_SNK) {
0237         if (!wusb3801->vbus_on) {
0238             ret = regulator_enable(wusb3801->vbus_supply);
0239             if (ret)
0240                 dev_warn(dev, "Failed to enable VBUS: %d\n", ret);
0241             wusb3801->vbus_on = true;
0242         }
0243     } else {
0244         if (wusb3801->vbus_on) {
0245             regulator_disable(wusb3801->vbus_supply);
0246             wusb3801->vbus_on = false;
0247         }
0248     }
0249 
0250     if (partner_type != wusb3801->partner_type) {
0251         struct typec_partner_desc desc = {};
0252         enum typec_data_role data_role;
0253         enum typec_role pwr_role = wusb3801_get_default_role(wusb3801);
0254 
0255         switch (partner_type) {
0256         case WUSB3801_STAT_PARTNER_STANDBY:
0257             break;
0258         case WUSB3801_STAT_PARTNER_SNK:
0259             pwr_role = TYPEC_SOURCE;
0260             break;
0261         case WUSB3801_STAT_PARTNER_SRC:
0262             pwr_role = TYPEC_SINK;
0263             break;
0264         case WUSB3801_STAT_PARTNER_AUDIO:
0265             desc.accessory = TYPEC_ACCESSORY_AUDIO;
0266             break;
0267         case WUSB3801_STAT_PARTNER_DEBUG:
0268             desc.accessory = TYPEC_ACCESSORY_DEBUG;
0269             break;
0270         }
0271 
0272         if (wusb3801->partner) {
0273             typec_unregister_partner(wusb3801->partner);
0274             wusb3801->partner = NULL;
0275         }
0276 
0277         if (partner_type != WUSB3801_STAT_PARTNER_STANDBY) {
0278             wusb3801->partner = typec_register_partner(port, &desc);
0279             if (IS_ERR(wusb3801->partner))
0280                 dev_err(dev, "Failed to register partner: %ld\n",
0281                     PTR_ERR(wusb3801->partner));
0282         }
0283 
0284         data_role = pwr_role == TYPEC_SOURCE ? TYPEC_HOST : TYPEC_DEVICE;
0285         typec_set_data_role(port, data_role);
0286         typec_set_pwr_role(port, pwr_role);
0287         typec_set_vconn_role(port, pwr_role);
0288     }
0289 
0290     typec_set_pwr_opmode(wusb3801->port,
0291                  partner_type == WUSB3801_STAT_PARTNER_SRC
0292                 ? wusb3801_unmap_pwr_opmode(status)
0293                 : wusb3801->pwr_opmode);
0294     typec_set_orientation(wusb3801->port,
0295                   wusb3801_unmap_orientation(status));
0296 
0297     wusb3801->partner_type = partner_type;
0298 }
0299 
0300 static irqreturn_t wusb3801_irq(int irq, void *data)
0301 {
0302     struct wusb3801 *wusb3801 = data;
0303     unsigned int dummy;
0304 
0305     /*
0306      * The interrupt register must be read in order to clear the IRQ,
0307      * but all of the useful information is in the status register.
0308      */
0309     regmap_read(wusb3801->regmap, WUSB3801_REG_INT, &dummy);
0310 
0311     wusb3801_hw_update(wusb3801);
0312 
0313     return IRQ_HANDLED;
0314 }
0315 
0316 static const struct regmap_config config = {
0317     .reg_bits   = 8,
0318     .val_bits   = 8,
0319     .max_register   = WUSB3801_REG_TEST12,
0320 };
0321 
0322 static int wusb3801_probe(struct i2c_client *client)
0323 {
0324     struct device *dev = &client->dev;
0325     struct fwnode_handle *connector;
0326     struct wusb3801 *wusb3801;
0327     const char *cap_str;
0328     int ret;
0329 
0330     wusb3801 = devm_kzalloc(dev, sizeof(*wusb3801), GFP_KERNEL);
0331     if (!wusb3801)
0332         return -ENOMEM;
0333 
0334     i2c_set_clientdata(client, wusb3801);
0335 
0336     wusb3801->dev = dev;
0337 
0338     wusb3801->regmap = devm_regmap_init_i2c(client, &config);
0339     if (IS_ERR(wusb3801->regmap))
0340         return PTR_ERR(wusb3801->regmap);
0341 
0342     wusb3801->vbus_supply = devm_regulator_get(dev, "vbus");
0343     if (IS_ERR(wusb3801->vbus_supply))
0344         return PTR_ERR(wusb3801->vbus_supply);
0345 
0346     connector = device_get_named_child_node(dev, "connector");
0347     if (!connector)
0348         return -ENODEV;
0349 
0350     ret = typec_get_fw_cap(&wusb3801->cap, connector);
0351     if (ret)
0352         goto err_put_connector;
0353     wusb3801->port_type = wusb3801->cap.type;
0354 
0355     ret = fwnode_property_read_string(connector, "typec-power-opmode", &cap_str);
0356     if (ret)
0357         goto err_put_connector;
0358 
0359     ret = typec_find_pwr_opmode(cap_str);
0360     if (ret < 0 || ret == TYPEC_PWR_MODE_PD)
0361         goto err_put_connector;
0362     wusb3801->pwr_opmode = ret;
0363 
0364     /* Initialize the hardware with the devicetree settings. */
0365     ret = wusb3801_hw_init(wusb3801);
0366     if (ret)
0367         return ret;
0368 
0369     wusb3801->cap.revision      = USB_TYPEC_REV_1_2;
0370     wusb3801->cap.accessory[0]  = TYPEC_ACCESSORY_AUDIO;
0371     wusb3801->cap.accessory[1]  = TYPEC_ACCESSORY_DEBUG;
0372     wusb3801->cap.orientation_aware = true;
0373     wusb3801->cap.driver_data   = wusb3801;
0374     wusb3801->cap.ops       = &wusb3801_typec_ops;
0375 
0376     wusb3801->port = typec_register_port(dev, &wusb3801->cap);
0377     if (IS_ERR(wusb3801->port)) {
0378         ret = PTR_ERR(wusb3801->port);
0379         goto err_put_connector;
0380     }
0381 
0382     /* Initialize the port attributes from the hardware state. */
0383     wusb3801_hw_update(wusb3801);
0384 
0385     ret = request_threaded_irq(client->irq, NULL, wusb3801_irq,
0386                    IRQF_ONESHOT, dev_name(dev), wusb3801);
0387     if (ret)
0388         goto err_unregister_port;
0389 
0390     fwnode_handle_put(connector);
0391 
0392     return 0;
0393 
0394 err_unregister_port:
0395     typec_unregister_port(wusb3801->port);
0396 err_put_connector:
0397     fwnode_handle_put(connector);
0398 
0399     return ret;
0400 }
0401 
0402 static int wusb3801_remove(struct i2c_client *client)
0403 {
0404     struct wusb3801 *wusb3801 = i2c_get_clientdata(client);
0405 
0406     free_irq(client->irq, wusb3801);
0407 
0408     if (wusb3801->partner)
0409         typec_unregister_partner(wusb3801->partner);
0410     typec_unregister_port(wusb3801->port);
0411 
0412     if (wusb3801->vbus_on)
0413         regulator_disable(wusb3801->vbus_supply);
0414 
0415     return 0;
0416 }
0417 
0418 static const struct of_device_id wusb3801_of_match[] = {
0419     { .compatible = "willsemi,wusb3801" },
0420     {}
0421 };
0422 MODULE_DEVICE_TABLE(of, wusb3801_of_match);
0423 
0424 static struct i2c_driver wusb3801_driver = {
0425     .probe_new  = wusb3801_probe,
0426     .remove     = wusb3801_remove,
0427     .driver     = {
0428         .name       = "wusb3801",
0429         .of_match_table = wusb3801_of_match,
0430     },
0431 };
0432 
0433 module_i2c_driver(wusb3801_driver);
0434 
0435 MODULE_AUTHOR("Samuel Holland <samuel@sholland.org>");
0436 MODULE_DESCRIPTION("Willsemi WUSB3801 Type-C port controller driver");
0437 MODULE_LICENSE("GPL");