tusb322.rs 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. use field_offset::offset_of;
  2. use stm32l4xx_hal::prelude::_embedded_hal_blocking_i2c_Write;
  3. use tock_registers::{
  4. interfaces::{ReadWriteable, Readable},
  5. register_bitfields, register_structs,
  6. registers::InMemoryRegister,
  7. };
  8. const TUSB322_ADDR: u8 = 0x47;
  9. register_bitfields![
  10. u8,
  11. // Connection status register
  12. ConnStatus1 [
  13. // Indicates that active cable has been plugged in
  14. ACTIVE_CABLE_DETECTION OFFSET(0) NUMBITS(1) [],
  15. // Read by the application to determine if accessory was attached
  16. ACCESSORY_CONNECTED OFFSET(1) NUMBITS(3) [
  17. None = 0,
  18. Audio = 4,
  19. AudioCharged = 5,
  20. DebugDfp = 6,
  21. DebugUfp = 7,
  22. ],
  23. // Set in UFP mode with the detected current mode
  24. CURRENT_MODE_DETECT OFFSET(4) NUMBITS(2) [
  25. Default = 0,
  26. Medium = 1,
  27. ChargeThrough = 2,
  28. High = 3,
  29. ],
  30. // Programmed by application to change current advertisement
  31. CURRENT_MODE_ADVERTISE OFFSET(6) NUMBITS(2) [
  32. Default = 0,
  33. Mid = 1,
  34. High = 2,
  35. Reserved = 3,
  36. ],
  37. ],
  38. // Connection status and control register
  39. ConnStatus2 [
  40. // Setting this field will disable UFP accessory support
  41. DISABLE_UFP_ACCESSORY OFFSET(0) NUMBITS(1) [],
  42. // Percentage of time that a DRP advertised DFP during tDRP
  43. DRP_DUTY_CYCLE OFFSET(1) NUMBITS(2) [
  44. p30 = 0,
  45. p40 = 1,
  46. p50 = 2,
  47. p60 = 3,
  48. ],
  49. // Set when over-current limit is triggered
  50. VCONN_FAULT OFFSET(3) NUMBITS(1) [],
  51. // Pulled low when a control or status register changes
  52. INTERRUPT_STATUS OFFSET(4) NUMBITS(1) [
  53. Clear = 0,
  54. Changed = 1,
  55. ],
  56. // Cable orientation
  57. CABLE_DIR OFFSET(5) NUMBITS(1) [
  58. CC1 = 0,
  59. CC2 = 1,
  60. ],
  61. // Attached state (same as ID pin)
  62. ATTACHED_STATE OFFSET(6) NUMBITS(2) [
  63. NotAttached = 0,
  64. AttachedSrc_DFP = 1,
  65. AttachedSnk_UFP = 2,
  66. AttachedAccessory = 3,
  67. ],
  68. ],
  69. // General control register
  70. Control [
  71. // Disable CC pin termination
  72. DISABLE_TERM OFFSET(0) NUMBITS(1) [],
  73. // Control behavior when configured as DRP
  74. SOURCE_PERF OFFSET(1) NUMBITS(2) [
  75. StandardDrp = 0,
  76. DrpTrySnk = 1,
  77. Reserved = 2,
  78. DrpTrySrc = 3,
  79. ],
  80. // Soft reset internal logic (self-clearing)
  81. I2C_SOFT_RESET OFFSET(3) NUMBITS(1) [],
  82. // Configure device operation mode
  83. MODE_SELECT OFFSET(4) NUMBITS(2) [
  84. Drp = 0,
  85. Ufp = 1,
  86. Dfp = 2,
  87. ],
  88. // Debounce time on CC pins
  89. DEBOUNCE OFFSET(6) NUMBITS(2) [
  90. ms168 = 0,
  91. ms118 = 1,
  92. ms134 = 2,
  93. ms152 = 3,
  94. ],
  95. ],
  96. ];
  97. register_structs! {
  98. Tusb322Registers {
  99. (0x00 => id: [u8; 8]),
  100. (0x08 => stat1: InMemoryRegister<u8, ConnStatus1::Register>),
  101. (0x09 => stat2: InMemoryRegister<u8, ConnStatus2::Register>),
  102. (0x0A => ctrl: InMemoryRegister<u8, Control::Register>),
  103. (0x0B => @END),
  104. }
  105. }
  106. impl Tusb322Registers {
  107. const fn default() -> Self {
  108. Self {
  109. id: [0; 8],
  110. stat1: InMemoryRegister::new(0x00),
  111. stat2: InMemoryRegister::new(0x00),
  112. ctrl: InMemoryRegister::new(0x00),
  113. }
  114. }
  115. // Program control registers
  116. fn i2c_write_regs(&self, address: u8, i2c: &mut impl _embedded_hal_blocking_i2c_Write) {
  117. let mut buffer: [u8; 4] = [0; 4];
  118. buffer[0] = offset_of!(Tusb322Registers => stat1).get_byte_offset() as u8;
  119. buffer[1] = self.stat1.get();
  120. buffer[2] = self.stat2.get();
  121. buffer[3] = self.ctrl.get();
  122. match i2c.write(address, &buffer) {
  123. Ok(_) => (),
  124. Err(_) => panic!(),
  125. }
  126. }
  127. }
  128. pub fn init(i2c: &mut impl _embedded_hal_blocking_i2c_Write) {
  129. let reg: Tusb322Registers = Tusb322Registers::default();
  130. // Disable UFP accessory support (otherwise IC stays in DRP mode)
  131. reg.stat2.modify(ConnStatus2::DISABLE_UFP_ACCESSORY::SET);
  132. // Disable CC termination to change to UFP mode
  133. reg.ctrl.modify(Control::DISABLE_TERM::SET);
  134. // For operation in UFP mode
  135. reg.ctrl.modify(Control::MODE_SELECT::Ufp);
  136. reg.i2c_write_regs(TUSB322_ADDR, i2c);
  137. // Re-enable CC termination
  138. reg.ctrl.modify(Control::DISABLE_TERM::CLEAR);
  139. reg.i2c_write_regs(TUSB322_ADDR, i2c);
  140. }