Browse Source
Add generic functions that will be common to all TCPCI compliant drivers like registers reading, writing and updating. Signed-off-by: Michał Barnaś <barnas@google.com>pull/78282/head
5 changed files with 594 additions and 0 deletions
@ -0,0 +1,25 @@ |
|||||||
|
# USB-C TCPCI-compliant devices configuration options |
||||||
|
|
||||||
|
# Copyright 2024 Google LLC |
||||||
|
# SPDX-License-Identifier: Apache-2.0 |
||||||
|
|
||||||
|
config USBC_TCPC_TCPCI |
||||||
|
bool |
||||||
|
select I2C |
||||||
|
help |
||||||
|
Enable support for Type-C Port Controller Interface. |
||||||
|
This symbol should be selected by TCPCI-compliant drivers to allow the use of generic |
||||||
|
TCPCI functions for registers operations. |
||||||
|
|
||||||
|
if USBC_TCPC_TCPCI |
||||||
|
|
||||||
|
config USBC_TCPC_TCPCI_I2C_RETRIES |
||||||
|
int "I2C communication retries" |
||||||
|
default 2 |
||||||
|
help |
||||||
|
Number of I2C transaction tries that will be performed for each request. |
||||||
|
Some TCPCs are going into deep sleep mode when no charger is connected and won't respond |
||||||
|
to the i2c address immediately. If device won't respond after retries, it means that |
||||||
|
it is not responsible or is not connected. |
||||||
|
|
||||||
|
endif |
@ -0,0 +1,448 @@ |
|||||||
|
/*
|
||||||
|
* Copyright 2024 Google LLC |
||||||
|
* SPDX-License-Identifier: Apache-2.0 |
||||||
|
*/ |
||||||
|
|
||||||
|
#include <zephyr/device.h> |
||||||
|
#include <zephyr/logging/log.h> |
||||||
|
#include <zephyr/sys/util.h> |
||||||
|
#include <zephyr/kernel.h> |
||||||
|
#include <zephyr/usb_c/usbc.h> |
||||||
|
#include <zephyr/usb_c/tcpci.h> |
||||||
|
#include <zephyr/sys/byteorder.h> |
||||||
|
#include <zephyr/drivers/usb_c/tcpci_priv.h> |
||||||
|
|
||||||
|
LOG_MODULE_REGISTER(tcpci, CONFIG_USBC_LOG_LEVEL); |
||||||
|
|
||||||
|
#define LOG_COMM_ERR_STR "Can't communicate with TCPC %s@%x (%s %x = %04x)" |
||||||
|
|
||||||
|
const struct tcpci_reg_dump_map tcpci_std_regs[TCPCI_STD_REGS_SIZE] = { |
||||||
|
{ |
||||||
|
.addr = TCPC_REG_VENDOR_ID, |
||||||
|
.name = "VENDOR_ID", |
||||||
|
.size = 2, |
||||||
|
}, |
||||||
|
{ |
||||||
|
.addr = TCPC_REG_PRODUCT_ID, |
||||||
|
.name = "PRODUCT_ID", |
||||||
|
.size = 2, |
||||||
|
}, |
||||||
|
{ |
||||||
|
.addr = TCPC_REG_BCD_DEV, |
||||||
|
.name = "DEVICE_ID", |
||||||
|
.size = 2, |
||||||
|
}, |
||||||
|
{ |
||||||
|
.addr = TCPC_REG_TC_REV, |
||||||
|
.name = "USBTYPEC_REV", |
||||||
|
.size = 2, |
||||||
|
}, |
||||||
|
{ |
||||||
|
.addr = TCPC_REG_PD_REV, |
||||||
|
.name = "USBPD_REV_VER", |
||||||
|
.size = 2, |
||||||
|
}, |
||||||
|
{ |
||||||
|
.addr = TCPC_REG_PD_INT_REV, |
||||||
|
.name = "PD_INTERFACE_REV", |
||||||
|
.size = 2, |
||||||
|
}, |
||||||
|
{ |
||||||
|
.addr = TCPC_REG_ALERT, |
||||||
|
.name = "ALERT", |
||||||
|
.size = 2, |
||||||
|
}, |
||||||
|
{ |
||||||
|
.addr = TCPC_REG_ALERT_MASK, |
||||||
|
.name = "ALERT_MASK", |
||||||
|
.size = 2, |
||||||
|
}, |
||||||
|
{ |
||||||
|
.addr = TCPC_REG_POWER_STATUS_MASK, |
||||||
|
.name = "POWER_STATUS_MASK", |
||||||
|
.size = 1, |
||||||
|
}, |
||||||
|
{ |
||||||
|
.addr = TCPC_REG_FAULT_STATUS_MASK, |
||||||
|
.name = "FAULT_STATUS_MASK", |
||||||
|
.size = 1, |
||||||
|
}, |
||||||
|
{ |
||||||
|
.addr = TCPC_REG_EXT_STATUS_MASK, |
||||||
|
.name = "EXTENDED_STATUS_MASK", |
||||||
|
.size = 1, |
||||||
|
}, |
||||||
|
{ |
||||||
|
.addr = TCPC_REG_ALERT_EXT_MASK, |
||||||
|
.name = "ALERT_EXTENDED_MASK", |
||||||
|
.size = 1, |
||||||
|
}, |
||||||
|
{ |
||||||
|
.addr = TCPC_REG_CONFIG_STD_OUTPUT, |
||||||
|
.name = "CFG_STANDARD_OUTPUT", |
||||||
|
.size = 1, |
||||||
|
}, |
||||||
|
{ |
||||||
|
.addr = TCPC_REG_TCPC_CTRL, |
||||||
|
.name = "TCPC_CONTROL", |
||||||
|
.size = 1, |
||||||
|
}, |
||||||
|
{ |
||||||
|
.addr = TCPC_REG_ROLE_CTRL, |
||||||
|
.name = "ROLE_CONTROL", |
||||||
|
.size = 1, |
||||||
|
}, |
||||||
|
{ |
||||||
|
.addr = TCPC_REG_FAULT_CTRL, |
||||||
|
.name = "FAULT_CONTROL", |
||||||
|
.size = 1, |
||||||
|
}, |
||||||
|
{ |
||||||
|
.addr = TCPC_REG_POWER_CTRL, |
||||||
|
.name = "POWER_CONTROL", |
||||||
|
.size = 1, |
||||||
|
}, |
||||||
|
{ |
||||||
|
.addr = TCPC_REG_CC_STATUS, |
||||||
|
.name = "CC_STATUS", |
||||||
|
.size = 1, |
||||||
|
}, |
||||||
|
{ |
||||||
|
.addr = TCPC_REG_POWER_STATUS, |
||||||
|
.name = "POWER_STATUS", |
||||||
|
.size = 1, |
||||||
|
}, |
||||||
|
{ |
||||||
|
.addr = TCPC_REG_FAULT_STATUS, |
||||||
|
.name = "FAULT_STATUS", |
||||||
|
.size = 1, |
||||||
|
}, |
||||||
|
{ |
||||||
|
.addr = TCPC_REG_EXT_STATUS, |
||||||
|
.name = "EXTENDED_STATUS", |
||||||
|
.size = 1, |
||||||
|
}, |
||||||
|
{ |
||||||
|
.addr = TCPC_REG_ALERT_EXT, |
||||||
|
.name = "ALERT_EXTENDED", |
||||||
|
.size = 1, |
||||||
|
}, |
||||||
|
{ |
||||||
|
.addr = TCPC_REG_DEV_CAP_1, |
||||||
|
.name = "DEVICE_CAPABILITIES_1", |
||||||
|
.size = 2, |
||||||
|
}, |
||||||
|
{ |
||||||
|
.addr = TCPC_REG_DEV_CAP_2, |
||||||
|
.name = "DEVICE_CAPABILITIES_2", |
||||||
|
.size = 2, |
||||||
|
}, |
||||||
|
{ |
||||||
|
.addr = TCPC_REG_STD_INPUT_CAP, |
||||||
|
.name = "STANDARD_INPUT_CAPABILITIES", |
||||||
|
.size = 1, |
||||||
|
}, |
||||||
|
{ |
||||||
|
.addr = TCPC_REG_STD_OUTPUT_CAP, |
||||||
|
.name = "STANDARD_OUTPUT_CAPABILITIES", |
||||||
|
.size = 1, |
||||||
|
}, |
||||||
|
{ |
||||||
|
.addr = TCPC_REG_CONFIG_EXT_1, |
||||||
|
.name = "CFG_EXTENDED1", |
||||||
|
.size = 1, |
||||||
|
}, |
||||||
|
{ |
||||||
|
.addr = TCPC_REG_GENERIC_TIMER, |
||||||
|
.name = "GENERIC_TIMER", |
||||||
|
.size = 2, |
||||||
|
}, |
||||||
|
{ |
||||||
|
.addr = TCPC_REG_MSG_HDR_INFO, |
||||||
|
.name = "MESSAGE_HEADER_INFO", |
||||||
|
.size = 1, |
||||||
|
}, |
||||||
|
{ |
||||||
|
.addr = TCPC_REG_RX_DETECT, |
||||||
|
.name = "RECEIVE_DETECT", |
||||||
|
.size = 1, |
||||||
|
}, |
||||||
|
{ |
||||||
|
.addr = TCPC_REG_TRANSMIT, |
||||||
|
.name = "TRANSMIT", |
||||||
|
.size = 1, |
||||||
|
}, |
||||||
|
{ |
||||||
|
.addr = TCPC_REG_VBUS_VOLTAGE, |
||||||
|
.name = "VBUS_VOLTAGE", |
||||||
|
.size = 2, |
||||||
|
}, |
||||||
|
{ |
||||||
|
.addr = TCPC_REG_VBUS_SINK_DISCONNECT_THRESH, |
||||||
|
.name = "VBUS_SINK_DISCONNECT_THRESHOLD", |
||||||
|
.size = 2, |
||||||
|
}, |
||||||
|
{ |
||||||
|
.addr = TCPC_REG_VBUS_STOP_DISCHARGE_THRESH, |
||||||
|
.name = "VBUS_STOP_DISCHARGE_THRESHOLD", |
||||||
|
.size = 2, |
||||||
|
}, |
||||||
|
{ |
||||||
|
.addr = TCPC_REG_VBUS_VOLTAGE_ALARM_HI_CFG, |
||||||
|
.name = "VBUS_VOLTAGE_ALARM_HI_CFG", |
||||||
|
.size = 2, |
||||||
|
}, |
||||||
|
{ |
||||||
|
.addr = TCPC_REG_VBUS_VOLTAGE_ALARM_LO_CFG, |
||||||
|
.name = "VBUS_VOLTAGE_ALARM_LO_CFG", |
||||||
|
.size = 2, |
||||||
|
}, |
||||||
|
{ |
||||||
|
.addr = TCPC_REG_VBUS_NONDEFAULT_TARGET, |
||||||
|
.name = "VBUS_NONDEFAULT_TARGET", |
||||||
|
.size = 2, |
||||||
|
}, |
||||||
|
{ |
||||||
|
.addr = TCPC_REG_DEV_CAP_3, |
||||||
|
.name = "DEVICE_CAPABILITIES_3", |
||||||
|
.size = 2, |
||||||
|
}, |
||||||
|
}; |
||||||
|
|
||||||
|
int tcpci_read_reg8(const struct i2c_dt_spec *i2c, uint8_t reg, uint8_t *value) |
||||||
|
{ |
||||||
|
int ret; |
||||||
|
|
||||||
|
for (int a = 0; a < CONFIG_USBC_TCPC_TCPCI_I2C_RETRIES; a++) { |
||||||
|
ret = i2c_write_read(i2c->bus, i2c->addr, ®, sizeof(reg), value, sizeof(*value)); |
||||||
|
|
||||||
|
if (ret == 0) { |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (ret != 0) { |
||||||
|
LOG_ERR(LOG_COMM_ERR_STR, i2c->bus->name, i2c->addr, "r8", reg, *value); |
||||||
|
} |
||||||
|
|
||||||
|
return ret; |
||||||
|
} |
||||||
|
|
||||||
|
int tcpci_write_reg8(const struct i2c_dt_spec *i2c, uint8_t reg, uint8_t value) |
||||||
|
{ |
||||||
|
uint8_t buf[2] = {reg, value}; |
||||||
|
int ret; |
||||||
|
|
||||||
|
for (int a = 0; a < CONFIG_USBC_TCPC_TCPCI_I2C_RETRIES; a++) { |
||||||
|
ret = i2c_write(i2c->bus, buf, 2, i2c->addr); |
||||||
|
|
||||||
|
if (ret == 0) { |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (ret != 0) { |
||||||
|
LOG_ERR(LOG_COMM_ERR_STR, i2c->bus->name, i2c->addr, "w8", reg, value); |
||||||
|
} |
||||||
|
|
||||||
|
return ret; |
||||||
|
} |
||||||
|
|
||||||
|
int tcpci_update_reg8(const struct i2c_dt_spec *i2c, uint8_t reg, uint8_t mask, uint8_t value) |
||||||
|
{ |
||||||
|
uint8_t old_value; |
||||||
|
int ret; |
||||||
|
|
||||||
|
ret = tcpci_read_reg8(i2c, reg, &old_value); |
||||||
|
if (ret != 0) { |
||||||
|
return ret; |
||||||
|
} |
||||||
|
|
||||||
|
old_value &= ~mask; |
||||||
|
old_value |= (value & mask); |
||||||
|
|
||||||
|
ret = tcpci_write_reg8(i2c, reg, old_value); |
||||||
|
|
||||||
|
return ret; |
||||||
|
} |
||||||
|
|
||||||
|
int tcpci_read_reg16(const struct i2c_dt_spec *i2c, uint8_t reg, uint16_t *value) |
||||||
|
{ |
||||||
|
int ret; |
||||||
|
|
||||||
|
for (int a = 0; a < CONFIG_USBC_TCPC_TCPCI_I2C_RETRIES; a++) { |
||||||
|
ret = i2c_write_read(i2c->bus, i2c->addr, ®, sizeof(reg), value, sizeof(*value)); |
||||||
|
|
||||||
|
if (ret == 0) { |
||||||
|
*value = sys_le16_to_cpu(*value); |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (ret != 0) { |
||||||
|
LOG_ERR(LOG_COMM_ERR_STR, i2c->bus->name, i2c->addr, "r16", reg, *value); |
||||||
|
} |
||||||
|
|
||||||
|
return ret; |
||||||
|
} |
||||||
|
|
||||||
|
int tcpci_write_reg16(const struct i2c_dt_spec *i2c, uint8_t reg, uint16_t value) |
||||||
|
{ |
||||||
|
value = sys_cpu_to_le16(value); |
||||||
|
uint8_t *value_ptr = (uint8_t *)&value; |
||||||
|
uint8_t buf[3] = {reg, value_ptr[0], value_ptr[1]}; |
||||||
|
int ret; |
||||||
|
|
||||||
|
for (int a = 0; a < CONFIG_USBC_TCPC_TCPCI_I2C_RETRIES; a++) { |
||||||
|
ret = i2c_write(i2c->bus, buf, 3, i2c->addr); |
||||||
|
if (ret == 0) { |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (ret != 0) { |
||||||
|
LOG_ERR(LOG_COMM_ERR_STR, i2c->bus->name, i2c->addr, "w16", reg, value); |
||||||
|
} |
||||||
|
|
||||||
|
return ret; |
||||||
|
} |
||||||
|
|
||||||
|
enum tcpc_alert tcpci_alert_reg_to_enum(uint16_t reg) |
||||||
|
{ |
||||||
|
/**
|
||||||
|
* Hard reset enum has priority since it causes other bits to be ignored. Other values |
||||||
|
* are sorted by corresponding bits index in the register. |
||||||
|
*/ |
||||||
|
if (reg & TCPC_REG_ALERT_RX_HARD_RST) { |
||||||
|
/** Received Hard Reset message */ |
||||||
|
return TCPC_ALERT_HARD_RESET_RECEIVED; |
||||||
|
} else if (reg & TCPC_REG_ALERT_CC_STATUS) { |
||||||
|
/** CC status changed */ |
||||||
|
return TCPC_ALERT_CC_STATUS; |
||||||
|
} else if (reg & TCPC_REG_ALERT_POWER_STATUS) { |
||||||
|
/** Power status changed */ |
||||||
|
return TCPC_ALERT_POWER_STATUS; |
||||||
|
} else if (reg & TCPC_REG_ALERT_RX_STATUS) { |
||||||
|
/** Receive Buffer register changed */ |
||||||
|
return TCPC_ALERT_MSG_STATUS; |
||||||
|
} else if (reg & TCPC_REG_ALERT_TX_FAILED) { |
||||||
|
/** SOP* message transmission not successful */ |
||||||
|
return TCPC_ALERT_TRANSMIT_MSG_FAILED; |
||||||
|
} else if (reg & TCPC_REG_ALERT_TX_DISCARDED) { |
||||||
|
/**
|
||||||
|
* Reset or SOP* message transmission not sent |
||||||
|
* due to an incoming receive message |
||||||
|
*/ |
||||||
|
return TCPC_ALERT_TRANSMIT_MSG_DISCARDED; |
||||||
|
} else if (reg & TCPC_REG_ALERT_TX_SUCCESS) { |
||||||
|
/** Reset or SOP* message transmission successful */ |
||||||
|
return TCPC_ALERT_TRANSMIT_MSG_SUCCESS; |
||||||
|
} else if (reg & TCPC_REG_ALERT_V_ALARM_HI) { |
||||||
|
/** A high-voltage alarm has occurred */ |
||||||
|
return TCPC_ALERT_VBUS_ALARM_HI; |
||||||
|
} else if (reg & TCPC_REG_ALERT_V_ALARM_LO) { |
||||||
|
/** A low-voltage alarm has occurred */ |
||||||
|
return TCPC_ALERT_VBUS_ALARM_LO; |
||||||
|
} else if (reg & TCPC_REG_ALERT_FAULT) { |
||||||
|
/** A fault has occurred. Read the FAULT_STATUS register */ |
||||||
|
return TCPC_ALERT_FAULT_STATUS; |
||||||
|
} else if (reg & TCPC_REG_ALERT_RX_BUF_OVF) { |
||||||
|
/** TCPC RX buffer has overflowed */ |
||||||
|
return TCPC_ALERT_RX_BUFFER_OVERFLOW; |
||||||
|
} else if (reg & TCPC_REG_ALERT_VBUS_DISCNCT) { |
||||||
|
/** The TCPC in Attached.SNK state has detected a sink disconnect */ |
||||||
|
return TCPC_ALERT_VBUS_SNK_DISCONNECT; |
||||||
|
} else if (reg & TCPC_REG_ALERT_RX_BEGINNING) { |
||||||
|
/** Receive buffer register changed */ |
||||||
|
return TCPC_ALERT_BEGINNING_MSG_STATUS; |
||||||
|
} else if (reg & TCPC_REG_ALERT_EXT_STATUS) { |
||||||
|
/** Extended status changed */ |
||||||
|
return TCPC_ALERT_EXTENDED_STATUS; |
||||||
|
} else if (reg & TCPC_REG_ALERT_ALERT_EXT) { |
||||||
|
/**
|
||||||
|
* An extended interrupt event has occurred. Read the alert_extended |
||||||
|
* register |
||||||
|
*/ |
||||||
|
return TCPC_ALERT_EXTENDED; |
||||||
|
} else if (reg & TCPC_REG_ALERT_VENDOR_DEF) { |
||||||
|
/** A vendor defined alert has been detected */ |
||||||
|
return TCPC_ALERT_VENDOR_DEFINED; |
||||||
|
} |
||||||
|
|
||||||
|
LOG_ERR("Invalid alert register value"); |
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
int tcpci_tcpm_get_cc(const struct i2c_dt_spec *bus, enum tc_cc_voltage_state *cc1, |
||||||
|
enum tc_cc_voltage_state *cc2) |
||||||
|
{ |
||||||
|
uint8_t role; |
||||||
|
uint8_t status; |
||||||
|
int cc1_present_rd, cc2_present_rd; |
||||||
|
int rv; |
||||||
|
|
||||||
|
if (cc1 == NULL || cc2 == NULL) { |
||||||
|
return -EINVAL; |
||||||
|
} |
||||||
|
|
||||||
|
/* errors will return CC as open */ |
||||||
|
*cc1 = TC_CC_VOLT_OPEN; |
||||||
|
*cc2 = TC_CC_VOLT_OPEN; |
||||||
|
|
||||||
|
/* Get the ROLE CONTROL and CC STATUS values */ |
||||||
|
rv = tcpci_read_reg8(bus, TCPC_REG_ROLE_CTRL, &role); |
||||||
|
if (rv != 0) { |
||||||
|
return rv; |
||||||
|
} |
||||||
|
|
||||||
|
rv = tcpci_read_reg8(bus, TCPC_REG_CC_STATUS, &status); |
||||||
|
if (rv != 0) { |
||||||
|
return rv; |
||||||
|
} |
||||||
|
|
||||||
|
/* Get the current CC values from the CC STATUS */ |
||||||
|
*cc1 = TCPC_REG_CC_STATUS_CC1_STATE(status); |
||||||
|
*cc2 = TCPC_REG_CC_STATUS_CC2_STATE(status); |
||||||
|
|
||||||
|
/* Determine if we are presenting Rd */ |
||||||
|
cc1_present_rd = 0; |
||||||
|
cc2_present_rd = 0; |
||||||
|
if (role & TCPC_REG_ROLE_CTRL_DRP_MASK) { |
||||||
|
/*
|
||||||
|
* We are doing DRP. We will use the CC STATUS |
||||||
|
* ConnectResult to determine if we are presenting |
||||||
|
* Rd or Rp. |
||||||
|
*/ |
||||||
|
int term; |
||||||
|
|
||||||
|
term = !!(status & TCPC_REG_CC_STATUS_CONNECT_RESULT); |
||||||
|
|
||||||
|
if (*cc1 != TC_CC_VOLT_OPEN) { |
||||||
|
cc1_present_rd = term; |
||||||
|
} |
||||||
|
if (*cc2 != TC_CC_VOLT_OPEN) { |
||||||
|
cc2_present_rd = term; |
||||||
|
} |
||||||
|
} else { |
||||||
|
/*
|
||||||
|
* We are not doing DRP. We will use the ROLE CONTROL |
||||||
|
* CC values to determine if we are presenting Rd or Rp. |
||||||
|
*/ |
||||||
|
int role_cc1, role_cc2; |
||||||
|
|
||||||
|
role_cc1 = TCPC_REG_ROLE_CTRL_CC1(role); |
||||||
|
role_cc2 = TCPC_REG_ROLE_CTRL_CC2(role); |
||||||
|
|
||||||
|
if (*cc1 != TC_CC_VOLT_OPEN) { |
||||||
|
cc1_present_rd = (role_cc1 == TC_CC_RD); |
||||||
|
} |
||||||
|
if (*cc2 != TC_CC_VOLT_OPEN) { |
||||||
|
cc2_present_rd = (role_cc2 == TC_CC_RD); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
*cc1 |= cc1_present_rd << 2; |
||||||
|
*cc2 |= cc2_present_rd << 2; |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
@ -0,0 +1,119 @@ |
|||||||
|
/*
|
||||||
|
* Copyright 2024 Google LLC |
||||||
|
* SPDX-License-Identifier: Apache-2.0 |
||||||
|
*/ |
||||||
|
|
||||||
|
/**
|
||||||
|
* @file |
||||||
|
* @brief Helper functions to use by the TCPCI-compliant drivers |
||||||
|
* |
||||||
|
* This file contains generic TCPCI functions that may be used by the drivers to TCPCI-compliant |
||||||
|
* devices that want to implement vendor-specific functionality without the need to reimplement the |
||||||
|
* TCPCI generic functionality and register operations. |
||||||
|
*/ |
||||||
|
|
||||||
|
#ifndef ZEPHYR_INCLUDE_DRIVERS_USBC_TCPCI_PRIV_H_ |
||||||
|
#define ZEPHYR_INCLUDE_DRIVERS_USBC_TCPCI_PRIV_H_ |
||||||
|
|
||||||
|
#include <stdint.h> |
||||||
|
#include <zephyr/drivers/i2c.h> |
||||||
|
#include <zephyr/usb_c/usbc.h> |
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Structure used to bind the register address to name in registers dump |
||||||
|
*/ |
||||||
|
struct tcpci_reg_dump_map { |
||||||
|
/** Address of I2C device register */ |
||||||
|
uint8_t addr; |
||||||
|
/** Human readable name of register */ |
||||||
|
const char *name; |
||||||
|
/** Size in bytes of the register */ |
||||||
|
uint8_t size; |
||||||
|
}; |
||||||
|
|
||||||
|
/** Size of the array containing the standard registers used by tcpci dump command */ |
||||||
|
#define TCPCI_STD_REGS_SIZE 38 |
||||||
|
/**
|
||||||
|
* @brief Array containing the standard TCPCI registers list. |
||||||
|
* If the TCPC driver contain any vendor-specific registers, it may override the TCPCI dump_std_reg |
||||||
|
* function tp dump them and should also dump the standard registers using this array. |
||||||
|
* |
||||||
|
*/ |
||||||
|
extern const struct tcpci_reg_dump_map tcpci_std_regs[TCPCI_STD_REGS_SIZE]; |
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Function to read the 8-bit register of TCPCI device |
||||||
|
* |
||||||
|
* @param bus I2C bus |
||||||
|
* @param reg Address of TCPCI register |
||||||
|
* @param value Pointer to variable that will store the register value |
||||||
|
* @return int Status of I2C operation, 0 in case of success |
||||||
|
*/ |
||||||
|
int tcpci_read_reg8(const struct i2c_dt_spec *bus, uint8_t reg, uint8_t *value); |
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Function to write a value to the 8-bit register of TCPCI device |
||||||
|
* |
||||||
|
* @param bus I2C bus |
||||||
|
* @param reg Address of TCPCI register |
||||||
|
* @param value Value that will be written to the device register |
||||||
|
* @return int Status of I2C operation, 0 in case of success |
||||||
|
*/ |
||||||
|
int tcpci_write_reg8(const struct i2c_dt_spec *bus, uint8_t reg, uint8_t value); |
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Function to read and update part of the 8-bit register of TCPCI device |
||||||
|
* The function is NOT performing this operation atomically. |
||||||
|
* |
||||||
|
* @param bus I2C bus |
||||||
|
* @param reg Address of TCPCI register |
||||||
|
* @param mask Bitmask specifying which bits of the device register will be modified |
||||||
|
* @param value Value that will be written to the device register after being ANDed with mask |
||||||
|
* @return int Status of I2C operation, 0 in case of success |
||||||
|
*/ |
||||||
|
int tcpci_update_reg8(const struct i2c_dt_spec *bus, uint8_t reg, uint8_t mask, uint8_t value); |
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Function to read the 16-bit register of TCPCI device |
||||||
|
* |
||||||
|
* @param bus I2C bus |
||||||
|
* @param reg Address of TCPCI register |
||||||
|
* @param value Pointer to variable that will store the register value |
||||||
|
* @return int Status of I2C operation, 0 in case of success |
||||||
|
*/ |
||||||
|
int tcpci_read_reg16(const struct i2c_dt_spec *bus, uint8_t reg, uint16_t *value); |
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Function to write a value to the 16-bit register of TCPCI device |
||||||
|
* |
||||||
|
* @param bus I2C bus |
||||||
|
* @param reg Address of TCPCI register |
||||||
|
* @param value Value that will be written to the device register |
||||||
|
* @return int Status of I2C operation, 0 in case of success |
||||||
|
*/ |
||||||
|
int tcpci_write_reg16(const struct i2c_dt_spec *bus, uint8_t reg, uint16_t value); |
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Function that converts the TCPCI alert register to the tcpc_alert enum |
||||||
|
* The hard reset value takes priority, where the rest are returned in the bit order from least |
||||||
|
* significant to most significant. |
||||||
|
* |
||||||
|
* @param reg Value of the TCPCI alert register. This parameter must have value other than zero. |
||||||
|
* @return enum tcpc_alert Value of one of the flags being set in the alert register |
||||||
|
*/ |
||||||
|
enum tcpc_alert tcpci_alert_reg_to_enum(uint16_t reg); |
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Function that reads the CC status registers and converts read values to enums |
||||||
|
* representing voltages state and partner detection status. |
||||||
|
* |
||||||
|
* @param bus I2C bus |
||||||
|
* @param cc1 pointer to variable where detected CC1 voltage state will be stored |
||||||
|
* @param cc2 pointer to variable where detected CC2 voltage state will be stored |
||||||
|
* @return -EINVAL if cc1 or cc2 pointer is NULL |
||||||
|
* @return int Status of I2C operation, 0 in case of success |
||||||
|
*/ |
||||||
|
int tcpci_tcpm_get_cc(const struct i2c_dt_spec *bus, enum tc_cc_voltage_state *cc1, |
||||||
|
enum tc_cc_voltage_state *cc2); |
||||||
|
|
||||||
|
#endif /* ZEPHYR_INCLUDE_DRIVERS_USBC_TCPCI_PRIV_H_ */ |
Loading…
Reference in new issue