Skip to content

Commit 8f94390

Browse files
ShuFan Leegregkh
authored andcommitted
staging: typec: handle vendor defined part and modify drp toggling flow
Handle vendor defined behavior in tcpci_init, tcpci_set_vconn, tcpci_start_drp_toggling and export tcpci_irq. More operations can be extended in tcpci_data if needed. According to TCPCI specification, 4.4.5.2 ROLE_CONTROL, TCPC shall not start DRP toggling until subsequently the TCPM writes to the COMMAND register to start DRP toggling. DRP toggling flow is changed as following: - Write DRP = 1, Rp level and RC.CCx to Rd/Rd or Rp/Rp - Set LOOK4CONNECTION command Signed-off-by: ShuFan Lee <[email protected]> Reviewed-by: Guenter Roeck <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent b27560e commit 8f94390

File tree

2 files changed

+116
-26
lines changed

2 files changed

+116
-26
lines changed

drivers/staging/typec/tcpci.c

Lines changed: 101 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121

2222
struct tcpci {
2323
struct device *dev;
24-
struct i2c_client *client;
2524

2625
struct tcpm_port *port;
2726

@@ -30,15 +29,20 @@ struct tcpci {
3029
bool controls_vbus;
3130

3231
struct tcpc_dev tcpc;
32+
struct tcpci_data *data;
33+
};
34+
35+
struct tcpci_chip {
36+
struct tcpci *tcpci;
37+
struct tcpci_data data;
3338
};
3439

3540
static inline struct tcpci *tcpc_to_tcpci(struct tcpc_dev *tcpc)
3641
{
3742
return container_of(tcpc, struct tcpci, tcpc);
3843
}
3944

40-
static int tcpci_read16(struct tcpci *tcpci, unsigned int reg,
41-
u16 *val)
45+
static int tcpci_read16(struct tcpci *tcpci, unsigned int reg, u16 *val)
4246
{
4347
return regmap_raw_read(tcpci->regmap, reg, val, sizeof(u16));
4448
}
@@ -98,9 +102,17 @@ static int tcpci_set_cc(struct tcpc_dev *tcpc, enum typec_cc_status cc)
98102
static int tcpci_start_drp_toggling(struct tcpc_dev *tcpc,
99103
enum typec_cc_status cc)
100104
{
105+
int ret;
101106
struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
102107
unsigned int reg = TCPC_ROLE_CTRL_DRP;
103108

109+
/* Handle vendor drp toggling */
110+
if (tcpci->data->start_drp_toggling) {
111+
ret = tcpci->data->start_drp_toggling(tcpci, tcpci->data, cc);
112+
if (ret < 0)
113+
return ret;
114+
}
115+
104116
switch (cc) {
105117
default:
106118
case TYPEC_CC_RP_DEF:
@@ -117,7 +129,17 @@ static int tcpci_start_drp_toggling(struct tcpc_dev *tcpc,
117129
break;
118130
}
119131

120-
return regmap_write(tcpci->regmap, TCPC_ROLE_CTRL, reg);
132+
if (cc == TYPEC_CC_RD)
133+
reg |= (TCPC_ROLE_CTRL_CC_RD << TCPC_ROLE_CTRL_CC1_SHIFT) |
134+
(TCPC_ROLE_CTRL_CC_RD << TCPC_ROLE_CTRL_CC2_SHIFT);
135+
else
136+
reg |= (TCPC_ROLE_CTRL_CC_RP << TCPC_ROLE_CTRL_CC1_SHIFT) |
137+
(TCPC_ROLE_CTRL_CC_RP << TCPC_ROLE_CTRL_CC2_SHIFT);
138+
ret = regmap_write(tcpci->regmap, TCPC_ROLE_CTRL, reg);
139+
if (ret < 0)
140+
return ret;
141+
return regmap_write(tcpci->regmap, TCPC_COMMAND,
142+
TCPC_CMD_LOOK4CONNECTION);
121143
}
122144

123145
static enum typec_cc_status tcpci_to_typec_cc(unsigned int cc, bool sink)
@@ -178,6 +200,13 @@ static int tcpci_set_vconn(struct tcpc_dev *tcpc, bool enable)
178200
struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
179201
int ret;
180202

203+
/* Handle vendor set vconn */
204+
if (tcpci->data->set_vconn) {
205+
ret = tcpci->data->set_vconn(tcpci, tcpci->data, enable);
206+
if (ret < 0)
207+
return ret;
208+
}
209+
181210
ret = regmap_write(tcpci->regmap, TCPC_POWER_CTRL,
182211
enable ? TCPC_POWER_CTRL_VCONN_ENABLE : 0);
183212
if (ret < 0)
@@ -323,6 +352,13 @@ static int tcpci_init(struct tcpc_dev *tcpc)
323352
if (time_after(jiffies, timeout))
324353
return -ETIMEDOUT;
325354

355+
/* Handle vendor init */
356+
if (tcpci->data->init) {
357+
ret = tcpci->data->init(tcpci, tcpci->data);
358+
if (ret < 0)
359+
return ret;
360+
}
361+
326362
/* Clear all events */
327363
ret = tcpci_write16(tcpci, TCPC_ALERT, 0xffff);
328364
if (ret < 0)
@@ -344,9 +380,8 @@ static int tcpci_init(struct tcpc_dev *tcpc)
344380
return tcpci_write16(tcpci, TCPC_ALERT_MASK, reg);
345381
}
346382

347-
static irqreturn_t tcpci_irq(int irq, void *dev_id)
383+
irqreturn_t tcpci_irq(struct tcpci *tcpci)
348384
{
349-
struct tcpci *tcpci = dev_id;
350385
u16 status;
351386

352387
tcpci_read16(tcpci, TCPC_ALERT, &status);
@@ -412,6 +447,14 @@ static irqreturn_t tcpci_irq(int irq, void *dev_id)
412447

413448
return IRQ_HANDLED;
414449
}
450+
EXPORT_SYMBOL_GPL(tcpci_irq);
451+
452+
static irqreturn_t _tcpci_irq(int irq, void *dev_id)
453+
{
454+
struct tcpci *tcpci = dev_id;
455+
456+
return tcpci_irq(tcpci);
457+
}
415458

416459
static const struct regmap_config tcpci_regmap_config = {
417460
.reg_bits = 8,
@@ -435,22 +478,18 @@ static int tcpci_parse_config(struct tcpci *tcpci)
435478
return 0;
436479
}
437480

438-
static int tcpci_probe(struct i2c_client *client,
439-
const struct i2c_device_id *i2c_id)
481+
struct tcpci *tcpci_register_port(struct device *dev, struct tcpci_data *data)
440482
{
441483
struct tcpci *tcpci;
442484
int err;
443485

444-
tcpci = devm_kzalloc(&client->dev, sizeof(*tcpci), GFP_KERNEL);
486+
tcpci = devm_kzalloc(dev, sizeof(*tcpci), GFP_KERNEL);
445487
if (!tcpci)
446-
return -ENOMEM;
488+
return ERR_PTR(-ENOMEM);
447489

448-
tcpci->client = client;
449-
tcpci->dev = &client->dev;
450-
i2c_set_clientdata(client, tcpci);
451-
tcpci->regmap = devm_regmap_init_i2c(client, &tcpci_regmap_config);
452-
if (IS_ERR(tcpci->regmap))
453-
return PTR_ERR(tcpci->regmap);
490+
tcpci->dev = dev;
491+
tcpci->data = data;
492+
tcpci->regmap = data->regmap;
454493

455494
tcpci->tcpc.init = tcpci_init;
456495
tcpci->tcpc.get_vbus = tcpci_get_vbus;
@@ -467,27 +506,63 @@ static int tcpci_probe(struct i2c_client *client,
467506

468507
err = tcpci_parse_config(tcpci);
469508
if (err < 0)
470-
return err;
509+
return ERR_PTR(err);
510+
511+
tcpci->port = tcpm_register_port(tcpci->dev, &tcpci->tcpc);
512+
if (PTR_ERR_OR_ZERO(tcpci->port))
513+
return ERR_CAST(tcpci->port);
514+
515+
return tcpci;
516+
}
517+
EXPORT_SYMBOL_GPL(tcpci_register_port);
518+
519+
void tcpci_unregister_port(struct tcpci *tcpci)
520+
{
521+
tcpm_unregister_port(tcpci->port);
522+
}
523+
EXPORT_SYMBOL_GPL(tcpci_unregister_port);
524+
525+
static int tcpci_probe(struct i2c_client *client,
526+
const struct i2c_device_id *i2c_id)
527+
{
528+
struct tcpci_chip *chip;
529+
int err;
530+
u16 val = 0;
471531

472-
/* Disable chip interrupts */
473-
tcpci_write16(tcpci, TCPC_ALERT_MASK, 0);
532+
chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
533+
if (!chip)
534+
return -ENOMEM;
535+
536+
chip->data.regmap = devm_regmap_init_i2c(client, &tcpci_regmap_config);
537+
if (IS_ERR(chip->data.regmap))
538+
return PTR_ERR(chip->data.regmap);
474539

475-
err = devm_request_threaded_irq(tcpci->dev, client->irq, NULL,
476-
tcpci_irq,
540+
/* Disable chip interrupts before requesting irq */
541+
err = regmap_raw_write(chip->data.regmap, TCPC_ALERT_MASK, &val,
542+
sizeof(u16));
543+
if (err < 0)
544+
return err;
545+
546+
err = devm_request_threaded_irq(&client->dev, client->irq, NULL,
547+
_tcpci_irq,
477548
IRQF_ONESHOT | IRQF_TRIGGER_LOW,
478-
dev_name(tcpci->dev), tcpci);
549+
dev_name(&client->dev), chip);
479550
if (err < 0)
480551
return err;
481552

482-
tcpci->port = tcpm_register_port(tcpci->dev, &tcpci->tcpc);
483-
return PTR_ERR_OR_ZERO(tcpci->port);
553+
chip->tcpci = tcpci_register_port(&client->dev, &chip->data);
554+
if (PTR_ERR_OR_ZERO(chip->tcpci))
555+
return PTR_ERR(chip->tcpci);
556+
557+
i2c_set_clientdata(client, chip);
558+
return 0;
484559
}
485560

486561
static int tcpci_remove(struct i2c_client *client)
487562
{
488-
struct tcpci *tcpci = i2c_get_clientdata(client);
563+
struct tcpci_chip *chip = i2c_get_clientdata(client);
489564

490-
tcpm_unregister_port(tcpci->port);
565+
tcpci_unregister_port(chip->tcpci);
491566

492567
return 0;
493568
}

drivers/staging/typec/tcpci.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
#define TCPC_POWER_CTRL_VCONN_ENABLE BIT(0)
6060

6161
#define TCPC_CC_STATUS 0x1d
62+
#define TCPC_CC_STATUS_DRPRST BIT(5)
6263
#define TCPC_CC_STATUS_TERM BIT(4)
6364
#define TCPC_CC_STATUS_CC2_SHIFT 2
6465
#define TCPC_CC_STATUS_CC2_MASK 0x3
@@ -121,4 +122,18 @@
121122
#define TCPC_VBUS_VOLTAGE_ALARM_HI_CFG 0x76
122123
#define TCPC_VBUS_VOLTAGE_ALARM_LO_CFG 0x78
123124

125+
struct tcpci;
126+
struct tcpci_data {
127+
struct regmap *regmap;
128+
int (*init)(struct tcpci *tcpci, struct tcpci_data *data);
129+
int (*set_vconn)(struct tcpci *tcpci, struct tcpci_data *data,
130+
bool enable);
131+
int (*start_drp_toggling)(struct tcpci *tcpci, struct tcpci_data *data,
132+
enum typec_cc_status cc);
133+
};
134+
135+
struct tcpci *tcpci_register_port(struct device *dev, struct tcpci_data *data);
136+
void tcpci_unregister_port(struct tcpci *tcpci);
137+
irqreturn_t tcpci_irq(struct tcpci *tcpci);
138+
124139
#endif /* __LINUX_USB_TCPCI_H */

0 commit comments

Comments
 (0)