-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #67 from qmsk/usb-pd-st4500-sink
ST4500 USB-PD Sink
- Loading branch information
Showing
23 changed files
with
1,944 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
idf_component_register( | ||
SRC_DIRS . | ||
INCLUDE_DIRS "include" | ||
PRIV_REQUIRES logging | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +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 "Request maximum available source current from source" | ||
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 |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
#pragma once | ||
|
||
#include <freertos/FreeRTOS.h> | ||
#include <hal/i2c_types.h> | ||
#include <stdio.h> | ||
|
||
#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_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; | ||
|
||
int usb_pd_sink_new(struct usb_pd_sink **sinkp, const struct usb_pd_sink_options *options); | ||
|
||
/* | ||
* Setup USB-PD Sink using static Kconfig defaults. | ||
*/ | ||
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 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); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
#include "stusb4500.h" | ||
#include "stusb4500_i2c.h" | ||
|
||
#include <esp_err.h> | ||
|
||
#include <logging.h> | ||
|
||
int stusb4500_init(struct stusb4500 *stusb4500, const struct usb_pd_sink_options *options) | ||
{ | ||
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; | ||
} | ||
|
||
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 = {}; | ||
int err; | ||
|
||
if ((err = stusb4500_nvm_read(stusb4500, &nvm))) { | ||
LOG_ERROR("stusb4500_nvm_read"); | ||
return err; | ||
} | ||
|
||
if ((err = stusb4500_nvm_validate(&nvm)) < 0) { | ||
LOG_ERROR("stusb4500_nvm_validate"); | ||
return err; | ||
} else if (!err) { | ||
LOG_DEBUG("stusb4500_nvm_validate OK"); | ||
} else { | ||
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"); | ||
return err; | ||
} | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
#pragma once | ||
|
||
#include "stusb4500_i2c.h" | ||
#include "stusb4500_nvm.h" | ||
|
||
#include <usb_pd_sink.h> | ||
|
||
struct stusb4500 { | ||
i2c_port_t i2c_port; | ||
uint8_t i2c_addr; | ||
TickType_t i2c_timeout; | ||
}; | ||
|
||
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); | ||
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); | ||
|
||
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_nvm_config(union stusb4500_nvm *nvm); | ||
|
||
int stusb4500_nvm_print(const union stusb4500_nvm *nvm, FILE *file); |
Oops, something went wrong.