usb2422.c (15411B)
1 /* Copyright 2021 QMK 2 * 3 * This program is free software: you can redistribute it and/or modify 4 * it under the terms of the GNU General Public License as published by 5 * the Free Software Foundation, either version 3 of the License, or 6 * (at your option) any later version. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 * 13 * You should have received a copy of the GNU General Public License 14 * along with this program. If not, see <http://www.gnu.org/licenses/>. 15 */ 16 #include <string.h> 17 #include "usb2422.h" 18 #include "i2c_master.h" 19 #include "wait.h" 20 #include "gpio.h" 21 22 /* -------- USB2422_VID : (USB2422L Offset: 0x00) (R/W 16) Vendor ID -------- */ 23 typedef union { 24 struct { 25 uint16_t VID_LSB : 8; 26 uint16_t VID_MSB : 8; 27 } bit; /*!< Structure used for bit access */ 28 uint16_t reg; /*!< Type used for register access */ 29 } USB2422_VID_Type; 30 31 /* -------- USB2422_PID : (USB2422L Offset: 0x02) (R/W 16) Product ID -------- */ 32 typedef union { 33 struct { 34 uint16_t PID_LSB : 8; 35 uint16_t PID_MSB : 8; 36 } bit; /*!< Structure used for bit access */ 37 uint16_t reg; /*!< Type used for register access */ 38 } USB2422_PID_Type; 39 40 /* -------- USB2422_DID : (USB2422L Offset: 0x04) (R/W 16) Device ID -------- */ 41 typedef union { 42 struct { 43 uint16_t DID_LSB : 8; 44 uint16_t DID_MSB : 8; 45 } bit; /*!< Structure used for bit access */ 46 uint16_t reg; /*!< Type used for register access */ 47 } USB2422_DID_Type; 48 49 /* -------- USB2422_CFG1 : (USB2422L Offset: 0x06) (R/W 8) Configuration Data Byte 1-------- */ 50 typedef union { 51 struct { 52 uint8_t PORT_PWR : 1; 53 uint8_t CURRENT_SNS : 2; 54 uint8_t EOP_DISABLE : 1; 55 uint8_t MTT_ENABLE : 1; 56 uint8_t HS_DISABLE : 1; 57 uint8_t : 1; 58 uint8_t SELF_BUS_PWR : 1; 59 } bit; /*!< Structure used for bit access */ 60 uint8_t reg; /*!< Type used for register access */ 61 } USB2422_CFG1_Type; 62 63 /* -------- USB2422_CFG2 : (USB2422L Offset: 0x07) (R/W 8) Configuration Data Byte 2-------- */ 64 typedef union { 65 struct { 66 uint8_t : 3; 67 uint8_t COMPOUND : 1; 68 uint8_t OC_TIMER : 2; 69 uint8_t : 1; 70 uint8_t DYNAMIC : 1; 71 } bit; /*!< Structure used for bit access */ 72 uint8_t reg; /*!< Type used for register access */ 73 } USB2422_CFG2_Type; 74 75 /* -------- USB2422_CFG3 : (USB2422L Offset: 0x08) (R/W 16) Configuration Data Byte 3-------- */ 76 typedef union { 77 struct { 78 uint8_t STRING_EN : 1; 79 uint8_t : 2; 80 uint8_t PRTMAP_EN : 1; 81 uint8_t : 4; 82 } bit; /*!< Structure used for bit access */ 83 uint8_t reg; /*!< Type used for register access */ 84 } USB2422_CFG3_Type; 85 86 /* -------- USB2422_NRD : (USB2422L Offset: 0x09) (R/W 8) Non Removable Device -------- */ 87 typedef union { 88 struct { 89 uint8_t : 5; 90 uint8_t PORT2_NR : 1; 91 uint8_t PORT1_NR : 1; 92 uint8_t : 1; 93 } bit; /*!< Structure used for bit access */ 94 uint8_t reg; /*!< Type used for register access */ 95 } USB2422_NRD_Type; 96 97 /* -------- USB2422_PDS : (USB2422L Offset: 0x0A) (R/W 8) Port Diable for Self-Powered Operation -------- */ 98 typedef union { 99 struct { 100 uint8_t : 1; 101 uint8_t PORT1_DIS : 1; 102 uint8_t PORT2_DIS : 1; 103 uint8_t : 5; 104 } bit; /*!< Structure used for bit access */ 105 uint8_t reg; /*!< Type used for register access */ 106 } USB2422_PDS_Type; 107 108 /* -------- USB2422_PDB : (USB2422L Offset: 0x0B) (R/W 8) Port Diable for Bus-Powered Operation -------- */ 109 110 typedef union { 111 struct { 112 uint8_t : 1; 113 uint8_t PORT1_DIS : 1; 114 uint8_t PORT2_DIS : 1; 115 uint8_t : 5; 116 } bit; /*!< Structure used for bit access */ 117 uint8_t reg; /*!< Type used for register access */ 118 } USB2422_PDB_Type; 119 120 /* -------- USB2422_MAXPS : (USB2422L Offset: 0x0C) (R/W 8) Max Power for Self-Powered Operation -------- */ 121 typedef union { 122 struct { 123 uint8_t MAX_PWR_SP : 8; 124 } bit; /*!< Structure used for bit access */ 125 uint8_t reg; /*!< Type used for register access */ 126 } USB2422_MAXPS_Type; 127 128 /* -------- USB2422_MAXPB : (USB2422L Offset: 0x0D) (R/W 8) Max Power for Bus-Powered Operation -------- */ 129 typedef union { 130 struct { 131 uint8_t MAX_PWR_BP : 8; 132 } bit; /*!< Structure used for bit access */ 133 uint8_t reg; /*!< Type used for register access */ 134 } USB2422_MAXPB_Type; 135 136 /* -------- USB2422_HCMCS : (USB2422L Offset: 0x0E) (R/W 8) Hub Controller Max Current for Self-Powered Operation -------- */ 137 typedef union { 138 struct { 139 uint8_t HC_MAX_C_SP : 8; 140 } bit; /*!< Structure used for bit access */ 141 uint8_t reg; /*!< Type used for register access */ 142 } USB2422_HCMCS_Type; 143 144 /* -------- USB2422_HCMCB : (USB2422L Offset: 0x0F) (R/W 8) Hub Controller Max Current for Bus-Powered Operation -------- */ 145 typedef union { 146 struct { 147 uint8_t HC_MAX_C_BP : 8; 148 } bit; /*!< Structure used for bit access */ 149 uint8_t reg; /*!< Type used for register access */ 150 } USB2422_HCMCB_Type; 151 152 /* -------- USB2422_PWRT : (USB2422L Offset: 0x10) (R/W 8) Power On Time -------- */ 153 typedef union { 154 struct { 155 uint8_t POWER_ON_TIME : 8; 156 } bit; /*!< Structure used for bit access */ 157 uint8_t reg; /*!< Type used for register access */ 158 } USB2422_PWRT_Type; 159 160 /* -------- USB2422_LANGID LSB : (USB2422L Offset: 0x11) (R/W 16) Language ID -------- */ 161 typedef union { 162 struct { 163 uint8_t LANGID_LSB : 8; 164 } bit; /*!< Structure used for bit access */ 165 uint8_t reg; /*!< Type used for register access */ 166 } USB2422_LANGID_LSB_Type; 167 168 /* -------- USB2422_LANGID MSB : (USB2422L Offset: 0x12) (R/W 16) Language ID -------- */ 169 typedef union { 170 struct { 171 uint8_t LANGID_MSB : 8; 172 } bit; /*!< Structure used for bit access */ 173 uint8_t reg; /*!< Type used for register access */ 174 } USB2422_LANGID_MSB_Type; 175 176 /* -------- USB2422_MFRSL : (USB2422L Offset: 0x13) (R/W 8) Manufacturer String Length -------- */ 177 typedef union { 178 struct { 179 uint8_t MFR_STR_LEN : 8; 180 } bit; /*!< Structure used for bit access */ 181 uint8_t reg; /*!< Type used for register access */ 182 } USB2422_MFRSL_Type; 183 184 /* -------- USB2422_PRDSL : (USB2422L Offset: 0x14) (R/W 8) Product String Length -------- */ 185 typedef union { 186 struct { 187 uint8_t PRD_STR_LEN : 8; 188 } bit; /*!< Structure used for bit access */ 189 uint8_t reg; /*!< Type used for register access */ 190 } USB2422_PRDSL_Type; 191 192 /* -------- USB2422_SERSL : (USB2422L Offset: 0x15) (R/W 8) Serial String Length -------- */ 193 typedef union { 194 struct { 195 uint8_t SER_STR_LEN : 8; 196 } bit; /*!< Structure used for bit access */ 197 uint8_t reg; /*!< Type used for register access */ 198 } USB2422_SERSL_Type; 199 200 /* -------- USB2422_MFRSTR : (USB2422L Offset: 0x16-53) (R/W 8) Maufacturer String -------- */ 201 typedef uint16_t USB2422_MFRSTR_Type; 202 203 /* -------- USB2422_PRDSTR : (USB2422L Offset: 0x54-91) (R/W 8) Product String -------- */ 204 typedef uint16_t USB2422_PRDSTR_Type; 205 206 /* -------- USB2422_SERSTR : (USB2422L Offset: 0x92-CF) (R/W 8) Serial String -------- */ 207 typedef uint16_t USB2422_SERSTR_Type; 208 209 /* -------- USB2422_BCEN : (USB2422L Offset: 0xD0) (R/W 8) Battery Charging Enable -------- */ 210 211 typedef union { 212 struct { 213 uint8_t : 1; 214 uint8_t PORT1_BCE : 1; 215 uint8_t PORT2_BCE : 1; 216 uint8_t : 5; 217 } bit; /*!< Structure used for bit access */ 218 uint8_t reg; /*!< Type used for register access */ 219 } USB2422_BCEN_Type; 220 221 /* -------- USB2422_BOOSTUP : (USB2422L Offset: 0xF6) (R/W 8) Boost Upstream -------- */ 222 typedef union { 223 struct { 224 uint8_t BOOST : 2; 225 uint8_t : 6; 226 } bit; /*!< Structure used for bit access */ 227 uint8_t reg; /*!< Type used for register access */ 228 } USB2422_BOOSTUP_Type; 229 230 /* -------- USB2422_BOOSTDOWN : (USB2422L Offset: 0xF8) (R/W 8) Boost Downstream -------- */ 231 typedef union { 232 struct { 233 uint8_t BOOST1 : 2; 234 uint8_t BOOST2 : 2; 235 uint8_t : 4; 236 } bit; /*!< Structure used for bit access */ 237 uint8_t reg; /*!< Type used for register access */ 238 } USB2422_BOOSTDOWN_Type; 239 240 /* -------- USB2422_PRTSP : (USB2422L Offset: 0xFA) (R/W 8) Port Swap -------- */ 241 typedef union { 242 struct { 243 uint8_t : 1; 244 uint8_t PORT1_SP : 1; 245 uint8_t PORT2_SP : 1; 246 uint8_t : 5; 247 } bit; /*!< Structure used for bit access */ 248 uint8_t reg; /*!< Type used for register access */ 249 } USB2422_PRTSP_Type; 250 251 /* -------- USB2422_PRTR12 : (USB2422L Offset: 0xFB) (R/W 8) Port 1/2 Remap -------- */ 252 typedef union { 253 struct { 254 uint8_t PORT1_REMAP : 4; 255 uint8_t PORT2_REMAP : 4; 256 } bit; /*!< Structure used for bit access */ 257 uint8_t reg; /*!< Type used for register access */ 258 } USB2422_PRTR12_Type; 259 260 #define USB2422_PRTR12_DISABLE 0 261 #define USB2422_PRT12_P2TOL1 1 262 #define USB2422_PRT12_P2XTOL2 2 263 #define USB2422_PRT12_P1TOL1 1 264 #define USB2422_PRT12_P1XTOL2 2 265 266 /* -------- USB2422_STCD : (USB2422L Offset: 0xFF) (R/W 8) Status Command -------- */ 267 typedef union { 268 struct { 269 uint8_t USB_ATTACH : 1; 270 uint8_t RESET : 1; 271 uint8_t INTF_PWRDN : 1; 272 uint8_t : 5; 273 } bit; /*!< Structure used for bit access */ 274 uint8_t reg; /*!< Type used for register access */ 275 } USB2422_STCD_Type; 276 277 /** \brief USB2422 device hardware registers */ 278 typedef struct { 279 USB2422_VID_Type VID; /**< \brief Offset: 0x00*/ 280 USB2422_PID_Type PID; /**< \brief Offset: 0x02*/ 281 USB2422_DID_Type DID; /**< \brief Offset: 0x04*/ 282 USB2422_CFG1_Type CFG1; /**< \brief Offset: 0x06*/ 283 USB2422_CFG2_Type CFG2; /**< \brief Offset: 0x07*/ 284 USB2422_CFG3_Type CFG3; /**< \brief Offset: 0x08*/ 285 USB2422_NRD_Type NRD; /**< \brief Offset: 0x09*/ 286 USB2422_PDS_Type PDS; /**< \brief Offset: 0x0A*/ 287 USB2422_PDB_Type PDB; /**< \brief Offset: 0x0B*/ 288 USB2422_MAXPS_Type MAXPS; /**< \brief Offset: 0x0C*/ 289 USB2422_MAXPB_Type MAXPB; /**< \brief Offset: 0x0D*/ 290 USB2422_HCMCS_Type HCMCS; /**< \brief Offset: 0x0E*/ 291 USB2422_HCMCB_Type HCMCB; /**< \brief Offset: 0x0F*/ 292 USB2422_PWRT_Type PWRT; /**< \brief Offset: 0x10*/ 293 USB2422_LANGID_LSB_Type LANGID_LSB; /**< \brief Offset: 0x11*/ 294 USB2422_LANGID_MSB_Type LANGID_MSB; /**< \brief Offset: 0x12*/ 295 USB2422_MFRSL_Type MFRSL; /**< \brief Offset: 0x13*/ 296 USB2422_PRDSL_Type PRDSL; /**< \brief Offset: 0x14*/ 297 USB2422_SERSL_Type SERSL; /**< \brief Offset: 0x15*/ 298 USB2422_MFRSTR_Type MFRSTR[31]; /**< \brief Offset: 0x16*/ 299 USB2422_PRDSTR_Type PRDSTR[31]; /**< \brief Offset: 0x54*/ 300 USB2422_SERSTR_Type SERSTR[31]; /**< \brief Offset: 0x92*/ 301 USB2422_BCEN_Type BCEN; /**< \brief Offset: 0xD0*/ 302 uint8_t Reserved1[0x25]; 303 USB2422_BOOSTUP_Type BOOSTUP; /**< \brief Offset: 0xF6*/ 304 uint8_t Reserved2[0x1]; 305 USB2422_BOOSTDOWN_Type BOOSTDOWN; /**< \brief Offset: 0xF8*/ 306 uint8_t Reserved3[0x1]; 307 USB2422_PRTSP_Type PRTSP; /**< \brief Offset: 0xFA*/ 308 USB2422_PRTR12_Type PRTR12; /**< \brief Offset: 0xFB*/ 309 uint8_t Reserved4[0x3]; 310 USB2422_STCD_Type STCD; /**< \brief Offset: 0xFF*/ 311 } Usb2422_t; 312 313 // *************************************************************** 314 315 static Usb2422_t config; 316 317 // *************************************************************** 318 319 /** \brief Handle the conversion to allow simple strings 320 */ 321 static void USB2422_strcpy(const char* str, USB2422_MFRSTR_Type* dest, uint8_t len) { 322 for (uint8_t i = 0; i < len; i++) { 323 dest[i] = str[i]; 324 } 325 } 326 327 /** \brief Handle the conversion to allow simple strings 328 */ 329 static void USB2422_write_block(void) { 330 static unsigned char i2c0_buf[34]; 331 332 unsigned char* dest = i2c0_buf; 333 unsigned char* src; 334 unsigned char* base = (unsigned char*)&config; 335 336 for (src = base; src < base + 256; src += 32) { 337 dest[0] = src - base; 338 dest[1] = 32; 339 memcpy(&dest[2], src, 32); 340 i2c_transmit(USB2422_ADDRESS, dest, 34, 50000); 341 wait_us(100); 342 } 343 } 344 345 // *************************************************************** 346 347 void USB2422_init(void) { 348 #ifdef USB2422_RESET_PIN 349 gpio_set_pin_output(USB2422_RESET_PIN); 350 #endif 351 #ifdef USB2422_ACTIVE_PIN 352 gpio_set_pin_input(USB2422_ACTIVE_PIN); 353 #endif 354 355 i2c_init(); // IC2 clk must be high at USB2422 reset release time to signal SMB configuration 356 } 357 358 void USB2422_configure(void) { 359 static const char SERNAME[] = "Unavailable"; 360 361 memset(&config, 0, sizeof(Usb2422_t)); 362 363 // configure Usb2422 registers 364 config.VID.reg = USB2422_VENDOR_ID; 365 config.PID.reg = USB2422_PRODUCT_ID; 366 config.DID.reg = USB2422_DEVICE_VER; // BCD format, eg 01.01 367 config.CFG1.bit.SELF_BUS_PWR = 1; // self powered for now 368 config.CFG1.bit.HS_DISABLE = 1; // full or high speed 369 // config.CFG2.bit.COMPOUND = 0; // compound device 370 config.CFG3.bit.STRING_EN = 1; // strings enabled 371 // config.NRD.bit.PORT2_NR = 0; // MCU is non-removable 372 config.MAXPB.reg = 20; // 0mA 373 config.HCMCB.reg = 20; // 0mA 374 config.MFRSL.reg = sizeof(USB2422_MANUFACTURER); 375 config.PRDSL.reg = sizeof(USB2422_PRODUCT); 376 config.SERSL.reg = sizeof(SERNAME); 377 USB2422_strcpy(USB2422_MANUFACTURER, config.MFRSTR, sizeof(USB2422_MANUFACTURER)); 378 USB2422_strcpy(USB2422_PRODUCT, config.PRDSTR, sizeof(USB2422_PRODUCT)); 379 USB2422_strcpy(SERNAME, config.SERSTR, sizeof(SERNAME)); 380 // config.BOOSTUP.bit.BOOST=3; //upstream port 381 // config.BOOSTDOWN.bit.BOOST1=0; // extra port 382 // config.BOOSTDOWN.bit.BOOST2=2; //MCU is close 383 config.STCD.bit.USB_ATTACH = 1; 384 385 USB2422_write_block(); 386 } 387 388 void USB2422_reset(void) { 389 #ifdef USB2422_RESET_PIN 390 gpio_write_pin_low(USB2422_RESET_PIN); 391 wait_us(2); 392 gpio_write_pin_high(USB2422_RESET_PIN); 393 #endif 394 } 395 396 bool USB2422_active(void) { 397 #ifdef USB2422_ACTIVE_PIN 398 return gpio_read_pin(USB2422_ACTIVE_PIN); 399 #else 400 return 1; 401 #endif 402 }