FILE
hd3ss3220.c
File preview with syntax highlighting.
linux-6.19.14/drivers/usb/typec/hd3ss3220.c
1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * TI HD3SS3220 Type-C DRP Port Controller Driver 4 * 5 * Copyright (C) 2019 Renesas Electronics Corp. 6 */ 7 8#include <linux/module.h> 9#include <linux/i2c.h> 10#include <linux/usb/role.h> 11#include <linux/irqreturn.h> 12#include <linux/interrupt.h> 13#include <linux/regmap.h> 14#include <linux/slab.h> 15#include <linux/usb/typec.h> 16#include <linux/delay.h> 17#include <linux/workqueue.h> 18#include <linux/gpio/consumer.h> 19#include <linux/regulator/consumer.h> 20#include <linux/of_graph.h> 21 22#define HD3SS3220_REG_CN_STAT 0x08 23#define HD3SS3220_REG_CN_STAT_CTRL 0x09 24#define HD3SS3220_REG_GEN_CTRL 0x0A 25#define HD3SS3220_REG_DEV_REV 0xA0 26 27/* Register HD3SS3220_REG_CN_STAT */ 28#define HD3SS3220_REG_CN_STAT_CURRENT_MODE_MASK (BIT(7) | BIT(6)) 29#define HD3SS3220_REG_CN_STAT_CURRENT_MODE_DEFAULT 0x00 30#define HD3SS3220_REG_CN_STAT_CURRENT_MODE_MID BIT(6) 31#define HD3SS3220_REG_CN_STAT_CURRENT_MODE_HIGH BIT(7) 32 33/* Register HD3SS3220_REG_CN_STAT_CTRL*/ 34#define HD3SS3220_REG_CN_STAT_CTRL_ATTACHED_STATE_MASK (BIT(7) | BIT(6)) 35#define HD3SS3220_REG_CN_STAT_CTRL_AS_DFP BIT(6) 36#define HD3SS3220_REG_CN_STAT_CTRL_AS_UFP BIT(7) 37#define HD3SS3220_REG_CN_STAT_CTRL_TO_ACCESSORY (BIT(7) | BIT(6)) 38#define HD3SS3220_REG_CN_STAT_CTRL_INT_STATUS BIT(4) 39 40/* Register HD3SS3220_REG_GEN_CTRL*/ 41#define HD3SS3220_REG_GEN_CTRL_DISABLE_TERM BIT(0) 42#define HD3SS3220_REG_GEN_CTRL_SRC_PREF_MASK (BIT(2) | BIT(1)) 43#define HD3SS3220_REG_GEN_CTRL_SRC_PREF_DRP_DEFAULT 0x00 44#define HD3SS3220_REG_GEN_CTRL_SRC_PREF_DRP_TRY_SNK BIT(1) 45#define HD3SS3220_REG_GEN_CTRL_SRC_PREF_DRP_TRY_SRC (BIT(2) | BIT(1)) 46#define HD3SS3220_REG_GEN_CTRL_MODE_SELECT_MASK (BIT(5) | BIT(4)) 47#define HD3SS3220_REG_GEN_CTRL_MODE_SELECT_DEFAULT 0x00 48#define HD3SS3220_REG_GEN_CTRL_MODE_SELECT_DFP BIT(5) 49#define HD3SS3220_REG_GEN_CTRL_MODE_SELECT_UFP BIT(4) 50#define HD3SS3220_REG_GEN_CTRL_MODE_SELECT_DRP (BIT(5) | BIT(4)) 51 52struct hd3ss3220 { 53 struct device *dev; 54 struct regmap *regmap; 55 struct usb_role_switch *role_sw; 56 struct typec_port *port; 57 struct delayed_work output_poll_work; 58 enum usb_role role_state; 59 bool poll; 60 61 struct gpio_desc *id_gpiod; 62 int id_irq; 63 64 struct regulator *vbus; 65}; 66 67static int hd3ss3220_set_power_opmode(struct hd3ss3220 *hd3ss3220, int power_opmode) 68{ 69 int current_mode; 70 71 switch (power_opmode) { 72 case TYPEC_PWR_MODE_USB: 73 current_mode = HD3SS3220_REG_CN_STAT_CURRENT_MODE_DEFAULT; 74 break; 75 case TYPEC_PWR_MODE_1_5A: 76 current_mode = HD3SS3220_REG_CN_STAT_CURRENT_MODE_MID; 77 break; 78 case TYPEC_PWR_MODE_3_0A: 79 current_mode = HD3SS3220_REG_CN_STAT_CURRENT_MODE_HIGH; 80 break; 81 case TYPEC_PWR_MODE_PD: /* Power delivery not supported */ 82 default: 83 dev_err(hd3ss3220->dev, "bad power operation mode: %d\n", power_opmode); 84 return -EINVAL; 85 } 86 87 return regmap_update_bits(hd3ss3220->regmap, HD3SS3220_REG_CN_STAT, 88 HD3SS3220_REG_CN_STAT_CURRENT_MODE_MASK, 89 current_mode); 90} 91 92static int hd3ss3220_set_port_type(struct hd3ss3220 *hd3ss3220, int type) 93{ 94 int mode_select, err; 95 96 switch (type) { 97 case TYPEC_PORT_SRC: 98 mode_select = HD3SS3220_REG_GEN_CTRL_MODE_SELECT_DFP; 99 break; 100 case TYPEC_PORT_SNK: 101 mode_select = HD3SS3220_REG_GEN_CTRL_MODE_SELECT_UFP; 102 break; 103 case TYPEC_PORT_DRP: 104 mode_select = HD3SS3220_REG_GEN_CTRL_MODE_SELECT_DRP; 105 break; 106 default: 107 dev_err(hd3ss3220->dev, "bad port type: %d\n", type); 108 return -EINVAL; 109 } 110 111 /* Disable termination before changing MODE_SELECT as required by datasheet */ 112 err = regmap_update_bits(hd3ss3220->regmap, HD3SS3220_REG_GEN_CTRL, 113 HD3SS3220_REG_GEN_CTRL_DISABLE_TERM, 114 HD3SS3220_REG_GEN_CTRL_DISABLE_TERM); 115 if (err < 0) { 116 dev_err(hd3ss3220->dev, "Failed to disable port for mode change: %d\n", err); 117 return err; 118 } 119 120 err = regmap_update_bits(hd3ss3220->regmap, HD3SS3220_REG_GEN_CTRL, 121 HD3SS3220_REG_GEN_CTRL_MODE_SELECT_MASK, 122 mode_select); 123 if (err < 0) { 124 dev_err(hd3ss3220->dev, "Failed to change mode: %d\n", err); 125 regmap_update_bits(hd3ss3220->regmap, HD3SS3220_REG_GEN_CTRL, 126 HD3SS3220_REG_GEN_CTRL_DISABLE_TERM, 0); 127 return err; 128 } 129 130 err = regmap_update_bits(hd3ss3220->regmap, HD3SS3220_REG_GEN_CTRL, 131 HD3SS3220_REG_GEN_CTRL_DISABLE_TERM, 0); 132 if (err < 0) 133 dev_err(hd3ss3220->dev, "Failed to re-enable port after mode change: %d\n", err); 134 135 return err; 136} 137 138static int hd3ss3220_set_source_pref(struct hd3ss3220 *hd3ss3220, int prefer_role) 139{ 140 int src_pref; 141 142 switch (prefer_role) { 143 case TYPEC_NO_PREFERRED_ROLE: 144 src_pref = HD3SS3220_REG_GEN_CTRL_SRC_PREF_DRP_DEFAULT; 145 break; 146 case TYPEC_SINK: 147 src_pref = HD3SS3220_REG_GEN_CTRL_SRC_PREF_DRP_TRY_SNK; 148 break; 149 case TYPEC_SOURCE: 150 src_pref = HD3SS3220_REG_GEN_CTRL_SRC_PREF_DRP_TRY_SRC; 151 break; 152 default: 153 dev_err(hd3ss3220->dev, "bad role preference: %d\n", prefer_role); 154 return -EINVAL; 155 } 156 157 return regmap_update_bits(hd3ss3220->regmap, HD3SS3220_REG_GEN_CTRL, 158 HD3SS3220_REG_GEN_CTRL_SRC_PREF_MASK, 159 src_pref); 160} 161 162static enum usb_role hd3ss3220_get_attached_state(struct hd3ss3220 *hd3ss3220) 163{ 164 unsigned int reg_val; 165 enum usb_role attached_state; 166 int ret; 167 168 ret = regmap_read(hd3ss3220->regmap, HD3SS3220_REG_CN_STAT_CTRL, 169 ®_val); 170 if (ret < 0) 171 return ret; 172 173 switch (reg_val & HD3SS3220_REG_CN_STAT_CTRL_ATTACHED_STATE_MASK) { 174 case HD3SS3220_REG_CN_STAT_CTRL_AS_DFP: 175 attached_state = USB_ROLE_HOST; 176 break; 177 case HD3SS3220_REG_CN_STAT_CTRL_AS_UFP: 178 attached_state = USB_ROLE_DEVICE; 179 break; 180 default: 181 attached_state = USB_ROLE_NONE; 182 break; 183 } 184 185 return attached_state; 186} 187 188static int hd3ss3220_try_role(struct typec_port *port, int role) 189{ 190 struct hd3ss3220 *hd3ss3220 = typec_get_drvdata(port); 191 192 return hd3ss3220_set_source_pref(hd3ss3220, role); 193} 194 195static int hd3ss3220_port_type_set(struct typec_port *port, enum typec_port_type type) 196{ 197 struct hd3ss3220 *hd3ss3220 = typec_get_drvdata(port); 198 199 return hd3ss3220_set_port_type(hd3ss3220, type); 200} 201 202static const struct typec_operations hd3ss3220_ops = { 203 .try_role = hd3ss3220_try_role, 204 .port_type_set = hd3ss3220_port_type_set, 205}; 206 207static void hd3ss3220_set_role(struct hd3ss3220 *hd3ss3220) 208{ 209 enum usb_role role_state = hd3ss3220_get_attached_state(hd3ss3220); 210 211 usb_role_switch_set_role(hd3ss3220->role_sw, role_state); 212 213 switch (role_state) { 214 case USB_ROLE_HOST: 215 typec_set_data_role(hd3ss3220->port, TYPEC_HOST); 216 break; 217 case USB_ROLE_DEVICE: 218 typec_set_data_role(hd3ss3220->port, TYPEC_DEVICE); 219 break; 220 default: 221 break; 222 } 223 224 hd3ss3220->role_state = role_state; 225} 226 227static void output_poll_execute(struct work_struct *work) 228{ 229 struct delayed_work *delayed_work = to_delayed_work(work); 230 struct hd3ss3220 *hd3ss3220 = container_of(delayed_work, 231 struct hd3ss3220, 232 output_poll_work); 233 enum usb_role role_state = hd3ss3220_get_attached_state(hd3ss3220); 234 235 if (hd3ss3220->role_state != role_state) 236 hd3ss3220_set_role(hd3ss3220); 237 238 schedule_delayed_work(&hd3ss3220->output_poll_work, HZ); 239} 240 241static irqreturn_t hd3ss3220_irq(struct hd3ss3220 *hd3ss3220) 242{ 243 int err; 244 245 hd3ss3220_set_role(hd3ss3220); 246 err = regmap_write_bits(hd3ss3220->regmap, HD3SS3220_REG_CN_STAT_CTRL, 247 HD3SS3220_REG_CN_STAT_CTRL_INT_STATUS, 248 HD3SS3220_REG_CN_STAT_CTRL_INT_STATUS); 249 if (err < 0) 250 return IRQ_NONE; 251 252 return IRQ_HANDLED; 253} 254 255static irqreturn_t hd3ss3220_irq_handler(int irq, void *data) 256{ 257 struct i2c_client *client = to_i2c_client(data); 258 struct hd3ss3220 *hd3ss3220 = i2c_get_clientdata(client); 259 260 return hd3ss3220_irq(hd3ss3220); 261} 262 263static int hd3ss3220_configure_power_opmode(struct hd3ss3220 *hd3ss3220, 264 struct fwnode_handle *connector) 265{ 266 /* 267 * Supported power operation mode can be configured through device tree 268 */ 269 const char *cap_str; 270 int ret, power_opmode; 271 272 ret = fwnode_property_read_string(connector, "typec-power-opmode", &cap_str); 273 if (ret) 274 return 0; 275 276 power_opmode = typec_find_pwr_opmode(cap_str); 277 return hd3ss3220_set_power_opmode(hd3ss3220, power_opmode); 278} 279 280static int hd3ss3220_configure_port_type(struct hd3ss3220 *hd3ss3220, 281 struct fwnode_handle *connector, 282 struct typec_capability *cap) 283{ 284 /* 285 * Port type can be configured through device tree 286 */ 287 const char *cap_str; 288 int ret; 289 290 ret = fwnode_property_read_string(connector, "power-role", &cap_str); 291 if (ret) 292 return 0; 293 294 ret = typec_find_port_power_role(cap_str); 295 if (ret < 0) 296 return ret; 297 298 cap->type = ret; 299 return hd3ss3220_set_port_type(hd3ss3220, cap->type); 300} 301 302static int hd3ss3220_configure_source_pref(struct hd3ss3220 *hd3ss3220, 303 struct fwnode_handle *connector, 304 struct typec_capability *cap) 305{ 306 /* 307 * Preferred role can be configured through device tree 308 */ 309 const char *cap_str; 310 int ret; 311 312 ret = fwnode_property_read_string(connector, "try-power-role", &cap_str); 313 if (ret) 314 return 0; 315 316 ret = typec_find_power_role(cap_str); 317 if (ret < 0) 318 return ret; 319 320 cap->prefer_role = ret; 321 return hd3ss3220_set_source_pref(hd3ss3220, cap->prefer_role); 322} 323 324static const struct regmap_config config = { 325 .reg_bits = 8, 326 .val_bits = 8, 327 .max_register = 0x0A, 328}; 329 330static irqreturn_t hd3ss3220_id_isr(int irq, void *dev_id) 331{ 332 struct hd3ss3220 *hd3ss3220 = dev_id; 333 int ret; 334 int id; 335 336 id = gpiod_get_value_cansleep(hd3ss3220->id_gpiod); 337 if (!id) 338 ret = regulator_enable(hd3ss3220->vbus); 339 else 340 ret = regulator_disable(hd3ss3220->vbus); 341 342 if (ret) 343 dev_err(hd3ss3220->dev, 344 "vbus regulator %s failed: %d\n", id ? "disable" : "enable", ret); 345 346 return IRQ_HANDLED; 347} 348 349static int hd3ss3220_probe(struct i2c_client *client) 350{ 351 struct typec_capability typec_cap = { }; 352 struct fwnode_handle *connector, *ep; 353 struct hd3ss3220 *hd3ss3220; 354 struct regulator *vbus; 355 unsigned int data; 356 int ret; 357 358 hd3ss3220 = devm_kzalloc(&client->dev, sizeof(struct hd3ss3220), 359 GFP_KERNEL); 360 if (!hd3ss3220) 361 return -ENOMEM; 362 363 i2c_set_clientdata(client, hd3ss3220); 364 365 hd3ss3220->dev = &client->dev; 366 hd3ss3220->regmap = devm_regmap_init_i2c(client, &config); 367 if (IS_ERR(hd3ss3220->regmap)) 368 return PTR_ERR(hd3ss3220->regmap); 369 370 /* For backward compatibility check the connector child node first */ 371 connector = device_get_named_child_node(hd3ss3220->dev, "connector"); 372 if (connector) { 373 hd3ss3220->role_sw = fwnode_usb_role_switch_get(connector); 374 } else { 375 ep = fwnode_graph_get_next_endpoint(dev_fwnode(hd3ss3220->dev), NULL); 376 if (!ep) 377 return -ENODEV; 378 connector = fwnode_graph_get_remote_port_parent(ep); 379 fwnode_handle_put(ep); 380 if (!connector) 381 return -ENODEV; 382 hd3ss3220->role_sw = usb_role_switch_get(hd3ss3220->dev); 383 } 384 385 if (IS_ERR(hd3ss3220->role_sw)) { 386 ret = PTR_ERR(hd3ss3220->role_sw); 387 goto err_put_fwnode; 388 } 389 390 vbus = devm_of_regulator_get_optional(hd3ss3220->dev, 391 to_of_node(connector), 392 "vbus"); 393 if (IS_ERR(vbus) && vbus != ERR_PTR(-ENODEV)) { 394 ret = PTR_ERR(vbus); 395 dev_err(hd3ss3220->dev, "failed to get vbus: %d", ret); 396 goto err_put_fwnode; 397 } 398 399 hd3ss3220->vbus = (vbus == ERR_PTR(-ENODEV) ? NULL : vbus); 400 401 if (hd3ss3220->vbus) { 402 hd3ss3220->id_gpiod = devm_gpiod_get_optional(hd3ss3220->dev, 403 "id", 404 GPIOD_IN); 405 if (IS_ERR(hd3ss3220->id_gpiod)) { 406 ret = PTR_ERR(hd3ss3220->id_gpiod); 407 goto err_put_fwnode; 408 } 409 } 410 411 if (hd3ss3220->id_gpiod) { 412 hd3ss3220->id_irq = gpiod_to_irq(hd3ss3220->id_gpiod); 413 if (hd3ss3220->id_irq < 0) { 414 ret = hd3ss3220->id_irq; 415 dev_err(hd3ss3220->dev, 416 "failed to get ID gpio: %d\n", 417 hd3ss3220->id_irq); 418 goto err_put_fwnode; 419 } 420 421 ret = devm_request_threaded_irq(hd3ss3220->dev, 422 hd3ss3220->id_irq, NULL, 423 hd3ss3220_id_isr, 424 IRQF_TRIGGER_RISING | 425 IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 426 dev_name(hd3ss3220->dev), hd3ss3220); 427 if (ret < 0) { 428 dev_err(hd3ss3220->dev, "failed to get ID irq: %d\n", ret); 429 goto err_put_fwnode; 430 } 431 } 432 433 typec_cap.prefer_role = TYPEC_NO_PREFERRED_ROLE; 434 typec_cap.driver_data = hd3ss3220; 435 typec_cap.type = TYPEC_PORT_DRP; 436 typec_cap.data = TYPEC_PORT_DRD; 437 typec_cap.ops = &hd3ss3220_ops; 438 typec_cap.fwnode = connector; 439 440 ret = hd3ss3220_configure_source_pref(hd3ss3220, connector, &typec_cap); 441 if (ret < 0) 442 goto err_put_role; 443 444 ret = hd3ss3220_configure_port_type(hd3ss3220, connector, &typec_cap); 445 if (ret < 0) 446 goto err_put_role; 447 448 hd3ss3220->port = typec_register_port(&client->dev, &typec_cap); 449 if (IS_ERR(hd3ss3220->port)) { 450 ret = PTR_ERR(hd3ss3220->port); 451 goto err_put_role; 452 } 453 454 ret = hd3ss3220_configure_power_opmode(hd3ss3220, connector); 455 if (ret < 0) 456 goto err_unreg_port; 457 458 hd3ss3220_set_role(hd3ss3220); 459 ret = regmap_read(hd3ss3220->regmap, HD3SS3220_REG_CN_STAT_CTRL, &data); 460 if (ret < 0) 461 goto err_unreg_port; 462 463 if (data & HD3SS3220_REG_CN_STAT_CTRL_INT_STATUS) { 464 ret = regmap_write(hd3ss3220->regmap, 465 HD3SS3220_REG_CN_STAT_CTRL, 466 data | HD3SS3220_REG_CN_STAT_CTRL_INT_STATUS); 467 if (ret < 0) 468 goto err_unreg_port; 469 } 470 471 if (client->irq > 0) { 472 ret = devm_request_threaded_irq(&client->dev, client->irq, NULL, 473 hd3ss3220_irq_handler, 474 IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 475 "hd3ss3220", &client->dev); 476 if (ret) 477 goto err_unreg_port; 478 } else { 479 INIT_DELAYED_WORK(&hd3ss3220->output_poll_work, output_poll_execute); 480 hd3ss3220->poll = true; 481 } 482 483 ret = i2c_smbus_read_byte_data(client, HD3SS3220_REG_DEV_REV); 484 if (ret < 0) 485 goto err_unreg_port; 486 487 fwnode_handle_put(connector); 488 489 if (hd3ss3220->poll) 490 schedule_delayed_work(&hd3ss3220->output_poll_work, HZ); 491 492 dev_info(&client->dev, "probed revision=0x%x\n", ret); 493 494 return 0; 495err_unreg_port: 496 typec_unregister_port(hd3ss3220->port); 497err_put_role: 498 usb_role_switch_put(hd3ss3220->role_sw); 499err_put_fwnode: 500 fwnode_handle_put(connector); 501 502 return ret; 503} 504 505static void hd3ss3220_remove(struct i2c_client *client) 506{ 507 struct hd3ss3220 *hd3ss3220 = i2c_get_clientdata(client); 508 509 if (hd3ss3220->poll) 510 cancel_delayed_work_sync(&hd3ss3220->output_poll_work); 511 512 typec_unregister_port(hd3ss3220->port); 513 usb_role_switch_put(hd3ss3220->role_sw); 514} 515 516static const struct of_device_id dev_ids[] = { 517 { .compatible = "ti,hd3ss3220"}, 518 {} 519}; 520MODULE_DEVICE_TABLE(of, dev_ids); 521 522static struct i2c_driver hd3ss3220_driver = { 523 .driver = { 524 .name = "hd3ss3220", 525 .of_match_table = dev_ids, 526 }, 527 .probe = hd3ss3220_probe, 528 .remove = hd3ss3220_remove, 529}; 530 531module_i2c_driver(hd3ss3220_driver); 532 533MODULE_AUTHOR("Biju Das <biju.das@bp.renesas.com>"); 534MODULE_DESCRIPTION("TI HD3SS3220 DRP Port Controller Driver"); 535MODULE_LICENSE("GPL");
~/
Read-only file preview.