1 /* 2 * SPDX-License-Identifier: BSD-3-Clause 3 * Copyright(c) 2023 Napatech A/S 4 */ 5 6 #include "nt_util.h" 7 #include "ntlog.h" 8 9 #include "nthw_drv.h" 10 #include "nthw_register.h" 11 12 #include "nthw_iic.h" 13 14 #define I2C_TRANSMIT_WR (0x00) 15 #define I2C_TRANSMIT_RD (0x01) 16 17 #define I2C_WAIT_US(x) nt_os_wait_usec(x) 18 19 /* 20 * Minimum timing values for I2C for a Marvel 88E11111 Phy. 21 * This Phy is used in many Trispeed NIMs. 22 * In order to access this Phy, the I2C clock speed is needed to be set to 100KHz. 23 */ 24 static const uint32_t SUSTA = 4700; /* ns */ 25 static const uint32_t SUSTO = 4000; /* ns */ 26 static const uint32_t HDSTA = 4000; /* ns */ 27 static const uint32_t SUDAT = 250; /* ns */ 28 static const uint32_t BUF = 4700; /* ns */ 29 static const uint32_t HIGH = 4000; /* ns */ 30 static const uint32_t LOW = 4700; /* ns */ 31 static const uint32_t HDDAT = 300; /* ns */ 32 33 static int nthw_iic_reg_control_txfifo_reset(nthw_iic_t *p) 34 { 35 nthw_field_update_register(p->mp_fld_cr_txfifo_reset); 36 37 nthw_field_set_all(p->mp_fld_cr_txfifo_reset); 38 nthw_field_flush_register(p->mp_fld_cr_txfifo_reset); 39 40 nthw_field_clr_all(p->mp_fld_cr_txfifo_reset); 41 nthw_field_flush_register(p->mp_fld_cr_txfifo_reset); 42 43 return 0; 44 } 45 46 static int nthw_iic_reg_tx_fifo_write(nthw_iic_t *p, uint32_t data, bool start, bool stop) 47 { 48 if (start) 49 nthw_field_set_all(p->mp_fld_tx_fifo_start); 50 51 else 52 nthw_field_clr_all(p->mp_fld_tx_fifo_start); 53 54 if (stop) 55 nthw_field_set_all(p->mp_fld_tx_fifo_stop); 56 57 else 58 nthw_field_clr_all(p->mp_fld_tx_fifo_stop); 59 60 nthw_field_set_val32(p->mp_fld_tx_fifo_txdata, data); 61 62 nthw_register_flush(p->mp_reg_tx_fifo, 1); 63 64 return 0; 65 } 66 67 static int nthw_iic_reg_read_i2c_rx_fifo(nthw_iic_t *p, uint8_t *p_data) 68 { 69 assert(p_data); 70 71 *p_data = (uint8_t)nthw_field_get_updated(p->mp_fld_rx_fifo_rxdata); 72 73 return 0; 74 } 75 76 static int nthw_iic_reg_softr(nthw_iic_t *p) 77 { 78 nthw_field_update_register(p->mp_fld_cr_en); 79 nthw_field_set_val_flush32(p->mp_fld_softr_rkey, 0x0A); 80 81 return 0; 82 } 83 84 static int nthw_iic_reg_enable(nthw_iic_t *p) 85 { 86 nthw_field_update_register(p->mp_fld_cr_en); 87 nthw_field_set_flush(p->mp_fld_cr_en); 88 89 return 0; 90 } 91 92 static int nthw_iic_reg_busbusy(nthw_iic_t *p, bool *pb_flag) 93 { 94 assert(pb_flag); 95 96 *pb_flag = nthw_field_get_updated(p->mp_fld_sr_bb) ? true : false; 97 98 return 0; 99 } 100 101 static int nthw_iic_reg_rxfifo_empty(nthw_iic_t *p, bool *pb_flag) 102 { 103 assert(pb_flag); 104 105 *pb_flag = nthw_field_get_updated(p->mp_fld_sr_rxfifo_empty) ? true : false; 106 107 return 0; 108 } 109 110 /* 111 * n_iic_cycle_time is the I2C clock cycle time in ns ie 125MHz = 8ns 112 */ 113 static int nthw_iic_reg_set_timing(nthw_iic_t *p, uint32_t n_iic_cycle_time) 114 { 115 uint32_t val; 116 117 val = SUSTA / n_iic_cycle_time; 118 nthw_field_set_val_flush(p->mp_fld_tsusta, &val, 1); 119 120 val = SUSTO / n_iic_cycle_time; 121 nthw_field_set_val_flush(p->mp_fld_tsusto, &val, 1); 122 123 val = HDSTA / n_iic_cycle_time; 124 nthw_field_set_val_flush(p->mp_fld_thdsta, &val, 1); 125 126 val = SUDAT / n_iic_cycle_time; 127 nthw_field_set_val_flush(p->mp_fld_tsudat, &val, 1); 128 129 val = BUF / n_iic_cycle_time; 130 nthw_field_set_val_flush(p->mp_fld_tbuf, &val, 1); 131 132 val = HIGH / n_iic_cycle_time; 133 nthw_field_set_val_flush(p->mp_fld_thigh, &val, 1); 134 135 val = LOW / n_iic_cycle_time; 136 nthw_field_set_val_flush(p->mp_fld_tlow, &val, 1); 137 138 val = HDDAT / n_iic_cycle_time; 139 nthw_field_set_val_flush(p->mp_fld_thddat, &val, 1); 140 141 return 0; 142 } 143 144 nthw_iic_t *nthw_iic_new(void) 145 { 146 nthw_iic_t *p = malloc(sizeof(nthw_iic_t)); 147 148 if (p) 149 memset(p, 0, sizeof(nthw_iic_t)); 150 151 return p; 152 } 153 154 int nthw_iic_init(nthw_iic_t *p, nthw_fpga_t *p_fpga, int n_iic_instance, 155 uint32_t n_iic_cycle_time) 156 { 157 const char *const p_adapter_id_str = p_fpga->p_fpga_info->mp_adapter_id_str; 158 nthw_module_t *mod = nthw_fpga_query_module(p_fpga, MOD_IIC, n_iic_instance); 159 160 if (p == NULL) 161 return mod == NULL ? -1 : 0; 162 163 if (mod == NULL) { 164 NT_LOG(ERR, NTHW, "%s: I2C %d: no such instance\n", p_adapter_id_str, 165 n_iic_instance); 166 return -1; 167 } 168 169 p->mp_fpga = p_fpga; 170 p->mn_iic_instance = n_iic_instance; 171 172 p->mn_iic_cycle_time = n_iic_cycle_time; 173 174 nthw_iic_set_retry_params(p, -1, -1, -1, -1, -1); 175 176 p->mp_mod_iic = mod; 177 178 /* I2C is a primary communication channel - turn off debug by default */ 179 nthw_module_set_debug_mode(p->mp_mod_iic, 0x00); 180 181 p->mp_reg_tsusta = nthw_module_get_register(p->mp_mod_iic, IIC_TSUSTA); 182 p->mp_fld_tsusta = nthw_register_get_field(p->mp_reg_tsusta, IIC_TSUSTA_TSUSTA_VAL); 183 184 p->mp_reg_tsusto = nthw_module_get_register(p->mp_mod_iic, IIC_TSUSTO); 185 p->mp_fld_tsusto = nthw_register_get_field(p->mp_reg_tsusto, IIC_TSUSTO_TSUSTO_VAL); 186 187 p->mp_reg_thdsta = nthw_module_get_register(p->mp_mod_iic, IIC_THDSTA); 188 p->mp_fld_thdsta = nthw_register_get_field(p->mp_reg_thdsta, IIC_THDSTA_THDSTA_VAL); 189 190 p->mp_reg_tsudat = nthw_module_get_register(p->mp_mod_iic, IIC_TSUDAT); 191 p->mp_fld_tsudat = nthw_register_get_field(p->mp_reg_tsudat, IIC_TSUDAT_TSUDAT_VAL); 192 193 p->mp_reg_tbuf = nthw_module_get_register(p->mp_mod_iic, IIC_TBUF); 194 p->mp_fld_tbuf = nthw_register_get_field(p->mp_reg_tbuf, IIC_TBUF_TBUF_VAL); 195 196 p->mp_reg_thigh = nthw_module_get_register(p->mp_mod_iic, IIC_THIGH); 197 p->mp_fld_thigh = nthw_register_get_field(p->mp_reg_thigh, IIC_THIGH_THIGH_VAL); 198 199 p->mp_reg_tlow = nthw_module_get_register(p->mp_mod_iic, IIC_TLOW); 200 p->mp_fld_tlow = nthw_register_get_field(p->mp_reg_tlow, IIC_TLOW_TLOW_VAL); 201 202 p->mp_reg_thddat = nthw_module_get_register(p->mp_mod_iic, IIC_THDDAT); 203 p->mp_fld_thddat = nthw_register_get_field(p->mp_reg_thddat, IIC_THDDAT_THDDAT_VAL); 204 205 p->mp_reg_cr = nthw_module_get_register(p->mp_mod_iic, IIC_CR); 206 p->mp_fld_cr_en = nthw_register_get_field(p->mp_reg_cr, IIC_CR_EN); 207 p->mp_fld_cr_msms = nthw_register_get_field(p->mp_reg_cr, IIC_CR_MSMS); 208 p->mp_fld_cr_txfifo_reset = nthw_register_get_field(p->mp_reg_cr, IIC_CR_TXFIFO_RESET); 209 p->mp_fld_cr_txak = nthw_register_get_field(p->mp_reg_cr, IIC_CR_TXAK); 210 211 p->mp_reg_sr = nthw_module_get_register(p->mp_mod_iic, IIC_SR); 212 p->mp_fld_sr_bb = nthw_register_get_field(p->mp_reg_sr, IIC_SR_BB); 213 p->mp_fld_sr_rxfifo_full = nthw_register_get_field(p->mp_reg_sr, IIC_SR_RXFIFO_FULL); 214 p->mp_fld_sr_rxfifo_empty = nthw_register_get_field(p->mp_reg_sr, IIC_SR_RXFIFO_EMPTY); 215 p->mp_fld_sr_txfifo_full = nthw_register_get_field(p->mp_reg_sr, IIC_SR_TXFIFO_FULL); 216 p->mp_fld_sr_txfifo_empty = nthw_register_get_field(p->mp_reg_sr, IIC_SR_TXFIFO_EMPTY); 217 218 p->mp_reg_tx_fifo = nthw_module_get_register(p->mp_mod_iic, IIC_TX_FIFO); 219 p->mp_fld_tx_fifo_txdata = nthw_register_get_field(p->mp_reg_tx_fifo, IIC_TX_FIFO_TXDATA); 220 p->mp_fld_tx_fifo_start = nthw_register_get_field(p->mp_reg_tx_fifo, IIC_TX_FIFO_START); 221 p->mp_fld_tx_fifo_stop = nthw_register_get_field(p->mp_reg_tx_fifo, IIC_TX_FIFO_STOP); 222 223 p->mp_reg_rx_fifo_pirq = nthw_module_get_register(p->mp_mod_iic, IIC_RX_FIFO_PIRQ); 224 p->mp_fld_rx_fifo_pirq_cmp_val = 225 nthw_register_get_field(p->mp_reg_rx_fifo_pirq, IIC_RX_FIFO_PIRQ_CMP_VAL); 226 227 p->mp_reg_rx_fifo = nthw_module_get_register(p->mp_mod_iic, IIC_RX_FIFO); 228 p->mp_fld_rx_fifo_rxdata = nthw_register_get_field(p->mp_reg_rx_fifo, IIC_RX_FIFO_RXDATA); 229 230 p->mp_reg_softr = nthw_module_get_register(p->mp_mod_iic, IIC_SOFTR); 231 p->mp_fld_softr_rkey = nthw_register_get_field(p->mp_reg_softr, IIC_SOFTR_RKEY); 232 233 /* 234 * Initialize I2C controller by applying soft reset and enable the controller 235 */ 236 nthw_iic_reg_softr(p); 237 /* Enable the controller */ 238 nthw_iic_reg_enable(p); 239 240 /* Setup controller timing */ 241 if (p->mn_iic_cycle_time) { 242 NT_LOG(DBG, NTHW, "%s: I2C%d: cycletime=%d\n", p_adapter_id_str, 243 p->mn_iic_instance, p->mn_iic_cycle_time); 244 nthw_iic_reg_set_timing(p, p->mn_iic_cycle_time); 245 } 246 247 /* Reset TX fifo - must be after enable */ 248 nthw_iic_reg_control_txfifo_reset(p); 249 nthw_iic_reg_tx_fifo_write(p, 0, 0, 0); 250 251 return 0; 252 } 253 254 void nthw_iic_delete(nthw_iic_t *p) 255 { 256 if (p) { 257 memset(p, 0, sizeof(nthw_iic_t)); 258 free(p); 259 } 260 } 261 262 int nthw_iic_set_retry_params(nthw_iic_t *p, const int n_poll_delay, const int n_bus_ready_retry, 263 const int n_data_ready_retry, const int n_read_data_retry, 264 const int n_write_data_retry) 265 { 266 p->mn_poll_delay = n_poll_delay >= 0 ? n_poll_delay : 10; 267 268 p->mn_bus_ready_retry = n_bus_ready_retry >= 0 ? n_bus_ready_retry : 1000; 269 p->mn_data_ready_retry = n_data_ready_retry >= 0 ? n_data_ready_retry : 1000; 270 271 p->mn_read_data_retry = n_read_data_retry >= 0 ? n_read_data_retry : 10; 272 p->mn_write_data_retry = n_write_data_retry >= 0 ? n_write_data_retry : 10; 273 274 return 0; 275 } 276 277 int nthw_iic_read_data(nthw_iic_t *p, uint8_t dev_addr, uint8_t a_reg_addr, uint8_t data_len, 278 void *p_void) 279 { 280 const char *const p_adapter_id_str = p->mp_fpga->p_fpga_info->mp_adapter_id_str; 281 const int n_debug_mode = nthw_module_get_debug_mode(p->mp_mod_iic); 282 283 uint8_t *pb = (uint8_t *)p_void; 284 int retry = (p->mn_read_data_retry >= 0 ? p->mn_read_data_retry : 10); 285 286 if (n_debug_mode == 0xff) { 287 NT_LOG(DBG, NTHW, "%s: adr=0x%2.2x, reg=%d, len=%d\n", p_adapter_id_str, dev_addr, 288 a_reg_addr, data_len); 289 } 290 291 while (nthw_iic_readbyte(p, dev_addr, a_reg_addr, data_len, pb) != 0) { 292 retry--; 293 294 if (retry <= 0) { 295 NT_LOG(ERR, NTHW, 296 "%s: I2C%d: Read retry exhausted (dev_addr=%d a_reg_addr=%d)\n", 297 p_adapter_id_str, p->mn_iic_instance, dev_addr, a_reg_addr); 298 return -1; 299 300 } else { 301 NT_LOG(DBG, NTHW, "%s: I2C%d: Read retry=%d (dev_addr=%d a_reg_addr=%d)\n", 302 p_adapter_id_str, p->mn_iic_instance, retry, dev_addr, a_reg_addr); 303 } 304 } 305 306 if (n_debug_mode == 0xff) { 307 NT_LOG(DBG, NTHW, "%s: adr=0x%2.2x, reg=%d, len=%d, retries remaining: %d\n", 308 p_adapter_id_str, dev_addr, a_reg_addr, data_len, retry); 309 } 310 311 return 0; 312 } 313 314 int nthw_iic_readbyte(nthw_iic_t *p, uint8_t dev_addr, uint8_t a_reg_addr, uint8_t data_len, 315 uint8_t *p_byte) 316 { 317 const char *const p_adapter_id_str = p->mp_fpga->p_fpga_info->mp_adapter_id_str; 318 319 uint32_t value; 320 uint32_t i; 321 322 if (nthw_iic_bus_ready(p)) { 323 /* Reset TX fifo */ 324 nthw_iic_reg_control_txfifo_reset(p); 325 326 /* Write device address to TX_FIFO and set start bit!! */ 327 value = (dev_addr << 1) | I2C_TRANSMIT_WR; 328 nthw_iic_reg_tx_fifo_write(p, value, 1, 0); 329 330 /* Write a_reg_addr to TX FIFO */ 331 nthw_iic_reg_tx_fifo_write(p, a_reg_addr, 0, 1); 332 333 if (!nthw_iic_bus_ready(p)) { 334 NT_LOG_DBGX(ERR, NTHW, "%s: error:\n", p_adapter_id_str); 335 return -1; 336 } 337 338 /* Write device address + RD bit to TX_FIFO and set start bit!! */ 339 value = (dev_addr << 1) | I2C_TRANSMIT_RD; 340 nthw_iic_reg_tx_fifo_write(p, value, 1, 0); 341 342 /* Write data_len to TX_FIFO and set stop bit!! */ 343 nthw_iic_reg_tx_fifo_write(p, data_len, 0, 1); 344 345 for (i = 0; i < data_len; i++) { 346 /* Wait for RX FIFO not empty */ 347 if (!nthw_iic_data_ready(p)) 348 return -1; 349 350 /* Read data_len bytes from RX_FIFO */ 351 nthw_iic_reg_read_i2c_rx_fifo(p, p_byte); 352 p_byte++; 353 } 354 355 return 0; 356 357 } else { 358 NT_LOG_DBGX(ERR, NTHW, "%s: error\n", p_adapter_id_str); 359 return -1; 360 } 361 362 return 0; 363 } 364 365 int nthw_iic_write_data(nthw_iic_t *p, uint8_t dev_addr, uint8_t a_reg_addr, uint8_t data_len, 366 void *p_void) 367 { 368 const char *const p_adapter_id_str = p->mp_fpga->p_fpga_info->mp_adapter_id_str; 369 int retry = (p->mn_write_data_retry >= 0 ? p->mn_write_data_retry : 10); 370 uint8_t *pb = (uint8_t *)p_void; 371 372 while (nthw_iic_writebyte(p, dev_addr, a_reg_addr, data_len, pb) != 0) { 373 retry--; 374 375 if (retry <= 0) { 376 NT_LOG(ERR, NTHW, 377 "%s: I2C%d: Write retry exhausted (dev_addr=%d a_reg_addr=%d)\n", 378 p_adapter_id_str, p->mn_iic_instance, dev_addr, a_reg_addr); 379 return -1; 380 381 } else { 382 NT_LOG(DBG, NTHW, 383 "%s: I2C%d: Write retry=%d (dev_addr=%d a_reg_addr=%d)\n", 384 p_adapter_id_str, p->mn_iic_instance, retry, dev_addr, a_reg_addr); 385 } 386 } 387 388 return 0; 389 } 390 391 int nthw_iic_writebyte(nthw_iic_t *p, uint8_t dev_addr, uint8_t a_reg_addr, uint8_t data_len, 392 uint8_t *p_byte) 393 { 394 const char *const p_adapter_id_str = p->mp_fpga->p_fpga_info->mp_adapter_id_str; 395 uint32_t value; 396 int count; 397 int i; 398 399 if (data_len == 0) 400 return -1; 401 402 count = data_len - 1; 403 404 if (nthw_iic_bus_ready(p)) { 405 /* Reset TX fifo */ 406 nthw_iic_reg_control_txfifo_reset(p); 407 408 /* Write device address to TX_FIFO and set start bit!! */ 409 value = (dev_addr << 1) | I2C_TRANSMIT_WR; 410 nthw_iic_reg_tx_fifo_write(p, value, 1, 0); 411 412 /* Write a_reg_addr to TX FIFO */ 413 nthw_iic_reg_tx_fifo_write(p, a_reg_addr, 0, 0); 414 415 for (i = 0; i < count; i++) { 416 /* Write data byte to TX fifo and set stop bit */ 417 nthw_iic_reg_tx_fifo_write(p, *p_byte, 0, 0); 418 p_byte++; 419 } 420 421 /* Write data byte to TX fifo and set stop bit */ 422 nthw_iic_reg_tx_fifo_write(p, *p_byte, 0, 1); 423 424 if (!nthw_iic_bus_ready(p)) { 425 NT_LOG_DBGX(WARNING, NTHW, "%s: warn: !busReady\n", p_adapter_id_str); 426 427 while (true) 428 if (nthw_iic_bus_ready(p)) { 429 NT_LOG_DBGX(DEBUG, NTHW, "%s: info: busReady\n", 430 p_adapter_id_str); 431 break; 432 } 433 } 434 435 return 0; 436 437 } else { 438 NT_LOG_DBGX(WARNING, NTHW, "%s\n", p_adapter_id_str); 439 return -1; 440 } 441 } 442 443 /* 444 * Support function for read/write functions below. Waits for bus ready. 445 */ 446 bool nthw_iic_bus_ready(nthw_iic_t *p) 447 { 448 int count = (p->mn_bus_ready_retry >= 0 ? p->mn_bus_ready_retry : 1000); 449 bool b_bus_busy = true; 450 451 while (true) { 452 nthw_iic_reg_busbusy(p, &b_bus_busy); 453 454 if (!b_bus_busy) 455 break; 456 457 count--; 458 459 if (count <= 0) /* Test for timeout */ 460 break; 461 462 if (p->mn_poll_delay != 0) 463 I2C_WAIT_US(p->mn_poll_delay); 464 } 465 466 if (count == 0) 467 return false; 468 469 return true; 470 } 471 472 /* 473 * Support function for read function. Waits for data ready. 474 */ 475 bool nthw_iic_data_ready(nthw_iic_t *p) 476 { 477 int count = (p->mn_data_ready_retry >= 0 ? p->mn_data_ready_retry : 1000); 478 bool b_rx_fifo_empty = true; 479 480 while (true) { 481 nthw_iic_reg_rxfifo_empty(p, &b_rx_fifo_empty); 482 483 if (!b_rx_fifo_empty) 484 break; 485 486 count--; 487 488 if (count <= 0) /* Test for timeout */ 489 break; 490 491 if (p->mn_poll_delay != 0) 492 I2C_WAIT_US(p->mn_poll_delay); 493 } 494 495 if (count == 0) 496 return false; 497 498 return true; 499 } 500 501 int nthw_iic_scan_dev_addr(nthw_iic_t *p, int n_dev_addr, int n_reg_addr) 502 { 503 const char *const p_adapter_id_str = p->mp_fpga->p_fpga_info->mp_adapter_id_str; 504 (void)p_adapter_id_str; 505 int res; 506 uint8_t data_val = -1; 507 res = nthw_iic_readbyte(p, (uint8_t)n_dev_addr, (uint8_t)n_reg_addr, 1, &data_val); 508 509 if (res == 0) { 510 NT_LOG(DBG, NTHW, 511 "%s: I2C%d: devaddr=0x%02X (%03d) regaddr=%02X val=%02X (%03d) res=%d\n", 512 p_adapter_id_str, p->mn_iic_instance, n_dev_addr, n_dev_addr, n_reg_addr, 513 data_val, data_val, res); 514 } 515 516 return res; 517 } 518 519 int nthw_iic_scan(nthw_iic_t *p) 520 { 521 int i; 522 523 for (i = 0; i < 128; i++) 524 (void)nthw_iic_scan_dev_addr(p, i, 0x00); 525 526 return 0; 527 } 528