dw_i2c.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. /*
  2. * SPDX-License-Identifier: BSD-2-Clause
  3. *
  4. * Copyright (c) 2022 starfivetech.com
  5. *
  6. * Authors:
  7. * Minda Chen <minda.chen@starfivetech.com>
  8. */
  9. #include <sbi/riscv_io.h>
  10. #include <sbi/sbi_error.h>
  11. #include <sbi/sbi_timer.h>
  12. #include <sbi/sbi_console.h>
  13. #include <sbi/sbi_string.h>
  14. #include <sbi/sbi_bitops.h>
  15. #include <sbi_utils/i2c/dw_i2c.h>
  16. #define DW_IC_CON 0x00
  17. #define DW_IC_TAR 0x04
  18. #define DW_IC_SAR 0x08
  19. #define DW_IC_DATA_CMD 0x10
  20. #define DW_IC_SS_SCL_HCNT 0x14
  21. #define DW_IC_SS_SCL_LCNT 0x18
  22. #define DW_IC_FS_SCL_HCNT 0x1c
  23. #define DW_IC_FS_SCL_LCNT 0x20
  24. #define DW_IC_HS_SCL_HCNT 0x24
  25. #define DW_IC_HS_SCL_LCNT 0x28
  26. #define DW_IC_INTR_STAT 0x2c
  27. #define DW_IC_INTR_MASK 0x30
  28. #define DW_IC_RAW_INTR_STAT 0x34
  29. #define DW_IC_RX_TL 0x38
  30. #define DW_IC_TX_TL 0x3c
  31. #define DW_IC_CLR_INTR 0x40
  32. #define DW_IC_CLR_RX_UNDER 0x44
  33. #define DW_IC_CLR_RX_OVER 0x48
  34. #define DW_IC_CLR_TX_OVER 0x4c
  35. #define DW_IC_CLR_RD_REQ 0x50
  36. #define DW_IC_CLR_TX_ABRT 0x54
  37. #define DW_IC_CLR_RX_DONE 0x58
  38. #define DW_IC_CLR_ACTIVITY 0x5c
  39. #define DW_IC_CLR_STOP_DET 0x60
  40. #define DW_IC_CLR_START_DET 0x64
  41. #define DW_IC_CLR_GEN_CALL 0x68
  42. #define DW_IC_ENABLE 0x6c
  43. #define DW_IC_STATUS 0x70
  44. #define DW_IC_TXFLR 0x74
  45. #define DW_IC_RXFLR 0x78
  46. #define DW_IC_SDA_HOLD 0x7c
  47. #define DW_IC_TX_ABRT_SOURCE 0x80
  48. #define DW_IC_ENABLE_STATUS 0x9c
  49. #define DW_IC_CLR_RESTART_DET 0xa8
  50. #define DW_IC_COMP_PARAM_1 0xf4
  51. #define DW_IC_COMP_VERSION 0xf8
  52. #define DW_I2C_STATUS_TXFIFO_EMPTY BIT(2)
  53. #define DW_I2C_STATUS_RXFIFO_NOT_EMPTY BIT(3)
  54. #define IC_DATA_CMD_READ BIT(8)
  55. #define IC_DATA_CMD_STOP BIT(9)
  56. #define IC_DATA_CMD_RESTART BIT(10)
  57. #define IC_INT_STATUS_STOPDET BIT(9)
  58. static inline void dw_i2c_setreg(struct dw_i2c_adapter *adap,
  59. u8 reg, u32 value)
  60. {
  61. writel(value, (void *)adap->addr + reg);
  62. }
  63. static inline u32 dw_i2c_getreg(struct dw_i2c_adapter *adap,
  64. u32 reg)
  65. {
  66. return readl((void *)adap->addr + reg);
  67. }
  68. static int dw_i2c_adapter_poll(struct dw_i2c_adapter *adap,
  69. u32 mask, u32 addr,
  70. bool inverted)
  71. {
  72. unsigned int timeout = 10; /* msec */
  73. int count = 0;
  74. u32 val;
  75. do {
  76. val = dw_i2c_getreg(adap, addr);
  77. if (inverted) {
  78. if (!(val & mask))
  79. return 0;
  80. } else {
  81. if (val & mask)
  82. return 0;
  83. }
  84. sbi_timer_udelay(2);
  85. count += 1;
  86. if (count == (timeout * 1000))
  87. return SBI_ETIMEDOUT;
  88. } while (1);
  89. }
  90. #define dw_i2c_adapter_poll_rxrdy(adap) \
  91. dw_i2c_adapter_poll(adap, DW_I2C_STATUS_RXFIFO_NOT_EMPTY, DW_IC_STATUS, 0)
  92. #define dw_i2c_adapter_poll_txfifo_ready(adap) \
  93. dw_i2c_adapter_poll(adap, DW_I2C_STATUS_TXFIFO_EMPTY, DW_IC_STATUS, 0)
  94. static int dw_i2c_write_addr(struct dw_i2c_adapter *adap, u8 addr)
  95. {
  96. dw_i2c_setreg(adap, DW_IC_ENABLE, 0);
  97. dw_i2c_setreg(adap, DW_IC_TAR, addr);
  98. dw_i2c_setreg(adap, DW_IC_ENABLE, 1);
  99. return 0;
  100. }
  101. static int dw_i2c_adapter_read(struct i2c_adapter *ia, u8 addr,
  102. u8 reg, u8 *buffer, int len)
  103. {
  104. struct dw_i2c_adapter *adap =
  105. container_of(ia, struct dw_i2c_adapter, adapter);
  106. int rc;
  107. dw_i2c_write_addr(adap, addr);
  108. rc = dw_i2c_adapter_poll_txfifo_ready(adap);
  109. if (rc)
  110. return rc;
  111. /* set register address */
  112. dw_i2c_setreg(adap, DW_IC_DATA_CMD, reg);
  113. /* set value */
  114. while (len) {
  115. if (len == 1)
  116. dw_i2c_setreg(adap, DW_IC_DATA_CMD,
  117. IC_DATA_CMD_READ | IC_DATA_CMD_STOP);
  118. else
  119. dw_i2c_setreg(adap, DW_IC_DATA_CMD, IC_DATA_CMD_READ);
  120. rc = dw_i2c_adapter_poll_rxrdy(adap);
  121. if (rc)
  122. return rc;
  123. *buffer = dw_i2c_getreg(adap, DW_IC_DATA_CMD) & 0xff;
  124. buffer++;
  125. len--;
  126. }
  127. return 0;
  128. }
  129. static int dw_i2c_adapter_write(struct i2c_adapter *ia, u8 addr,
  130. u8 reg, u8 *buffer, int len)
  131. {
  132. struct dw_i2c_adapter *adap =
  133. container_of(ia, struct dw_i2c_adapter, adapter);
  134. int rc;
  135. dw_i2c_write_addr(adap, addr);
  136. rc = dw_i2c_adapter_poll_txfifo_ready(adap);
  137. if (rc)
  138. return rc;
  139. /* set register address */
  140. dw_i2c_setreg(adap, DW_IC_DATA_CMD, reg);
  141. while (len) {
  142. rc = dw_i2c_adapter_poll_txfifo_ready(adap);
  143. if (rc)
  144. return rc;
  145. if (len == 1)
  146. dw_i2c_setreg(adap, DW_IC_DATA_CMD, *buffer | IC_DATA_CMD_STOP);
  147. else
  148. dw_i2c_setreg(adap, DW_IC_DATA_CMD, *buffer);
  149. buffer++;
  150. len--;
  151. }
  152. rc = dw_i2c_adapter_poll_txfifo_ready(adap);
  153. return rc;
  154. }
  155. int dw_i2c_init(struct i2c_adapter *adapter, int nodeoff)
  156. {
  157. adapter->id = nodeoff;
  158. adapter->write = dw_i2c_adapter_write;
  159. adapter->read = dw_i2c_adapter_read;
  160. return i2c_adapter_add(adapter);
  161. }