From 947d555342ffd1d75c3c5a191524504711befec0 Mon Sep 17 00:00:00 2001 From: Tero Marttila Date: Fri, 19 Jan 2024 00:22:03 +0200 Subject: [PATCH 01/24] components: usb_pd_sink with stusb4500 support for reading rev/status registers --- components/usb_pd_sink/CMakeLists.txt | 5 + components/usb_pd_sink/component.mk | 0 components/usb_pd_sink/include/usb_pd_sink.h | 28 ++++ components/usb_pd_sink/stusb4500.c | 99 ++++++++++++ components/usb_pd_sink/stusb4500.h | 12 ++ components/usb_pd_sink/stusb4500_i2c.h | 162 +++++++++++++++++++ components/usb_pd_sink/usb_pd_sink.c | 52 ++++++ components/usb_pd_sink/usb_pd_sink.h | 13 ++ 8 files changed, 371 insertions(+) create mode 100644 components/usb_pd_sink/CMakeLists.txt create mode 100644 components/usb_pd_sink/component.mk create mode 100644 components/usb_pd_sink/include/usb_pd_sink.h create mode 100644 components/usb_pd_sink/stusb4500.c create mode 100644 components/usb_pd_sink/stusb4500.h create mode 100644 components/usb_pd_sink/stusb4500_i2c.h create mode 100644 components/usb_pd_sink/usb_pd_sink.c create mode 100644 components/usb_pd_sink/usb_pd_sink.h diff --git a/components/usb_pd_sink/CMakeLists.txt b/components/usb_pd_sink/CMakeLists.txt new file mode 100644 index 00000000..9a27cb8e --- /dev/null +++ b/components/usb_pd_sink/CMakeLists.txt @@ -0,0 +1,5 @@ +idf_component_register( + SRC_DIRS . + INCLUDE_DIRS "include" + PRIV_REQUIRES logging +) diff --git a/components/usb_pd_sink/component.mk b/components/usb_pd_sink/component.mk new file mode 100644 index 00000000..e69de29b diff --git a/components/usb_pd_sink/include/usb_pd_sink.h b/components/usb_pd_sink/include/usb_pd_sink.h new file mode 100644 index 00000000..f8876e69 --- /dev/null +++ b/components/usb_pd_sink/include/usb_pd_sink.h @@ -0,0 +1,28 @@ +#pragma once + +#include +#include + +#define USB_PD_SINK_STUSB4500_I2C_ADDR_BASE 0x28 +#define USB_PD_SINK_STUSB4500_I2C_ADDR_MASK 0x03 +#define USB_PD_SINK_STUSB4500_I2C_ADDR(addr) (USB_PD_SINK_STUSB4500_I2C_ADDR_BASE | ((addr) & USB_PD_SINK_STUSB4500_I2C_ADDR_MASK)) +#define USB_PD_SINK_STUSB4500_I2C_TIMEOUT (1000 / portTICK_RATE_MS) + +enum usb_pd_sink_type { + USB_PD_SINK_STUSB4500, +}; + +struct usb_pd_sink_options { + enum usb_pd_sink_type type; + + i2c_port_t i2c_port; + uint8_t i2c_addr; + // gpio_pin_t int_pin; + +}; + +struct usb_pd_sink; + +int usb_pd_sink_new(struct usb_pd_sink **sinkp, const struct usb_pd_sink_options *options); + +int usb_pd_sink_start(struct usb_pd_sink *sink); diff --git a/components/usb_pd_sink/stusb4500.c b/components/usb_pd_sink/stusb4500.c new file mode 100644 index 00000000..f6ff32db --- /dev/null +++ b/components/usb_pd_sink/stusb4500.c @@ -0,0 +1,99 @@ +#include "stusb4500.h" +#include "stusb4500_i2c.h" + +#include +#include + +#define DEBUG + +#include + +int stusb4500_init(struct stusb4500 *stusb, const struct usb_pd_sink_options *options) +{ + stusb->i2c_port = options->i2c_port; + stusb->i2c_addr = USB_PD_SINK_STUSB4500_I2C_ADDR(options->i2c_addr); + stusb->i2c_timeout = USB_PD_SINK_STUSB4500_I2C_TIMEOUT; + + return 0; +} + +static int stusb4500_read(struct stusb4500 *stusb, enum stusb4500_i2c_register reg, void *out, size_t size) +{ + uint8_t cmd[] = { reg }; + esp_err_t err; + + if ((err = i2c_master_write_read_device(stusb->i2c_port, stusb->i2c_addr, cmd, sizeof(cmd), out, size, stusb->i2c_timeout))) { + LOG_ERROR("i2c_master_write_to_device port=%d addr=%u: %s", stusb->i2c_port, stusb->i2c_addr, esp_err_to_name(err)); + return -1; + } + + return 0; +} + +int stusb4500_start(struct stusb4500 *stusb) +{ + struct stusb4500_i2c_rev rev; + struct stusb4500_i2c_status status; + int err; + + if ((err = stusb4500_read(stusb, STUSB4500_BCD_TYPEC_REV_LOW, &rev, sizeof(rev)))) { + return err; + } + + if ((err = stusb4500_read(stusb, STUSB4500_PORT_STATUS_0, &status, sizeof(status)))) { + return err; + } + + LOG_DEBUG("bcd_rev: typec_low=%u.%u typec_high=%u.%u usbpd_low=%u.%u usbpd_high=%u.%u", + rev.bcd_typec_rev_low.major, rev.bcd_typec_rev_low.minor, + rev.bcd_typec_rev_high.major, rev.bcd_typec_rev_high.minor, + rev.bcd_usbpd_rev_low.major, rev.bcd_usbpd_rev_low.minor, + rev.bcd_usbpd_rev_high.major, rev.bcd_usbpd_rev_high.minor + ); + + LOG_DEBUG("port_status: attach_trans=%u attached_device=%u power_mode=%u data_mode=%u attach=%u", + status.port_status_0.attach_trans, + status.port_status_1.attached_device, + status.port_status_1.power_mode, + status.port_status_1.data_mode, + status.port_status_1.attach + ); + + LOG_DEBUG("typec_monitoring_status: vbus_low_status=%u vbus_high_status=%u vbus_valid_snk=%u vbus_vsafe0v=%u vbus_ready=%u", + status.typec_monitoring_status_0.vbus_low_status, + status.typec_monitoring_status_0.vbus_high_status, + status.typec_monitoring_status_1.vbus_valid_snk, + status.typec_monitoring_status_1.vbus_vsafe0v, + status.typec_monitoring_status_1.vbus_ready + ); + + LOG_DEBUG("cc_status: cc1_state=%u cc2_state=%u connect_result=%u looking_4_connection=%u", + status.cc_status.cc1_state, + status.cc_status.cc2_state, + status.cc_status.connect_result, + status.cc_status.looking_4_connection + ); + + LOG_DEBUG("cc_hw_fault_status: vbus_disch_fault=%u vpu_valid=%u vpu_ovp_fault=%u", + status.cc_hw_fault_status_1.vbus_disch_fault, + status.cc_hw_fault_status_1.vpu_valid, + status.cc_hw_fault_status_1.vpu_ovp_fault + ); + + LOG_DEBUG("pd_typec_status: pd_typec_hand_check=%u", + status.pd_typec_status.pd_typec_hand_check + ); + + LOG_DEBUG("typec_status: typec_fsm_state=%u reverse=%u", + status.typec_status.typec_fsm_state, + status.typec_status.reverse + ); + + LOG_DEBUG("prt_status: prl_hw_rst_received=%u prl_msg_received=%u prt_bist_received=%u", + status.prt_status.prl_hw_rst_received, + status.prt_status.prl_msg_received, + status.prt_status.prt_bist_received + ); + + return 0; +} diff --git a/components/usb_pd_sink/stusb4500.h b/components/usb_pd_sink/stusb4500.h new file mode 100644 index 00000000..c9f2b0a4 --- /dev/null +++ b/components/usb_pd_sink/stusb4500.h @@ -0,0 +1,12 @@ +#pragma once + +#include + +struct stusb4500 { + i2c_port_t i2c_port; + uint8_t i2c_addr; + TickType_t i2c_timeout; +}; + +int stusb4500_init(struct stusb4500 *stusb, const struct usb_pd_sink_options *options); +int stusb4500_start(struct stusb4500 *stusb); diff --git a/components/usb_pd_sink/stusb4500_i2c.h b/components/usb_pd_sink/stusb4500_i2c.h new file mode 100644 index 00000000..79c7e7a6 --- /dev/null +++ b/components/usb_pd_sink/stusb4500_i2c.h @@ -0,0 +1,162 @@ +#pragma once + +enum stusb4500_i2c_register { + STUSB4500_BCD_TYPEC_REV_LOW = 0x06, + STUSB4500_BCD_TYPEC_REV_HIGH = 0x07, + STUSB4500_BCD_USBPD_REV_LOW = 0x08, + STUSB4500_BCD_USBPD_REV_HIGH = 0x09, + STUSB4500_DEVICE_CAPAB_HIGH = 0x0A, + STUSB4500_ALERT_STATUS_1 = 0x0B, + STUSB4500_ALERT_STATUS_1_MASK = 0x0C, + STUSB4500_PORT_STATUS_0 = 0x0D, + STUSB4500_PORT_STATUS_1 = 0x0E, + STUSB4500_TYPEC_MONITORING_STATUS_0 = 0x0F, + STUSB4500_TYPEC_MONITORING_STATUS_1 = 0x10, + STUSB4500_CC_STATUS = 0x11, + STUSB4500_CC_HW_FAULT_STATUS_0 = 0x12, + STUSB4500_CC_HW_FAULT_STATUS_1 = 0x13, + STUSB4500_PD_TYPEC_STATUS = 0x14, + STUSB4500_TYPEC_STATUS = 0x15, + STUSB4500_PRT_STATUS = 0x16, +}; + +enum stusb4500_port_status_attached_device { + STUSB4500_PORT_STATUS_ATTACHED_DEVICE_NONE = 0b000, + STUSB4500_PORT_STATUS_ATTACHED_DEVICE_SINK = 0b001, + STUSB4500_PORT_STATUS_ATTACHED_DEVICE_DEBUG = 0b011, +}; + +enum stusb4500_typec_fsm_state { + STUSB4500_TYPEC_FSM_STATE_UNATTACHED_SNK = 0b00000, + STUSB4500_TYPEC_FSM_STATE_ATTACHWAIT_SNK = 0b00001, + STUSB4500_TYPEC_FSM_STATE_ATTACHED_SNK = 0b00010, + STUSB4500_TYPEC_FSM_STATE_DEBUGACCESSORY_SNK = 0b00011, + STUSB4500_TYPEC_FSM_STATE_TRY_SRC = 0b01100, + STUSB4500_TYPEC_FSM_STATE_UNATTACHED_ACCESSORY = 0b01101, + STUSB4500_TYPEC_FSM_STATE_ATTACHWAIT_ACCESSORY = 0b01110, + STUSB4500_TYPEC_FSM_STATE_TYPEC_ERRORRECOVERY = 0b10011, +}; + +struct stusb4500_i2c_rev { + // STUSB4500_BCD_TYPEC_REV_LOW + struct stusb4500_bcd_typec_rev_low { + uint8_t minor : 4; + uint8_t major : 4; + } bcd_typec_rev_low; + + // STUSB4500_BCD_TYPEC_REV_HIGH + struct stusb4500_bcd_typec_rev_high { + uint8_t minor : 4; + uint8_t major : 4; + } bcd_typec_rev_high; + + // STUSB4500_BCD_USBPD_REV_LOW + struct stusb4500_bcd_usbpd_rev_low { + uint8_t minor : 4; + uint8_t major : 4; + } bcd_usbpd_rev_low; + + struct stusb4500_bcd_usbpd_rev_high { + uint8_t minor : 4; + uint8_t major : 4; + } bcd_usbpd_rev_high; +}; + +struct stusb4500_device_capab_high { + uint8_t not_used; +}; + +struct stusb4500_i2c_alert_status { + struct stusb4500_alert_status_1 { + uint8_t reserved0 : 1; + uint8_t prt_status_al : 1; + uint8_t reserved2 : 1; + uint8_t pd_typec_status_al : 1; + uint8_t cc_hw_fault_status_al : 1; + uint8_t typec_monitoring_status_al : 1; + uint8_t port_status_al : 1; + uint8_t reserved7 : 1; + } alert_status_1 ; + + struct stusb4500_alert_status_1_mask { + uint8_t bits; + } alert_status_1_mask; +}; + +struct stusb4500_i2c_status { + struct stusb4500_port_status_0 { + uint8_t attach_trans : 1; // Transition detected in attached state + uint8_t reserved1 : 7; + } port_status_0; + + struct stusb4500_port_status_1 { + uint8_t attach : 1; // 1 = ATTACHED + uint8_t reserved2 : 1; + uint8_t data_mode : 1; // 0 = UFP + uint8_t power_mode : 1; // 0 = device is sinking power + uint8_t reserved3 : 1; + uint8_t attached_device : 3; // STUSB4500_PORT_STATUS_ATTACHED_DEVICE_* + } port_status_1; + + struct stusb4500_typec_monitoring_status_0 { + uint8_t reserved0 : 1; + uint8_t vbus_valid_snk_trans : 1; + uint8_t vbus_vsafe0v_trans : 1; + uint8_t vbus_ready_trans : 1; + uint8_t vbus_low_status : 1; + uint8_t vbus_high_status : 1; + uint8_t reserved6 : 2; + } typec_monitoring_status_0; + + struct stusb4500_typec_monitoring_status_1 { + uint8_t reserved0 : 1; + uint8_t vbus_valid_snk : 1; + uint8_t vbus_vsafe0v : 1; + uint8_t vbus_ready : 1; + uint8_t reserved4 : 4; + } typec_monitoring_status_1; + + struct stusb4500_cc_status { + uint8_t cc1_state : 1; + uint8_t cc2_state : 1; + uint8_t connect_result : 1; + uint8_t looking_4_connection : 1; + uint8_t reserved4 : 4; + } cc_status; + + struct stusb4500_cc_hw_fault_status_0 { + uint8_t reserved0 : 4; + uint8_t vpu_ovp_fault_trans : 1; + uint8_t vpu_valid_trans : 1; + uint8_t reserved6 : 2; + } cc_hw_fault_status_0; + + struct stusb4500_cc_hw_fault_status_1 { + uint8_t reserved0 : 4; + uint8_t vbus_disch_fault : 1; + uint8_t reserved5 : 1; + uint8_t vpu_valid : 1; + uint8_t vpu_ovp_fault : 1; + } cc_hw_fault_status_1; + + struct stusb4500_pd_typec_status { + uint8_t pd_typec_hand_check : 4; + uint8_t reserved4 : 4; + } pd_typec_status; + + struct stusb4500_typec_status { + uint8_t typec_fsm_state : 5; // enum stusb4500_typec_fsm_state + uint8_t reserved5 : 1; + uint8_t reserved6 : 1; + uint8_t reverse : 1; + } typec_status; + + struct stusb4500_prt_status { + uint8_t prl_hw_rst_received : 1; + uint8_t reserved1 : 1; + uint8_t prl_msg_received : 1; + uint8_t reserved3 : 1; + uint8_t prt_bist_received : 1; + uint8_t reserved5 : 3; + } prt_status; +}; diff --git a/components/usb_pd_sink/usb_pd_sink.c b/components/usb_pd_sink/usb_pd_sink.c new file mode 100644 index 00000000..e8bf1086 --- /dev/null +++ b/components/usb_pd_sink/usb_pd_sink.c @@ -0,0 +1,52 @@ +#include "usb_pd_sink.h" + +#include + +#include + +int usb_pd_sink_init(struct usb_pd_sink *sink, const struct usb_pd_sink_options *options) +{ + switch ((sink->type = options->type)) { + case USB_PD_SINK_STUSB4500: + return stusb4500_init(&sink->state.stusb4500, options); + + default: + LOG_FATAL("invalid type=%d", options->type); + } +} + +int usb_pd_sink_new(struct usb_pd_sink **sinkp, const struct usb_pd_sink_options *options) +{ + struct usb_pd_sink *sink; + int err; + + if (!(sink = calloc(1, sizeof(*sink)))) { + LOG_ERROR("calloc"); + return -1; + } + + if ((err = usb_pd_sink_init(sink, options))) { + goto error; + } + + *sinkp = sink; + + return 0; + +error: + free(sink); + + return err; +} + +int usb_pd_sink_start(struct usb_pd_sink *sink) +{ + switch (sink->type) { + case USB_PD_SINK_STUSB4500: + return stusb4500_start(&sink->state.stusb4500); + + default: + LOG_FATAL("invalid type=%d", sink->type); + } + +} diff --git a/components/usb_pd_sink/usb_pd_sink.h b/components/usb_pd_sink/usb_pd_sink.h new file mode 100644 index 00000000..9dbb9a1d --- /dev/null +++ b/components/usb_pd_sink/usb_pd_sink.h @@ -0,0 +1,13 @@ +#pragma once + +#include + +#include "stusb4500.h" + +struct usb_pd_sink { + enum usb_pd_sink_type type; + + union { + struct stusb4500 stusb4500; + } state; +}; From 11991c06ac20859660d9ef91be06fc60c0476925 Mon Sep 17 00:00:00 2001 From: Tero Marttila Date: Fri, 19 Jan 2024 00:22:17 +0200 Subject: [PATCH 02/24] main: usb_pd_sink --- main/Kconfig | 23 +++++++++++++++++++++++ main/main.c | 15 +++++++++++++++ main/usb_pd_sink.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ main/usb_pd_sink.h | 8 ++++++++ 4 files changed, 91 insertions(+) create mode 100644 main/usb_pd_sink.c create mode 100644 main/usb_pd_sink.h diff --git a/main/Kconfig b/main/Kconfig index 445e31f2..6759717a 100644 --- a/main/Kconfig +++ b/main/Kconfig @@ -424,3 +424,26 @@ menu "qmsk-esp-sdcard" bool "SD Card support" endmenu + +menu "qmsk-esp-usb-pd-sink" + config USB_PD_SINK_ENABLED + bool "USB-PD Sink support" + + choice USB_PD_SINK_TYPE + prompt "USB-PD Sink type" + + config USB_PD_SINK_TYPE_NONE + bool "Disabled" + + config USB_PD_SINK_TYPE_STUSB4500 + bool "STUSB4500" + select USB_PD_SINK_ENABLED + endchoice + + config USB_PD_SINK_TYPE_STUSB4500_I2C_ADDR + depends on USB_PD_SINK_TYPE_STUSB4500 + int "Configurable STUSB4500 I2C address bits (0-3)" + range 0 3 + default 0 + +endmenu diff --git a/main/main.c b/main/main.c index b1b63383..267e3aeb 100644 --- a/main/main.c +++ b/main/main.c @@ -14,6 +14,7 @@ #include "sdcard.h" #include "system.h" #include "user.h" +#include "usb_pd_sink.h" #include "user_events.h" #include "user_leds.h" #include "wifi.h" @@ -111,6 +112,13 @@ void app_main(void) } #endif +#if CONFIG_USB_PD_SINK_ENABLED + if ((err = init_usb_pd_sink())) { + LOG_ERROR("init_usb_pd_sink"); + user_alert(USER_ALERT_ERROR_SETUP); + } +#endif + LOG_INFO("config"); if ((err = init_config()) < 0) { @@ -133,6 +141,13 @@ void app_main(void) } #endif +#if CONFIG_USB_PD_SINK_ENABLED + if ((err = start_usb_pd_sink())) { + LOG_ERROR("start_usb_pd_sink"); + user_alert(USER_ALERT_ERROR_START); + } +#endif + LOG_INFO("setup"); if ((err = init_wifi())) { diff --git a/main/usb_pd_sink.c b/main/usb_pd_sink.c new file mode 100644 index 00000000..80bc5c08 --- /dev/null +++ b/main/usb_pd_sink.c @@ -0,0 +1,45 @@ +#include "usb_pd_sink.h" +#include "i2c_master.h" + +#include + +#include + +#if CONFIG_USB_PD_SINK_ENABLED + struct usb_pd_sink *usb_pd_sink; + + int init_usb_pd_sink() + { + struct usb_pd_sink_options options = { + #if CONFIG_USB_PD_SINK_TYPE_STUSB4500 + .type = USB_PD_SINK_STUSB4500, + .i2c_port = I2C_MASTER_PORT, + .i2c_addr = CONFIG_USB_PD_SINK_TYPE_STUSB4500_I2C_ADDR, + #else + #error "No USB-PD Sink Type selected" + #endif + }; + int err; + + LOG_INFO("type=%d i2c_port=%d i2c_addr=%d", options.type, options.i2c_port, options.i2c_addr); + + if ((err = usb_pd_sink_new(&usb_pd_sink, &options))) { + LOG_ERROR("usb_pd_sink_new"); + return err; + } + + return 0; + } + + int start_usb_pd_sink() + { + int err; + + if ((err = usb_pd_sink_start(usb_pd_sink))) { + LOG_ERROR("usb_pd_sink_start"); + return err; + } + + return 0; + } +#endif diff --git a/main/usb_pd_sink.h b/main/usb_pd_sink.h new file mode 100644 index 00000000..a6fa5ef8 --- /dev/null +++ b/main/usb_pd_sink.h @@ -0,0 +1,8 @@ +#pragma once + +#include + +#if CONFIG_USB_PD_SINK_ENABLED + int init_usb_pd_sink(); + int start_usb_pd_sink(); +#endif From 36a3f3cab93b24f88eaec1a04cf0b6fc84260d14 Mon Sep 17 00:00:00 2001 From: Tero Marttila Date: Fri, 19 Jan 2024 19:13:53 +0200 Subject: [PATCH 03/24] usb_pd_sink: read fsm_state, device_id --- components/usb_pd_sink/stusb4500.c | 18 ++++++++++++++++++ components/usb_pd_sink/stusb4500_i2c.h | 12 ++++++++++++ 2 files changed, 30 insertions(+) diff --git a/components/usb_pd_sink/stusb4500.c b/components/usb_pd_sink/stusb4500.c index f6ff32db..4ffced02 100644 --- a/components/usb_pd_sink/stusb4500.c +++ b/components/usb_pd_sink/stusb4500.c @@ -34,6 +34,8 @@ int stusb4500_start(struct stusb4500 *stusb) { struct stusb4500_i2c_rev rev; struct stusb4500_i2c_status status; + struct stusb4500_pe_fsm pe_fsm; + struct stusb4500_device_id device_id; int err; if ((err = stusb4500_read(stusb, STUSB4500_BCD_TYPEC_REV_LOW, &rev, sizeof(rev)))) { @@ -44,6 +46,14 @@ int stusb4500_start(struct stusb4500 *stusb) return err; } + if ((err = stusb4500_read(stusb, STUSB4500_PE_FSM, &pe_fsm, sizeof(pe_fsm)))) { + return err; + } + + if ((err = stusb4500_read(stusb, STUSB4500_DEVICE_ID, &device_id, sizeof(device_id)))) { + return err; + } + LOG_DEBUG("bcd_rev: typec_low=%u.%u typec_high=%u.%u usbpd_low=%u.%u usbpd_high=%u.%u", rev.bcd_typec_rev_low.major, rev.bcd_typec_rev_low.minor, rev.bcd_typec_rev_high.major, rev.bcd_typec_rev_high.minor, @@ -95,5 +105,13 @@ int stusb4500_start(struct stusb4500 *stusb) status.prt_status.prt_bist_received ); + LOG_DEBUG("pe_fsm: pe_fsm_state=%u", + pe_fsm.pe_fsm_state + ); + + LOG_DEBUG("device_id: device_id=%u", + device_id.device_id + ); + return 0; } diff --git a/components/usb_pd_sink/stusb4500_i2c.h b/components/usb_pd_sink/stusb4500_i2c.h index 79c7e7a6..39e725ed 100644 --- a/components/usb_pd_sink/stusb4500_i2c.h +++ b/components/usb_pd_sink/stusb4500_i2c.h @@ -18,6 +18,10 @@ enum stusb4500_i2c_register { STUSB4500_PD_TYPEC_STATUS = 0x14, STUSB4500_TYPEC_STATUS = 0x15, STUSB4500_PRT_STATUS = 0x16, + + STUSB4500_PE_FSM = 0x29, + + STUSB4500_DEVICE_ID = 0x2F, }; enum stusb4500_port_status_attached_device { @@ -160,3 +164,11 @@ struct stusb4500_i2c_status { uint8_t reserved5 : 3; } prt_status; }; + +struct stusb4500_pe_fsm { + uint8_t pe_fsm_state : 8; +}; + +struct stusb4500_device_id { + uint8_t device_id : 8; +}; From 7d79c2e6d96fb6936341d18ee9c380faffb3be7f Mon Sep 17 00:00:00 2001 From: Tero Marttila Date: Fri, 19 Jan 2024 20:36:38 +0200 Subject: [PATCH 04/24] usb_pd_sink stusb4500: rename main var --- components/usb_pd_sink/stusb4500.c | 24 ++++++++++++------------ components/usb_pd_sink/stusb4500.h | 4 ++-- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/components/usb_pd_sink/stusb4500.c b/components/usb_pd_sink/stusb4500.c index 4ffced02..ba107d98 100644 --- a/components/usb_pd_sink/stusb4500.c +++ b/components/usb_pd_sink/stusb4500.c @@ -8,29 +8,29 @@ #include -int stusb4500_init(struct stusb4500 *stusb, const struct usb_pd_sink_options *options) +int stusb4500_init(struct stusb4500 *stusb4500, const struct usb_pd_sink_options *options) { - stusb->i2c_port = options->i2c_port; - stusb->i2c_addr = USB_PD_SINK_STUSB4500_I2C_ADDR(options->i2c_addr); - stusb->i2c_timeout = USB_PD_SINK_STUSB4500_I2C_TIMEOUT; + stusb4500->i2c_port = options->i2c_port; + stusb4500->i2c_addr = USB_PD_SINK_STUSB4500_I2C_ADDR(options->i2c_addr); + stusb4500->i2c_timeout = USB_PD_SINK_STUSB4500_I2C_TIMEOUT; return 0; } -static int stusb4500_read(struct stusb4500 *stusb, enum stusb4500_i2c_register reg, void *out, size_t size) +static int stusb4500_read(struct stusb4500 *stusb4500, enum stusb4500_i2c_register reg, void *out, size_t size) { uint8_t cmd[] = { reg }; esp_err_t err; - if ((err = i2c_master_write_read_device(stusb->i2c_port, stusb->i2c_addr, cmd, sizeof(cmd), out, size, stusb->i2c_timeout))) { - LOG_ERROR("i2c_master_write_to_device port=%d addr=%u: %s", stusb->i2c_port, stusb->i2c_addr, esp_err_to_name(err)); + if ((err = i2c_master_write_read_device(stusb4500->i2c_port, stusb4500->i2c_addr, cmd, sizeof(cmd), out, size, stusb4500->i2c_timeout))) { + LOG_ERROR("i2c_master_write_to_device port=%d addr=%u: %s", stusb4500->i2c_port, stusb4500->i2c_addr, esp_err_to_name(err)); return -1; } return 0; } -int stusb4500_start(struct stusb4500 *stusb) +int stusb4500_start(struct stusb4500 *stusb4500) { struct stusb4500_i2c_rev rev; struct stusb4500_i2c_status status; @@ -38,19 +38,19 @@ int stusb4500_start(struct stusb4500 *stusb) struct stusb4500_device_id device_id; int err; - if ((err = stusb4500_read(stusb, STUSB4500_BCD_TYPEC_REV_LOW, &rev, sizeof(rev)))) { + if ((err = stusb4500_read(stusb4500, STUSB4500_BCD_TYPEC_REV_LOW, &rev, sizeof(rev)))) { return err; } - if ((err = stusb4500_read(stusb, STUSB4500_PORT_STATUS_0, &status, sizeof(status)))) { + if ((err = stusb4500_read(stusb4500, STUSB4500_PORT_STATUS_0, &status, sizeof(status)))) { return err; } - if ((err = stusb4500_read(stusb, STUSB4500_PE_FSM, &pe_fsm, sizeof(pe_fsm)))) { + if ((err = stusb4500_read(stusb4500, STUSB4500_PE_FSM, &pe_fsm, sizeof(pe_fsm)))) { return err; } - if ((err = stusb4500_read(stusb, STUSB4500_DEVICE_ID, &device_id, sizeof(device_id)))) { + if ((err = stusb4500_read(stusb4500, STUSB4500_DEVICE_ID, &device_id, sizeof(device_id)))) { return err; } diff --git a/components/usb_pd_sink/stusb4500.h b/components/usb_pd_sink/stusb4500.h index c9f2b0a4..8191f26d 100644 --- a/components/usb_pd_sink/stusb4500.h +++ b/components/usb_pd_sink/stusb4500.h @@ -8,5 +8,5 @@ struct stusb4500 { TickType_t i2c_timeout; }; -int stusb4500_init(struct stusb4500 *stusb, const struct usb_pd_sink_options *options); -int stusb4500_start(struct stusb4500 *stusb); +int stusb4500_init(struct stusb4500 *stusb4500, const struct usb_pd_sink_options *options); +int stusb4500_start(struct stusb4500 *stusb4500); From 7515af335da0f68a58e76eaccc2bd661f6391b34 Mon Sep 17 00:00:00 2001 From: Tero Marttila Date: Fri, 19 Jan 2024 20:36:47 +0200 Subject: [PATCH 05/24] usb_pd_sink stusb4500: read pdo/rdo --- components/usb_pd_sink/stusb4500.c | 86 +++++++++++++++++++++++++- components/usb_pd_sink/stusb4500_i2c.h | 68 ++++++++++++++++++++ 2 files changed, 153 insertions(+), 1 deletion(-) diff --git a/components/usb_pd_sink/stusb4500.c b/components/usb_pd_sink/stusb4500.c index ba107d98..662c68c3 100644 --- a/components/usb_pd_sink/stusb4500.c +++ b/components/usb_pd_sink/stusb4500.c @@ -30,7 +30,7 @@ static int stusb4500_read(struct stusb4500 *stusb4500, enum stusb4500_i2c_regist return 0; } -int stusb4500_start(struct stusb4500 *stusb4500) +int stusb4500_get_status(struct stusb4500 *stusb4500) { struct stusb4500_i2c_rev rev; struct stusb4500_i2c_status status; @@ -115,3 +115,87 @@ int stusb4500_start(struct stusb4500 *stusb4500) return 0; } + +int stusb4500_get_pdo(struct stusb4500 *stusb4500) +{ + struct stusb4500_dpm_pdo_numb pdo_numb; + union stusb4500_pdo pdo; + int err; + + if ((err = stusb4500_read(stusb4500, STUSB4500_DPM_PDO_NUMB, &pdo_numb, sizeof(pdo_numb)))) { + return err; + } + + for (int i = 0; i < pdo_numb.dpm_snk_pdo_numb && i < STUSB4500_DPM_SNK_PDO_COUNT; i++) { + if ((err = stusb4500_read(stusb4500, STUSB4500_DPM_SNK_PDO(i), &pdo, sizeof(pdo)))) { + LOG_ERROR("stusb4500_read STUSB4500_DPM_SNK_PDO(%d)", i); + return err; + } + + switch(pdo.header.type) { + case STUSB4500_PDO_TYPE_FIXED_SUPPLY: + LOG_DEBUG("dpm_snk_pdo%d: fixed_supply max_current=%u voltage=%u fast_role_swap=%u dual_role_data=%u usb_comm_capable=%u unconstrained_power=%u higher_capability=%u dual_role_power=%u", i, + pdo.fixed_supply.max_current, + pdo.fixed_supply.voltage, + pdo.fixed_supply.fast_role_swap, + pdo.fixed_supply.dual_role_data, + pdo.fixed_supply.usb_comm_capable, + pdo.fixed_supply.unconstrained_power, + pdo.fixed_supply.higher_capability, + pdo.fixed_supply.dual_role_power + ); + break; + + default: + LOG_WARN("dpm_snk_pdo%d: unsupported type=%u", i, pdo.header.type); + break; + } + } + + return 0; +} + +int stusb4500_get_rdo(struct stusb4500 *stusb4500) +{ + union stusb4500_rdo_reg_status rdo; + int err; + + if ((err = stusb4500_read(stusb4500, STUSB4500_RDO_REG_STATUS_0, &rdo, sizeof(rdo)))) { + return err; + } + + LOG_DEBUG("rdo: fixed_supply max_current=%u operating_current=%u unchunked_messages_supported=%u no_usb_suspend=%u usb_comm_capable=%u capability_mismatch=%u give_back=%u object_position=%u", + rdo.fixed_supply.max_current, + rdo.fixed_supply.operating_current, + rdo.fixed_supply.unchunked_messages_supported, + rdo.fixed_supply.no_usb_suspend, + rdo.fixed_supply.usb_comm_capable, + rdo.fixed_supply.capability_mismatch, + rdo.fixed_supply.give_back, + rdo.fixed_supply.object_position + ); + + return 0; +} + +int stusb4500_start(struct stusb4500 *stusb4500) +{ + int err; + + if ((err = stusb4500_get_status(stusb4500))) { + LOG_ERROR("stusb4500_get_status"); + return err; + } + + if ((err = stusb4500_get_pdo(stusb4500))) { + LOG_ERROR("stusb4500_get_pdo"); + return err; + } + + if ((err = stusb4500_get_rdo(stusb4500))) { + LOG_ERROR("stusb4500_get_rdo"); + return err; + } + + return 0; +} diff --git a/components/usb_pd_sink/stusb4500_i2c.h b/components/usb_pd_sink/stusb4500_i2c.h index 39e725ed..f54bc8ee 100644 --- a/components/usb_pd_sink/stusb4500_i2c.h +++ b/components/usb_pd_sink/stusb4500_i2c.h @@ -1,5 +1,8 @@ #pragma once +#define STUSB4500_DPM_SNK_PDO(i) (STUSB4500_DPM_SNK_PDO1_0 + 4 * (i)) +#define STUSB4500_DPM_SNK_PDO_COUNT 3 + enum stusb4500_i2c_register { STUSB4500_BCD_TYPEC_REV_LOW = 0x06, STUSB4500_BCD_TYPEC_REV_HIGH = 0x07, @@ -22,6 +25,24 @@ enum stusb4500_i2c_register { STUSB4500_PE_FSM = 0x29, STUSB4500_DEVICE_ID = 0x2F, + + STUSB4500_DPM_PDO_NUMB = 0x70, + STUSB4500_DPM_SNK_PDO1_0 = 0x85, + STUSB4500_DPM_SNK_PDO1_1 = 0x86, + STUSB4500_DPM_SNK_PDO1_2 = 0x87, + STUSB4500_DPM_SNK_PDO1_3 = 0x88, + STUSB4500_DPM_SNK_PDO2_0 = 0x89, + STUSB4500_DPM_SNK_PDO2_1 = 0x8A, + STUSB4500_DPM_SNK_PDO2_2 = 0x8B, + STUSB4500_DPM_SNK_PDO2_3 = 0x8C, + STUSB4500_DPM_SNK_PDO3_0 = 0x8D, + STUSB4500_DPM_SNK_PDO3_1 = 0x8E, + STUSB4500_DPM_SNK_PDO3_2 = 0x8F, + STUSB4500_DPM_SNK_PDO3_3 = 0x90, + STUSB4500_RDO_REG_STATUS_0 = 0x91, + STUSB4500_RDO_REG_STATUS_1 = 0x92, + STUSB4500_RDO_REG_STATUS_2 = 0x93, + STUSB4500_RDO_REG_STATUS_3 = 0x94, }; enum stusb4500_port_status_attached_device { @@ -41,6 +62,13 @@ enum stusb4500_typec_fsm_state { STUSB4500_TYPEC_FSM_STATE_TYPEC_ERRORRECOVERY = 0b10011, }; +enum stusb4500_pdo_type { + STUSB4500_PDO_TYPE_FIXED_SUPPLY = 0b00, + STUSB4500_PDO_TYPE_BATTERY = 0b01, + STUSB4500_PDO_TYPE_VARIABLE_SUPPLY = 0b10, + // Augmented Power Data Object (APDO) = 0b11, // XXX: PD 3.0 +}; + struct stusb4500_i2c_rev { // STUSB4500_BCD_TYPEC_REV_LOW struct stusb4500_bcd_typec_rev_low { @@ -172,3 +200,43 @@ struct stusb4500_pe_fsm { struct stusb4500_device_id { uint8_t device_id : 8; }; + +struct stusb4500_dpm_pdo_numb { + uint8_t dpm_snk_pdo_numb : 3; + uint8_t reserved3 : 5; +}; + +union stusb4500_pdo { + struct stusb4500_pdo_header { + uint32_t body : 30; + uint32_t type : 2; + } header; + + struct stusb4500_sink_fixed_supply_pdo { + uint32_t max_current : 10; // 10mA + uint32_t voltage : 10; // 50mV + uint32_t reserved20 : 3; // peak_current for source + uint32_t fast_role_swap : 2; // XXX: PD 3.0 + uint32_t dual_role_data : 1; + uint32_t usb_comm_capable : 1; + uint32_t unconstrained_power : 1; + uint32_t higher_capability : 1; // usb_suspend_supported for source + uint32_t dual_role_power : 1; + uint32_t type : 2; + } fixed_supply; +}; + +union stusb4500_rdo_reg_status { + struct stusb4500_fuxed_supply_rdo { + uint32_t max_current : 10; // 10mA + uint32_t operating_current : 10; // 10mA + uint32_t reserved20 : 3; + uint32_t unchunked_messages_supported : 1; // XXX: PD3.0 + uint32_t no_usb_suspend : 1; + uint32_t usb_comm_capable : 1; + uint32_t capability_mismatch : 1; + uint32_t give_back : 1; + uint32_t object_position : 3; + uint32_t reserved31 : 1; + } fixed_supply; +}; From 5d6952421fc891eb80968c57d814d930807c7b16 Mon Sep 17 00:00:00 2001 From: Tero Marttila Date: Fri, 19 Jan 2024 21:47:27 +0200 Subject: [PATCH 06/24] usb_pd_sink stusb4500: dump ctrl registers --- components/usb_pd_sink/stusb4500.c | 38 ++++++++++++++++++ components/usb_pd_sink/stusb4500_i2c.h | 53 ++++++++++++++++++++++++++ 2 files changed, 91 insertions(+) diff --git a/components/usb_pd_sink/stusb4500.c b/components/usb_pd_sink/stusb4500.c index 662c68c3..62880688 100644 --- a/components/usb_pd_sink/stusb4500.c +++ b/components/usb_pd_sink/stusb4500.c @@ -116,6 +116,39 @@ int stusb4500_get_status(struct stusb4500 *stusb4500) return 0; } +int stusb4500_get_ctrl(struct stusb4500 *stusb4500) +{ + struct stusb4500_monitoring_ctrl_0 monitoring_ctrl_0; + struct stusb4500_monitoring_ctrl_1 monitoring_ctrl_1; + struct stusb4500_monitoring_ctrl_2 monitoring_ctrl_2; + struct stusb4500_vbus_discharge_time_ctrl vbus_discharge_time_ctrl; + int err; + + if ((err = stusb4500_read(stusb4500, STUSB4500_MONITORING_CTRL_0, &monitoring_ctrl_0, sizeof(monitoring_ctrl_0)))) { + return err; + } + + if ((err = stusb4500_read(stusb4500, STUSB4500_MONITORING_CTRL_1, &monitoring_ctrl_1, sizeof(monitoring_ctrl_1)))) { + return err; + } + + if ((err = stusb4500_read(stusb4500, STUSB4500_MONITORING_CTRL_2, &monitoring_ctrl_2, sizeof(monitoring_ctrl_2)))) { + return err; + } + + if ((err = stusb4500_read(stusb4500, STUSB4500_VBUS_DISCHARGE_TIME_CTRL, &vbus_discharge_time_ctrl, sizeof(vbus_discharge_time_ctrl)))) { + return err; + } + + LOG_DEBUG("monitoring_ctrl: vbus_snk_disc_threshold=%u voltage=%u vshift_low=%u vshift_high=%u", + monitoring_ctrl_0.vbus_snk_disc_threshold, + monitoring_ctrl_1.voltage, + monitoring_ctrl_2.vshift_low, monitoring_ctrl_2.vshift_high + ); + + return 0; +} + int stusb4500_get_pdo(struct stusb4500 *stusb4500) { struct stusb4500_dpm_pdo_numb pdo_numb; @@ -187,6 +220,11 @@ int stusb4500_start(struct stusb4500 *stusb4500) return err; } + if ((err = stusb4500_get_ctrl(stusb4500))) { + LOG_ERROR("stusb4500_get_ctrl"); + return err; + } + if ((err = stusb4500_get_pdo(stusb4500))) { LOG_ERROR("stusb4500_get_pdo"); return err; diff --git a/components/usb_pd_sink/stusb4500_i2c.h b/components/usb_pd_sink/stusb4500_i2c.h index f54bc8ee..b6a0ec47 100644 --- a/components/usb_pd_sink/stusb4500_i2c.h +++ b/components/usb_pd_sink/stusb4500_i2c.h @@ -22,6 +22,17 @@ enum stusb4500_i2c_register { STUSB4500_TYPEC_STATUS = 0x15, STUSB4500_PRT_STATUS = 0x16, + STUSB4500_PD_COMMAND_CTRL = 0x1A, + + STUSB4500_MONITORING_CTRL_0 = 0x20, + STUSB4500_MONITORING_CTRL_1 = 0x21, // undocumented + STUSB4500_MONITORING_CTRL_2 = 0x22, + STUSB4500_RESET_CTRL = 0x23, + + STUSB4500_VBUS_DISCHARGE_TIME_CTRL = 0x25, + STUSB4500_VBUS_DISCHARGE_CTRL = 0x26, + STUSB4500_VBUS_CTRL = 0x27, + STUSB4500_PE_FSM = 0x29, STUSB4500_DEVICE_ID = 0x2F, @@ -193,6 +204,48 @@ struct stusb4500_i2c_status { } prt_status; }; +struct stusb4500_pd_command_ctrl { + uint8_t send_message_command : 6; + uint8_t reserved6 : 2; +}; + +struct stusb4500_monitoring_ctrl_0 { + uint8_t reserved0 : 3; + uint8_t vbus_snk_disc_threshold : 1; + uint8_t reserved4 : 4; +}; + +struct stusb4500_monitoring_ctrl_1 { + uint8_t voltage; // undocumented, 100mV +}; + +struct stusb4500_monitoring_ctrl_2 { + uint8_t vshift_low : 4; + uint8_t vshift_high : 4; +}; + +struct stusb4500_reset_ctrl { + uint8_t reset_sw_en : 1; + uint8_t reserved1 : 7; +}; + +struct stusb4500_vbus_discharge_time_ctrl { + uint8_t discharge_time_transition : 4; + uint8_t discharge_time_to_0v : 4; +}; + +struct stusb4500_vbus_discharge_ctrl { + uint8_t reserved0 : 6; + uint8_t reserved6 : 1; + uint8_t vbus_discharge_en : 1; +}; + +struct stusb4500_vbus_ctrl { + uint8_t reserved0 : 1; + uint8_t sink_vbus_en : 1; + uint8_t reserved2 : 6; +}; + struct stusb4500_pe_fsm { uint8_t pe_fsm_state : 8; }; From c507e3225af8317b270c7f891c631095579bb9d7 Mon Sep 17 00:00:00 2001 From: Tero Marttila Date: Fri, 19 Jan 2024 21:47:41 +0200 Subject: [PATCH 07/24] usb_pd_sink stusb4500: fix stusb4500_alert_status_1_mask --- components/usb_pd_sink/stusb4500_i2c.h | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/components/usb_pd_sink/stusb4500_i2c.h b/components/usb_pd_sink/stusb4500_i2c.h index b6a0ec47..4de212a8 100644 --- a/components/usb_pd_sink/stusb4500_i2c.h +++ b/components/usb_pd_sink/stusb4500_i2c.h @@ -106,7 +106,7 @@ struct stusb4500_i2c_rev { }; struct stusb4500_device_capab_high { - uint8_t not_used; + uint8_t device_capab_high : 8; // not used }; struct stusb4500_i2c_alert_status { @@ -122,7 +122,14 @@ struct stusb4500_i2c_alert_status { } alert_status_1 ; struct stusb4500_alert_status_1_mask { - uint8_t bits; + uint8_t reserved0 : 1; + uint8_t prt_status_al_mask : 1; + uint8_t reserved2 : 1; + uint8_t reserved3 : 1; // XXX: pd_typec_status_al_mask? + uint8_t cc_fault_status_al_mask : 1; + uint8_t typec_monitoring_status_mask : 1; + uint8_t port_status_al_mask : 1; + uint8_t reserved7 : 1; } alert_status_1_mask; }; From 145ccb14e65ca6cc6422a60b42554cbe0632201e Mon Sep 17 00:00:00 2001 From: Tero Marttila Date: Fri, 19 Jan 2024 23:44:12 +0200 Subject: [PATCH 08/24] usb_pd_sink: split stusb4500_i2c.c --- components/usb_pd_sink/stusb4500.c | 38 +++----- components/usb_pd_sink/stusb4500.h | 5 + components/usb_pd_sink/stusb4500_i2c.c | 123 +++++++++++++++++++++++++ components/usb_pd_sink/stusb4500_i2c.h | 2 + 4 files changed, 142 insertions(+), 26 deletions(-) create mode 100644 components/usb_pd_sink/stusb4500_i2c.c diff --git a/components/usb_pd_sink/stusb4500.c b/components/usb_pd_sink/stusb4500.c index 62880688..dc4ddd43 100644 --- a/components/usb_pd_sink/stusb4500.c +++ b/components/usb_pd_sink/stusb4500.c @@ -1,7 +1,6 @@ #include "stusb4500.h" #include "stusb4500_i2c.h" -#include #include #define DEBUG @@ -17,19 +16,6 @@ int stusb4500_init(struct stusb4500 *stusb4500, const struct usb_pd_sink_options return 0; } -static int stusb4500_read(struct stusb4500 *stusb4500, enum stusb4500_i2c_register reg, void *out, size_t size) -{ - uint8_t cmd[] = { reg }; - esp_err_t err; - - if ((err = i2c_master_write_read_device(stusb4500->i2c_port, stusb4500->i2c_addr, cmd, sizeof(cmd), out, size, stusb4500->i2c_timeout))) { - LOG_ERROR("i2c_master_write_to_device port=%d addr=%u: %s", stusb4500->i2c_port, stusb4500->i2c_addr, esp_err_to_name(err)); - return -1; - } - - return 0; -} - int stusb4500_get_status(struct stusb4500 *stusb4500) { struct stusb4500_i2c_rev rev; @@ -38,19 +24,19 @@ int stusb4500_get_status(struct stusb4500 *stusb4500) struct stusb4500_device_id device_id; int err; - if ((err = stusb4500_read(stusb4500, STUSB4500_BCD_TYPEC_REV_LOW, &rev, sizeof(rev)))) { + if ((err = stusb4500_i2c_read(stusb4500, STUSB4500_BCD_TYPEC_REV_LOW, &rev, sizeof(rev)))) { return err; } - if ((err = stusb4500_read(stusb4500, STUSB4500_PORT_STATUS_0, &status, sizeof(status)))) { + if ((err = stusb4500_i2c_read(stusb4500, STUSB4500_PORT_STATUS_0, &status, sizeof(status)))) { return err; } - if ((err = stusb4500_read(stusb4500, STUSB4500_PE_FSM, &pe_fsm, sizeof(pe_fsm)))) { + if ((err = stusb4500_i2c_read(stusb4500, STUSB4500_PE_FSM, &pe_fsm, sizeof(pe_fsm)))) { return err; } - if ((err = stusb4500_read(stusb4500, STUSB4500_DEVICE_ID, &device_id, sizeof(device_id)))) { + if ((err = stusb4500_i2c_read(stusb4500, STUSB4500_DEVICE_ID, &device_id, sizeof(device_id)))) { return err; } @@ -124,19 +110,19 @@ int stusb4500_get_ctrl(struct stusb4500 *stusb4500) struct stusb4500_vbus_discharge_time_ctrl vbus_discharge_time_ctrl; int err; - if ((err = stusb4500_read(stusb4500, STUSB4500_MONITORING_CTRL_0, &monitoring_ctrl_0, sizeof(monitoring_ctrl_0)))) { + if ((err = stusb4500_i2c_read(stusb4500, STUSB4500_MONITORING_CTRL_0, &monitoring_ctrl_0, sizeof(monitoring_ctrl_0)))) { return err; } - if ((err = stusb4500_read(stusb4500, STUSB4500_MONITORING_CTRL_1, &monitoring_ctrl_1, sizeof(monitoring_ctrl_1)))) { + if ((err = stusb4500_i2c_read(stusb4500, STUSB4500_MONITORING_CTRL_1, &monitoring_ctrl_1, sizeof(monitoring_ctrl_1)))) { return err; } - if ((err = stusb4500_read(stusb4500, STUSB4500_MONITORING_CTRL_2, &monitoring_ctrl_2, sizeof(monitoring_ctrl_2)))) { + if ((err = stusb4500_i2c_read(stusb4500, STUSB4500_MONITORING_CTRL_2, &monitoring_ctrl_2, sizeof(monitoring_ctrl_2)))) { return err; } - if ((err = stusb4500_read(stusb4500, STUSB4500_VBUS_DISCHARGE_TIME_CTRL, &vbus_discharge_time_ctrl, sizeof(vbus_discharge_time_ctrl)))) { + if ((err = stusb4500_i2c_read(stusb4500, STUSB4500_VBUS_DISCHARGE_TIME_CTRL, &vbus_discharge_time_ctrl, sizeof(vbus_discharge_time_ctrl)))) { return err; } @@ -155,13 +141,13 @@ int stusb4500_get_pdo(struct stusb4500 *stusb4500) union stusb4500_pdo pdo; int err; - if ((err = stusb4500_read(stusb4500, STUSB4500_DPM_PDO_NUMB, &pdo_numb, sizeof(pdo_numb)))) { + if ((err = stusb4500_i2c_read(stusb4500, STUSB4500_DPM_PDO_NUMB, &pdo_numb, sizeof(pdo_numb)))) { return err; } for (int i = 0; i < pdo_numb.dpm_snk_pdo_numb && i < STUSB4500_DPM_SNK_PDO_COUNT; i++) { - if ((err = stusb4500_read(stusb4500, STUSB4500_DPM_SNK_PDO(i), &pdo, sizeof(pdo)))) { - LOG_ERROR("stusb4500_read STUSB4500_DPM_SNK_PDO(%d)", i); + if ((err = stusb4500_i2c_read(stusb4500, STUSB4500_DPM_SNK_PDO(i), &pdo, sizeof(pdo)))) { + LOG_ERROR("stusb4500_i2c_read STUSB4500_DPM_SNK_PDO(%d)", i); return err; } @@ -193,7 +179,7 @@ int stusb4500_get_rdo(struct stusb4500 *stusb4500) union stusb4500_rdo_reg_status rdo; int err; - if ((err = stusb4500_read(stusb4500, STUSB4500_RDO_REG_STATUS_0, &rdo, sizeof(rdo)))) { + if ((err = stusb4500_i2c_read(stusb4500, STUSB4500_RDO_REG_STATUS_0, &rdo, sizeof(rdo)))) { return err; } diff --git a/components/usb_pd_sink/stusb4500.h b/components/usb_pd_sink/stusb4500.h index 8191f26d..c4081847 100644 --- a/components/usb_pd_sink/stusb4500.h +++ b/components/usb_pd_sink/stusb4500.h @@ -1,5 +1,7 @@ #pragma once +#include "stusb4500_i2c.h" + #include struct stusb4500 { @@ -10,3 +12,6 @@ struct stusb4500 { int stusb4500_init(struct stusb4500 *stusb4500, const struct usb_pd_sink_options *options); int stusb4500_start(struct stusb4500 *stusb4500); + +int stusb4500_i2c_read(struct stusb4500 *stusb4500, enum stusb4500_i2c_register reg, void *out, size_t size); +int stusb4500_i2c_write(struct stusb4500 *stusb4500, enum stusb4500_i2c_register reg, void *buf, size_t size); diff --git a/components/usb_pd_sink/stusb4500_i2c.c b/components/usb_pd_sink/stusb4500_i2c.c new file mode 100644 index 00000000..229b5999 --- /dev/null +++ b/components/usb_pd_sink/stusb4500_i2c.c @@ -0,0 +1,123 @@ +#include "stusb4500.h" +#include "stusb4500_i2c.h" + +#include +#include + +#include + +int stusb4500_i2c_read(struct stusb4500 *stusb4500, enum stusb4500_i2c_register cmd, void *buf, size_t size) +{ + uint8_t buffer[I2C_LINK_RECOMMENDED_SIZE(2)] = { 0 }; + i2c_cmd_handle_t handle; + esp_err_t err; + + if (!(handle = i2c_cmd_link_create_static(buffer, sizeof(buffer)))) { + LOG_ERROR("i2c_cmd_link_create_static"); + return -1; + } + + if ((err = i2c_master_start(handle))) { + LOG_ERROR("i2c_master_start: %s", esp_err_to_name(err)); + goto error; + } + + LOG_DEBUG("i2c_addr=%u cmd=%u", stusb4500->i2c_addr, cmd); + + if ((err = i2c_master_write_byte(handle, stusb4500->i2c_addr << 1 | I2C_MASTER_WRITE, true))) { + LOG_ERROR("i2c_master_write_byte: %s", esp_err_to_name(err)); + goto error; + } + + if ((err = i2c_master_write_byte(handle, cmd, true))) { + LOG_ERROR("i2c_master_write_byte: %s", esp_err_to_name(err)); + goto error; + } + + if ((err = i2c_master_start(handle))) { + LOG_ERROR("i2c_master_start: %s", esp_err_to_name(err)); + goto error; + } + + if ((err = i2c_master_write_byte(handle, stusb4500->i2c_addr << 1 | I2C_MASTER_READ, true))) { + LOG_ERROR("i2c_master_write_byte: %s", esp_err_to_name(err)); + goto error; + } + + if ((err = i2c_master_read(handle, buf, size, I2C_MASTER_LAST_NACK))) { + LOG_ERROR("i2c_master_write: %s", esp_err_to_name(err)); + goto error; + } + + if ((err = i2c_master_stop(handle))) { + LOG_ERROR("i2c_master_stop: %s", esp_err_to_name(err)); + goto error; + } + + if ((err = i2c_master_cmd_begin(stusb4500->i2c_port, handle, stusb4500->i2c_timeout))) { + LOG_ERROR("i2c_master_cmd_begin: %s", esp_err_to_name(err)); + goto error; + } + + for (int i = 0; i < size; i++) { + LOG_DEBUG("\t%02x", ((uint8_t *) buf)[i]); + } + +error: + i2c_cmd_link_delete_static(handle); + + return err; +} + +int stusb4500_i2c_write(struct stusb4500 *stusb4500, enum stusb4500_i2c_register cmd, void *buf, size_t size) +{ + uint8_t buffer[I2C_LINK_RECOMMENDED_SIZE(1)] = { 0 }; + i2c_cmd_handle_t handle; + esp_err_t err; + + if (!(handle = i2c_cmd_link_create_static(buffer, sizeof(buffer)))) { + LOG_ERROR("i2c_cmd_link_create_static"); + return -1; + } + + if ((err = i2c_master_start(handle))) { + LOG_ERROR("i2c_master_start: %s", esp_err_to_name(err)); + goto error; + } + + LOG_DEBUG("i2c_addr=%u cmd=%u", stusb4500->i2c_addr, cmd); + + if ((err = i2c_master_write_byte(handle, stusb4500->i2c_addr << 1 | I2C_MASTER_WRITE, true))) { + LOG_ERROR("i2c_master_write_byte: %s", esp_err_to_name(err)); + goto error; + } + + if ((err = i2c_master_write_byte(handle, cmd, true))) { + LOG_ERROR("i2c_master_write_byte: %s", esp_err_to_name(err)); + goto error; + } + + for (int i = 0; i < size; i++) { + LOG_DEBUG("\t%02x", ((uint8_t *) buf)[i]); + } + + if ((err = i2c_master_write(handle, buf, size, true))) { + LOG_ERROR("i2c_master_write: %s", esp_err_to_name(err)); + goto error; + } + + if ((err = i2c_master_stop(handle))) { + LOG_ERROR("i2c_master_stop: %s", esp_err_to_name(err)); + goto error; + } + + if ((err = i2c_master_cmd_begin(stusb4500->i2c_port, handle, stusb4500->i2c_timeout))) { + LOG_ERROR("i2c_master_cmd_begin: %s", esp_err_to_name(err)); + goto error; + } + +error: + i2c_cmd_link_delete_static(handle); + + return err; +} diff --git a/components/usb_pd_sink/stusb4500_i2c.h b/components/usb_pd_sink/stusb4500_i2c.h index 4de212a8..ee727fd5 100644 --- a/components/usb_pd_sink/stusb4500_i2c.h +++ b/components/usb_pd_sink/stusb4500_i2c.h @@ -1,5 +1,7 @@ #pragma once +#include + #define STUSB4500_DPM_SNK_PDO(i) (STUSB4500_DPM_SNK_PDO1_0 + 4 * (i)) #define STUSB4500_DPM_SNK_PDO_COUNT 3 From 799b476bfbbf5b22318778504aed640d82382576 Mon Sep 17 00:00:00 2001 From: Tero Marttila Date: Fri, 19 Jan 2024 23:45:15 +0200 Subject: [PATCH 09/24] usb_pd_sink: nvm read --- components/usb_pd_sink/stusb4500.c | 31 ++++++ components/usb_pd_sink/stusb4500.h | 3 + components/usb_pd_sink/stusb4500_i2c.h | 55 ++++++++++ components/usb_pd_sink/stusb4500_nvm.c | 143 +++++++++++++++++++++++++ components/usb_pd_sink/stusb4500_nvm.h | 12 +++ 5 files changed, 244 insertions(+) create mode 100644 components/usb_pd_sink/stusb4500_nvm.c create mode 100644 components/usb_pd_sink/stusb4500_nvm.h diff --git a/components/usb_pd_sink/stusb4500.c b/components/usb_pd_sink/stusb4500.c index dc4ddd43..d52fadd1 100644 --- a/components/usb_pd_sink/stusb4500.c +++ b/components/usb_pd_sink/stusb4500.c @@ -197,10 +197,41 @@ int stusb4500_get_rdo(struct stusb4500 *stusb4500) return 0; } +int stusb4500_get_nvm(struct stusb4500 *stusb4500) +{ + struct stusb4500_nvm nvm = {}; + int err; + + if ((err = stusb4500_nvm_read(stusb4500, &nvm))) { + LOG_ERROR("stusb4500_nvm_read"); + return err; + } + + for (int i = 0; i < STUSB4500_NVM_SECTOR_COUNT; i++) { + LOG_DEBUG("nvm sector[%d]: %02x %02x %02x %02x %02x %02x %02x %02x", i, + nvm.sectors[i][0], + nvm.sectors[i][1], + nvm.sectors[i][2], + nvm.sectors[i][3], + nvm.sectors[i][4], + nvm.sectors[i][5], + nvm.sectors[i][6], + nvm.sectors[i][7] + ); + } + + return 0; +} + int stusb4500_start(struct stusb4500 *stusb4500) { int err; + if ((err = stusb4500_get_nvm(stusb4500))) { + LOG_ERROR("stusb4500_get_nvm"); + return err; + } + if ((err = stusb4500_get_status(stusb4500))) { LOG_ERROR("stusb4500_get_status"); return err; diff --git a/components/usb_pd_sink/stusb4500.h b/components/usb_pd_sink/stusb4500.h index c4081847..3fdb814f 100644 --- a/components/usb_pd_sink/stusb4500.h +++ b/components/usb_pd_sink/stusb4500.h @@ -1,6 +1,7 @@ #pragma once #include "stusb4500_i2c.h" +#include "stusb4500_nvm.h" #include @@ -15,3 +16,5 @@ int stusb4500_start(struct stusb4500 *stusb4500); int stusb4500_i2c_read(struct stusb4500 *stusb4500, enum stusb4500_i2c_register reg, void *out, size_t size); int stusb4500_i2c_write(struct stusb4500 *stusb4500, enum stusb4500_i2c_register reg, void *buf, size_t size); + +int stusb4500_nvm_read(struct stusb4500 *stusb4500, struct stusb4500_nvm *nvm); diff --git a/components/usb_pd_sink/stusb4500_i2c.h b/components/usb_pd_sink/stusb4500_i2c.h index ee727fd5..a4621617 100644 --- a/components/usb_pd_sink/stusb4500_i2c.h +++ b/components/usb_pd_sink/stusb4500_i2c.h @@ -39,6 +39,15 @@ enum stusb4500_i2c_register { STUSB4500_DEVICE_ID = 0x2F, + STUSB4500_RW_BUFFER_0 = 0x53, // NVM + STUSB4500_RW_BUFFER_1, + STUSB4500_RW_BUFFER_2, + STUSB4500_RW_BUFFER_3, + STUSB4500_RW_BUFFER_4, + STUSB4500_RW_BUFFER_5, + STUSB4500_RW_BUFFER_6, + STUSB4500_RW_BUFFER_7, + STUSB4500_DPM_PDO_NUMB = 0x70, STUSB4500_DPM_SNK_PDO1_0 = 0x85, STUSB4500_DPM_SNK_PDO1_1 = 0x86, @@ -56,6 +65,9 @@ enum stusb4500_i2c_register { STUSB4500_RDO_REG_STATUS_1 = 0x92, STUSB4500_RDO_REG_STATUS_2 = 0x93, STUSB4500_RDO_REG_STATUS_3 = 0x94, + STUSB4500_FTP_CUST_PASSWORD = 0x95, // NVM + STUSB4500_FTP_CTRL_0 = 0x96, // NVM + STUSB4500_FTP_CTRL_1 = 0x97, // NVM }; enum stusb4500_port_status_attached_device { @@ -263,6 +275,10 @@ struct stusb4500_device_id { uint8_t device_id : 8; }; +struct stusb4500_rw_buffer { + uint8_t data[8]; +}; + struct stusb4500_dpm_pdo_numb { uint8_t dpm_snk_pdo_numb : 3; uint8_t reserved3 : 5; @@ -302,3 +318,42 @@ union stusb4500_rdo_reg_status { uint32_t reserved31 : 1; } fixed_supply; }; + +static const uint8_t stusb4500_ftp_cust_password_password = 0x47; + +struct stusb4500_ftp_cust_password { + uint8_t password : 8; +}; + +enum stusb4500_ftp_ctrl_opcode { + STUSB4500_FTP_CTRL_OPCODE_READ = 0x00, + STUSB4500_FTP_CTRL_OPCODE_WRITE_PL = 0x01, + STUSB4500_FTP_CTRL_OPCODE_WRITE_SER = 0x02, + STUSB4500_FTP_CTRL_OPCODE_READ_PL = 0x03, + STUSB4500_FTP_CTRL_OPCODE_READ_SER = 0x04, + STUSB4500_FTP_CTRL_OPCODE_ERASE_SECTOR = 0x05, + STUSB4500_FTP_CTRL_OPCODE_PROG_SECTOR = 0x06, + STUSB4500_FTP_CTRL_OPCODE_SOFT_PROG_SECTOR = 0x07, +}; + +enum stusb4500_ftp_ctrl_ser { + STUSB4500_FTP_SER_SECTOR_0 = 0x01, + STUSB4500_FTP_SER_SECTOR_1 = 0x02, + STUSB4500_FTP_SER_SECTOR_2 = 0x04, + STUSB4500_FTP_SER_SECTOR_3 = 0x08, + STUSB4500_FTP_SER_SECTOR_4 = 0x10, +}; + +struct stusb4500_ftp_ctrl_0 { + uint8_t sector : 3; + uint8_t _3 : 1; + uint8_t req : 1; + uint8_t _5 : 1; + uint8_t rst_n : 1; + uint8_t pwr : 1; +}; + +struct stusb4500_ftp_ctrl_1 { + uint8_t opcode : 3; + uint8_t ser : 5; +}; diff --git a/components/usb_pd_sink/stusb4500_nvm.c b/components/usb_pd_sink/stusb4500_nvm.c new file mode 100644 index 00000000..e4dbd722 --- /dev/null +++ b/components/usb_pd_sink/stusb4500_nvm.c @@ -0,0 +1,143 @@ +#include "stusb4500.h" +#include "stusb4500_i2c.h" +#include "stusb4500_nvm.h" + +#include + +#define DEBUG + +#include + +static int stusb4500_nvm_unlock(struct stusb4500 *stusb4500) +{ + struct stusb4500_ftp_cust_password password = { .password = stusb4500_ftp_cust_password_password }; + int err; + + if ((err = stusb4500_i2c_write(stusb4500, STUSB4500_FTP_CUST_PASSWORD, &password, sizeof(password)))) { + LOG_ERROR("stusb4500_i2c_write STUSB4500_FTP_CUST_PASSWORD"); + return err; + } + + return 0; +} + +static int stusb4500_nvm_lock(struct stusb4500 *stusb4500) +{ + struct stusb4500_ftp_ctrl_0 ctrl0_reset = {}; + struct stusb4500_ftp_ctrl_0 ctrl0_off = { .rst_n = 1 }; + struct stusb4500_ftp_ctrl_1 ctrl1_clear = { }; + struct stusb4500_ftp_cust_password password_clear = { }; + int err; + + if ((err = stusb4500_i2c_write(stusb4500, STUSB4500_FTP_CTRL_0, &ctrl0_reset, sizeof(ctrl0_reset)))) { + LOG_ERROR("stusb4500_i2c_write STUSB4500_FTP_CTRL_0"); + return err; + } + + if ((err = stusb4500_i2c_write(stusb4500, STUSB4500_FTP_CTRL_0, &ctrl0_off, sizeof(ctrl0_off)))) { + LOG_ERROR("stusb4500_i2c_write STUSB4500_FTP_CTRL_0"); + return err; + } + + if ((err = stusb4500_i2c_write(stusb4500, STUSB4500_FTP_CTRL_1, &ctrl1_clear, sizeof(ctrl1_clear)))) { + LOG_ERROR("stusb4500_i2c_write STUSB4500_FTP_CTRL_1"); + return err; + } + + if ((err = stusb4500_i2c_write(stusb4500, STUSB4500_FTP_CUST_PASSWORD, &password_clear, sizeof(password_clear)))) { + LOG_ERROR("stusb4500_i2c_write STUSB4500_FTP_CUST_PASSWORD"); + return err; + } + + return 0; +} + +static int stusb4500_nvm_reset(struct stusb4500 *stusb4500) +{ + struct stusb4500_ftp_ctrl_0 ctrl0_reset = {}; + struct stusb4500_ftp_ctrl_0 ctrl0_on = { .rst_n = 1, .pwr = 1 }; + int err; + + if ((err = stusb4500_i2c_write(stusb4500, STUSB4500_FTP_CTRL_0, &ctrl0_reset, sizeof(ctrl0_reset)))) { + LOG_ERROR("stusb4500_i2c_write STUSB4500_FTP_CTRL_0"); + return err; + } + + if ((err = stusb4500_i2c_write(stusb4500, STUSB4500_FTP_CTRL_0, &ctrl0_on, sizeof(ctrl0_on)))) { + LOG_ERROR("stusb4500_i2c_write STUSB4500_FTP_CTRL_0"); + return err; + } + + return 0; +} + +static int stusb4500_nvm_op(struct stusb4500 *stusb4500, uint8_t opcode, uint8_t ser, uint8_t sector) +{ + struct stusb4500_ftp_ctrl_1 ctrl1_op = { .opcode = opcode, .ser = ser }; + struct stusb4500_ftp_ctrl_0 ctrl0_op = { .sector = sector, .req = 1, .rst_n = 1, .pwr = 1 }; + int err; + + if ((err = stusb4500_i2c_write(stusb4500, STUSB4500_FTP_CTRL_1, &ctrl1_op, sizeof(ctrl1_op)))) { + LOG_ERROR("stusb4500_i2c_write STUSB4500_FTP_CTRL_1"); + return err; + } + + if ((err = stusb4500_i2c_write(stusb4500, STUSB4500_FTP_CTRL_0, &ctrl0_op, sizeof(ctrl0_op)))) { + LOG_ERROR("stusb4500_i2c_write STUSB4500_FTP_CTRL_1"); + return err; + } + + while (ctrl0_op.req) { + if ((err = stusb4500_i2c_read(stusb4500, STUSB4500_FTP_CTRL_0, &ctrl0_op, sizeof(ctrl0_op)))) { + LOG_ERROR("stusb4500_i2c_read STUSB4500_FTP_CTRL_0"); + return err; + } + } + + return 0; +} + +static int stusb4500_nvm_read_sector(struct stusb4500 *stusb4500, uint8_t sector, stusb4500_nvm_sector_t *data) +{ + int err; + + if ((err = stusb4500_nvm_reset(stusb4500))) { + return err; + } + + if ((err = stusb4500_nvm_op(stusb4500, STUSB4500_FTP_CTRL_OPCODE_READ, 0, sector))) { + return err; + } + + if ((err = stusb4500_i2c_read(stusb4500, STUSB4500_RW_BUFFER_0, data, sizeof(*data)))) { + LOG_ERROR("stusb4500_i2c_read STUSB4500_RW_BUFFER_0"); + return err; + } + + return 0; +} + +int stusb4500_nvm_read(struct stusb4500 *stusb4500, struct stusb4500_nvm *nvm) +{ + int err; + + if ((err = stusb4500_nvm_unlock(stusb4500))) { + LOG_ERROR("stusb4500_nvm_unlock"); + return err; + } + + for (int i = 0; i < STUSB4500_NVM_SECTOR_COUNT; i++) { + if ((err = stusb4500_nvm_read_sector(stusb4500, i, &nvm->sectors[i]))) { + LOG_ERROR("stusb4500_nvm_read_sector %d", i); + return err; + } + } + + if ((err = stusb4500_nvm_lock(stusb4500))) { + LOG_ERROR("stusb4500_nvm_lock"); + return err; + } + + + return 0; +} diff --git a/components/usb_pd_sink/stusb4500_nvm.h b/components/usb_pd_sink/stusb4500_nvm.h new file mode 100644 index 00000000..d6ac1243 --- /dev/null +++ b/components/usb_pd_sink/stusb4500_nvm.h @@ -0,0 +1,12 @@ +#pragma once + +#include + +#define STUSB4500_NVM_SECTOR_COUNT 5 +#define STUSB4500_NVM_SECTOR_SIZE 8 + +typedef uint8_t stusb4500_nvm_sector_t[STUSB4500_NVM_SECTOR_SIZE]; + +struct stusb4500_nvm { + stusb4500_nvm_sector_t sectors[STUSB4500_NVM_SECTOR_COUNT]; +}; From f974a63ba15c7d7c1ee4b386e658ed160cdf4caa Mon Sep 17 00:00:00 2001 From: Tero Marttila Date: Sat, 20 Jan 2024 00:39:12 +0200 Subject: [PATCH 10/24] usb_pd_sink stusb4500: map nvm banks from docs --- components/usb_pd_sink/stusb4500.c | 43 ++++++++++++- components/usb_pd_sink/stusb4500.h | 2 +- components/usb_pd_sink/stusb4500_nvm.c | 2 +- components/usb_pd_sink/stusb4500_nvm.h | 86 +++++++++++++++++++++++++- 4 files changed, 129 insertions(+), 4 deletions(-) diff --git a/components/usb_pd_sink/stusb4500.c b/components/usb_pd_sink/stusb4500.c index d52fadd1..a2b35fbc 100644 --- a/components/usb_pd_sink/stusb4500.c +++ b/components/usb_pd_sink/stusb4500.c @@ -199,7 +199,7 @@ int stusb4500_get_rdo(struct stusb4500 *stusb4500) int stusb4500_get_nvm(struct stusb4500 *stusb4500) { - struct stusb4500_nvm nvm = {}; + union stusb4500_nvm nvm = {}; int err; if ((err = stusb4500_nvm_read(stusb4500, &nvm))) { @@ -220,6 +220,47 @@ int stusb4500_get_nvm(struct stusb4500 *stusb4500) ); } + LOG_DEBUG("nvm bank0 vendor_id=%04x product_id=%04x bcd_device_id=%04x port_role_ctrl=%u device_power_role_ctrl=%u", + nvm.banks.bank0.vendor_id, + nvm.banks.bank0.product_id, + nvm.banks.bank0.bcd_device_id, + nvm.banks.bank0.port_role_ctrl, + nvm.banks.bank0.device_power_role_ctrl + ); + + LOG_DEBUG("nvm bank1 gpio_cfg=%u vbus_dchg_mask=%u vbus_disch_time_to_pdo=%u discharge_time_to_0v=%u", + nvm.banks.bank1.gpio_cfg, + nvm.banks.bank1.vbus_dchg_mask, + nvm.banks.bank1.vbus_disch_time_to_pdo, + nvm.banks.bank1.discharge_time_to_0v + ); + + LOG_DEBUG("nvm bank3 usb_comm_capable=%u dpm_snk_pdo_numb=%u snk_uncons_power=%u", + nvm.banks.bank3.usb_comm_capable, + nvm.banks.bank3.dpm_snk_pdo_numb, + nvm.banks.bank3.snk_uncons_power + ); + + LOG_DEBUG("nvm bank3 pdo1(i=%u ll=%u hl=%u) pdo2(i=%u ll=%u hl=%u) pdo3(i=%u ll=%u hl=%u)", + nvm.banks.bank3.lut_snk_pdo1_i, + nvm.banks.bank3.snk_ll1, + nvm.banks.bank3.snk_hl1, + nvm.banks.bank3.lut_snk_pdo2_i, + nvm.banks.bank3.snk_ll2, + nvm.banks.bank3.snk_hl2, + nvm.banks.bank3.lut_snk_pdo3_i, + nvm.banks.bank3.snk_ll3, + nvm.banks.bank3.snk_hl3 + ); + + LOG_DEBUG("nvm bank4 snk_pdo_flex1_v=%u snk_pdo_flex2_v=%u snk_pdo_flex_i=%u power_ok_cfg=%u req_src_current=%u", + nvm.banks.bank4.snk_pdo_flex1_v, + nvm.banks.bank4.snk_pdo_flex2_v, + nvm.banks.bank4.snk_pdo_flex_i, + nvm.banks.bank4.power_ok_cfg, + nvm.banks.bank4.req_src_current + ); + return 0; } diff --git a/components/usb_pd_sink/stusb4500.h b/components/usb_pd_sink/stusb4500.h index 3fdb814f..66be199d 100644 --- a/components/usb_pd_sink/stusb4500.h +++ b/components/usb_pd_sink/stusb4500.h @@ -17,4 +17,4 @@ int stusb4500_start(struct stusb4500 *stusb4500); int stusb4500_i2c_read(struct stusb4500 *stusb4500, enum stusb4500_i2c_register reg, void *out, size_t size); int stusb4500_i2c_write(struct stusb4500 *stusb4500, enum stusb4500_i2c_register reg, void *buf, size_t size); -int stusb4500_nvm_read(struct stusb4500 *stusb4500, struct stusb4500_nvm *nvm); +int stusb4500_nvm_read(struct stusb4500 *stusb4500, union stusb4500_nvm *nvm); diff --git a/components/usb_pd_sink/stusb4500_nvm.c b/components/usb_pd_sink/stusb4500_nvm.c index e4dbd722..2a2861cf 100644 --- a/components/usb_pd_sink/stusb4500_nvm.c +++ b/components/usb_pd_sink/stusb4500_nvm.c @@ -117,7 +117,7 @@ static int stusb4500_nvm_read_sector(struct stusb4500 *stusb4500, uint8_t sector return 0; } -int stusb4500_nvm_read(struct stusb4500 *stusb4500, struct stusb4500_nvm *nvm) +int stusb4500_nvm_read(struct stusb4500 *stusb4500, union stusb4500_nvm *nvm) { int err; diff --git a/components/usb_pd_sink/stusb4500_nvm.h b/components/usb_pd_sink/stusb4500_nvm.h index d6ac1243..aa249905 100644 --- a/components/usb_pd_sink/stusb4500_nvm.h +++ b/components/usb_pd_sink/stusb4500_nvm.h @@ -7,6 +7,90 @@ typedef uint8_t stusb4500_nvm_sector_t[STUSB4500_NVM_SECTOR_SIZE]; -struct stusb4500_nvm { +union stusb4500_nvm { stusb4500_nvm_sector_t sectors[STUSB4500_NVM_SECTOR_COUNT]; + + // from STUSB4500_NVM TNxxx + // https://community.st.com/t5/interface-and-connectivity-ics/about-the-nvm-programming-for-stusb4500/m-p/378217/highlight/true#M6664 + struct stusb4500_banks { + struct stusb4500_bank0 { + uint16_t vendor_id; // 0x0000 + + uint16_t product_id; // 0xAAB0 + + uint16_t bcd_device_id; // 0x4500 + + uint16_t port_role_ctrl : 8; // 0x00 + uint16_t device_power_role_ctrl : 8; // 0x00 + } bank0; + + struct stusb4500_bank1 { + uint8_t reserved0_0 : 4; // 0x0 + uint8_t gpio_cfg : 2; + uint8_t reserved0_6 : 2; // 0b00 + + uint8_t reserved1_0 : 5; // 0b00000 + uint8_t vbus_dchg_mask : 1; + uint8_t reserved1_6 : 1; // 1 + uint8_t reserved1_7 : 1; // 0 + + uint8_t vbus_disch_time_to_pdo : 4; + uint8_t discharge_time_to_0v : 4; + + uint8_t reserved3 : 8; // 0x1C + uint8_t reserved4 : 8; // 0xFF + uint8_t reserved5 : 8; // 0x01 + uint8_t reserved6 : 8; // 0x3C + uint8_t reserved7 : 8; // 0xDF + } bank1; + + struct stusb4500_bank2 { + uint8_t reserved0 : 8; // 0x02 + uint8_t reserved1 : 8; // 0x40 + uint8_t reserved2 : 8; // 0x0F + uint8_t reserved3 : 8; // 0x00 + uint8_t reserved4 : 8; // 0x32 + uint8_t reserved5 : 8; // 0x00 + uint8_t reserved6 : 8; // 0xFC + uint8_t reserved7 : 8; // 0xF1 + } bank2; + + struct stusb4500_bank3 { + uint8_t reserved0 : 8; // 0x00 + uint8_t reserved1 : 8; // 0x19 + + uint8_t usb_comm_capable : 1; + uint8_t dpm_snk_pdo_numb : 2; + uint8_t snk_uncons_power : 1; + uint8_t lut_snk_pdo1_i : 4; + + uint8_t snk_ll1 : 4; + uint8_t snk_hl1 : 4; + + uint8_t lut_snk_pdo2_i : 4; + uint8_t snk_ll2 : 4; + + uint8_t snk_hl2 : 4; + uint8_t lut_snk_pdo3_i : 4; + + uint8_t snk_ll3 : 4; + uint8_t snk_hl3 : 4; + + uint8_t reserved7 : 8; // SNK_PDO_FILL_0xDF = 0x00 + } bank3; + + struct stusb4500_bank4 { + uint64_t reserved0_0 : 6; // 0b000000 + uint64_t snk_pdo_flex1_v : 10; + uint64_t snk_pdo_flex2_v : 10; + uint64_t snk_pdo_flex_i : 10; + uint64_t reserved5_4 : 1; // 0 + uint64_t power_ok_cfg : 2; + uint64_t reserved5_7 : 1; // 0 + uint64_t reserved6_0 : 4; // 0x0 + uint64_t req_src_current : 1; + uint64_t reserved6_5 : 3; // 0b010 + uint64_t reserved7 : 8; // ALERT_STATUS_1_MASK + } bank4; + } banks; }; From 744abfbb53ae8f331bea7f742567f64ad0639097 Mon Sep 17 00:00:00 2001 From: Tero Marttila Date: Sat, 20 Jan 2024 00:40:15 +0200 Subject: [PATCH 11/24] usb_pd_sink stusb4500: add nvm power_only_above_5v at bank 4, byte 6, bit 3 --- components/usb_pd_sink/stusb4500.c | 3 ++- components/usb_pd_sink/stusb4500_nvm.h | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/components/usb_pd_sink/stusb4500.c b/components/usb_pd_sink/stusb4500.c index a2b35fbc..745c0e2c 100644 --- a/components/usb_pd_sink/stusb4500.c +++ b/components/usb_pd_sink/stusb4500.c @@ -253,11 +253,12 @@ int stusb4500_get_nvm(struct stusb4500 *stusb4500) nvm.banks.bank3.snk_hl3 ); - LOG_DEBUG("nvm bank4 snk_pdo_flex1_v=%u snk_pdo_flex2_v=%u snk_pdo_flex_i=%u power_ok_cfg=%u req_src_current=%u", + LOG_DEBUG("nvm bank4 snk_pdo_flex1_v=%u snk_pdo_flex2_v=%u snk_pdo_flex_i=%u power_ok_cfg=%u power_only_above_5v=%u req_src_current=%u", nvm.banks.bank4.snk_pdo_flex1_v, nvm.banks.bank4.snk_pdo_flex2_v, nvm.banks.bank4.snk_pdo_flex_i, nvm.banks.bank4.power_ok_cfg, + nvm.banks.bank4.power_only_above_5v, nvm.banks.bank4.req_src_current ); diff --git a/components/usb_pd_sink/stusb4500_nvm.h b/components/usb_pd_sink/stusb4500_nvm.h index aa249905..dc205243 100644 --- a/components/usb_pd_sink/stusb4500_nvm.h +++ b/components/usb_pd_sink/stusb4500_nvm.h @@ -87,7 +87,8 @@ union stusb4500_nvm { uint64_t reserved5_4 : 1; // 0 uint64_t power_ok_cfg : 2; uint64_t reserved5_7 : 1; // 0 - uint64_t reserved6_0 : 4; // 0x0 + uint64_t reserved6_0 : 3; // 0x0 + uint64_t power_only_above_5v : 1; uint64_t req_src_current : 1; uint64_t reserved6_5 : 3; // 0b010 uint64_t reserved7 : 8; // ALERT_STATUS_1_MASK From 4da373a48c7c218fc2f1317963ba920f1391c624 Mon Sep 17 00:00:00 2001 From: Tero Marttila Date: Sat, 20 Jan 2024 01:57:37 +0200 Subject: [PATCH 12/24] usb_pd_sink stusb4500: nvm write --- components/usb_pd_sink/stusb4500.h | 5 +- components/usb_pd_sink/stusb4500_i2c.c | 6 +- components/usb_pd_sink/stusb4500_i2c.h | 2 + components/usb_pd_sink/stusb4500_nvm.c | 89 ++++++++++++++++++++++++-- 4 files changed, 92 insertions(+), 10 deletions(-) diff --git a/components/usb_pd_sink/stusb4500.h b/components/usb_pd_sink/stusb4500.h index 66be199d..d5ca8bf1 100644 --- a/components/usb_pd_sink/stusb4500.h +++ b/components/usb_pd_sink/stusb4500.h @@ -14,7 +14,8 @@ struct stusb4500 { int stusb4500_init(struct stusb4500 *stusb4500, const struct usb_pd_sink_options *options); int stusb4500_start(struct stusb4500 *stusb4500); -int stusb4500_i2c_read(struct stusb4500 *stusb4500, enum stusb4500_i2c_register reg, void *out, size_t size); -int stusb4500_i2c_write(struct stusb4500 *stusb4500, enum stusb4500_i2c_register reg, void *buf, size_t size); +int stusb4500_i2c_read(struct stusb4500 *stusb4500, enum stusb4500_i2c_register reg, void *buf, size_t size); +int stusb4500_i2c_write(struct stusb4500 *stusb4500, enum stusb4500_i2c_register reg, const void *buf, size_t size); int stusb4500_nvm_read(struct stusb4500 *stusb4500, union stusb4500_nvm *nvm); +int stusb4500_nvm_write(struct stusb4500 *stusb4500, const union stusb4500_nvm *nvm); diff --git a/components/usb_pd_sink/stusb4500_i2c.c b/components/usb_pd_sink/stusb4500_i2c.c index 229b5999..652eec96 100644 --- a/components/usb_pd_sink/stusb4500_i2c.c +++ b/components/usb_pd_sink/stusb4500_i2c.c @@ -22,7 +22,7 @@ int stusb4500_i2c_read(struct stusb4500 *stusb4500, enum stusb4500_i2c_register goto error; } - LOG_DEBUG("i2c_addr=%u cmd=%u", stusb4500->i2c_addr, cmd); + LOG_DEBUG("i2c_addr=%02x cmd=%02x", stusb4500->i2c_addr, cmd); if ((err = i2c_master_write_byte(handle, stusb4500->i2c_addr << 1 | I2C_MASTER_WRITE, true))) { LOG_ERROR("i2c_master_write_byte: %s", esp_err_to_name(err)); @@ -69,7 +69,7 @@ int stusb4500_i2c_read(struct stusb4500 *stusb4500, enum stusb4500_i2c_register return err; } -int stusb4500_i2c_write(struct stusb4500 *stusb4500, enum stusb4500_i2c_register cmd, void *buf, size_t size) +int stusb4500_i2c_write(struct stusb4500 *stusb4500, enum stusb4500_i2c_register cmd, const void *buf, size_t size) { uint8_t buffer[I2C_LINK_RECOMMENDED_SIZE(1)] = { 0 }; i2c_cmd_handle_t handle; @@ -85,7 +85,7 @@ int stusb4500_i2c_write(struct stusb4500 *stusb4500, enum stusb4500_i2c_register goto error; } - LOG_DEBUG("i2c_addr=%u cmd=%u", stusb4500->i2c_addr, cmd); + LOG_DEBUG("i2c_addr=%02x cmd=%02x", stusb4500->i2c_addr, cmd); if ((err = i2c_master_write_byte(handle, stusb4500->i2c_addr << 1 | I2C_MASTER_WRITE, true))) { LOG_ERROR("i2c_master_write_byte: %s", esp_err_to_name(err)); diff --git a/components/usb_pd_sink/stusb4500_i2c.h b/components/usb_pd_sink/stusb4500_i2c.h index a4621617..19c61680 100644 --- a/components/usb_pd_sink/stusb4500_i2c.h +++ b/components/usb_pd_sink/stusb4500_i2c.h @@ -336,6 +336,8 @@ enum stusb4500_ftp_ctrl_opcode { STUSB4500_FTP_CTRL_OPCODE_SOFT_PROG_SECTOR = 0x07, }; +#define STUSB4500_FTP_SER_SECTORS (0x1F) + enum stusb4500_ftp_ctrl_ser { STUSB4500_FTP_SER_SECTOR_0 = 0x01, STUSB4500_FTP_SER_SECTOR_1 = 0x02, diff --git a/components/usb_pd_sink/stusb4500_nvm.c b/components/usb_pd_sink/stusb4500_nvm.c index 2a2861cf..cfe6a3ff 100644 --- a/components/usb_pd_sink/stusb4500_nvm.c +++ b/components/usb_pd_sink/stusb4500_nvm.c @@ -21,7 +21,7 @@ static int stusb4500_nvm_unlock(struct stusb4500 *stusb4500) return 0; } -static int stusb4500_nvm_lock(struct stusb4500 *stusb4500) +static int stusb4500_nvm_lock(struct stusb4500 *stusb4500, bool reset) { struct stusb4500_ftp_ctrl_0 ctrl0_reset = {}; struct stusb4500_ftp_ctrl_0 ctrl0_off = { .rst_n = 1 }; @@ -29,9 +29,11 @@ static int stusb4500_nvm_lock(struct stusb4500 *stusb4500) struct stusb4500_ftp_cust_password password_clear = { }; int err; - if ((err = stusb4500_i2c_write(stusb4500, STUSB4500_FTP_CTRL_0, &ctrl0_reset, sizeof(ctrl0_reset)))) { - LOG_ERROR("stusb4500_i2c_write STUSB4500_FTP_CTRL_0"); - return err; + if (reset) { + if ((err = stusb4500_i2c_write(stusb4500, STUSB4500_FTP_CTRL_0, &ctrl0_reset, sizeof(ctrl0_reset)))) { + LOG_ERROR("stusb4500_i2c_write STUSB4500_FTP_CTRL_0"); + return err; + } } if ((err = stusb4500_i2c_write(stusb4500, STUSB4500_FTP_CTRL_0, &ctrl0_off, sizeof(ctrl0_off)))) { @@ -117,6 +119,52 @@ static int stusb4500_nvm_read_sector(struct stusb4500 *stusb4500, uint8_t sector return 0; } +static int stusb4500_nvm_erase_sectors(struct stusb4500 *stusb4500, uint8_t ser) +{ + stusb4500_nvm_sector_t sector_empty = {}; + int err; + + // RWBUFFER must be 0 for Partial Erase + if ((err = stusb4500_i2c_write(stusb4500, STUSB4500_RW_BUFFER_0, §or_empty, sizeof(sector_empty)))) { + LOG_ERROR("stusb4500_i2c_write STUSB4500_RW_BUFFER_0"); + return err; + } + + if ((err = stusb4500_nvm_op(stusb4500, STUSB4500_FTP_CTRL_OPCODE_WRITE_SER, ser, 0))) { + return err; + } + + if ((err = stusb4500_nvm_op(stusb4500, STUSB4500_FTP_CTRL_OPCODE_SOFT_PROG_SECTOR, 0, 0))) { + return err; + } + + if ((err = stusb4500_nvm_op(stusb4500, STUSB4500_FTP_CTRL_OPCODE_ERASE_SECTOR, 0, 0))) { + return err; + } + + return 0; +} + +static int stusb4500_nvm_write_sector(struct stusb4500 *stusb4500, uint8_t sector, const stusb4500_nvm_sector_t *data) +{ + int err; + + if ((err = stusb4500_i2c_write(stusb4500, STUSB4500_RW_BUFFER_0, data, sizeof(*data)))) { + LOG_ERROR("stusb4500_i2c_write STUSB4500_RW_BUFFER_0"); + return err; + } + + if ((err = stusb4500_nvm_op(stusb4500, STUSB4500_FTP_CTRL_OPCODE_WRITE_PL, 0, 0))) { + return err; + } + + if ((err = stusb4500_nvm_op(stusb4500, STUSB4500_FTP_CTRL_OPCODE_PROG_SECTOR, 0, sector))) { + return err; + } + + return 0; +} + int stusb4500_nvm_read(struct stusb4500 *stusb4500, union stusb4500_nvm *nvm) { int err; @@ -133,11 +181,42 @@ int stusb4500_nvm_read(struct stusb4500 *stusb4500, union stusb4500_nvm *nvm) } } - if ((err = stusb4500_nvm_lock(stusb4500))) { + if ((err = stusb4500_nvm_lock(stusb4500, true))) { LOG_ERROR("stusb4500_nvm_lock"); return err; } + return 0; +} + +int stusb4500_nvm_write(struct stusb4500 *stusb4500, const union stusb4500_nvm *nvm) +{ + int err; + + if ((err = stusb4500_nvm_unlock(stusb4500))) { + LOG_ERROR("stusb4500_nvm_unlock"); + return err; + } + + if ((err = stusb4500_nvm_reset(stusb4500))) { + return err; + } + + if ((err = stusb4500_nvm_erase_sectors(stusb4500, STUSB4500_FTP_SER_SECTORS))) { + return err; + } + + for (int i = 0; i < STUSB4500_NVM_SECTOR_COUNT; i++) { + if ((err = stusb4500_nvm_write_sector(stusb4500, i, &nvm->sectors[i]))) { + LOG_ERROR("stusb4500_nvm_write_sector %d", i); + return err; + } + } + + if ((err = stusb4500_nvm_lock(stusb4500, false))) { + LOG_ERROR("stusb4500_nvm_lock"); + return err; + } return 0; } From 2af981bd21d8b4218f4a0e8a72915163106b8b98 Mon Sep 17 00:00:00 2001 From: Tero Marttila Date: Sat, 20 Jan 2024 01:58:07 +0200 Subject: [PATCH 13/24] usb_pd_sink stusb4500: setup -> nvm config from Kconfig --- components/usb_pd_sink/Kconfig | 5 + components/usb_pd_sink/include/usb_pd_sink.h | 8 ++ components/usb_pd_sink/stusb4500.c | 113 +++++++++++-------- components/usb_pd_sink/stusb4500.h | 4 + components/usb_pd_sink/stusb4500_config.c | 68 +++++++++++ components/usb_pd_sink/stusb4500_nvm.h | 4 + components/usb_pd_sink/usb_pd_sink.c | 12 ++ main/usb_pd_sink.c | 5 + 8 files changed, 170 insertions(+), 49 deletions(-) create mode 100644 components/usb_pd_sink/Kconfig create mode 100644 components/usb_pd_sink/stusb4500_config.c diff --git a/components/usb_pd_sink/Kconfig b/components/usb_pd_sink/Kconfig new file mode 100644 index 00000000..f12f0c56 --- /dev/null +++ b/components/usb_pd_sink/Kconfig @@ -0,0 +1,5 @@ +menu "STUSB4500" + config STUSB4500_POWER_ONLY_ABOVE_5V + bool "Only enable VBUS_EN_SNK pin when source attached and voltage is negotiated to PDO2/3" + +endmenu diff --git a/components/usb_pd_sink/include/usb_pd_sink.h b/components/usb_pd_sink/include/usb_pd_sink.h index f8876e69..69efd999 100644 --- a/components/usb_pd_sink/include/usb_pd_sink.h +++ b/components/usb_pd_sink/include/usb_pd_sink.h @@ -25,4 +25,12 @@ struct usb_pd_sink; int usb_pd_sink_new(struct usb_pd_sink **sinkp, const struct usb_pd_sink_options *options); +/* + * Static USB-PD Sink setup from Kconfig. + */ +int usb_pd_sink_setup(struct usb_pd_sink *sink); + +/* + * Start USB-PD Sink. + */ int usb_pd_sink_start(struct usb_pd_sink *sink); diff --git a/components/usb_pd_sink/stusb4500.c b/components/usb_pd_sink/stusb4500.c index 745c0e2c..e2940083 100644 --- a/components/usb_pd_sink/stusb4500.c +++ b/components/usb_pd_sink/stusb4500.c @@ -197,83 +197,98 @@ int stusb4500_get_rdo(struct stusb4500 *stusb4500) return 0; } -int stusb4500_get_nvm(struct stusb4500 *stusb4500) +static void stusb4500_nvm_debug(const union stusb4500_nvm *nvm) { - union stusb4500_nvm nvm = {}; - int err; - - if ((err = stusb4500_nvm_read(stusb4500, &nvm))) { - LOG_ERROR("stusb4500_nvm_read"); - return err; - } - for (int i = 0; i < STUSB4500_NVM_SECTOR_COUNT; i++) { LOG_DEBUG("nvm sector[%d]: %02x %02x %02x %02x %02x %02x %02x %02x", i, - nvm.sectors[i][0], - nvm.sectors[i][1], - nvm.sectors[i][2], - nvm.sectors[i][3], - nvm.sectors[i][4], - nvm.sectors[i][5], - nvm.sectors[i][6], - nvm.sectors[i][7] + nvm->sectors[i][0], + nvm->sectors[i][1], + nvm->sectors[i][2], + nvm->sectors[i][3], + nvm->sectors[i][4], + nvm->sectors[i][5], + nvm->sectors[i][6], + nvm->sectors[i][7] ); } LOG_DEBUG("nvm bank0 vendor_id=%04x product_id=%04x bcd_device_id=%04x port_role_ctrl=%u device_power_role_ctrl=%u", - nvm.banks.bank0.vendor_id, - nvm.banks.bank0.product_id, - nvm.banks.bank0.bcd_device_id, - nvm.banks.bank0.port_role_ctrl, - nvm.banks.bank0.device_power_role_ctrl + nvm->banks.bank0.vendor_id, + nvm->banks.bank0.product_id, + nvm->banks.bank0.bcd_device_id, + nvm->banks.bank0.port_role_ctrl, + nvm->banks.bank0.device_power_role_ctrl ); LOG_DEBUG("nvm bank1 gpio_cfg=%u vbus_dchg_mask=%u vbus_disch_time_to_pdo=%u discharge_time_to_0v=%u", - nvm.banks.bank1.gpio_cfg, - nvm.banks.bank1.vbus_dchg_mask, - nvm.banks.bank1.vbus_disch_time_to_pdo, - nvm.banks.bank1.discharge_time_to_0v + nvm->banks.bank1.gpio_cfg, + nvm->banks.bank1.vbus_dchg_mask, + nvm->banks.bank1.vbus_disch_time_to_pdo, + nvm->banks.bank1.discharge_time_to_0v ); LOG_DEBUG("nvm bank3 usb_comm_capable=%u dpm_snk_pdo_numb=%u snk_uncons_power=%u", - nvm.banks.bank3.usb_comm_capable, - nvm.banks.bank3.dpm_snk_pdo_numb, - nvm.banks.bank3.snk_uncons_power + nvm->banks.bank3.usb_comm_capable, + nvm->banks.bank3.dpm_snk_pdo_numb, + nvm->banks.bank3.snk_uncons_power ); LOG_DEBUG("nvm bank3 pdo1(i=%u ll=%u hl=%u) pdo2(i=%u ll=%u hl=%u) pdo3(i=%u ll=%u hl=%u)", - nvm.banks.bank3.lut_snk_pdo1_i, - nvm.banks.bank3.snk_ll1, - nvm.banks.bank3.snk_hl1, - nvm.banks.bank3.lut_snk_pdo2_i, - nvm.banks.bank3.snk_ll2, - nvm.banks.bank3.snk_hl2, - nvm.banks.bank3.lut_snk_pdo3_i, - nvm.banks.bank3.snk_ll3, - nvm.banks.bank3.snk_hl3 + nvm->banks.bank3.lut_snk_pdo1_i, + nvm->banks.bank3.snk_ll1, + nvm->banks.bank3.snk_hl1, + nvm->banks.bank3.lut_snk_pdo2_i, + nvm->banks.bank3.snk_ll2, + nvm->banks.bank3.snk_hl2, + nvm->banks.bank3.lut_snk_pdo3_i, + nvm->banks.bank3.snk_ll3, + nvm->banks.bank3.snk_hl3 ); LOG_DEBUG("nvm bank4 snk_pdo_flex1_v=%u snk_pdo_flex2_v=%u snk_pdo_flex_i=%u power_ok_cfg=%u power_only_above_5v=%u req_src_current=%u", - nvm.banks.bank4.snk_pdo_flex1_v, - nvm.banks.bank4.snk_pdo_flex2_v, - nvm.banks.bank4.snk_pdo_flex_i, - nvm.banks.bank4.power_ok_cfg, - nvm.banks.bank4.power_only_above_5v, - nvm.banks.bank4.req_src_current + nvm->banks.bank4.snk_pdo_flex1_v, + nvm->banks.bank4.snk_pdo_flex2_v, + nvm->banks.bank4.snk_pdo_flex_i, + nvm->banks.bank4.power_ok_cfg, + nvm->banks.bank4.power_only_above_5v, + nvm->banks.bank4.req_src_current ); - - return 0; } -int stusb4500_start(struct stusb4500 *stusb4500) +int stusb4500_setup(struct stusb4500 *stusb4500) { + union stusb4500_nvm nvm = {}; int err; - if ((err = stusb4500_get_nvm(stusb4500))) { - LOG_ERROR("stusb4500_get_nvm"); + if ((err = stusb4500_nvm_read(stusb4500, &nvm))) { + LOG_ERROR("stusb4500_nvm_read"); + return err; + } + + stusb4500_nvm_debug(&nvm); + + if ((err = stusb4500_config_nvm(&nvm)) < 0) { + LOG_ERROR("stusb4500_config_nvm"); + return err; + } else if (!err) { + LOG_DEBUG("NVM OK"); + return 0; + } else { + LOG_WARN("NVM changes, write..."); + } + + if ((err = stusb4500_nvm_write(stusb4500, &nvm))) { + LOG_ERROR("stusb4500_nvm_write"); return err; } + return 0; +} + +int stusb4500_start(struct stusb4500 *stusb4500) +{ + int err; + if ((err = stusb4500_get_status(stusb4500))) { LOG_ERROR("stusb4500_get_status"); return err; diff --git a/components/usb_pd_sink/stusb4500.h b/components/usb_pd_sink/stusb4500.h index d5ca8bf1..33192b3e 100644 --- a/components/usb_pd_sink/stusb4500.h +++ b/components/usb_pd_sink/stusb4500.h @@ -12,6 +12,7 @@ struct stusb4500 { }; int stusb4500_init(struct stusb4500 *stusb4500, const struct usb_pd_sink_options *options); +int stusb4500_setup(struct stusb4500 *stusb4500); int stusb4500_start(struct stusb4500 *stusb4500); int stusb4500_i2c_read(struct stusb4500 *stusb4500, enum stusb4500_i2c_register reg, void *buf, size_t size); @@ -19,3 +20,6 @@ int stusb4500_i2c_write(struct stusb4500 *stusb4500, enum stusb4500_i2c_register int stusb4500_nvm_read(struct stusb4500 *stusb4500, union stusb4500_nvm *nvm); int stusb4500_nvm_write(struct stusb4500 *stusb4500, const union stusb4500_nvm *nvm); + +/* Return 0 if unchanged, >0 if modified, <0 on errors */ +int stusb4500_config_nvm(union stusb4500_nvm *nvm); diff --git a/components/usb_pd_sink/stusb4500_config.c b/components/usb_pd_sink/stusb4500_config.c new file mode 100644 index 00000000..8a9a4a77 --- /dev/null +++ b/components/usb_pd_sink/stusb4500_config.c @@ -0,0 +1,68 @@ +#include "stusb4500.h" +#include "stusb4500_nvm.h" + +#include + +#include + +#include + +int stusb4500_config_nvm(union stusb4500_nvm *nvm) +{ + stusb4500_nvm_sector_t zero_sector = {}; + + // sanity-check + for (int i = 0; i < STUSB4500_NVM_SECTOR_COUNT; i++) { + if (!memcmp(nvm->sectors[i], &zero_sector, sizeof(zero_sector))) { + LOG_ERROR("sector%d is all-zeroes, corrupted read?", i); + return -1; + } + } + + for (int i = 1; i < STUSB4500_NVM_SECTOR_COUNT; i++) { + if (!memcmp(nvm->sectors[i], nvm->sectors[i - 1], sizeof(nvm->sectors[i]))) { + LOG_ERROR("sector%d is identical to sector%d, corrupted read?", i, i - 1); + return -1; + } + } + + if (nvm->banks.bank0.vendor_id != STUSB4500_NVM_VENDOR_ID) { + LOG_ERROR("bank0 vendor_id=%04x product_id=%04x bcd_device_id=%04x unsupported vendor_id", + nvm->banks.bank0.vendor_id, + nvm->banks.bank0.product_id, + nvm->banks.bank0.bcd_device_id + ); + return -1; + } + + if (nvm->banks.bank0.product_id != STUSB4500_NVM_PRODUCT_ID) { + LOG_ERROR("bank0 vendor_id=%04x product_id=%04x bcd_device_id=%04x unsupported product_id", + nvm->banks.bank0.vendor_id, + nvm->banks.bank0.product_id, + nvm->banks.bank0.bcd_device_id + ); + return -1; + } + + if (nvm->banks.bank0.bcd_device_id != STUSB4500_NVM_DEVICE_ID) { + LOG_ERROR("bank0 vendor_id=%04x product_id=%04x bcd_device_id=%04x unsupported bcd_device_id", + nvm->banks.bank0.vendor_id, + nvm->banks.bank0.product_id, + nvm->banks.bank0.bcd_device_id + ); + return -1; + } + + // apply config changes + int ret = 0; + + if (nvm->banks.bank4.power_only_above_5v != CONFIG_STUSB4500_POWER_ONLY_ABOVE_5V) { + nvm->banks.bank4.power_only_above_5v = CONFIG_STUSB4500_POWER_ONLY_ABOVE_5V; + + LOG_WARN("set POWER_ONLY_ABOVE_5V = %u", CONFIG_STUSB4500_POWER_ONLY_ABOVE_5V); + + ret++; + } + + return ret; +} diff --git a/components/usb_pd_sink/stusb4500_nvm.h b/components/usb_pd_sink/stusb4500_nvm.h index dc205243..e51f4c31 100644 --- a/components/usb_pd_sink/stusb4500_nvm.h +++ b/components/usb_pd_sink/stusb4500_nvm.h @@ -5,6 +5,10 @@ #define STUSB4500_NVM_SECTOR_COUNT 5 #define STUSB4500_NVM_SECTOR_SIZE 8 +#define STUSB4500_NVM_VENDOR_ID 0x0000 +#define STUSB4500_NVM_PRODUCT_ID 0xABB0 +#define STUSB4500_NVM_DEVICE_ID 0x4500 + typedef uint8_t stusb4500_nvm_sector_t[STUSB4500_NVM_SECTOR_SIZE]; union stusb4500_nvm { diff --git a/components/usb_pd_sink/usb_pd_sink.c b/components/usb_pd_sink/usb_pd_sink.c index e8bf1086..3bd22711 100644 --- a/components/usb_pd_sink/usb_pd_sink.c +++ b/components/usb_pd_sink/usb_pd_sink.c @@ -39,6 +39,18 @@ int usb_pd_sink_new(struct usb_pd_sink **sinkp, const struct usb_pd_sink_options return err; } +int usb_pd_sink_setup(struct usb_pd_sink *sink) +{ + switch (sink->type) { + case USB_PD_SINK_STUSB4500: + return stusb4500_setup(&sink->state.stusb4500); + + default: + LOG_FATAL("invalid type=%d", sink->type); + } + +} + int usb_pd_sink_start(struct usb_pd_sink *sink) { switch (sink->type) { diff --git a/main/usb_pd_sink.c b/main/usb_pd_sink.c index 80bc5c08..6cf4efe7 100644 --- a/main/usb_pd_sink.c +++ b/main/usb_pd_sink.c @@ -28,6 +28,11 @@ return err; } + if ((err = usb_pd_sink_setup(usb_pd_sink))) { + LOG_ERROR("usb_pd_sink_setup"); + return err; + } + return 0; } From c8e7563d86bb2013bfccbe5d7119295ec396a7a9 Mon Sep 17 00:00:00 2001 From: Tero Marttila Date: Sat, 20 Jan 2024 03:04:17 +0200 Subject: [PATCH 14/24] usb_pd_sink stusb4500: reset at boot to apply nvm changes, clear dynamic config --- components/usb_pd_sink/include/usb_pd_sink.h | 2 +- components/usb_pd_sink/stusb4500.c | 39 ++++++++++++++++++-- components/usb_pd_sink/stusb4500.h | 1 + 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/components/usb_pd_sink/include/usb_pd_sink.h b/components/usb_pd_sink/include/usb_pd_sink.h index 69efd999..66a57f42 100644 --- a/components/usb_pd_sink/include/usb_pd_sink.h +++ b/components/usb_pd_sink/include/usb_pd_sink.h @@ -26,7 +26,7 @@ struct usb_pd_sink; int usb_pd_sink_new(struct usb_pd_sink **sinkp, const struct usb_pd_sink_options *options); /* - * Static USB-PD Sink setup from Kconfig. + * Setup USB-PD Sink using static Kconfig defaults. */ int usb_pd_sink_setup(struct usb_pd_sink *sink); diff --git a/components/usb_pd_sink/stusb4500.c b/components/usb_pd_sink/stusb4500.c index e2940083..c7278b79 100644 --- a/components/usb_pd_sink/stusb4500.c +++ b/components/usb_pd_sink/stusb4500.c @@ -255,6 +255,32 @@ static void stusb4500_nvm_debug(const union stusb4500_nvm *nvm) ); } +int stusb4500_reset(struct stusb4500 *stusb4500) +{ + struct stusb4500_reset_ctrl reset_ctrl = { .reset_sw_en = 1 }; + struct stusb4500_reset_ctrl reset_ctrl_clear = { .reset_sw_en = 0 }; + int err; + + if ((err = stusb4500_i2c_write(stusb4500, STUSB4500_RESET_CTRL, &reset_ctrl, sizeof(reset_ctrl)))) { + return err; + } + + if ((err = stusb4500_i2c_read(stusb4500, STUSB4500_RESET_CTRL, &reset_ctrl, sizeof(reset_ctrl)))) { + return err; + } + + // TODO: delay 25ms? + LOG_DEBUG("reset_ctrl: reset_sw_en=%u", + reset_ctrl.reset_sw_en + ); + + if ((err = stusb4500_i2c_write(stusb4500, STUSB4500_RESET_CTRL, &reset_ctrl_clear, sizeof(reset_ctrl_clear)))) { + return err; + } + + return 0; +} + int stusb4500_setup(struct stusb4500 *stusb4500) { union stusb4500_nvm nvm = {}; @@ -271,14 +297,19 @@ int stusb4500_setup(struct stusb4500 *stusb4500) LOG_ERROR("stusb4500_config_nvm"); return err; } else if (!err) { - LOG_DEBUG("NVM OK"); - return 0; + LOG_INFO("NVM OK"); } else { LOG_WARN("NVM changes, write..."); + + if ((err = stusb4500_nvm_write(stusb4500, &nvm))) { + LOG_ERROR("stusb4500_nvm_write"); + return err; + } } - if ((err = stusb4500_nvm_write(stusb4500, &nvm))) { - LOG_ERROR("stusb4500_nvm_write"); + // reset runtime state to NVM defaults + if ((err = stusb4500_reset(stusb4500))) { + LOG_ERROR("stusb4500_reset"); return err; } diff --git a/components/usb_pd_sink/stusb4500.h b/components/usb_pd_sink/stusb4500.h index 33192b3e..0626af21 100644 --- a/components/usb_pd_sink/stusb4500.h +++ b/components/usb_pd_sink/stusb4500.h @@ -12,6 +12,7 @@ struct stusb4500 { }; int stusb4500_init(struct stusb4500 *stusb4500, const struct usb_pd_sink_options *options); +int stusb4500_reset(struct stusb4500 *stusb4500); int stusb4500_setup(struct stusb4500 *stusb4500); int stusb4500_start(struct stusb4500 *stusb4500); From 1965b84c13d8ac66222ab629a4330db6fe73e83c Mon Sep 17 00:00:00 2001 From: Tero Marttila Date: Sat, 20 Jan 2024 03:04:31 +0200 Subject: [PATCH 15/24] usb_pd_sink stusb4500: add more kconfig options for NVM setup --- components/usb_pd_sink/Kconfig | 95 ++++++++++++++ components/usb_pd_sink/stusb4500_config.c | 144 ++++++++++++++++++++++ 2 files changed, 239 insertions(+) diff --git a/components/usb_pd_sink/Kconfig b/components/usb_pd_sink/Kconfig index f12f0c56..69d2fcd8 100644 --- a/components/usb_pd_sink/Kconfig +++ b/components/usb_pd_sink/Kconfig @@ -1,5 +1,100 @@ menu "STUSB4500" + config STUSB4500_SNK_PDO_NUMB + int "Number of sink PDOs" + range 1 3 + default 3 + + config STUSB4500_V_SNK_PDO2 + int "Voltage value for SNK_PDO2 (mV)" + range 5000 20000 + default 15000 + + config STUSB4500_V_SNK_PDO3 + int "Voltage value for SNK_PDO3 (mV)" + range 5000 20000 + default 20000 + + config STUSB4500_I_SNK_PDO1 + int "Current value for SNK_PDO1 (mA)" + range 500 5000 + default 1500 + + config STUSB4500_I_SNK_PDO2 + int "Current value for SNK_PDO2 (mA)" + range 500 5000 + default 1500 + + config STUSB4500_I_SNK_PDO3 + int "Current value for SNK_PDO3 (mA)" + range 500 5000 + default 1000 + + config STUSB4500_VBUS_DISCH_DISABLE + bool "VBUS discharge deactivation on VBUS_VS_DISCH and DISCH pins" + default 0 + + config STUSB4500_USB_COMM_CAPABLE + bool "USB 2.0 or 3.x data communication capability by sink system" + default 0 + + config STUSB4500_SNK_UNCONS_POWER + bool "Unconstrained Power bit setting in capabilities message sent by the sink" + default 0 + + config STUSB4500_REQ_SRC_CURRENT + bool "In case of match, selects which operating current from the sink or the source is to be requested in the RDO message" + default 0 + + choice STUSB4500_POWER_OK_CFG_CHOICE + prompt "Selects POWER_OK pins configuration" + default STUSB4500_POWER_OK_CFG_2 + + config STUSB4500_POWER_OK_CFG_1 + bool "Configuration 1" + + config STUSB4500_POWER_OK_CFG_2 + bool "Configuration 2" + + config STUSB4500_POWER_OK_CFG_3 + bool "Configuration 2" + + endchoice + + config STUSB4500_POWER_OK_CFG + int "Selects POWER_OK pins configuration" + range 0 3 + default 0 if STUSB4500_POWER_OK_CFG_1 + default 2 if STUSB4500_POWER_OK_CFG_2 + default 3 if STUSB4500_POWER_OK_CFG_3 + config STUSB4500_POWER_ONLY_ABOVE_5V bool "Only enable VBUS_EN_SNK pin when source attached and voltage is negotiated to PDO2/3" + default 0 + + choice STUSB4500_GPIO_CFG_CHOICE + prompt "Selects POWER_OK pins configuration" + default STUSB4500_GPIO_CFG_ERROR_RECOVERY + + config STUSB4500_GPIO_CFG_SW_CTRL_GPIO + bool "SW_CTRL_GPIO" + + config STUSB4500_GPIO_CFG_ERROR_RECOVERY + bool "ERROR_RECOVERY" + + config STUSB4500_GPIO_CFG_DEBUG + bool "DEBUG" + + config STUSB4500_GPIO_CFG_SINK_POWER + bool "SINK_POWER" + + endchoice + + config STUSB4500_GPIO_CFG + int "Selects GPIO pin configuration" + range 0 3 + default 0 if STUSB4500_GPIO_CFG_SW_CTRL_GPIO + default 1 if STUSB4500_GPIO_CFG_ERROR_RECOVERY + default 2 if STUSB4500_GPIO_CFG_DEBUG + default 3 if STUSB4500_GPIO_CFG_SINK_POWER endmenu diff --git a/components/usb_pd_sink/stusb4500_config.c b/components/usb_pd_sink/stusb4500_config.c index 8a9a4a77..316225b1 100644 --- a/components/usb_pd_sink/stusb4500_config.c +++ b/components/usb_pd_sink/stusb4500_config.c @@ -7,6 +7,46 @@ #include +#ifndef CONFIG_STUSB4500_VBUS_DISCH_DISABLE + #define CONFIG_STUSB4500_VBUS_DISCH_DISABLE 0 +#endif + +#ifndef CONFIG_STUSB4500_USB_COMM_CAPABLE + #define CONFIG_STUSB4500_USB_COMM_CAPABLE 0 +#endif + +#ifndef CONFIG_STUSB4500_SNK_UNCONS_POWER + #define CONFIG_STUSB4500_SNK_UNCONS_POWER 0 +#endif + +#ifndef CONFIG_STUSB4500_REQ_SRC_CURRENT + #define CONFIG_STUSB4500_REQ_SRC_CURRENT 0 +#endif + +#ifndef CONFIG_STUSB4500_POWER_ONLY_ABOVE_5V + #define CONFIG_STUSB4500_POWER_ONLY_ABOVE_5V 0 +#endif + +// convert from kconfig mV -> flex_v [50mV] +static inline unsigned config_snk_pdo_flex_v(unsigned config_mV) +{ + return config_mV / 50; +} + +// convert from kconfig mA -> lut_i +static inline unsigned config_snk_pdo_i(unsigned config_mA) +{ + if (config_mA < 500) { + return 0b001; // 0.5A + } else if (config_mA < 3000) { + return (config_mA - 500) / 250 + 1; + } else if (config_mA < 5000) { + return (config_mA - 3000) / 500 + 11; + } else { + return 0b1111; + } +} + int stusb4500_config_nvm(union stusb4500_nvm *nvm) { stusb4500_nvm_sector_t zero_sector = {}; @@ -56,6 +96,102 @@ int stusb4500_config_nvm(union stusb4500_nvm *nvm) // apply config changes int ret = 0; + if (nvm->banks.bank3.dpm_snk_pdo_numb != CONFIG_STUSB4500_SNK_PDO_NUMB) { + nvm->banks.bank3.dpm_snk_pdo_numb = CONFIG_STUSB4500_SNK_PDO_NUMB; + + LOG_WARN("set CONFIG_STUSB4500_SNK_PDO_NUMB = %u", CONFIG_STUSB4500_SNK_PDO_NUMB); + + ret++; + } + + if (nvm->banks.bank4.snk_pdo_flex1_v != config_snk_pdo_flex_v(CONFIG_STUSB4500_V_SNK_PDO2)) { + nvm->banks.bank4.snk_pdo_flex1_v = config_snk_pdo_flex_v(CONFIG_STUSB4500_V_SNK_PDO2); + + LOG_WARN("set CONFIG_STUSB4500_V_SNK_PDO2 = %u", config_snk_pdo_flex_v(CONFIG_STUSB4500_V_SNK_PDO2)); + + ret++; + } + + if (nvm->banks.bank4.snk_pdo_flex2_v != config_snk_pdo_flex_v(CONFIG_STUSB4500_V_SNK_PDO3)) { + nvm->banks.bank4.snk_pdo_flex2_v = config_snk_pdo_flex_v(CONFIG_STUSB4500_V_SNK_PDO3); + + LOG_WARN("set CONFIG_STUSB4500_V_SNK_PDO3 = %u", config_snk_pdo_flex_v(CONFIG_STUSB4500_V_SNK_PDO3)); + + ret++; + } + + if (nvm->banks.bank3.lut_snk_pdo1_i != config_snk_pdo_i(CONFIG_STUSB4500_I_SNK_PDO1)) { + nvm->banks.bank3.lut_snk_pdo1_i = config_snk_pdo_i(CONFIG_STUSB4500_I_SNK_PDO1); + + LOG_WARN("set CONFIG_STUSB4500_I_SNK_PDO1 = %u", config_snk_pdo_i(CONFIG_STUSB4500_I_SNK_PDO1)); + + ret++; + } + + if (nvm->banks.bank3.lut_snk_pdo2_i != config_snk_pdo_i(CONFIG_STUSB4500_I_SNK_PDO2)) { + nvm->banks.bank3.lut_snk_pdo2_i = config_snk_pdo_i(CONFIG_STUSB4500_I_SNK_PDO2); + + LOG_WARN("set STUSB4500_I_SNK_PDO2 = %u", config_snk_pdo_i(CONFIG_STUSB4500_I_SNK_PDO2)); + + ret++; + } + + if (nvm->banks.bank3.lut_snk_pdo3_i != config_snk_pdo_i(CONFIG_STUSB4500_I_SNK_PDO3)) { + nvm->banks.bank3.lut_snk_pdo3_i = config_snk_pdo_i(CONFIG_STUSB4500_I_SNK_PDO3); + + LOG_WARN("set STUSB4500_I_SNK_PDO3 = %u", config_snk_pdo_i(CONFIG_STUSB4500_I_SNK_PDO3)); + + ret++; + } + + if (nvm->banks.bank3.dpm_snk_pdo_numb != CONFIG_STUSB4500_SNK_PDO_NUMB) { + nvm->banks.bank3.dpm_snk_pdo_numb = CONFIG_STUSB4500_SNK_PDO_NUMB; + + LOG_WARN("set CONFIG_STUSB4500_SNK_PDO_NUMB = %u", CONFIG_STUSB4500_SNK_PDO_NUMB); + + ret++; + } + + if (nvm->banks.bank1.vbus_dchg_mask != CONFIG_STUSB4500_VBUS_DISCH_DISABLE) { + nvm->banks.bank1.vbus_dchg_mask = CONFIG_STUSB4500_VBUS_DISCH_DISABLE; + + LOG_WARN("set CONFIG_STUSB4500_VBUS_DISCH_DISABLE = %u", CONFIG_STUSB4500_VBUS_DISCH_DISABLE); + + ret++; + } + + if (nvm->banks.bank3.usb_comm_capable != CONFIG_STUSB4500_USB_COMM_CAPABLE) { + nvm->banks.bank3.usb_comm_capable = CONFIG_STUSB4500_USB_COMM_CAPABLE; + + LOG_WARN("set CONFIG_STUSB4500_USB_COMM_CAPABLE = %u", CONFIG_STUSB4500_USB_COMM_CAPABLE); + + ret++; + } + + if (nvm->banks.bank3.snk_uncons_power != CONFIG_STUSB4500_SNK_UNCONS_POWER) { + nvm->banks.bank3.snk_uncons_power = CONFIG_STUSB4500_SNK_UNCONS_POWER; + + LOG_WARN("set CONFIG_STUSB4500_SNK_UNCONS_POWER = %u", CONFIG_STUSB4500_SNK_UNCONS_POWER); + + ret++; + } + + if (nvm->banks.bank4.req_src_current != CONFIG_STUSB4500_REQ_SRC_CURRENT) { + nvm->banks.bank4.req_src_current = CONFIG_STUSB4500_REQ_SRC_CURRENT; + + LOG_WARN("set CONFIG_STUSB4500_REQ_SRC_CURRENT = %u", CONFIG_STUSB4500_REQ_SRC_CURRENT); + + ret++; + } + + if (nvm->banks.bank4.power_ok_cfg != CONFIG_STUSB4500_POWER_OK_CFG) { + nvm->banks.bank4.power_ok_cfg = CONFIG_STUSB4500_POWER_OK_CFG; + + LOG_WARN("set CONFIG_STUSB4500_POWER_OK_CFG = %u", CONFIG_STUSB4500_POWER_OK_CFG); + + ret++; + } + if (nvm->banks.bank4.power_only_above_5v != CONFIG_STUSB4500_POWER_ONLY_ABOVE_5V) { nvm->banks.bank4.power_only_above_5v = CONFIG_STUSB4500_POWER_ONLY_ABOVE_5V; @@ -64,5 +200,13 @@ int stusb4500_config_nvm(union stusb4500_nvm *nvm) ret++; } + if (nvm->banks.bank1.gpio_cfg != CONFIG_STUSB4500_GPIO_CFG) { + nvm->banks.bank1.gpio_cfg = CONFIG_STUSB4500_GPIO_CFG; + + LOG_WARN("set STUSB4500_GPIO_CFG = %u", CONFIG_STUSB4500_GPIO_CFG); + + ret++; + } + return ret; } From 48950ffbc68dc882f616b893b54e2cc8bf5de3ce Mon Sep 17 00:00:00 2001 From: Tero Marttila Date: Sat, 20 Jan 2024 03:33:23 +0200 Subject: [PATCH 16/24] usb_pd_sink stusb4500: status api --- components/usb_pd_sink/include/usb_pd_sink.h | 20 ++++++++ components/usb_pd_sink/stusb4500.c | 48 +++++++++++++++++++- components/usb_pd_sink/stusb4500.h | 1 + components/usb_pd_sink/stusb4500_i2c.h | 2 +- components/usb_pd_sink/usb_pd_sink.c | 10 ++++ 5 files changed, 78 insertions(+), 3 deletions(-) diff --git a/components/usb_pd_sink/include/usb_pd_sink.h b/components/usb_pd_sink/include/usb_pd_sink.h index 66a57f42..8458f2e7 100644 --- a/components/usb_pd_sink/include/usb_pd_sink.h +++ b/components/usb_pd_sink/include/usb_pd_sink.h @@ -18,7 +18,22 @@ struct usb_pd_sink_options { i2c_port_t i2c_port; uint8_t i2c_addr; // gpio_pin_t int_pin; +}; + +struct usb_pd_sink_status { + uint8_t usb_pd_version_major; + uint8_t usb_pd_version_minor; + + bool port_attached; + bool port_power; // USB-PD Sink active + bool vbus_ready; // VBUS at 5V or higher negotiated power level + + uint8_t pdo_number; // negotiated source PDO, 0 if no USB-PD + bool pd_capability_mismatch; // failed to match source/sink PDO + unsigned voltage_mV; // negotiated voltage in mV + unsigned operating_current_mA; // negotiated operating current in mA + unsigned maximum_current_mA; // negotiated maximum current in mA }; struct usb_pd_sink; @@ -34,3 +49,8 @@ int usb_pd_sink_setup(struct usb_pd_sink *sink); * Start USB-PD Sink. */ int usb_pd_sink_start(struct usb_pd_sink *sink); + +/* + * Get USB-PD Sink info. + */ +int usb_pd_sink_status(struct usb_pd_sink *sink, struct usb_pd_sink_status *status); diff --git a/components/usb_pd_sink/stusb4500.c b/components/usb_pd_sink/stusb4500.c index c7278b79..f0430f7a 100644 --- a/components/usb_pd_sink/stusb4500.c +++ b/components/usb_pd_sink/stusb4500.c @@ -3,8 +3,6 @@ #include -#define DEBUG - #include int stusb4500_init(struct stusb4500 *stusb4500, const struct usb_pd_sink_options *options) @@ -342,3 +340,49 @@ int stusb4500_start(struct stusb4500 *stusb4500) return 0; } + +int stusb4500_status(struct stusb4500 *stusb4500, struct usb_pd_sink_status *status) +{ + struct stusb4500_bcd_usbpd_rev_high bcd_usbpd_rev_high; + struct stusb4500_port_status_1 port_status_1; + struct stusb4500_typec_monitoring_status_1 typec_monitoring_status_1; + struct stusb4500_monitoring_ctrl_1 monitoring_ctrl_1; + union stusb4500_rdo_reg_status rdo; + int err; + + if ((err = stusb4500_i2c_read(stusb4500, STUSB4500_BCD_USBPD_REV_HIGH, &bcd_usbpd_rev_high, sizeof(bcd_usbpd_rev_high)))) { + return err; + } + + if ((err = stusb4500_i2c_read(stusb4500, STUSB4500_PORT_STATUS_1, &port_status_1, sizeof(port_status_1)))) { + return err; + } + + if ((err = stusb4500_i2c_read(stusb4500, STUSB4500_TYPEC_MONITORING_STATUS_1, &typec_monitoring_status_1, sizeof(typec_monitoring_status_1)))) { + return err; + } + + if ((err = stusb4500_i2c_read(stusb4500, STUSB4500_MONITORING_CTRL_1, &monitoring_ctrl_1, sizeof(monitoring_ctrl_1)))) { + return err; + } + + if ((err = stusb4500_i2c_read(stusb4500, STUSB4500_RDO_REG_STATUS_0, &rdo, sizeof(rdo)))) { + return err; + } + + status->usb_pd_version_major = bcd_usbpd_rev_high.major; + status->usb_pd_version_minor = bcd_usbpd_rev_high.minor; + + status->port_attached = (port_status_1.attach == 1); + status->port_power = (port_status_1.power_mode == 0); + status->vbus_ready = (typec_monitoring_status_1.vbus_ready == 1); + + status->pdo_number = rdo.fixed_supply.object_position; + status->pd_capability_mismatch = rdo.fixed_supply.capability_mismatch; + + status->voltage_mV = monitoring_ctrl_1.voltage * 100; // 100mV -> mV + status->operating_current_mA = rdo.fixed_supply.operating_current * 10; // 10mA -> mA + status->maximum_current_mA = rdo.fixed_supply.max_current * 10; // 10mA -> mA + + return 0; +} diff --git a/components/usb_pd_sink/stusb4500.h b/components/usb_pd_sink/stusb4500.h index 0626af21..378842db 100644 --- a/components/usb_pd_sink/stusb4500.h +++ b/components/usb_pd_sink/stusb4500.h @@ -15,6 +15,7 @@ int stusb4500_init(struct stusb4500 *stusb4500, const struct usb_pd_sink_options int stusb4500_reset(struct stusb4500 *stusb4500); int stusb4500_setup(struct stusb4500 *stusb4500); int stusb4500_start(struct stusb4500 *stusb4500); +int stusb4500_status(struct stusb4500 *stusb4500, struct usb_pd_sink_status *status); int stusb4500_i2c_read(struct stusb4500 *stusb4500, enum stusb4500_i2c_register reg, void *buf, size_t size); int stusb4500_i2c_write(struct stusb4500 *stusb4500, enum stusb4500_i2c_register reg, const void *buf, size_t size); diff --git a/components/usb_pd_sink/stusb4500_i2c.h b/components/usb_pd_sink/stusb4500_i2c.h index 19c61680..af42c7e0 100644 --- a/components/usb_pd_sink/stusb4500_i2c.h +++ b/components/usb_pd_sink/stusb4500_i2c.h @@ -237,7 +237,7 @@ struct stusb4500_monitoring_ctrl_0 { }; struct stusb4500_monitoring_ctrl_1 { - uint8_t voltage; // undocumented, 100mV + uint8_t voltage : 8; // undocumented, 100mV }; struct stusb4500_monitoring_ctrl_2 { diff --git a/components/usb_pd_sink/usb_pd_sink.c b/components/usb_pd_sink/usb_pd_sink.c index 3bd22711..f490dc1d 100644 --- a/components/usb_pd_sink/usb_pd_sink.c +++ b/components/usb_pd_sink/usb_pd_sink.c @@ -60,5 +60,15 @@ int usb_pd_sink_start(struct usb_pd_sink *sink) default: LOG_FATAL("invalid type=%d", sink->type); } +} + +int usb_pd_sink_status(struct usb_pd_sink *sink, struct usb_pd_sink_status *status) +{ + switch (sink->type) { + case USB_PD_SINK_STUSB4500: + return stusb4500_status(&sink->state.stusb4500, status); + default: + LOG_FATAL("invalid type=%d", sink->type); + } } From 7ccf73167674ed496aa8772bb837821fff887e74 Mon Sep 17 00:00:00 2001 From: Tero Marttila Date: Sat, 20 Jan 2024 03:34:28 +0200 Subject: [PATCH 17/24] main: usb-pd status cmd --- main/console_cmd.c | 8 +++++++- main/usb_pd_cmd.c | 46 +++++++++++++++++++++++++++++++++++++++++++++ main/usb_pd_cmd.h | 8 ++++++++ main/usb_pd_sink.c | 2 ++ main/usb_pd_state.h | 5 +++++ 5 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 main/usb_pd_cmd.c create mode 100644 main/usb_pd_cmd.h create mode 100644 main/usb_pd_state.h diff --git a/main/console_cmd.c b/main/console_cmd.c index 414d6ab9..bf942c83 100644 --- a/main/console_cmd.c +++ b/main/console_cmd.c @@ -9,8 +9,9 @@ #include "log.h" #include "sdcard.h" #include "spiffs.h" -#include "user_leds.h" #include "system.h" +#include "usb_pd_cmd.h" +#include "user_leds.h" #include "vfs.h" #include "wifi.h" @@ -49,6 +50,11 @@ const struct cmd console_cli_commands[] = { { "config", .describe = "Configuration", .subcommands = &config_cmdtab, }, +#if CONFIG_USB_PD_SINK_ENABLED + { "usb-pd", .describe = "USB-PD Sink", + .subcommands = &usb_pd_cmdtab, + }, +#endif #if CONFIG_SDCARD_ENABLED { "sdcard", .describe = "SD Card", .subcommands = &sdcard_cmdtab, diff --git a/main/usb_pd_cmd.c b/main/usb_pd_cmd.c new file mode 100644 index 00000000..51e33e07 --- /dev/null +++ b/main/usb_pd_cmd.c @@ -0,0 +1,46 @@ +#include "usb_pd_cmd.h" +#include "usb_pd_state.h" + +#include + +#include + +#if CONFIG_USB_PD_SINK_ENABLED + int usb_pd_sink_status_cmd(int argc, char **argv, void *ctx) + { + struct usb_pd_sink_status status; + int err; + + if (!usb_pd_sink) { + LOG_ERROR("not initialized"); + return -1; + } + + if ((err = usb_pd_sink_status(usb_pd_sink, &status))) { + LOG_ERROR("usb_pd_sink_status"); + return -1; + } + + printf("USB-PD Version %d.%d\n", status.usb_pd_version_major, status.usb_pd_version_minor); + printf("Sink:\n"); + printf("\t%-25s: %d\n", "Port Attached", status.port_attached); + printf("\t%-25s: %d\n", "Port Powered", status.port_power); + printf("\t%-25s: %d\n", "VBUS Ready", status.vbus_ready); + + printf("\t%-25s: %d\n", "PDO #", status.pdo_number); + printf("\t%-25s: %d\n", "PD Capability Mismatch", status.pd_capability_mismatch); + printf("\t%-25s: %.2f\n", "Voltage", status.voltage_mV / 1000.0f); + printf("\t%-25s: %.2f - %.2f\n", "Current", status.operating_current_mA / 1000.0f, status.maximum_current_mA / 1000.0f); + + return 0; + } + + const struct cmd usb_pd_commands[] = { + { "status", usb_pd_sink_status_cmd, .describe = "Show USB-PD Sink Status" }, + {} + }; + + const struct cmdtab usb_pd_cmdtab = { + .commands = usb_pd_commands, + }; +#endif diff --git a/main/usb_pd_cmd.h b/main/usb_pd_cmd.h new file mode 100644 index 00000000..a341a785 --- /dev/null +++ b/main/usb_pd_cmd.h @@ -0,0 +1,8 @@ +#pragma once + +#include +#include + +#if CONFIG_USB_PD_SINK_ENABLED + extern const struct cmdtab usb_pd_cmdtab; +#endif diff --git a/main/usb_pd_sink.c b/main/usb_pd_sink.c index 6cf4efe7..9d0ab1c0 100644 --- a/main/usb_pd_sink.c +++ b/main/usb_pd_sink.c @@ -1,4 +1,6 @@ #include "usb_pd_sink.h" +#include "usb_pd_state.h" + #include "i2c_master.h" #include diff --git a/main/usb_pd_state.h b/main/usb_pd_state.h new file mode 100644 index 00000000..00ba06b5 --- /dev/null +++ b/main/usb_pd_state.h @@ -0,0 +1,5 @@ +#pragma once + +#include + +extern struct usb_pd_sink *usb_pd_sink; From 6f2f2a012cde8dc0db34cd1d64de7ebfade9fdde Mon Sep 17 00:00:00 2001 From: Tero Marttila Date: Sat, 20 Jan 2024 03:38:53 +0200 Subject: [PATCH 18/24] usb_pd_sink stusb4500: do not reset at setup, this drops the USB-PD supply voltage and kills the ESP --- components/usb_pd_sink/stusb4500.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/components/usb_pd_sink/stusb4500.c b/components/usb_pd_sink/stusb4500.c index f0430f7a..1c53f47a 100644 --- a/components/usb_pd_sink/stusb4500.c +++ b/components/usb_pd_sink/stusb4500.c @@ -305,12 +305,6 @@ int stusb4500_setup(struct stusb4500 *stusb4500) } } - // reset runtime state to NVM defaults - if ((err = stusb4500_reset(stusb4500))) { - LOG_ERROR("stusb4500_reset"); - return err; - } - return 0; } From e70e64a7cb200e9fa7919e50f420d8d3274fbd76 Mon Sep 17 00:00:00 2001 From: Tero Marttila Date: Sun, 21 Jan 2024 12:20:04 +0200 Subject: [PATCH 19/24] usb_pd_sink stusb4500: debug -> print to dump registers --- components/usb_pd_sink/include/usb_pd_sink.h | 8 +- components/usb_pd_sink/stusb4500.c | 263 ------------------- components/usb_pd_sink/stusb4500.h | 1 + components/usb_pd_sink/stusb4500_print.c | 259 ++++++++++++++++++ components/usb_pd_sink/usb_pd_sink.c | 11 + main/usb_pd_cmd.c | 18 ++ 6 files changed, 296 insertions(+), 264 deletions(-) create mode 100644 components/usb_pd_sink/stusb4500_print.c diff --git a/components/usb_pd_sink/include/usb_pd_sink.h b/components/usb_pd_sink/include/usb_pd_sink.h index 8458f2e7..86fbf688 100644 --- a/components/usb_pd_sink/include/usb_pd_sink.h +++ b/components/usb_pd_sink/include/usb_pd_sink.h @@ -2,6 +2,7 @@ #include #include +#include #define USB_PD_SINK_STUSB4500_I2C_ADDR_BASE 0x28 #define USB_PD_SINK_STUSB4500_I2C_ADDR_MASK 0x03 @@ -51,6 +52,11 @@ int usb_pd_sink_setup(struct usb_pd_sink *sink); int usb_pd_sink_start(struct usb_pd_sink *sink); /* - * Get USB-PD Sink info. + * Get generic USB-PD Sink info. */ int usb_pd_sink_status(struct usb_pd_sink *sink, struct usb_pd_sink_status *status); + +/* + * Print detailed USB-PD Sink info. + */ +int usb_pd_sink_print(struct usb_pd_sink *sink, FILE *file); diff --git a/components/usb_pd_sink/stusb4500.c b/components/usb_pd_sink/stusb4500.c index 1c53f47a..0ccdc661 100644 --- a/components/usb_pd_sink/stusb4500.c +++ b/components/usb_pd_sink/stusb4500.c @@ -14,245 +14,6 @@ int stusb4500_init(struct stusb4500 *stusb4500, const struct usb_pd_sink_options return 0; } -int stusb4500_get_status(struct stusb4500 *stusb4500) -{ - struct stusb4500_i2c_rev rev; - struct stusb4500_i2c_status status; - struct stusb4500_pe_fsm pe_fsm; - struct stusb4500_device_id device_id; - int err; - - if ((err = stusb4500_i2c_read(stusb4500, STUSB4500_BCD_TYPEC_REV_LOW, &rev, sizeof(rev)))) { - return err; - } - - if ((err = stusb4500_i2c_read(stusb4500, STUSB4500_PORT_STATUS_0, &status, sizeof(status)))) { - return err; - } - - if ((err = stusb4500_i2c_read(stusb4500, STUSB4500_PE_FSM, &pe_fsm, sizeof(pe_fsm)))) { - return err; - } - - if ((err = stusb4500_i2c_read(stusb4500, STUSB4500_DEVICE_ID, &device_id, sizeof(device_id)))) { - return err; - } - - LOG_DEBUG("bcd_rev: typec_low=%u.%u typec_high=%u.%u usbpd_low=%u.%u usbpd_high=%u.%u", - rev.bcd_typec_rev_low.major, rev.bcd_typec_rev_low.minor, - rev.bcd_typec_rev_high.major, rev.bcd_typec_rev_high.minor, - rev.bcd_usbpd_rev_low.major, rev.bcd_usbpd_rev_low.minor, - rev.bcd_usbpd_rev_high.major, rev.bcd_usbpd_rev_high.minor - ); - - LOG_DEBUG("port_status: attach_trans=%u attached_device=%u power_mode=%u data_mode=%u attach=%u", - status.port_status_0.attach_trans, - status.port_status_1.attached_device, - status.port_status_1.power_mode, - status.port_status_1.data_mode, - status.port_status_1.attach - ); - - LOG_DEBUG("typec_monitoring_status: vbus_low_status=%u vbus_high_status=%u vbus_valid_snk=%u vbus_vsafe0v=%u vbus_ready=%u", - status.typec_monitoring_status_0.vbus_low_status, - status.typec_monitoring_status_0.vbus_high_status, - status.typec_monitoring_status_1.vbus_valid_snk, - status.typec_monitoring_status_1.vbus_vsafe0v, - status.typec_monitoring_status_1.vbus_ready - ); - - LOG_DEBUG("cc_status: cc1_state=%u cc2_state=%u connect_result=%u looking_4_connection=%u", - status.cc_status.cc1_state, - status.cc_status.cc2_state, - status.cc_status.connect_result, - status.cc_status.looking_4_connection - ); - - LOG_DEBUG("cc_hw_fault_status: vbus_disch_fault=%u vpu_valid=%u vpu_ovp_fault=%u", - status.cc_hw_fault_status_1.vbus_disch_fault, - status.cc_hw_fault_status_1.vpu_valid, - status.cc_hw_fault_status_1.vpu_ovp_fault - ); - - LOG_DEBUG("pd_typec_status: pd_typec_hand_check=%u", - status.pd_typec_status.pd_typec_hand_check - ); - - LOG_DEBUG("typec_status: typec_fsm_state=%u reverse=%u", - status.typec_status.typec_fsm_state, - status.typec_status.reverse - ); - - LOG_DEBUG("prt_status: prl_hw_rst_received=%u prl_msg_received=%u prt_bist_received=%u", - status.prt_status.prl_hw_rst_received, - status.prt_status.prl_msg_received, - status.prt_status.prt_bist_received - ); - - LOG_DEBUG("pe_fsm: pe_fsm_state=%u", - pe_fsm.pe_fsm_state - ); - - LOG_DEBUG("device_id: device_id=%u", - device_id.device_id - ); - - return 0; -} - -int stusb4500_get_ctrl(struct stusb4500 *stusb4500) -{ - struct stusb4500_monitoring_ctrl_0 monitoring_ctrl_0; - struct stusb4500_monitoring_ctrl_1 monitoring_ctrl_1; - struct stusb4500_monitoring_ctrl_2 monitoring_ctrl_2; - struct stusb4500_vbus_discharge_time_ctrl vbus_discharge_time_ctrl; - int err; - - if ((err = stusb4500_i2c_read(stusb4500, STUSB4500_MONITORING_CTRL_0, &monitoring_ctrl_0, sizeof(monitoring_ctrl_0)))) { - return err; - } - - if ((err = stusb4500_i2c_read(stusb4500, STUSB4500_MONITORING_CTRL_1, &monitoring_ctrl_1, sizeof(monitoring_ctrl_1)))) { - return err; - } - - if ((err = stusb4500_i2c_read(stusb4500, STUSB4500_MONITORING_CTRL_2, &monitoring_ctrl_2, sizeof(monitoring_ctrl_2)))) { - return err; - } - - if ((err = stusb4500_i2c_read(stusb4500, STUSB4500_VBUS_DISCHARGE_TIME_CTRL, &vbus_discharge_time_ctrl, sizeof(vbus_discharge_time_ctrl)))) { - return err; - } - - LOG_DEBUG("monitoring_ctrl: vbus_snk_disc_threshold=%u voltage=%u vshift_low=%u vshift_high=%u", - monitoring_ctrl_0.vbus_snk_disc_threshold, - monitoring_ctrl_1.voltage, - monitoring_ctrl_2.vshift_low, monitoring_ctrl_2.vshift_high - ); - - return 0; -} - -int stusb4500_get_pdo(struct stusb4500 *stusb4500) -{ - struct stusb4500_dpm_pdo_numb pdo_numb; - union stusb4500_pdo pdo; - int err; - - if ((err = stusb4500_i2c_read(stusb4500, STUSB4500_DPM_PDO_NUMB, &pdo_numb, sizeof(pdo_numb)))) { - return err; - } - - for (int i = 0; i < pdo_numb.dpm_snk_pdo_numb && i < STUSB4500_DPM_SNK_PDO_COUNT; i++) { - if ((err = stusb4500_i2c_read(stusb4500, STUSB4500_DPM_SNK_PDO(i), &pdo, sizeof(pdo)))) { - LOG_ERROR("stusb4500_i2c_read STUSB4500_DPM_SNK_PDO(%d)", i); - return err; - } - - switch(pdo.header.type) { - case STUSB4500_PDO_TYPE_FIXED_SUPPLY: - LOG_DEBUG("dpm_snk_pdo%d: fixed_supply max_current=%u voltage=%u fast_role_swap=%u dual_role_data=%u usb_comm_capable=%u unconstrained_power=%u higher_capability=%u dual_role_power=%u", i, - pdo.fixed_supply.max_current, - pdo.fixed_supply.voltage, - pdo.fixed_supply.fast_role_swap, - pdo.fixed_supply.dual_role_data, - pdo.fixed_supply.usb_comm_capable, - pdo.fixed_supply.unconstrained_power, - pdo.fixed_supply.higher_capability, - pdo.fixed_supply.dual_role_power - ); - break; - - default: - LOG_WARN("dpm_snk_pdo%d: unsupported type=%u", i, pdo.header.type); - break; - } - } - - return 0; -} - -int stusb4500_get_rdo(struct stusb4500 *stusb4500) -{ - union stusb4500_rdo_reg_status rdo; - int err; - - if ((err = stusb4500_i2c_read(stusb4500, STUSB4500_RDO_REG_STATUS_0, &rdo, sizeof(rdo)))) { - return err; - } - - LOG_DEBUG("rdo: fixed_supply max_current=%u operating_current=%u unchunked_messages_supported=%u no_usb_suspend=%u usb_comm_capable=%u capability_mismatch=%u give_back=%u object_position=%u", - rdo.fixed_supply.max_current, - rdo.fixed_supply.operating_current, - rdo.fixed_supply.unchunked_messages_supported, - rdo.fixed_supply.no_usb_suspend, - rdo.fixed_supply.usb_comm_capable, - rdo.fixed_supply.capability_mismatch, - rdo.fixed_supply.give_back, - rdo.fixed_supply.object_position - ); - - return 0; -} - -static void stusb4500_nvm_debug(const union stusb4500_nvm *nvm) -{ - for (int i = 0; i < STUSB4500_NVM_SECTOR_COUNT; i++) { - LOG_DEBUG("nvm sector[%d]: %02x %02x %02x %02x %02x %02x %02x %02x", i, - nvm->sectors[i][0], - nvm->sectors[i][1], - nvm->sectors[i][2], - nvm->sectors[i][3], - nvm->sectors[i][4], - nvm->sectors[i][5], - nvm->sectors[i][6], - nvm->sectors[i][7] - ); - } - - LOG_DEBUG("nvm bank0 vendor_id=%04x product_id=%04x bcd_device_id=%04x port_role_ctrl=%u device_power_role_ctrl=%u", - nvm->banks.bank0.vendor_id, - nvm->banks.bank0.product_id, - nvm->banks.bank0.bcd_device_id, - nvm->banks.bank0.port_role_ctrl, - nvm->banks.bank0.device_power_role_ctrl - ); - - LOG_DEBUG("nvm bank1 gpio_cfg=%u vbus_dchg_mask=%u vbus_disch_time_to_pdo=%u discharge_time_to_0v=%u", - nvm->banks.bank1.gpio_cfg, - nvm->banks.bank1.vbus_dchg_mask, - nvm->banks.bank1.vbus_disch_time_to_pdo, - nvm->banks.bank1.discharge_time_to_0v - ); - - LOG_DEBUG("nvm bank3 usb_comm_capable=%u dpm_snk_pdo_numb=%u snk_uncons_power=%u", - nvm->banks.bank3.usb_comm_capable, - nvm->banks.bank3.dpm_snk_pdo_numb, - nvm->banks.bank3.snk_uncons_power - ); - - LOG_DEBUG("nvm bank3 pdo1(i=%u ll=%u hl=%u) pdo2(i=%u ll=%u hl=%u) pdo3(i=%u ll=%u hl=%u)", - nvm->banks.bank3.lut_snk_pdo1_i, - nvm->banks.bank3.snk_ll1, - nvm->banks.bank3.snk_hl1, - nvm->banks.bank3.lut_snk_pdo2_i, - nvm->banks.bank3.snk_ll2, - nvm->banks.bank3.snk_hl2, - nvm->banks.bank3.lut_snk_pdo3_i, - nvm->banks.bank3.snk_ll3, - nvm->banks.bank3.snk_hl3 - ); - - LOG_DEBUG("nvm bank4 snk_pdo_flex1_v=%u snk_pdo_flex2_v=%u snk_pdo_flex_i=%u power_ok_cfg=%u power_only_above_5v=%u req_src_current=%u", - nvm->banks.bank4.snk_pdo_flex1_v, - nvm->banks.bank4.snk_pdo_flex2_v, - nvm->banks.bank4.snk_pdo_flex_i, - nvm->banks.bank4.power_ok_cfg, - nvm->banks.bank4.power_only_above_5v, - nvm->banks.bank4.req_src_current - ); -} - int stusb4500_reset(struct stusb4500 *stusb4500) { struct stusb4500_reset_ctrl reset_ctrl = { .reset_sw_en = 1 }; @@ -289,8 +50,6 @@ int stusb4500_setup(struct stusb4500 *stusb4500) return err; } - stusb4500_nvm_debug(&nvm); - if ((err = stusb4500_config_nvm(&nvm)) < 0) { LOG_ERROR("stusb4500_config_nvm"); return err; @@ -310,28 +69,6 @@ int stusb4500_setup(struct stusb4500 *stusb4500) int stusb4500_start(struct stusb4500 *stusb4500) { - int err; - - if ((err = stusb4500_get_status(stusb4500))) { - LOG_ERROR("stusb4500_get_status"); - return err; - } - - if ((err = stusb4500_get_ctrl(stusb4500))) { - LOG_ERROR("stusb4500_get_ctrl"); - return err; - } - - if ((err = stusb4500_get_pdo(stusb4500))) { - LOG_ERROR("stusb4500_get_pdo"); - return err; - } - - if ((err = stusb4500_get_rdo(stusb4500))) { - LOG_ERROR("stusb4500_get_rdo"); - return err; - } - return 0; } diff --git a/components/usb_pd_sink/stusb4500.h b/components/usb_pd_sink/stusb4500.h index 378842db..8962ab05 100644 --- a/components/usb_pd_sink/stusb4500.h +++ b/components/usb_pd_sink/stusb4500.h @@ -16,6 +16,7 @@ int stusb4500_reset(struct stusb4500 *stusb4500); int stusb4500_setup(struct stusb4500 *stusb4500); int stusb4500_start(struct stusb4500 *stusb4500); int stusb4500_status(struct stusb4500 *stusb4500, struct usb_pd_sink_status *status); +int stusb4500_print(struct stusb4500 *stusb4500, FILE *file); int stusb4500_i2c_read(struct stusb4500 *stusb4500, enum stusb4500_i2c_register reg, void *buf, size_t size); int stusb4500_i2c_write(struct stusb4500 *stusb4500, enum stusb4500_i2c_register reg, const void *buf, size_t size); diff --git a/components/usb_pd_sink/stusb4500_print.c b/components/usb_pd_sink/stusb4500_print.c new file mode 100644 index 00000000..89cfc645 --- /dev/null +++ b/components/usb_pd_sink/stusb4500_print.c @@ -0,0 +1,259 @@ +#include "stusb4500.h" +#include "stusb4500_i2c.h" + +#include + +#include + +static void stusb4500_print_status(struct stusb4500 *stusb4500, FILE *file) +{ + struct stusb4500_i2c_rev rev; + struct stusb4500_i2c_status status; + struct stusb4500_pe_fsm pe_fsm; + struct stusb4500_device_id device_id; + int err; + + if ((err = stusb4500_i2c_read(stusb4500, STUSB4500_BCD_TYPEC_REV_LOW, &rev, sizeof(rev)))) { + LOG_ERROR("stusb4500_i2c_read STUSB4500_BCD_TYPEC_REV_LOW"); + } else { + fprintf(file, "\tbcd_rev: typec_low=%u.%u typec_high=%u.%u usbpd_low=%u.%u usbpd_high=%u.%u\n", + rev.bcd_typec_rev_low.major, rev.bcd_typec_rev_low.minor, + rev.bcd_typec_rev_high.major, rev.bcd_typec_rev_high.minor, + rev.bcd_usbpd_rev_low.major, rev.bcd_usbpd_rev_low.minor, + rev.bcd_usbpd_rev_high.major, rev.bcd_usbpd_rev_high.minor + ); + } + + if ((err = stusb4500_i2c_read(stusb4500, STUSB4500_PORT_STATUS_0, &status, sizeof(status)))) { + LOG_ERROR("stusb4500_i2c_read STUSB4500_PORT_STATUS_0"); + } else { + fprintf(file, "\tport_status: attach_trans=%u attached_device=%u power_mode=%u data_mode=%u attach=%u\n", + status.port_status_0.attach_trans, + status.port_status_1.attached_device, + status.port_status_1.power_mode, + status.port_status_1.data_mode, + status.port_status_1.attach + ); + + fprintf(file, "\ttypec_monitoring_status: vbus_low_status=%u vbus_high_status=%u vbus_valid_snk=%u vbus_vsafe0v=%u vbus_ready=%u\n", + status.typec_monitoring_status_0.vbus_low_status, + status.typec_monitoring_status_0.vbus_high_status, + status.typec_monitoring_status_1.vbus_valid_snk, + status.typec_monitoring_status_1.vbus_vsafe0v, + status.typec_monitoring_status_1.vbus_ready + ); + + fprintf(file, "\tcc_status: cc1_state=%u cc2_state=%u connect_result=%u looking_4_connection=%u\n", + status.cc_status.cc1_state, + status.cc_status.cc2_state, + status.cc_status.connect_result, + status.cc_status.looking_4_connection + ); + + fprintf(file, "\tcc_hw_fault_status: vbus_disch_fault=%u vpu_valid=%u vpu_ovp_fault=%u\n", + status.cc_hw_fault_status_1.vbus_disch_fault, + status.cc_hw_fault_status_1.vpu_valid, + status.cc_hw_fault_status_1.vpu_ovp_fault + ); + + fprintf(file, "\tpd_typec_status: pd_typec_hand_check=%u\n", + status.pd_typec_status.pd_typec_hand_check + ); + + fprintf(file, "\ttypec_status: typec_fsm_state=%u reverse=%u\n", + status.typec_status.typec_fsm_state, + status.typec_status.reverse + ); + + fprintf(file, "\tprt_status: prl_hw_rst_received=%u prl_msg_received=%u prt_bist_received=%u\n", + status.prt_status.prl_hw_rst_received, + status.prt_status.prl_msg_received, + status.prt_status.prt_bist_received + ); + + } + + if ((err = stusb4500_i2c_read(stusb4500, STUSB4500_PE_FSM, &pe_fsm, sizeof(pe_fsm)))) { + LOG_ERROR("stusb4500_i2c_read STUSB4500_PE_FSM"); + } else { + fprintf(file, "\tpe_fsm: pe_fsm_state=%u\n", + pe_fsm.pe_fsm_state + ); + } + + if ((err = stusb4500_i2c_read(stusb4500, STUSB4500_DEVICE_ID, &device_id, sizeof(device_id)))) { + LOG_ERROR("stusb4500_i2c_read STUSB4500_DEVICE_ID"); + } else { + fprintf(file, "\tdevice_id: device_id=%u\n", + device_id.device_id + ); + } +} + +static void stusb4500_print_ctrl(struct stusb4500 *stusb4500, FILE *file) +{ + struct stusb4500_monitoring_ctrl_0 monitoring_ctrl_0; + struct stusb4500_monitoring_ctrl_1 monitoring_ctrl_1; + struct stusb4500_monitoring_ctrl_2 monitoring_ctrl_2; + struct stusb4500_vbus_discharge_time_ctrl vbus_discharge_time_ctrl; + int err; + + if ((err = stusb4500_i2c_read(stusb4500, STUSB4500_MONITORING_CTRL_0, &monitoring_ctrl_0, sizeof(monitoring_ctrl_0)))) { + LOG_ERROR("stusb4500_i2c_read STUSB4500_MONITORING_CTRL_0"); + } else if ((err = stusb4500_i2c_read(stusb4500, STUSB4500_MONITORING_CTRL_1, &monitoring_ctrl_1, sizeof(monitoring_ctrl_1)))) { + LOG_ERROR("stusb4500_i2c_read STUSB4500_MONITORING_CTRL_1"); + } else if ((err = stusb4500_i2c_read(stusb4500, STUSB4500_MONITORING_CTRL_2, &monitoring_ctrl_2, sizeof(monitoring_ctrl_2)))) { + LOG_ERROR("stusb4500_i2c_read STUSB4500_MONITORING_CTRL_2"); + } else { + fprintf(file, "\tmonitoring_ctrl: vbus_snk_disc_threshold=%u voltage=%u vshift_low=%u vshift_high=%u\n", + monitoring_ctrl_0.vbus_snk_disc_threshold, + monitoring_ctrl_1.voltage, + monitoring_ctrl_2.vshift_low, monitoring_ctrl_2.vshift_high + ); + } + + if ((err = stusb4500_i2c_read(stusb4500, STUSB4500_VBUS_DISCHARGE_TIME_CTRL, &vbus_discharge_time_ctrl, sizeof(vbus_discharge_time_ctrl)))) { + LOG_ERROR("stusb4500_i2c_read STUSB4500_VBUS_DISCHARGE_TIME_CTRL"); + } else { + fprintf(file, "\tvbus_discharge_time_ctrl: discharge_time_transition=%u discharge_time_to_0v=%u\n", + vbus_discharge_time_ctrl.discharge_time_transition, + vbus_discharge_time_ctrl.discharge_time_to_0v + ); + } +} + +static void stusb4500_print_pdo(struct stusb4500 *stusb4500, FILE *file) +{ + struct stusb4500_dpm_pdo_numb pdo_numb; + union stusb4500_pdo pdo; + int err; + + if ((err = stusb4500_i2c_read(stusb4500, STUSB4500_DPM_PDO_NUMB, &pdo_numb, sizeof(pdo_numb)))) { + LOG_ERROR("stusb4500_i2c_read STUSB4500_DPM_PDO_NUMB"); + return; + } + + for (int i = 0; i < pdo_numb.dpm_snk_pdo_numb && i < STUSB4500_DPM_SNK_PDO_COUNT; i++) { + if ((err = stusb4500_i2c_read(stusb4500, STUSB4500_DPM_SNK_PDO(i), &pdo, sizeof(pdo)))) { + LOG_ERROR("stusb4500_i2c_read STUSB4500_DPM_SNK_PDO(%d)", i); + continue; + } + + switch(pdo.header.type) { + case STUSB4500_PDO_TYPE_FIXED_SUPPLY: + fprintf(file, "\tdpm_snk_pdo%d: fixed_supply max_current=%u voltage=%u fast_role_swap=%u dual_role_data=%u usb_comm_capable=%u unconstrained_power=%u higher_capability=%u dual_role_power=%u\n", i, + pdo.fixed_supply.max_current, + pdo.fixed_supply.voltage, + pdo.fixed_supply.fast_role_swap, + pdo.fixed_supply.dual_role_data, + pdo.fixed_supply.usb_comm_capable, + pdo.fixed_supply.unconstrained_power, + pdo.fixed_supply.higher_capability, + pdo.fixed_supply.dual_role_power + ); + break; + + default: + LOG_WARN("dpm_snk_pdo%d: unsupported type=%u", i, pdo.header.type); + break; + } + } +} + +static void stusb4500_print_rdo(struct stusb4500 *stusb4500, FILE *file) +{ + union stusb4500_rdo_reg_status rdo; + int err; + + if ((err = stusb4500_i2c_read(stusb4500, STUSB4500_RDO_REG_STATUS_0, &rdo, sizeof(rdo)))) { + LOG_ERROR("stusb4500_i2c_read STUSB4500_RDO_REG_STATUS_0"); + } else { + fprintf(file, "\trdo: fixed_supply max_current=%u operating_current=%u unchunked_messages_supported=%u no_usb_suspend=%u usb_comm_capable=%u capability_mismatch=%u give_back=%u object_position=%u\n", + rdo.fixed_supply.max_current, + rdo.fixed_supply.operating_current, + rdo.fixed_supply.unchunked_messages_supported, + rdo.fixed_supply.no_usb_suspend, + rdo.fixed_supply.usb_comm_capable, + rdo.fixed_supply.capability_mismatch, + rdo.fixed_supply.give_back, + rdo.fixed_supply.object_position + ); + } +} + +static void stusb4500_print_nvm(struct stusb4500 *stusb4500, FILE *file) +{ + union stusb4500_nvm nvm = {}; + int err; + + if ((err = stusb4500_nvm_read(stusb4500, &nvm))) { + LOG_ERROR("stusb4500_nvm_read"); + return; + } + + for (int i = 0; i < STUSB4500_NVM_SECTOR_COUNT; i++) { + fprintf(file, "\tnvm sector[%d]: %02x %02x %02x %02x %02x %02x %02x %02x\n", i, + nvm.sectors[i][0], + nvm.sectors[i][1], + nvm.sectors[i][2], + nvm.sectors[i][3], + nvm.sectors[i][4], + nvm.sectors[i][5], + nvm.sectors[i][6], + nvm.sectors[i][7] + ); + } + + fprintf(file, "\tnvm bank0 vendor_id=%04x product_id=%04x bcd_device_id=%04x port_role_ctrl=%u device_power_role_ctrl=%u\n", + nvm.banks.bank0.vendor_id, + nvm.banks.bank0.product_id, + nvm.banks.bank0.bcd_device_id, + nvm.banks.bank0.port_role_ctrl, + nvm.banks.bank0.device_power_role_ctrl + ); + + fprintf(file, "\tnvm bank1 gpio_cfg=%u vbus_dchg_mask=%u vbus_disch_time_to_pdo=%u discharge_time_to_0v=%u\n", + nvm.banks.bank1.gpio_cfg, + nvm.banks.bank1.vbus_dchg_mask, + nvm.banks.bank1.vbus_disch_time_to_pdo, + nvm.banks.bank1.discharge_time_to_0v + ); + + fprintf(file, "\tnvm bank3 usb_comm_capable=%u dpm_snk_pdo_numb=%u snk_uncons_power=%u\n", + nvm.banks.bank3.usb_comm_capable, + nvm.banks.bank3.dpm_snk_pdo_numb, + nvm.banks.bank3.snk_uncons_power + ); + + fprintf(file, "\tnvm bank3 pdo1(i=%u ll=%u hl=%u) pdo2(i=%u ll=%u hl=%u) pdo3(i=%u ll=%u hl=%u)\n", + nvm.banks.bank3.lut_snk_pdo1_i, + nvm.banks.bank3.snk_ll1, + nvm.banks.bank3.snk_hl1, + nvm.banks.bank3.lut_snk_pdo2_i, + nvm.banks.bank3.snk_ll2, + nvm.banks.bank3.snk_hl2, + nvm.banks.bank3.lut_snk_pdo3_i, + nvm.banks.bank3.snk_ll3, + nvm.banks.bank3.snk_hl3 + ); + + fprintf(file, "\tnvm bank4 snk_pdo_flex1_v=%u snk_pdo_flex2_v=%u snk_pdo_flex_i=%u power_ok_cfg=%u power_only_above_5v=%u req_src_current=%u\n", + nvm.banks.bank4.snk_pdo_flex1_v, + nvm.banks.bank4.snk_pdo_flex2_v, + nvm.banks.bank4.snk_pdo_flex_i, + nvm.banks.bank4.power_ok_cfg, + nvm.banks.bank4.power_only_above_5v, + nvm.banks.bank4.req_src_current + ); +} + +int stusb4500_print(struct stusb4500 *stusb4500, FILE *file) +{ + stusb4500_print_status(stusb4500, file); + stusb4500_print_ctrl(stusb4500, file); + stusb4500_print_pdo(stusb4500, file); + stusb4500_print_rdo(stusb4500, file); + stusb4500_print_nvm(stusb4500, file); + + return 0; +} diff --git a/components/usb_pd_sink/usb_pd_sink.c b/components/usb_pd_sink/usb_pd_sink.c index f490dc1d..482fa203 100644 --- a/components/usb_pd_sink/usb_pd_sink.c +++ b/components/usb_pd_sink/usb_pd_sink.c @@ -72,3 +72,14 @@ int usb_pd_sink_status(struct usb_pd_sink *sink, struct usb_pd_sink_status *stat LOG_FATAL("invalid type=%d", sink->type); } } + +int usb_pd_sink_print(struct usb_pd_sink *sink, FILE *file) +{ + switch (sink->type) { + case USB_PD_SINK_STUSB4500: + return stusb4500_print(&sink->state.stusb4500, file); + + default: + LOG_FATAL("invalid type=%d", sink->type); + } +} diff --git a/main/usb_pd_cmd.c b/main/usb_pd_cmd.c index 51e33e07..70d5d68f 100644 --- a/main/usb_pd_cmd.c +++ b/main/usb_pd_cmd.c @@ -35,8 +35,26 @@ return 0; } + int usb_pd_sink_debug_cmd(int argc, char **argv, void *ctx) + { + int err; + + if (!usb_pd_sink) { + LOG_ERROR("not initialized"); + return -1; + } + + if ((err = usb_pd_sink_print(usb_pd_sink, stdout))) { + LOG_ERROR("usb_pd_sink_print"); + return -1; + } + + return 0; + } + const struct cmd usb_pd_commands[] = { { "status", usb_pd_sink_status_cmd, .describe = "Show USB-PD Sink Status" }, + { "debug", usb_pd_sink_debug_cmd, .describe = "Print detailed USB-PD Sink Status" }, {} }; From fbef8f6bf93c83da8d3e9dab22e8c347eed688a9 Mon Sep 17 00:00:00 2001 From: Tero Marttila Date: Sun, 21 Jan 2024 12:26:58 +0200 Subject: [PATCH 20/24] usb_pd_sink stusb4500: fix nvm bank4 mappings for power_only_above_5v/req_src_current --- components/usb_pd_sink/stusb4500_nvm.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/components/usb_pd_sink/stusb4500_nvm.h b/components/usb_pd_sink/stusb4500_nvm.h index e51f4c31..f4793358 100644 --- a/components/usb_pd_sink/stusb4500_nvm.h +++ b/components/usb_pd_sink/stusb4500_nvm.h @@ -88,9 +88,10 @@ union stusb4500_nvm { uint64_t snk_pdo_flex1_v : 10; uint64_t snk_pdo_flex2_v : 10; uint64_t snk_pdo_flex_i : 10; - uint64_t reserved5_4 : 1; // 0 + uint64_t reserved4_4 : 1; // 0 uint64_t power_ok_cfg : 2; - uint64_t reserved5_7 : 1; // 0 + uint64_t reserved4_7 : 1; // 0 + uint64_t reserved5 : 8; // 0x0 uint64_t reserved6_0 : 3; // 0x0 uint64_t power_only_above_5v : 1; uint64_t req_src_current : 1; From 800c4e11fc59ff2342e3ad5da83313ebb50885d8 Mon Sep 17 00:00:00 2001 From: Tero Marttila Date: Sun, 21 Jan 2024 12:48:29 +0200 Subject: [PATCH 21/24] usb_pd_sink stusb4500: dump nvm on config changes --- components/usb_pd_sink/stusb4500.c | 22 +++- components/usb_pd_sink/stusb4500.h | 8 +- components/usb_pd_sink/stusb4500_nvm.h | 1 + ...sb4500_config.c => stusb4500_nvm_config.c} | 45 ++++++-- components/usb_pd_sink/stusb4500_print.c | 102 ++++++++++-------- 5 files changed, 122 insertions(+), 56 deletions(-) rename components/usb_pd_sink/{stusb4500_config.c => stusb4500_nvm_config.c} (88%) diff --git a/components/usb_pd_sink/stusb4500.c b/components/usb_pd_sink/stusb4500.c index 0ccdc661..3609fe67 100644 --- a/components/usb_pd_sink/stusb4500.c +++ b/components/usb_pd_sink/stusb4500.c @@ -50,13 +50,27 @@ int stusb4500_setup(struct stusb4500 *stusb4500) return err; } - if ((err = stusb4500_config_nvm(&nvm)) < 0) { - LOG_ERROR("stusb4500_config_nvm"); + if ((err = stusb4500_nvm_validate(&nvm)) < 0) { + LOG_ERROR("stusb4500_nvm_validate"); return err; } else if (!err) { - LOG_INFO("NVM OK"); + LOG_DEBUG("stusb4500_nvm_validate OK"); } else { - LOG_WARN("NVM changes, write..."); + LOG_WARN("stusb4500_nvm_validate"); + return err; + } + + if ((err = stusb4500_nvm_config(&nvm)) < 0) { + LOG_ERROR("stusb4500_nvm_config"); + return err; + } else if (!err) { + LOG_INFO("NVM config OK"); + } else { + LOG_WARN("NVM config changed:"); + + if ((err = stusb4500_nvm_print(&nvm, stderr))) { + LOG_WARN("stusb4500_nvm_print"); + } if ((err = stusb4500_nvm_write(stusb4500, &nvm))) { LOG_ERROR("stusb4500_nvm_write"); diff --git a/components/usb_pd_sink/stusb4500.h b/components/usb_pd_sink/stusb4500.h index 8962ab05..b668a0a5 100644 --- a/components/usb_pd_sink/stusb4500.h +++ b/components/usb_pd_sink/stusb4500.h @@ -16,6 +16,7 @@ int stusb4500_reset(struct stusb4500 *stusb4500); int stusb4500_setup(struct stusb4500 *stusb4500); int stusb4500_start(struct stusb4500 *stusb4500); int stusb4500_status(struct stusb4500 *stusb4500, struct usb_pd_sink_status *status); + int stusb4500_print(struct stusb4500 *stusb4500, FILE *file); int stusb4500_i2c_read(struct stusb4500 *stusb4500, enum stusb4500_i2c_register reg, void *buf, size_t size); @@ -24,5 +25,10 @@ int stusb4500_i2c_write(struct stusb4500 *stusb4500, enum stusb4500_i2c_register int stusb4500_nvm_read(struct stusb4500 *stusb4500, union stusb4500_nvm *nvm); int stusb4500_nvm_write(struct stusb4500 *stusb4500, const union stusb4500_nvm *nvm); +/* Return >0 if conents invalid */ +int stusb4500_nvm_validate(union stusb4500_nvm *nvm); + /* Return 0 if unchanged, >0 if modified, <0 on errors */ -int stusb4500_config_nvm(union stusb4500_nvm *nvm); +int stusb4500_nvm_config(union stusb4500_nvm *nvm); + +int stusb4500_nvm_print(const union stusb4500_nvm *nvm, FILE *file); diff --git a/components/usb_pd_sink/stusb4500_nvm.h b/components/usb_pd_sink/stusb4500_nvm.h index f4793358..f3563e61 100644 --- a/components/usb_pd_sink/stusb4500_nvm.h +++ b/components/usb_pd_sink/stusb4500_nvm.h @@ -2,6 +2,7 @@ #include +#define STUSB4500_NVM_START 0xC0 #define STUSB4500_NVM_SECTOR_COUNT 5 #define STUSB4500_NVM_SECTOR_SIZE 8 diff --git a/components/usb_pd_sink/stusb4500_config.c b/components/usb_pd_sink/stusb4500_nvm_config.c similarity index 88% rename from components/usb_pd_sink/stusb4500_config.c rename to components/usb_pd_sink/stusb4500_nvm_config.c index 316225b1..d9c1c856 100644 --- a/components/usb_pd_sink/stusb4500_config.c +++ b/components/usb_pd_sink/stusb4500_nvm_config.c @@ -47,22 +47,21 @@ static inline unsigned config_snk_pdo_i(unsigned config_mA) } } -int stusb4500_config_nvm(union stusb4500_nvm *nvm) +int stusb4500_nvm_validate(union stusb4500_nvm *nvm) { stusb4500_nvm_sector_t zero_sector = {}; - // sanity-check for (int i = 0; i < STUSB4500_NVM_SECTOR_COUNT; i++) { if (!memcmp(nvm->sectors[i], &zero_sector, sizeof(zero_sector))) { LOG_ERROR("sector%d is all-zeroes, corrupted read?", i); - return -1; + return 1; } } for (int i = 1; i < STUSB4500_NVM_SECTOR_COUNT; i++) { if (!memcmp(nvm->sectors[i], nvm->sectors[i - 1], sizeof(nvm->sectors[i]))) { LOG_ERROR("sector%d is identical to sector%d, corrupted read?", i, i - 1); - return -1; + return 1; } } @@ -72,7 +71,7 @@ int stusb4500_config_nvm(union stusb4500_nvm *nvm) nvm->banks.bank0.product_id, nvm->banks.bank0.bcd_device_id ); - return -1; + return 1; } if (nvm->banks.bank0.product_id != STUSB4500_NVM_PRODUCT_ID) { @@ -81,7 +80,7 @@ int stusb4500_config_nvm(union stusb4500_nvm *nvm) nvm->banks.bank0.product_id, nvm->banks.bank0.bcd_device_id ); - return -1; + return 1; } if (nvm->banks.bank0.bcd_device_id != STUSB4500_NVM_DEVICE_ID) { @@ -90,10 +89,14 @@ int stusb4500_config_nvm(union stusb4500_nvm *nvm) nvm->banks.bank0.product_id, nvm->banks.bank0.bcd_device_id ); - return -1; + return 1; } - // apply config changes + return 0; +} + +int stusb4500_nvm_config(union stusb4500_nvm *nvm) +{ int ret = 0; if (nvm->banks.bank3.dpm_snk_pdo_numb != CONFIG_STUSB4500_SNK_PDO_NUMB) { @@ -210,3 +213,29 @@ int stusb4500_config_nvm(union stusb4500_nvm *nvm) return ret; } + +int stusb4500_nvm_print(const union stusb4500_nvm *nvm, FILE *file) +{ + int err; + + for (int i = 0; i < STUSB4500_NVM_SECTOR_COUNT; i++) { + // using GUI file format + err = fprintf(file, "0x%02X:\t0x%02X\t0x%02X\t0x%02X\t0x%02X\t0x%02X\t0x%02X\t0x%02X\t0x%02X\r\n", + STUSB4500_NVM_START + i * STUSB4500_NVM_SECTOR_SIZE, + nvm->sectors[i][0], + nvm->sectors[i][1], + nvm->sectors[i][2], + nvm->sectors[i][3], + nvm->sectors[i][4], + nvm->sectors[i][5], + nvm->sectors[i][6], + nvm->sectors[i][7] + ); + + if (err < 0) { + return err; + } + } + + return 0; +} diff --git a/components/usb_pd_sink/stusb4500_print.c b/components/usb_pd_sink/stusb4500_print.c index 89cfc645..ca31a1e1 100644 --- a/components/usb_pd_sink/stusb4500_print.c +++ b/components/usb_pd_sink/stusb4500_print.c @@ -192,7 +192,7 @@ static void stusb4500_print_nvm(struct stusb4500 *stusb4500, FILE *file) } for (int i = 0; i < STUSB4500_NVM_SECTOR_COUNT; i++) { - fprintf(file, "\tnvm sector[%d]: %02x %02x %02x %02x %02x %02x %02x %02x\n", i, + fprintf(file, "\tnvm bank%d: %02x %02x %02x %02x %02x %02x %02x %02x", i, nvm.sectors[i][0], nvm.sectors[i][1], nvm.sectors[i][2], @@ -202,49 +202,64 @@ static void stusb4500_print_nvm(struct stusb4500 *stusb4500, FILE *file) nvm.sectors[i][6], nvm.sectors[i][7] ); - } - fprintf(file, "\tnvm bank0 vendor_id=%04x product_id=%04x bcd_device_id=%04x port_role_ctrl=%u device_power_role_ctrl=%u\n", - nvm.banks.bank0.vendor_id, - nvm.banks.bank0.product_id, - nvm.banks.bank0.bcd_device_id, - nvm.banks.bank0.port_role_ctrl, - nvm.banks.bank0.device_power_role_ctrl - ); - - fprintf(file, "\tnvm bank1 gpio_cfg=%u vbus_dchg_mask=%u vbus_disch_time_to_pdo=%u discharge_time_to_0v=%u\n", - nvm.banks.bank1.gpio_cfg, - nvm.banks.bank1.vbus_dchg_mask, - nvm.banks.bank1.vbus_disch_time_to_pdo, - nvm.banks.bank1.discharge_time_to_0v - ); - - fprintf(file, "\tnvm bank3 usb_comm_capable=%u dpm_snk_pdo_numb=%u snk_uncons_power=%u\n", - nvm.banks.bank3.usb_comm_capable, - nvm.banks.bank3.dpm_snk_pdo_numb, - nvm.banks.bank3.snk_uncons_power - ); - - fprintf(file, "\tnvm bank3 pdo1(i=%u ll=%u hl=%u) pdo2(i=%u ll=%u hl=%u) pdo3(i=%u ll=%u hl=%u)\n", - nvm.banks.bank3.lut_snk_pdo1_i, - nvm.banks.bank3.snk_ll1, - nvm.banks.bank3.snk_hl1, - nvm.banks.bank3.lut_snk_pdo2_i, - nvm.banks.bank3.snk_ll2, - nvm.banks.bank3.snk_hl2, - nvm.banks.bank3.lut_snk_pdo3_i, - nvm.banks.bank3.snk_ll3, - nvm.banks.bank3.snk_hl3 - ); - - fprintf(file, "\tnvm bank4 snk_pdo_flex1_v=%u snk_pdo_flex2_v=%u snk_pdo_flex_i=%u power_ok_cfg=%u power_only_above_5v=%u req_src_current=%u\n", - nvm.banks.bank4.snk_pdo_flex1_v, - nvm.banks.bank4.snk_pdo_flex2_v, - nvm.banks.bank4.snk_pdo_flex_i, - nvm.banks.bank4.power_ok_cfg, - nvm.banks.bank4.power_only_above_5v, - nvm.banks.bank4.req_src_current - ); + switch(i) { + case 0: + fprintf(file, "\tvendor_id=%04x product_id=%04x bcd_device_id=%04x port_role_ctrl=%u device_power_role_ctrl=%u", + nvm.banks.bank0.vendor_id, + nvm.banks.bank0.product_id, + nvm.banks.bank0.bcd_device_id, + nvm.banks.bank0.port_role_ctrl, + nvm.banks.bank0.device_power_role_ctrl + ); + break; + + case 1: + fprintf(file, "\tnvm bank1 gpio_cfg=%u vbus_dchg_mask=%u vbus_disch_time_to_pdo=%u discharge_time_to_0v=%u", + nvm.banks.bank1.gpio_cfg, + nvm.banks.bank1.vbus_dchg_mask, + nvm.banks.bank1.vbus_disch_time_to_pdo, + nvm.banks.bank1.discharge_time_to_0v + ); + + case 2: + // nothing interesting + break; + + case 3: + fprintf(file, "\tusb_comm_capable=%u dpm_snk_pdo_numb=%u snk_uncons_power=%u", + nvm.banks.bank3.usb_comm_capable, + nvm.banks.bank3.dpm_snk_pdo_numb, + nvm.banks.bank3.snk_uncons_power + ); + + fprintf(file, "\tpdo1(i=%u ll=%u hl=%u) pdo2(i=%u ll=%u hl=%u) pdo3(i=%u ll=%u hl=%u)", + nvm.banks.bank3.lut_snk_pdo1_i, + nvm.banks.bank3.snk_ll1, + nvm.banks.bank3.snk_hl1, + nvm.banks.bank3.lut_snk_pdo2_i, + nvm.banks.bank3.snk_ll2, + nvm.banks.bank3.snk_hl2, + nvm.banks.bank3.lut_snk_pdo3_i, + nvm.banks.bank3.snk_ll3, + nvm.banks.bank3.snk_hl3 + ); + break; + + case 4: + fprintf(file, "\tsnk_pdo_flex1_v=%u snk_pdo_flex2_v=%u snk_pdo_flex_i=%u power_ok_cfg=%u power_only_above_5v=%u req_src_current=%u", + nvm.banks.bank4.snk_pdo_flex1_v, + nvm.banks.bank4.snk_pdo_flex2_v, + nvm.banks.bank4.snk_pdo_flex_i, + nvm.banks.bank4.power_ok_cfg, + nvm.banks.bank4.power_only_above_5v, + nvm.banks.bank4.req_src_current + ); + break; + } + + fprintf(file, "\n"); + } } int stusb4500_print(struct stusb4500 *stusb4500, FILE *file) @@ -253,6 +268,7 @@ int stusb4500_print(struct stusb4500 *stusb4500, FILE *file) stusb4500_print_ctrl(stusb4500, file); stusb4500_print_pdo(stusb4500, file); stusb4500_print_rdo(stusb4500, file); + stusb4500_print_nvm(stusb4500, file); return 0; From 741a0d52088de6ae586ad24a9401a82635e95752 Mon Sep 17 00:00:00 2001 From: Tero Marttila Date: Sun, 21 Jan 2024 12:51:27 +0200 Subject: [PATCH 22/24] usb_pd_sink stusb4500: clarify STUSB4500_REQ_SRC_CURRENT config prompt --- components/usb_pd_sink/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/usb_pd_sink/Kconfig b/components/usb_pd_sink/Kconfig index 69d2fcd8..a3f4a5db 100644 --- a/components/usb_pd_sink/Kconfig +++ b/components/usb_pd_sink/Kconfig @@ -42,7 +42,7 @@ menu "STUSB4500" default 0 config STUSB4500_REQ_SRC_CURRENT - bool "In case of match, selects which operating current from the sink or the source is to be requested in the RDO message" + bool "Request maximum available source current from source" default 0 choice STUSB4500_POWER_OK_CFG_CHOICE From 942d7d86646fc516c5683d01b272459584e137f0 Mon Sep 17 00:00:00 2001 From: Tero Marttila Date: Sun, 21 Jan 2024 13:09:39 +0200 Subject: [PATCH 23/24] main: fix esp8266 build wihtout usb_pd_sink --- main/usb_pd_sink.c | 4 ++-- main/usb_pd_state.h | 8 ++++++-- projects/esp8266/Makefile | 1 + 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/main/usb_pd_sink.c b/main/usb_pd_sink.c index 9d0ab1c0..f6874599 100644 --- a/main/usb_pd_sink.c +++ b/main/usb_pd_sink.c @@ -3,11 +3,11 @@ #include "i2c_master.h" -#include - #include #if CONFIG_USB_PD_SINK_ENABLED + #include + struct usb_pd_sink *usb_pd_sink; int init_usb_pd_sink() diff --git a/main/usb_pd_state.h b/main/usb_pd_state.h index 00ba06b5..99555157 100644 --- a/main/usb_pd_state.h +++ b/main/usb_pd_state.h @@ -1,5 +1,9 @@ #pragma once -#include +#include -extern struct usb_pd_sink *usb_pd_sink; +#if CONFIG_USB_PD_SINK_ENABLED + #include + + extern struct usb_pd_sink *usb_pd_sink; +#endif diff --git a/projects/esp8266/Makefile b/projects/esp8266/Makefile index 2bed4eca..3bbe3380 100644 --- a/projects/esp8266/Makefile +++ b/projects/esp8266/Makefile @@ -2,6 +2,7 @@ PROJECT_NAME := qmsk-esp EXTRA_COMPONENT_DIRS := +EXCLUDE_COMPONENTS := usb_pd_sink COMPONENT_DIRS := $(abspath ../../components) ${EXTRA_COMPONENT_DIRS} ${IDF_PATH}/components $(abspath ../../main) include $(IDF_PATH)/make/project.mk From a40fbeaaf9cb4b59a680c3a13483af2bbf6720b9 Mon Sep 17 00:00:00 2001 From: Tero Marttila Date: Sun, 21 Jan 2024 13:27:51 +0200 Subject: [PATCH 24/24] usb_pd_sink stusb4500: fix nvm base1 print --- components/usb_pd_sink/stusb4500_print.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/usb_pd_sink/stusb4500_print.c b/components/usb_pd_sink/stusb4500_print.c index ca31a1e1..2912808d 100644 --- a/components/usb_pd_sink/stusb4500_print.c +++ b/components/usb_pd_sink/stusb4500_print.c @@ -215,7 +215,7 @@ static void stusb4500_print_nvm(struct stusb4500 *stusb4500, FILE *file) break; case 1: - fprintf(file, "\tnvm bank1 gpio_cfg=%u vbus_dchg_mask=%u vbus_disch_time_to_pdo=%u discharge_time_to_0v=%u", + fprintf(file, "\tgpio_cfg=%u vbus_dchg_mask=%u vbus_disch_time_to_pdo=%u discharge_time_to_0v=%u", nvm.banks.bank1.gpio_cfg, nvm.banks.bank1.vbus_dchg_mask, nvm.banks.bank1.vbus_disch_time_to_pdo,