1 // SPDX-License-Identifier: GPL-2.0
3 * drivers/extcon/extcon-tusb320.c - TUSB320 extcon driver
5 * Copyright (C) 2020 National Instruments Corporation
6 * Author: Michael Auchter <michael.auchter@ni.com>
9 #include <linux/bitfield.h>
10 #include <linux/extcon-provider.h>
11 #include <linux/i2c.h>
12 #include <linux/init.h>
13 #include <linux/interrupt.h>
14 #include <linux/kernel.h>
15 #include <linux/module.h>
16 #include <linux/regmap.h>
17 #include <linux/usb/typec.h>
18 #include <linux/usb/typec_altmode.h>
19 #include <linux/usb/role.h>
20 #include <linux/irq.h>
22 #define TUSB320_REG8 0x8
23 #define TUSB320_REG8_CURRENT_MODE_ADVERTISE GENMASK(7, 6)
24 #define TUSB320_REG8_CURRENT_MODE_ADVERTISE_USB 0x0
25 #define TUSB320_REG8_CURRENT_MODE_ADVERTISE_15A 0x1
26 #define TUSB320_REG8_CURRENT_MODE_ADVERTISE_30A 0x2
27 #define TUSB320_REG8_CURRENT_MODE_DETECT GENMASK(5, 4)
28 #define TUSB320_REG8_CURRENT_MODE_DETECT_DEF 0x0
29 #define TUSB320_REG8_CURRENT_MODE_DETECT_MED 0x1
30 #define TUSB320_REG8_CURRENT_MODE_DETECT_ACC 0x2
31 #define TUSB320_REG8_CURRENT_MODE_DETECT_HI 0x3
32 #define TUSB320_REG8_ACCESSORY_CONNECTED GENMASK(3, 1)
33 #define TUSB320_REG8_ACCESSORY_CONNECTED_NONE 0x0
34 #define TUSB320_REG8_ACCESSORY_CONNECTED_AUDIO 0x4
35 #define TUSB320_REG8_ACCESSORY_CONNECTED_ACHRG 0x5
36 #define TUSB320_REG8_ACCESSORY_CONNECTED_DBGDFP 0x6
37 #define TUSB320_REG8_ACCESSORY_CONNECTED_DBGUFP 0x7
38 #define TUSB320_REG8_ACTIVE_CABLE_DETECTION BIT(0)
40 #define TUSB320_REG9 0x9
41 #define TUSB320_REG9_ATTACHED_STATE GENMASK(7, 6)
42 #define TUSB320_REG9_CABLE_DIRECTION BIT(5)
43 #define TUSB320_REG9_INTERRUPT_STATUS BIT(4)
45 #define TUSB320_REGA 0xa
46 #define TUSB320L_REGA_DISABLE_TERM BIT(0)
47 #define TUSB320_REGA_I2C_SOFT_RESET BIT(3)
48 #define TUSB320_REGA_MODE_SELECT_SHIFT 4
49 #define TUSB320_REGA_MODE_SELECT_MASK 0x3
51 #define TUSB320L_REGA0_REVISION 0xa0
53 enum tusb320_attached_state
{
54 TUSB320_ATTACHED_STATE_NONE
,
55 TUSB320_ATTACHED_STATE_DFP
,
56 TUSB320_ATTACHED_STATE_UFP
,
57 TUSB320_ATTACHED_STATE_ACC
,
70 int (*set_mode
)(struct tusb320_priv
*priv
, enum tusb320_mode mode
);
71 int (*get_revision
)(struct tusb320_priv
*priv
, unsigned int *revision
);
76 struct regmap
*regmap
;
77 struct extcon_dev
*edev
;
78 struct tusb320_ops
*ops
;
79 enum tusb320_attached_state state
;
80 struct typec_port
*port
;
81 struct typec_capability cap
;
82 enum typec_port_type port_type
;
83 enum typec_pwr_opmode pwr_opmode
;
84 struct fwnode_handle
*connector_fwnode
;
85 struct usb_role_switch
*role_sw
;
88 static const char * const tusb_attached_states
[] = {
89 [TUSB320_ATTACHED_STATE_NONE
] = "not attached",
90 [TUSB320_ATTACHED_STATE_DFP
] = "downstream facing port",
91 [TUSB320_ATTACHED_STATE_UFP
] = "upstream facing port",
92 [TUSB320_ATTACHED_STATE_ACC
] = "accessory",
95 static const unsigned int tusb320_extcon_cable
[] = {
101 static int tusb320_check_signature(struct tusb320_priv
*priv
)
103 static const char sig
[] = { '\0', 'T', 'U', 'S', 'B', '3', '2', '0' };
107 for (i
= 0; i
< sizeof(sig
); i
++) {
108 ret
= regmap_read(priv
->regmap
, sizeof(sig
) - 1 - i
, &val
);
112 dev_err(priv
->dev
, "signature mismatch!\n");
120 static int tusb320_set_mode(struct tusb320_priv
*priv
, enum tusb320_mode mode
)
124 /* Mode cannot be changed while cable is attached */
125 if (priv
->state
!= TUSB320_ATTACHED_STATE_NONE
)
129 ret
= regmap_write_bits(priv
->regmap
, TUSB320_REGA
,
130 TUSB320_REGA_MODE_SELECT_MASK
<< TUSB320_REGA_MODE_SELECT_SHIFT
,
131 mode
<< TUSB320_REGA_MODE_SELECT_SHIFT
);
133 dev_err(priv
->dev
, "failed to write mode: %d\n", ret
);
140 static int tusb320l_set_mode(struct tusb320_priv
*priv
, enum tusb320_mode mode
)
144 /* Disable CC state machine */
145 ret
= regmap_write_bits(priv
->regmap
, TUSB320_REGA
,
146 TUSB320L_REGA_DISABLE_TERM
, 1);
149 "failed to disable CC state machine: %d\n", ret
);
154 ret
= regmap_write_bits(priv
->regmap
, TUSB320_REGA
,
155 TUSB320_REGA_MODE_SELECT_MASK
<< TUSB320_REGA_MODE_SELECT_SHIFT
,
156 mode
<< TUSB320_REGA_MODE_SELECT_SHIFT
);
158 dev_err(priv
->dev
, "failed to write mode: %d\n", ret
);
164 /* Re-enable CC state machine */
165 ret
= regmap_write_bits(priv
->regmap
, TUSB320_REGA
,
166 TUSB320L_REGA_DISABLE_TERM
, 0);
169 "failed to re-enable CC state machine: %d\n", ret
);
174 static int tusb320_reset(struct tusb320_priv
*priv
)
178 /* Set mode to default (follow PORT pin) */
179 ret
= priv
->ops
->set_mode(priv
, TUSB320_MODE_PORT
);
180 if (ret
&& ret
!= -EBUSY
) {
182 "failed to set mode to PORT: %d\n", ret
);
186 /* Perform soft reset */
187 ret
= regmap_write_bits(priv
->regmap
, TUSB320_REGA
,
188 TUSB320_REGA_I2C_SOFT_RESET
, 1);
191 "failed to write soft reset bit: %d\n", ret
);
195 /* Wait for chip to go through reset */
201 static int tusb320l_get_revision(struct tusb320_priv
*priv
, unsigned int *revision
)
203 return regmap_read(priv
->regmap
, TUSB320L_REGA0_REVISION
, revision
);
206 static struct tusb320_ops tusb320_ops
= {
207 .set_mode
= tusb320_set_mode
,
210 static struct tusb320_ops tusb320l_ops
= {
211 .set_mode
= tusb320l_set_mode
,
212 .get_revision
= tusb320l_get_revision
,
215 static int tusb320_set_adv_pwr_mode(struct tusb320_priv
*priv
)
219 if (priv
->pwr_opmode
== TYPEC_PWR_MODE_USB
)
220 mode
= TUSB320_REG8_CURRENT_MODE_ADVERTISE_USB
;
221 else if (priv
->pwr_opmode
== TYPEC_PWR_MODE_1_5A
)
222 mode
= TUSB320_REG8_CURRENT_MODE_ADVERTISE_15A
;
223 else if (priv
->pwr_opmode
== TYPEC_PWR_MODE_3_0A
)
224 mode
= TUSB320_REG8_CURRENT_MODE_ADVERTISE_30A
;
225 else /* No other mode is supported. */
228 return regmap_write_bits(priv
->regmap
, TUSB320_REG8
,
229 TUSB320_REG8_CURRENT_MODE_ADVERTISE
,
230 FIELD_PREP(TUSB320_REG8_CURRENT_MODE_ADVERTISE
,
234 static int tusb320_port_type_set(struct typec_port
*port
,
235 enum typec_port_type type
)
237 struct tusb320_priv
*priv
= typec_get_drvdata(port
);
239 if (type
== TYPEC_PORT_SRC
)
240 return priv
->ops
->set_mode(priv
, TUSB320_MODE_DFP
);
241 else if (type
== TYPEC_PORT_SNK
)
242 return priv
->ops
->set_mode(priv
, TUSB320_MODE_UFP
);
243 else if (type
== TYPEC_PORT_DRP
)
244 return priv
->ops
->set_mode(priv
, TUSB320_MODE_DRP
);
246 return priv
->ops
->set_mode(priv
, TUSB320_MODE_PORT
);
249 static const struct typec_operations tusb320_typec_ops
= {
250 .port_type_set
= tusb320_port_type_set
,
253 static void tusb320_extcon_irq_handler(struct tusb320_priv
*priv
, u8 reg
)
257 state
= FIELD_GET(TUSB320_REG9_ATTACHED_STATE
, reg
);
258 polarity
= !!(reg
& TUSB320_REG9_CABLE_DIRECTION
);
260 dev_dbg(priv
->dev
, "attached state: %s, polarity: %d\n",
261 tusb_attached_states
[state
], polarity
);
263 extcon_set_state(priv
->edev
, EXTCON_USB
,
264 state
== TUSB320_ATTACHED_STATE_UFP
);
265 extcon_set_state(priv
->edev
, EXTCON_USB_HOST
,
266 state
== TUSB320_ATTACHED_STATE_DFP
);
267 extcon_set_property(priv
->edev
, EXTCON_USB
,
268 EXTCON_PROP_USB_TYPEC_POLARITY
,
269 (union extcon_property_value
)polarity
);
270 extcon_set_property(priv
->edev
, EXTCON_USB_HOST
,
271 EXTCON_PROP_USB_TYPEC_POLARITY
,
272 (union extcon_property_value
)polarity
);
273 extcon_sync(priv
->edev
, EXTCON_USB
);
274 extcon_sync(priv
->edev
, EXTCON_USB_HOST
);
279 static void tusb320_typec_irq_handler(struct tusb320_priv
*priv
, u8 reg9
)
281 struct typec_port
*port
= priv
->port
;
282 struct device
*dev
= priv
->dev
;
284 enum usb_role usb_role
;
285 enum typec_role pwr_role
;
286 enum typec_data_role data_role
;
287 u8 state
, mode
, accessory
;
291 ret
= regmap_read(priv
->regmap
, TUSB320_REG8
, ®8
);
293 dev_err(dev
, "error during reg8 i2c read, ret=%d!\n", ret
);
297 ori
= reg9
& TUSB320_REG9_CABLE_DIRECTION
;
298 typec_set_orientation(port
, ori
? TYPEC_ORIENTATION_REVERSE
:
299 TYPEC_ORIENTATION_NORMAL
);
301 state
= FIELD_GET(TUSB320_REG9_ATTACHED_STATE
, reg9
);
302 accessory
= FIELD_GET(TUSB320_REG8_ACCESSORY_CONNECTED
, reg8
);
305 case TUSB320_ATTACHED_STATE_DFP
:
306 typec_mode
= TYPEC_MODE_USB2
;
307 usb_role
= USB_ROLE_HOST
;
308 pwr_role
= TYPEC_SOURCE
;
309 data_role
= TYPEC_HOST
;
311 case TUSB320_ATTACHED_STATE_UFP
:
312 typec_mode
= TYPEC_MODE_USB2
;
313 usb_role
= USB_ROLE_DEVICE
;
314 pwr_role
= TYPEC_SINK
;
315 data_role
= TYPEC_DEVICE
;
317 case TUSB320_ATTACHED_STATE_ACC
:
319 * Accessory detected. For debug accessories, just make some
320 * qualified guesses as to the role for lack of a better option.
322 if (accessory
== TUSB320_REG8_ACCESSORY_CONNECTED_AUDIO
||
323 accessory
== TUSB320_REG8_ACCESSORY_CONNECTED_ACHRG
) {
324 typec_mode
= TYPEC_MODE_AUDIO
;
325 usb_role
= USB_ROLE_NONE
;
326 pwr_role
= TYPEC_SINK
;
327 data_role
= TYPEC_DEVICE
;
329 } else if (accessory
==
330 TUSB320_REG8_ACCESSORY_CONNECTED_DBGDFP
) {
331 typec_mode
= TYPEC_MODE_DEBUG
;
332 pwr_role
= TYPEC_SOURCE
;
333 usb_role
= USB_ROLE_HOST
;
334 data_role
= TYPEC_HOST
;
336 } else if (accessory
==
337 TUSB320_REG8_ACCESSORY_CONNECTED_DBGUFP
) {
338 typec_mode
= TYPEC_MODE_DEBUG
;
339 pwr_role
= TYPEC_SINK
;
340 usb_role
= USB_ROLE_DEVICE
;
341 data_role
= TYPEC_DEVICE
;
345 dev_warn(priv
->dev
, "unexpected ACCESSORY_CONNECTED state %d\n",
350 typec_mode
= TYPEC_MODE_USB2
;
351 usb_role
= USB_ROLE_NONE
;
352 pwr_role
= TYPEC_SINK
;
353 data_role
= TYPEC_DEVICE
;
357 typec_set_vconn_role(port
, pwr_role
);
358 typec_set_pwr_role(port
, pwr_role
);
359 typec_set_data_role(port
, data_role
);
360 typec_set_mode(port
, typec_mode
);
361 usb_role_switch_set_role(priv
->role_sw
, usb_role
);
363 mode
= FIELD_GET(TUSB320_REG8_CURRENT_MODE_DETECT
, reg8
);
364 if (mode
== TUSB320_REG8_CURRENT_MODE_DETECT_DEF
)
365 typec_set_pwr_opmode(port
, TYPEC_PWR_MODE_USB
);
366 else if (mode
== TUSB320_REG8_CURRENT_MODE_DETECT_MED
)
367 typec_set_pwr_opmode(port
, TYPEC_PWR_MODE_1_5A
);
368 else if (mode
== TUSB320_REG8_CURRENT_MODE_DETECT_HI
)
369 typec_set_pwr_opmode(port
, TYPEC_PWR_MODE_3_0A
);
370 else /* Charge through accessory */
371 typec_set_pwr_opmode(port
, TYPEC_PWR_MODE_USB
);
374 static irqreturn_t
tusb320_state_update_handler(struct tusb320_priv
*priv
,
379 if (regmap_read(priv
->regmap
, TUSB320_REG9
, ®
)) {
380 dev_err(priv
->dev
, "error during i2c read!\n");
384 if (!force_update
&& !(reg
& TUSB320_REG9_INTERRUPT_STATUS
))
387 tusb320_extcon_irq_handler(priv
, reg
);
390 * Type-C support is optional. Only call the Type-C handler if a
391 * port had been registered previously.
394 tusb320_typec_irq_handler(priv
, reg
);
396 regmap_write(priv
->regmap
, TUSB320_REG9
, reg
);
401 static irqreturn_t
tusb320_irq_handler(int irq
, void *dev_id
)
403 struct tusb320_priv
*priv
= dev_id
;
405 return tusb320_state_update_handler(priv
, false);
408 static const struct regmap_config tusb320_regmap_config
= {
413 static int tusb320_extcon_probe(struct tusb320_priv
*priv
)
417 priv
->edev
= devm_extcon_dev_allocate(priv
->dev
, tusb320_extcon_cable
);
418 if (IS_ERR(priv
->edev
)) {
419 dev_err(priv
->dev
, "failed to allocate extcon device\n");
420 return PTR_ERR(priv
->edev
);
423 ret
= devm_extcon_dev_register(priv
->dev
, priv
->edev
);
425 dev_err(priv
->dev
, "failed to register extcon device\n");
429 extcon_set_property_capability(priv
->edev
, EXTCON_USB
,
430 EXTCON_PROP_USB_TYPEC_POLARITY
);
431 extcon_set_property_capability(priv
->edev
, EXTCON_USB_HOST
,
432 EXTCON_PROP_USB_TYPEC_POLARITY
);
437 static int tusb320_typec_probe(struct i2c_client
*client
,
438 struct tusb320_priv
*priv
)
440 struct fwnode_handle
*connector
;
444 /* The Type-C connector is optional, for backward compatibility. */
445 connector
= device_get_named_child_node(&client
->dev
, "connector");
449 /* Type-C connector found. */
450 ret
= typec_get_fw_cap(&priv
->cap
, connector
);
454 priv
->port_type
= priv
->cap
.type
;
456 /* This goes into register 0x8 field CURRENT_MODE_ADVERTISE */
457 ret
= fwnode_property_read_string(connector
, "typec-power-opmode", &cap_str
);
461 ret
= typec_find_pwr_opmode(cap_str
);
465 priv
->pwr_opmode
= ret
;
467 /* Initialize the hardware with the devicetree settings. */
468 ret
= tusb320_set_adv_pwr_mode(priv
);
472 priv
->cap
.revision
= USB_TYPEC_REV_1_1
;
473 priv
->cap
.accessory
[0] = TYPEC_ACCESSORY_AUDIO
;
474 priv
->cap
.accessory
[1] = TYPEC_ACCESSORY_DEBUG
;
475 priv
->cap
.orientation_aware
= true;
476 priv
->cap
.driver_data
= priv
;
477 priv
->cap
.ops
= &tusb320_typec_ops
;
478 priv
->cap
.fwnode
= connector
;
480 priv
->port
= typec_register_port(&client
->dev
, &priv
->cap
);
481 if (IS_ERR(priv
->port
)) {
482 ret
= PTR_ERR(priv
->port
);
486 /* Find any optional USB role switch that needs reporting to */
487 priv
->role_sw
= fwnode_usb_role_switch_get(connector
);
488 if (IS_ERR(priv
->role_sw
)) {
489 ret
= PTR_ERR(priv
->role_sw
);
493 priv
->connector_fwnode
= connector
;
498 typec_unregister_port(priv
->port
);
501 fwnode_handle_put(connector
);
506 static void tusb320_typec_remove(struct tusb320_priv
*priv
)
508 usb_role_switch_put(priv
->role_sw
);
509 typec_unregister_port(priv
->port
);
510 fwnode_handle_put(priv
->connector_fwnode
);
513 static int tusb320_probe(struct i2c_client
*client
)
515 struct tusb320_priv
*priv
;
516 const void *match_data
;
517 unsigned int revision
;
519 u32 irq_trigger_type
= IRQF_TRIGGER_FALLING
;
520 struct irq_data
*irq_d
;
522 priv
= devm_kzalloc(&client
->dev
, sizeof(*priv
), GFP_KERNEL
);
526 priv
->dev
= &client
->dev
;
527 i2c_set_clientdata(client
, priv
);
529 priv
->regmap
= devm_regmap_init_i2c(client
, &tusb320_regmap_config
);
530 if (IS_ERR(priv
->regmap
))
531 return PTR_ERR(priv
->regmap
);
533 ret
= tusb320_check_signature(priv
);
537 match_data
= device_get_match_data(&client
->dev
);
541 priv
->ops
= (struct tusb320_ops
*)match_data
;
543 if (priv
->ops
->get_revision
) {
544 ret
= priv
->ops
->get_revision(priv
, &revision
);
547 "failed to read revision register: %d\n", ret
);
549 dev_info(priv
->dev
, "chip revision %d\n", revision
);
552 ret
= tusb320_extcon_probe(priv
);
556 ret
= tusb320_typec_probe(client
, priv
);
560 /* update initial state */
561 tusb320_state_update_handler(priv
, true);
563 /* Reset chip to its default state */
564 ret
= tusb320_reset(priv
);
566 dev_warn(priv
->dev
, "failed to reset chip: %d\n", ret
);
569 * State and polarity might change after a reset, so update
570 * them again and make sure the interrupt status bit is cleared.
572 tusb320_state_update_handler(priv
, true);
574 irq_d
= irq_get_irq_data(client
->irq
);
576 irq_trigger_type
= irqd_get_trigger_type(irq_d
);
578 ret
= devm_request_threaded_irq(priv
->dev
, client
->irq
, NULL
,
580 IRQF_ONESHOT
| irq_trigger_type
,
583 tusb320_typec_remove(priv
);
588 static void tusb320_remove(struct i2c_client
*client
)
590 struct tusb320_priv
*priv
= i2c_get_clientdata(client
);
592 tusb320_typec_remove(priv
);
595 static const struct of_device_id tusb320_extcon_dt_match
[] = {
596 { .compatible
= "ti,tusb320", .data
= &tusb320_ops
, },
597 { .compatible
= "ti,tusb320l", .data
= &tusb320l_ops
, },
600 MODULE_DEVICE_TABLE(of
, tusb320_extcon_dt_match
);
602 static struct i2c_driver tusb320_extcon_driver
= {
603 .probe
= tusb320_probe
,
604 .remove
= tusb320_remove
,
606 .name
= "extcon-tusb320",
607 .of_match_table
= tusb320_extcon_dt_match
,
611 static int __init
tusb320_init(void)
613 return i2c_add_driver(&tusb320_extcon_driver
);
615 subsys_initcall(tusb320_init
);
617 static void __exit
tusb320_exit(void)
619 i2c_del_driver(&tusb320_extcon_driver
);
621 module_exit(tusb320_exit
);
623 MODULE_AUTHOR("Michael Auchter <michael.auchter@ni.com>");
624 MODULE_DESCRIPTION("TI TUSB320 extcon driver");
625 MODULE_LICENSE("GPL v2");