From feede444812562b7b68b061d8ec5cddf434e64ba Mon Sep 17 00:00:00 2001 From: Robert Zieba Date: Mon, 3 Mar 2025 10:38:21 -0700 Subject: [PATCH 1/6] asynchronous/internal: Add `set_port_control` function --- src/asynchronous/internal/mod.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/asynchronous/internal/mod.rs b/src/asynchronous/internal/mod.rs index 295439a..93e1df1 100644 --- a/src/asynchronous/internal/mod.rs +++ b/src/asynchronous/internal/mod.rs @@ -229,6 +229,19 @@ impl Tps6699x { .read_async() .await } + + /// Set port control + pub async fn set_port_control( + &mut self, + port: PortId, + control: registers::field_sets::PortControl, + ) -> Result<(), Error> { + self.borrow_port(port)? + .into_registers() + .port_control() + .write_async(|r| *r = control) + .await + } } #[cfg(test)] From 067c736d84679861ed01ea10528175c44783ed3d Mon Sep 17 00:00:00 2001 From: Robert Zieba Date: Fri, 7 Mar 2025 16:05:22 -0700 Subject: [PATCH 2/6] asynchronous/embassy: Add `set_port_control` wrapper --- src/asynchronous/embassy/mod.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/asynchronous/embassy/mod.rs b/src/asynchronous/embassy/mod.rs index 86b4361..62d2d86 100644 --- a/src/asynchronous/embassy/mod.rs +++ b/src/asynchronous/embassy/mod.rs @@ -153,6 +153,15 @@ impl<'a, M: RawMutex, B: I2c> Tps6699x<'a, M, B> { self.lock_inner().await.get_port_control(port).await } + /// Wrapper for `set_port_control` + pub async fn set_port_control( + &mut self, + port: PortId, + control: registers::field_sets::PortControl, + ) -> Result<(), Error> { + self.lock_inner().await.set_port_control(port, control).await + } + /// Returns the number of ports pub fn num_ports(&self) -> usize { self.controller.num_ports From cc6b48f3657f796015e80604b8d912ea0498e96d Mon Sep 17 00:00:00 2001 From: Robert Zieba Date: Mon, 3 Mar 2025 10:37:06 -0700 Subject: [PATCH 3/6] Add From/TryFrom implementations for internal type-C enums --- src/lib.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 74ee215..a849e13 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -51,6 +51,16 @@ pub mod registers { } } + impl From for TypecCurrent { + fn from(value: type_c::Current) -> Self { + match value { + type_c::Current::UsbDefault => TypecCurrent::UsbDefault, + type_c::Current::Current1A5 => TypecCurrent::Current1A5, + type_c::Current::Current3A0 => TypecCurrent::Current3A0, + } + } + } + impl TryFrom for type_c::Current { type Error = PdError; @@ -63,6 +73,16 @@ pub mod registers { } } } + + impl From for PdCcPullUp { + fn from(value: type_c::Current) -> Self { + match value { + type_c::Current::UsbDefault => PdCcPullUp::UsbDefault, + type_c::Current::Current1A5 => PdCcPullUp::Current1A5, + type_c::Current::Current3A0 => PdCcPullUp::Current3A0, + } + } + } } #[derive(Debug, Clone, Copy, PartialEq, Eq)] From b9190d45587cde14ef72c2a2aec1f0eaab82e893 Mon Sep 17 00:00:00 2001 From: Robert Zieba Date: Sat, 1 Mar 2025 13:47:09 -0700 Subject: [PATCH 4/6] asynchronous: Implement source enablement functions --- device.yaml | 215 +++++++++++++++++++++++++++++++ src/asynchronous/internal/mod.rs | 45 ++++++- 2 files changed, 259 insertions(+), 1 deletion(-) diff --git a/device.yaml b/device.yaml index b8dd19a..5d0a827 100644 --- a/device.yaml +++ b/device.yaml @@ -537,6 +537,221 @@ PowerPathStatus: Vbus: 0x2 Unknown: catch_all +SystemConfig: + type: register + address: 0x27 + access: RW + size_bits: 119 + reset_value: 0x000000000000000034003318671205 + description: Global system configuration + fields: + PaVconnConfig: + base: bool + start: 0 + description: Enable PA VCONN + PbVconnConfig: + base: bool + start: 2 + description: Enable PB VCONN + PaPp5vVbusSwConfig: + base: uint + start: 8 + end: 11 + description: PA PP5V VBUS configuration + conversion: + name: VbusSwConfig + Disabled: 0x0 + Source: 0x1 + Reserved: catch_all + PbPp5vVbusSwConfig: + base: uint + start: 11 + end: 14 + description: PB PP5V VBUS configuration + conversion: VbusSwConfig + IlimOverShoot: + base: uint + start: 14 + end: 16 + description: PP_5V ILIM configuration + conversion: + name: IlimOverShoot + NoOvershoot: 0x0 + Overshoot100ma: 0x1 + Overshoot200ma: 0x2 + Reserved: catch_all + PaPpextVbusSwConfig: + base: uint + start: 16 + end: 19 + description: PA PPEXT configuration + conversion: + name: PpextVbusSwConfig + Unused: 0x0 + Source: 0x1 + Sink: 0x2 + SinkWaitSrdy: 0x3 + BiDirectional: 0x4 + BiDirectionalWaitSrdy: 0x5 + Reserved: catch_all + PbPpextVbusSwConfig: + base: uint + start: 19 + end: 22 + description: PB PPEXT configuration + conversion: PpextVbusSwConfig + RcpThreshold: + base: uint + start: 22 + end: 24 + description: Threshold used for RCP on PP_EXT + conversion: + name: RcpThreshold + Threshold6mv: 0x0 + Threshold8mv: 0x1 + Threshold10mv: 0x2 + Threshold12mv: 0x3 + MultiPortSinkPolicyHighestPower: + base: bool + start: 24 + description: Automatic sink-path coordination, true for highest power, false for no sink management + TbtControllerType: + base: uint + start: 26 + end: 29 + description: Type of TBT controller + conversion: + name: TbtControllerType + Default: 0x0 + Ar: 0x1 + Tr: 0x2 + Icl: 0x3 + Gr: 0x4 + Br: 0x5 + Reserved: catch_all + EnableOneUfpPolicy: + base: bool + start: 29 + description: Enable bit for simple UFP policy manager + EnableSpm: + base: bool + start: 30 + description: Enable bit for simple source power management + MultiPortSinkNonOverlapTime: + base: uint + start: 31 + end: 33 + description: Delay configuration for MultiPortSinkPolicy + conversion: + name: MultiPortSinkNonOverlapTime + Delay1ms: 0x0 + Delay5ms: 0x1 + Delay10ms: 0x2 + Delay15ms: 0x3 + EnableI2cMultiControllerMode: + base: bool + start: 33 + description: Enables I2C Multi Controller mode + I2cTimeout: + base: uint + start: 34 + end: 37 + description: I2C bus timeout + conversion: + name: I2cTimeout + Timeout25ms: 0x0 + Timeout50ms: 0x1 + Timeout75ms: 0x2 + Timeout100ms: 0x3 + Timeout125ms: 0x4 + Timeout150ms: 0x5 + Timeout175ms: 0x6 + Timeout1000ms: 0x7 + DisableEepromUpdates: + base: bool + start: 37 + description: EEPROM updates not allowed if this bit asserted + EmulateSinglePort: + base: bool + start: 38 + description: Enable only port A + MinimumCurrentAdvertisement1A5: + base: bool + start: 39 + description: SPM minimum current advertisement, true for 1.5 A, false for USB default + UsbDefaultCurrent: + base: uint + start: 43 + end: 45 + description: Value for USB default current + conversion: + name: UsbDefaultCurrent + UsbDefault: 0x0 + Current900ma: 0x1 + Current150ma: 0x2 + Reserved: catch_all + EprSupportedAsSource: + base: bool + start: 45 + description: EPR supported as source + EprSupportedAsSink: + base: bool + start: 46 + description: EPR supported as sink + EnableLowPowerModeAmEntryExit: + base: bool + start: 47 + description: Enable AM entry/exit on low-power mode exit/entry + CrossbarPollingMode: + base: bool + start: 54 + description: Enable crossbar polling mode + CrossbarConfigType1Extended: + base: bool + start: 55 + description: Enable crossbar type 1 extended write + ExternalDcdcStatusPollingInterval: + base: uint + start: 56 + end: 64 + description: External DCDC Status Polling Interval + Port1I2c2TargetAddress: + base: uint + start: 64 + end: 72 + description: Target address for Port 1 on I2C2s + Port2I2c2TargetAddress: + base: uint + start: 72 + end: 78 + description: Target address for Port 2 on I2C2s + VsysPreventsHighPower: + base: bool + start: 80 + description: Halts setting up external DCDC configuration until 5V power is present from the system + WaitForVin3v3: + base: bool + start: 81 + description: Stalls the PD in PTCH mode until Vsys is present + WaitForMinimumPower: + base: bool + start: 82 + description: Stalls the PD in PTCH mode until a power connection is made that meets the needed conditions + SourcePolicyMode: + base: uint + start: 103 + end: 105 + description: Source Policy Mode + WaitForNgpio: + base: bool + start: 110 + description: Wait for nGPIO from battery charger + DeadBatteryAutoClear: + base: uint + start: 111 + end: 118 + description: Moisture Detection State + PortControl: type: register address: 0x29 diff --git a/src/asynchronous/internal/mod.rs b/src/asynchronous/internal/mod.rs index 93e1df1..2b38aea 100644 --- a/src/asynchronous/internal/mod.rs +++ b/src/asynchronous/internal/mod.rs @@ -2,7 +2,8 @@ use embedded_hal_async::i2c::I2c; use embedded_usb_pd::{Error, PdError, PortId}; -use crate::{registers, Mode, MAX_SUPPORTED_PORTS, PORT0, TPS66993_NUM_PORTS, TPS66994_NUM_PORTS}; +use crate::registers::{self}; +use crate::{Mode, MAX_SUPPORTED_PORTS, PORT0, PORT1, TPS66993_NUM_PORTS, TPS66994_NUM_PORTS}; mod command; @@ -242,6 +243,48 @@ impl Tps6699x { .write_async(|r| *r = control) .await } + + /// Get global system config + pub async fn get_system_config(&mut self) -> Result> { + // This is a controller-level command, shouldn't matter which port we use + self.borrow_port(PORT0)? + .into_registers() + .system_config() + .read_async() + .await + } + + /// Set global system config + pub async fn set_system_config( + &mut self, + config: registers::field_sets::SystemConfig, + ) -> Result<(), Error> { + // This is a controller-level command, shouldn't matter which port we use + self.borrow_port(PORT0)? + .into_registers() + .system_config() + .write_async(|r| *r = config) + .await + } + + /// Enable/disable sourcing on a given port + pub async fn enable_source(&mut self, port: PortId, enable: bool) -> Result<(), Error> { + let mut config = self.get_system_config().await?; + + let enable = if enable { + registers::VbusSwConfig::Source + } else { + registers::VbusSwConfig::Disabled + }; + match port { + PORT0 => config.set_pa_pp_5_v_vbus_sw_config(enable), + PORT1 => config.set_pb_pp_5_v_vbus_sw_config(enable), + _ => return PdError::InvalidPort.into(), + } + + self.set_system_config(config).await?; + Ok(()) + } } #[cfg(test)] From 882a12f08e31fea1c5852f964bf6045ad7f5c69a Mon Sep 17 00:00:00 2001 From: Robert Zieba Date: Fri, 7 Mar 2025 16:06:05 -0700 Subject: [PATCH 5/6] asynchronous/embassy: Add `system_config` wrappers --- src/asynchronous/embassy/mod.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/asynchronous/embassy/mod.rs b/src/asynchronous/embassy/mod.rs index 62d2d86..7070b24 100644 --- a/src/asynchronous/embassy/mod.rs +++ b/src/asynchronous/embassy/mod.rs @@ -162,6 +162,19 @@ impl<'a, M: RawMutex, B: I2c> Tps6699x<'a, M, B> { self.lock_inner().await.set_port_control(port, control).await } + /// Wrapper for `get_system_config` + pub async fn get_system_config(&mut self) -> Result> { + self.lock_inner().await.get_system_config().await + } + + /// Wrapper for `set_system_config` + pub async fn set_system_config( + &mut self, + config: registers::field_sets::SystemConfig, + ) -> Result<(), Error> { + self.lock_inner().await.set_system_config(config).await + } + /// Returns the number of ports pub fn num_ports(&self) -> usize { self.controller.num_ports From 5028e48df4b3ea92788d36a6c81fc1b64b956e9e Mon Sep 17 00:00:00 2001 From: Robert Zieba Date: Fri, 7 Mar 2025 16:06:47 -0700 Subject: [PATCH 6/6] asynchronous/embassy: Add `enable_source` wrapper --- src/asynchronous/embassy/mod.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/asynchronous/embassy/mod.rs b/src/asynchronous/embassy/mod.rs index 7070b24..93a3c7e 100644 --- a/src/asynchronous/embassy/mod.rs +++ b/src/asynchronous/embassy/mod.rs @@ -175,6 +175,11 @@ impl<'a, M: RawMutex, B: I2c> Tps6699x<'a, M, B> { self.lock_inner().await.set_system_config(config).await } + /// Wrapper for `enable_source` + pub async fn enable_source(&mut self, port: PortId, enable: bool) -> Result<(), Error> { + self.lock_inner().await.enable_source(port, enable).await + } + /// Returns the number of ports pub fn num_ports(&self) -> usize { self.controller.num_ports