1// SPDX-License-Identifier: GPL-2.0 2/* 3 * ITE IT5205 Type-C USB alternate mode passive mux 4 * 5 * Copyright (c) 2020 MediaTek Inc. 6 * Copyright (c) 2024 Collabora Ltd. 7 * AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> 8 * 9 */ 10 11#include <linux/delay.h> 12#include <linux/i2c.h> 13#include <linux/kernel.h> 14#include <linux/module.h> 15#include <linux/of_platform.h> 16#include <linux/platform_device.h> 17#include <linux/regmap.h> 18#include <linux/regulator/consumer.h> 19#include <linux/usb/tcpm.h> 20#include <linux/usb/typec.h> 21#include <linux/usb/typec_dp.h> 22#include <linux/usb/typec_mux.h> 23 24#define IT5205_REG_CHIP_ID(x) (0x4 + (x)) 25#define IT5205FN_CHIP_ID 0x35303235 /* "5025" -> "5205" */ 26 27/* MUX power down register */ 28#define IT5205_REG_MUXPDR 0x10 29#define IT5205_MUX_POWER_DOWN BIT(0) 30 31/* MUX control register */ 32#define IT5205_REG_MUXCR 0x11 33#define IT5205_POLARITY_INVERTED BIT(4) 34#define IT5205_DP_USB_CTRL_MASK GENMASK(3, 0) 35#define IT5205_DP 0x0f 36#define IT5205_DP_USB 0x03 37#define IT5205_USB 0x07 38 39/* Vref Select Register */ 40#define IT5205_REG_VSR 0x10 41#define IT5205_VREF_SELECT_MASK GENMASK(5, 4) 42#define IT5205_VREF_SELECT_3_3V 0x00 43#define IT5205_VREF_SELECT_OFF 0x20 44 45/* CSBU Over Voltage Protection Register */ 46#define IT5205_REG_CSBUOVPSR 0x1e 47#define IT5205_OVP_SELECT_MASK GENMASK(5, 4) 48#define IT5205_OVP_3_90V 0x00 49#define IT5205_OVP_3_68V 0x10 50#define IT5205_OVP_3_62V 0x20 51#define IT5205_OVP_3_57V 0x30 52 53/* CSBU Switch Register */ 54#define IT5205_REG_CSBUSR 0x22 55#define IT5205_CSBUSR_SWITCH BIT(0) 56 57/* Interrupt Switch Register */ 58#define IT5205_REG_ISR 0x25 59#define IT5205_ISR_CSBU_MASK BIT(4) 60#define IT5205_ISR_CSBU_OVP BIT(0) 61 62struct it5205 { 63 struct i2c_client *client; 64 struct regmap *regmap; 65 struct typec_switch_dev *sw; 66 struct typec_mux_dev *mux; 67}; 68 69static int it5205_switch_set(struct typec_switch_dev *sw, enum typec_orientation orientation) 70{ 71 struct it5205 *it = typec_switch_get_drvdata(sw); 72 73 switch (orientation) { 74 case TYPEC_ORIENTATION_NORMAL: 75 regmap_update_bits(it->regmap, IT5205_REG_MUXCR, 76 IT5205_POLARITY_INVERTED, 0); 77 break; 78 case TYPEC_ORIENTATION_REVERSE: 79 regmap_update_bits(it->regmap, IT5205_REG_MUXCR, 80 IT5205_POLARITY_INVERTED, IT5205_POLARITY_INVERTED); 81 break; 82 case TYPEC_ORIENTATION_NONE: 83 fallthrough; 84 default: 85 regmap_write(it->regmap, IT5205_REG_MUXCR, 0); 86 break; 87 } 88 89 return 0; 90} 91 92static int it5205_mux_set(struct typec_mux_dev *mux, struct typec_mux_state *state) 93{ 94 struct it5205 *it = typec_mux_get_drvdata(mux); 95 u8 val; 96 97 if (state->mode >= TYPEC_STATE_MODAL && 98 state->alt->svid != USB_TYPEC_DP_SID) 99 return -EINVAL; 100 101 switch (state->mode) { 102 case TYPEC_STATE_USB: 103 val = IT5205_USB; 104 break; 105 case TYPEC_DP_STATE_C: 106 fallthrough; 107 case TYPEC_DP_STATE_E: 108 val = IT5205_DP; 109 break; 110 case TYPEC_DP_STATE_D: 111 val = IT5205_DP_USB; 112 break; 113 case TYPEC_STATE_SAFE: 114 fallthrough; 115 default: 116 val = 0; 117 break; 118 } 119 120 return regmap_update_bits(it->regmap, IT5205_REG_MUXCR, 121 IT5205_DP_USB_CTRL_MASK, val); 122} 123 124static irqreturn_t it5205_irq_handler(int irq, void *data) 125{ 126 struct it5205 *it = data; 127 int ret; 128 u32 val; 129 130 ret = regmap_read(it->regmap, IT5205_REG_ISR, &val); 131 if (ret) 132 return IRQ_NONE; 133 134 if (val & IT5205_ISR_CSBU_OVP) { 135 dev_warn(&it->client->dev, "Overvoltage detected!\n"); 136 137 /* Reset CSBU */ 138 regmap_update_bits(it->regmap, IT5205_REG_CSBUSR, 139 IT5205_CSBUSR_SWITCH, 0); 140 regmap_update_bits(it->regmap, IT5205_REG_CSBUSR, 141 IT5205_CSBUSR_SWITCH, IT5205_CSBUSR_SWITCH); 142 } 143 144 return IRQ_HANDLED; 145} 146 147static void it5205_enable_ovp(struct it5205 *it) 148{ 149 /* Select Vref 3.3v */ 150 regmap_update_bits(it->regmap, IT5205_REG_VSR, 151 IT5205_VREF_SELECT_MASK, IT5205_VREF_SELECT_3_3V); 152 153 /* Trigger OVP at 3.68V */ 154 regmap_update_bits(it->regmap, IT5205_REG_CSBUOVPSR, 155 IT5205_OVP_SELECT_MASK, IT5205_OVP_3_68V); 156 157 /* Unmask OVP interrupt */ 158 regmap_update_bits(it->regmap, IT5205_REG_ISR, 159 IT5205_ISR_CSBU_MASK, 0); 160 161 /* Enable CSBU Interrupt */ 162 regmap_update_bits(it->regmap, IT5205_REG_CSBUSR, 163 IT5205_CSBUSR_SWITCH, IT5205_CSBUSR_SWITCH); 164} 165 166static const struct regmap_config it5205_regmap = { 167 .max_register = 0x2f, 168 .reg_bits = 8, 169 .val_bits = 8, 170}; 171 172static int it5205_probe(struct i2c_client *client) 173{ 174 struct typec_switch_desc sw_desc = { }; 175 struct typec_mux_desc mux_desc = { }; 176 struct device *dev = &client->dev; 177 struct it5205 *it; 178 u32 val, chipid = 0; 179 int i, ret; 180 181 it = devm_kzalloc(dev, sizeof(*it), GFP_KERNEL); 182 if (!it) 183 return -ENOMEM; 184 185 ret = devm_regulator_get_enable(dev, "vcc"); 186 if (ret) 187 return dev_err_probe(dev, ret, "Failed to get regulator\n"); 188 189 it->client = client; 190 191 it->regmap = devm_regmap_init_i2c(client, &it5205_regmap); 192 if (IS_ERR(it->regmap)) 193 return dev_err_probe(dev, PTR_ERR(it->regmap), 194 "Failed to init regmap\n"); 195 196 /* IT5205 needs a long time to power up after enabling regulator */ 197 msleep(50); 198 199 /* Unset poweroff bit */ 200 ret = regmap_write(it->regmap, IT5205_REG_MUXPDR, 0); 201 if (ret) 202 return dev_err_probe(dev, ret, "Failed to set power on\n"); 203 204 /* Read the 32 bits ChipID */ 205 for (i = 3; i >= 0; i--) { 206 ret = regmap_read(it->regmap, IT5205_REG_CHIP_ID(i), &val); 207 if (ret) 208 return ret; 209 210 chipid |= val << (i * 8); 211 } 212 213 if (chipid != IT5205FN_CHIP_ID) 214 return dev_err_probe(dev, -EINVAL, 215 "Unknown ChipID 0x%x\n", chipid); 216 217 /* Initialize as USB mode with default (non-inverted) polarity */ 218 ret = regmap_write(it->regmap, IT5205_REG_MUXCR, IT5205_USB); 219 if (ret) 220 return dev_err_probe(dev, ret, "Cannot set mode to USB\n"); 221 222 sw_desc.drvdata = it; 223 sw_desc.fwnode = dev_fwnode(dev); 224 sw_desc.set = it5205_switch_set; 225 226 it->sw = typec_switch_register(dev, &sw_desc); 227 if (IS_ERR(it->sw)) 228 return dev_err_probe(dev, PTR_ERR(it->sw), 229 "failed to register typec switch\n"); 230 231 mux_desc.drvdata = it; 232 mux_desc.fwnode = dev_fwnode(dev); 233 mux_desc.set = it5205_mux_set; 234 235 it->mux = typec_mux_register(dev, &mux_desc); 236 if (IS_ERR(it->mux)) { 237 typec_switch_unregister(it->sw); 238 return dev_err_probe(dev, PTR_ERR(it->mux), 239 "failed to register typec mux\n"); 240 } 241 242 i2c_set_clientdata(client, it); 243 244 if (of_property_read_bool(dev->of_node, "ite,ovp-enable") && client->irq) { 245 it5205_enable_ovp(it); 246 247 ret = devm_request_threaded_irq(dev, client->irq, NULL, 248 it5205_irq_handler, 249 IRQF_ONESHOT, dev_name(dev), it); 250 if (ret) { 251 typec_mux_unregister(it->mux); 252 typec_switch_unregister(it->sw); 253 return dev_err_probe(dev, ret, "Failed to request irq\n"); 254 } 255 } 256 257 return 0; 258} 259 260static void it5205_remove(struct i2c_client *client) 261{ 262 struct it5205 *it = i2c_get_clientdata(client); 263 264 typec_mux_unregister(it->mux); 265 typec_switch_unregister(it->sw); 266} 267 268static const struct i2c_device_id it5205_table[] = { 269 { "it5205" }, 270 { /* sentinel */ } 271}; 272MODULE_DEVICE_TABLE(i2c, it5205_table); 273 274static const struct of_device_id it5205_of_table[] = { 275 { .compatible = "ite,it5205" }, 276 { /* sentinel */ } 277}; 278MODULE_DEVICE_TABLE(of, it5205_of_table); 279 280static struct i2c_driver it5205_driver = { 281 .driver = { 282 .name = "it5205", 283 .of_match_table = it5205_of_table, 284 }, 285 .probe = it5205_probe, 286 .remove = it5205_remove, 287 .id_table = it5205_table, 288}; 289module_i2c_driver(it5205_driver); 290 291MODULE_AUTHOR("Tianping Fang <tianping.fang@mediatek.com>"); 292MODULE_AUTHOR("AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>"); 293MODULE_DESCRIPTION("ITE IT5205 alternate mode passive MUX driver"); 294MODULE_LICENSE("GPL"); 295