Skip to content

Commit 90530cb

Browse files
recalcikartben
authored andcommitted
usbc: add generic TCPCI related functions
Add generic functions that will be common to all TCPCI compliant drivers. Signed-off-by: Jianxiong Gu <[email protected]>
1 parent f4da9b9 commit 90530cb

File tree

3 files changed

+386
-2
lines changed

3 files changed

+386
-2
lines changed

drivers/usb_c/tcpc/tcpci.c

Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,3 +446,239 @@ int tcpci_tcpm_get_cc(const struct i2c_dt_spec *bus, enum tc_cc_voltage_state *c
446446

447447
return 0;
448448
}
449+
450+
int tcpci_tcpm_get_chip_info(const struct i2c_dt_spec *bus, struct tcpc_chip_info *chip_info)
451+
{
452+
int ret;
453+
454+
if (chip_info == NULL) {
455+
return -EIO;
456+
}
457+
458+
ret = tcpci_read_reg16(bus, TCPC_REG_VENDOR_ID, &chip_info->vendor_id);
459+
if (ret != 0) {
460+
return ret;
461+
}
462+
463+
ret = tcpci_read_reg16(bus, TCPC_REG_PRODUCT_ID, &chip_info->product_id);
464+
if (ret != 0) {
465+
return ret;
466+
}
467+
468+
return tcpci_read_reg16(bus, TCPC_REG_BCD_DEV, &chip_info->device_id);
469+
}
470+
471+
int tcpci_tcpm_dump_std_reg(const struct i2c_dt_spec *bus)
472+
{
473+
uint16_t value;
474+
475+
for (unsigned int a = 0; a < ARRAY_SIZE(tcpci_std_regs); a++) {
476+
switch (tcpci_std_regs[a].size) {
477+
case 1:
478+
tcpci_read_reg8(bus, tcpci_std_regs[a].addr, (uint8_t *)&value);
479+
LOG_INF("- %-30s(0x%02x) = 0x%02x", tcpci_std_regs[a].name,
480+
tcpci_std_regs[a].addr, (uint8_t)value);
481+
break;
482+
case 2:
483+
tcpci_read_reg16(bus, tcpci_std_regs[a].addr, &value);
484+
LOG_INF("- %-30s(0x%02x) = 0x%04x", tcpci_std_regs[a].name,
485+
tcpci_std_regs[a].addr, value);
486+
break;
487+
}
488+
}
489+
490+
return 0;
491+
}
492+
493+
int tcpci_tcpm_set_bist_test_mode(const struct i2c_dt_spec *bus, bool enable)
494+
{
495+
return tcpci_update_reg8(bus, TCPC_REG_TCPC_CTRL, TCPC_REG_TCPC_CTRL_BIST_TEST_MODE,
496+
enable ? TCPC_REG_TCPC_CTRL_BIST_TEST_MODE : 0);
497+
}
498+
499+
int tcpci_tcpm_transmit_data(const struct i2c_dt_spec *bus, struct pd_msg *msg,
500+
const uint8_t retries)
501+
{
502+
int reg = TCPC_REG_TX_BUFFER;
503+
int rv;
504+
int cnt = 4 * msg->header.number_of_data_objects;
505+
506+
/* If not SOP* transmission, just write to the transmit register */
507+
if (msg->header.message_type >= NUM_SOP_STAR_TYPES) {
508+
/*
509+
* Per TCPCI spec, do not specify retry (although the TCPC
510+
* should ignore retry field for these 3 types).
511+
*/
512+
return tcpci_write_reg8(
513+
bus, TCPC_REG_TRANSMIT,
514+
TCPC_REG_TRANSMIT_SET_WITHOUT_RETRY(msg->header.message_type));
515+
}
516+
517+
if (cnt > 0) {
518+
reg = TCPC_REG_TX_BUFFER;
519+
/* TX_BYTE_CNT includes extra bytes for message header */
520+
cnt += sizeof(msg->header.raw_value);
521+
522+
struct i2c_msg buf[3];
523+
524+
uint8_t tmp[2] = {TCPC_REG_TX_BUFFER, cnt};
525+
526+
buf[0].buf = tmp;
527+
buf[0].len = 2;
528+
buf[0].flags = I2C_MSG_WRITE;
529+
530+
buf[1].buf = (uint8_t *)&msg->header.raw_value;
531+
buf[1].len = sizeof(msg->header.raw_value);
532+
buf[1].flags = I2C_MSG_WRITE;
533+
534+
buf[2].buf = (uint8_t *)msg->data;
535+
buf[2].len = msg->len;
536+
buf[2].flags = I2C_MSG_WRITE | I2C_MSG_STOP;
537+
538+
if (cnt > sizeof(msg->header.raw_value)) {
539+
rv = i2c_transfer(bus->bus, buf, 3, bus->addr);
540+
} else {
541+
buf[1].flags |= I2C_MSG_STOP;
542+
rv = i2c_transfer(bus->bus, buf, 2, bus->addr);
543+
}
544+
545+
/* If tcpc write fails, return error */
546+
if (rv) {
547+
return rv;
548+
}
549+
}
550+
551+
/*
552+
* We always retry in TCPC hardware since the TCPM is too slow to
553+
* respond within tRetry (~195 usec).
554+
*
555+
* The retry count used is dependent on the maximum PD revision
556+
* supported at build time.
557+
*/
558+
rv = tcpci_write_reg8(bus, TCPC_REG_TRANSMIT,
559+
TCPC_REG_TRANSMIT_SET_WITH_RETRY(retries, msg->type));
560+
561+
return rv;
562+
}
563+
564+
int tcpci_tcpm_select_rp_value(const struct i2c_dt_spec *bus, enum tc_rp_value rp)
565+
{
566+
return tcpci_update_reg8(bus, TCPC_REG_ROLE_CTRL, TCPC_REG_ROLE_CTRL_RP_MASK,
567+
TCPC_REG_ROLE_CTRL_SET(0, rp, 0, 0));
568+
}
569+
570+
int tcpci_tcpm_get_rp_value(const struct i2c_dt_spec *bus, enum tc_rp_value *rp)
571+
{
572+
uint8_t reg_value = 0;
573+
int ret;
574+
575+
ret = tcpci_read_reg8(bus, TCPC_REG_ROLE_CTRL, &reg_value);
576+
*rp = TCPC_REG_ROLE_CTRL_RP(reg_value);
577+
578+
return ret;
579+
}
580+
581+
int tcpci_tcpm_set_cc(const struct i2c_dt_spec *bus, enum tc_cc_pull pull)
582+
{
583+
return tcpci_update_reg8(bus, TCPC_REG_ROLE_CTRL,
584+
TCPC_REG_ROLE_CTRL_CC1_MASK | TCPC_REG_ROLE_CTRL_CC2_MASK,
585+
TCPC_REG_ROLE_CTRL_SET(0, 0, pull, pull));
586+
}
587+
588+
int tcpci_tcpm_set_vconn(const struct i2c_dt_spec *bus, bool enable)
589+
{
590+
return tcpci_update_reg8(bus, TCPC_REG_POWER_CTRL, TCPC_REG_POWER_CTRL_VCONN_EN,
591+
enable ? TCPC_REG_POWER_CTRL_VCONN_EN : 0);
592+
}
593+
594+
int tcpci_tcpm_set_roles(const struct i2c_dt_spec *bus, enum pd_rev_type pd_rev,
595+
enum tc_power_role power_role, enum tc_data_role data_role)
596+
{
597+
return tcpci_update_reg8(bus, TCPC_REG_MSG_HDR_INFO, TCPC_REG_MSG_HDR_INFO_ROLES_MASK,
598+
TCPC_REG_MSG_HDR_INFO_SET(pd_rev, data_role, power_role));
599+
}
600+
601+
int tcpci_tcpm_set_drp_toggle(const struct i2c_dt_spec *bus, bool enable)
602+
{
603+
return tcpci_update_reg8(bus, TCPC_REG_ROLE_CTRL, TCPC_REG_ROLE_CTRL_DRP_MASK,
604+
TCPC_REG_ROLE_CTRL_SET(enable, 0, 0, 0));
605+
}
606+
607+
int tcpci_tcpm_set_rx_type(const struct i2c_dt_spec *bus, uint8_t rx_type)
608+
{
609+
return tcpci_write_reg8(bus, TCPC_REG_RX_DETECT, rx_type);
610+
}
611+
612+
int tcpci_tcpm_set_cc_polarity(const struct i2c_dt_spec *bus, enum tc_cc_polarity polarity)
613+
{
614+
return tcpci_update_reg8(
615+
bus, TCPC_REG_TCPC_CTRL, TCPC_REG_TCPC_CTRL_PLUG_ORIENTATION,
616+
(polarity == TC_POLARITY_CC1) ? 0 : TCPC_REG_TCPC_CTRL_PLUG_ORIENTATION);
617+
}
618+
619+
int tcpci_tcpm_get_status_register(const struct i2c_dt_spec *bus, enum tcpc_status_reg reg,
620+
uint16_t *status)
621+
{
622+
switch (reg) {
623+
case TCPC_ALERT_STATUS:
624+
return tcpci_read_reg16(bus, TCPC_REG_ALERT, status);
625+
case TCPC_CC_STATUS:
626+
return tcpci_read_reg16(bus, TCPC_REG_CC_STATUS, status);
627+
case TCPC_POWER_STATUS:
628+
return tcpci_read_reg8(bus, TCPC_REG_POWER_STATUS, (uint8_t *)status);
629+
case TCPC_FAULT_STATUS:
630+
return tcpci_read_reg8(bus, TCPC_REG_FAULT_STATUS, (uint8_t *)status);
631+
case TCPC_EXTENDED_STATUS:
632+
return tcpci_read_reg8(bus, TCPC_REG_EXT_STATUS, (uint8_t *)status);
633+
case TCPC_EXTENDED_ALERT_STATUS:
634+
return tcpci_read_reg8(bus, TCPC_REG_ALERT_EXT, (uint8_t *)status);
635+
default:
636+
LOG_ERR("Not a TCPCI-specified reg address");
637+
return -EINVAL;
638+
}
639+
}
640+
641+
int tcpci_tcpm_clear_status_register(const struct i2c_dt_spec *bus, enum tcpc_status_reg reg,
642+
uint16_t mask)
643+
{
644+
switch (reg) {
645+
case TCPC_ALERT_STATUS:
646+
return tcpci_write_reg16(bus, TCPC_REG_ALERT, mask);
647+
case TCPC_CC_STATUS:
648+
return tcpci_write_reg16(bus, TCPC_REG_CC_STATUS, mask);
649+
case TCPC_POWER_STATUS:
650+
return tcpci_write_reg8(bus, TCPC_REG_POWER_STATUS, (uint8_t)mask);
651+
case TCPC_FAULT_STATUS:
652+
return tcpci_write_reg8(bus, TCPC_REG_FAULT_STATUS, (uint8_t)mask);
653+
case TCPC_EXTENDED_STATUS:
654+
return tcpci_write_reg8(bus, TCPC_REG_EXT_STATUS, (uint8_t)mask);
655+
case TCPC_EXTENDED_ALERT_STATUS:
656+
return tcpci_write_reg8(bus, TCPC_REG_ALERT_EXT, (uint8_t)mask);
657+
default:
658+
LOG_ERR("Not a TCPCI-specified reg address");
659+
return -EINVAL;
660+
}
661+
}
662+
663+
int tcpci_tcpm_mask_status_register(const struct i2c_dt_spec *bus, enum tcpc_status_reg reg,
664+
uint16_t mask)
665+
{
666+
switch (reg) {
667+
case TCPC_ALERT_STATUS:
668+
return tcpci_write_reg16(bus, TCPC_REG_ALERT_MASK, mask);
669+
case TCPC_CC_STATUS:
670+
LOG_ERR("CC_STATUS does not have a corresponding mask register");
671+
return -EINVAL;
672+
case TCPC_POWER_STATUS:
673+
return tcpci_write_reg8(bus, TCPC_REG_POWER_STATUS_MASK, (uint8_t)mask);
674+
case TCPC_FAULT_STATUS:
675+
return tcpci_write_reg8(bus, TCPC_REG_FAULT_STATUS_MASK, (uint8_t)mask);
676+
case TCPC_EXTENDED_STATUS:
677+
return tcpci_write_reg8(bus, TCPC_REG_EXT_STATUS_MASK, (uint8_t)mask);
678+
case TCPC_EXTENDED_ALERT_STATUS:
679+
return tcpci_write_reg8(bus, TCPC_REG_ALERT_EXT_MASK, (uint8_t)mask);
680+
default:
681+
LOG_ERR("Not a TCPCI-specified reg address");
682+
return -EINVAL;
683+
}
684+
}

0 commit comments

Comments
 (0)