vsc3316_3308.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright 2012 Freescale Semiconductor, Inc.
  4. */
  5. #include "vsc3316_3308.h"
  6. #define REVISION_ID_REG 0x7E
  7. #define INTERFACE_MODE_REG 0x79
  8. #define CURRENT_PAGE_REGISTER 0x7F
  9. #define CONNECTION_CONFIG_PAGE 0x00
  10. #define INPUT_STATE_REG 0x13
  11. #define GLOBAL_INPUT_ISE1 0x51
  12. #define GLOBAL_INPUT_ISE2 0x52
  13. #define GLOBAL_INPUT_GAIN 0x53
  14. #define GLOBAL_INPUT_LOS 0x55
  15. #define GLOBAL_OUTPUT_PE1 0x56
  16. #define GLOBAL_OUTPUT_PE2 0x57
  17. #define GLOBAL_OUTPUT_LEVEL 0x58
  18. #define GLOBAL_OUTPUT_TERMINATION 0x5A
  19. #define GLOBAL_CORE_CNTRL 0x5D
  20. #define OUTPUT_MODE_PAGE 0x23
  21. #define CORE_CONTROL_PAGE 0x25
  22. #define CORE_CONFIG_REG 0x75
  23. int vsc_if_enable(unsigned int vsc_addr)
  24. {
  25. u8 data;
  26. debug("VSC:Configuring VSC at I2C address 0x%2x"
  27. " for 2-wire interface\n", vsc_addr);
  28. /* enable 2-wire Serial InterFace (I2C) */
  29. data = 0x02;
  30. return i2c_write(vsc_addr, INTERFACE_MODE_REG, 1, &data, 1);
  31. }
  32. int vsc3316_config(unsigned int vsc_addr, int8_t con_arr[][2],
  33. unsigned int num_con)
  34. {
  35. unsigned int i;
  36. u8 rev_id = 0;
  37. int ret;
  38. debug("VSC:Initializing VSC3316 at I2C address 0x%2x"
  39. " for Tx\n", vsc_addr);
  40. ret = i2c_read(vsc_addr, REVISION_ID_REG, 1, &rev_id, 1);
  41. if (ret < 0) {
  42. printf("VSC:0x%x could not read REV_ID from device.\n",
  43. vsc_addr);
  44. return ret;
  45. }
  46. if (rev_id != 0xab) {
  47. printf("VSC: device at address 0x%x is not VSC3316/3308.\n",
  48. vsc_addr);
  49. return -ENODEV;
  50. }
  51. ret = vsc_if_enable(vsc_addr);
  52. if (ret) {
  53. printf("VSC:0x%x could not configured for 2-wire I/F.\n",
  54. vsc_addr);
  55. return ret;
  56. }
  57. /* config connections - page 0x00 */
  58. i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, CONNECTION_CONFIG_PAGE);
  59. /* Making crosspoint connections, by connecting required
  60. * input to output */
  61. for (i = 0; i < num_con ; i++)
  62. i2c_reg_write(vsc_addr, con_arr[i][1], con_arr[i][0]);
  63. /* input state - page 0x13 */
  64. i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, INPUT_STATE_REG);
  65. /* Configuring the required input of the switch */
  66. for (i = 0; i < num_con ; i++)
  67. i2c_reg_write(vsc_addr, con_arr[i][0], 0x80);
  68. /* Setting Global Input LOS threshold value */
  69. i2c_reg_write(vsc_addr, GLOBAL_INPUT_LOS, 0x60);
  70. /* config output mode - page 0x23 */
  71. i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, OUTPUT_MODE_PAGE);
  72. /* Turn ON the Output driver correspond to required output*/
  73. for (i = 0; i < num_con ; i++)
  74. i2c_reg_write(vsc_addr, con_arr[i][1], 0);
  75. /* configure global core control register, Turn on Global core power */
  76. i2c_reg_write(vsc_addr, GLOBAL_CORE_CNTRL, 0);
  77. vsc_wp_config(vsc_addr);
  78. return 0;
  79. }
  80. #ifdef CONFIG_SYS_FSL_B4860QDS_XFI_ERR
  81. int vsc3308_config_adjust(unsigned int vsc_addr, const int8_t con_arr[][2],
  82. unsigned int num_con)
  83. {
  84. unsigned int i;
  85. u8 rev_id = 0;
  86. int ret;
  87. debug("VSC:Initializing VSC3308 at I2C address 0x%x for Tx\n",
  88. vsc_addr);
  89. ret = i2c_read(vsc_addr, REVISION_ID_REG, 1, &rev_id, 1);
  90. if (ret < 0) {
  91. printf("VSC:0x%x could not read REV_ID from device.\n",
  92. vsc_addr);
  93. return ret;
  94. }
  95. if (rev_id != 0xab) {
  96. printf("VSC: device at address 0x%x is not VSC3316/3308.\n",
  97. vsc_addr);
  98. return -ENODEV;
  99. }
  100. ret = vsc_if_enable(vsc_addr);
  101. if (ret) {
  102. printf("VSC:0x%x could not configured for 2-wire I/F.\n",
  103. vsc_addr);
  104. return ret;
  105. }
  106. /* config connections - page 0x00 */
  107. i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, CONNECTION_CONFIG_PAGE);
  108. /* Configure Global Input ISE */
  109. i2c_reg_write(vsc_addr, GLOBAL_INPUT_ISE1, 0);
  110. i2c_reg_write(vsc_addr, GLOBAL_INPUT_ISE2, 0);
  111. /* Configure Tx/Rx Global Output PE1 */
  112. i2c_reg_write(vsc_addr, GLOBAL_OUTPUT_PE1, 0);
  113. /* Configure Tx/Rx Global Output PE2 */
  114. i2c_reg_write(vsc_addr, GLOBAL_OUTPUT_PE2, 0);
  115. /* Configure Tx/Rx Global Input GAIN */
  116. i2c_reg_write(vsc_addr, GLOBAL_INPUT_GAIN, 0x3F);
  117. /* Setting Global Input LOS threshold value */
  118. i2c_reg_write(vsc_addr, GLOBAL_INPUT_LOS, 0xE0);
  119. /* Setting Global output termination */
  120. i2c_reg_write(vsc_addr, GLOBAL_OUTPUT_TERMINATION, 0);
  121. /* Configure Tx/Rx Global Output level */
  122. if (vsc_addr == VSC3308_TX_ADDRESS)
  123. i2c_reg_write(vsc_addr, GLOBAL_OUTPUT_LEVEL, 4);
  124. else
  125. i2c_reg_write(vsc_addr, GLOBAL_OUTPUT_LEVEL, 2);
  126. /* Making crosspoint connections, by connecting required
  127. * input to output */
  128. for (i = 0; i < num_con ; i++)
  129. i2c_reg_write(vsc_addr, con_arr[i][1], con_arr[i][0]);
  130. /* input state - page 0x13 */
  131. i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, INPUT_STATE_REG);
  132. /* Turning off all the required input of the switch */
  133. for (i = 0; i < num_con; i++)
  134. i2c_reg_write(vsc_addr, con_arr[i][0], 1);
  135. /* only turn on specific Tx/Rx requested by the XFI erratum */
  136. if (vsc_addr == VSC3308_TX_ADDRESS) {
  137. i2c_reg_write(vsc_addr, 2, 0);
  138. i2c_reg_write(vsc_addr, 3, 0);
  139. } else {
  140. i2c_reg_write(vsc_addr, 0, 0);
  141. i2c_reg_write(vsc_addr, 1, 0);
  142. }
  143. /* config output mode - page 0x23 */
  144. i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, OUTPUT_MODE_PAGE);
  145. /* Turn off the Output driver correspond to required output*/
  146. for (i = 0; i < num_con ; i++)
  147. i2c_reg_write(vsc_addr, con_arr[i][1], 1);
  148. /* only turn on specific Tx/Rx requested by the XFI erratum */
  149. if (vsc_addr == VSC3308_TX_ADDRESS) {
  150. i2c_reg_write(vsc_addr, 0, 0);
  151. i2c_reg_write(vsc_addr, 1, 0);
  152. } else {
  153. i2c_reg_write(vsc_addr, 3, 0);
  154. i2c_reg_write(vsc_addr, 4, 0);
  155. }
  156. /* configure global core control register, Turn on Global core power */
  157. i2c_reg_write(vsc_addr, GLOBAL_CORE_CNTRL, 0);
  158. vsc_wp_config(vsc_addr);
  159. return 0;
  160. }
  161. #endif
  162. int vsc3308_config(unsigned int vsc_addr, const int8_t con_arr[][2],
  163. unsigned int num_con)
  164. {
  165. unsigned int i;
  166. u8 rev_id = 0;
  167. int ret;
  168. debug("VSC:Initializing VSC3308 at I2C address 0x%x"
  169. " for Tx\n", vsc_addr);
  170. ret = i2c_read(vsc_addr, REVISION_ID_REG, 1, &rev_id, 1);
  171. if (ret < 0) {
  172. printf("VSC:0x%x could not read REV_ID from device.\n",
  173. vsc_addr);
  174. return ret;
  175. }
  176. if (rev_id != 0xab) {
  177. printf("VSC: device at address 0x%x is not VSC3316/3308.\n",
  178. vsc_addr);
  179. return -ENODEV;
  180. }
  181. ret = vsc_if_enable(vsc_addr);
  182. if (ret) {
  183. printf("VSC:0x%x could not configured for 2-wire I/F.\n",
  184. vsc_addr);
  185. return ret;
  186. }
  187. /* config connections - page 0x00 */
  188. i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, CONNECTION_CONFIG_PAGE);
  189. /* Making crosspoint connections, by connecting required
  190. * input to output */
  191. for (i = 0; i < num_con ; i++)
  192. i2c_reg_write(vsc_addr, con_arr[i][1], con_arr[i][0]);
  193. /*Configure Global Input ISE and gain */
  194. i2c_reg_write(vsc_addr, GLOBAL_INPUT_ISE1, 0x12);
  195. i2c_reg_write(vsc_addr, GLOBAL_INPUT_ISE2, 0x12);
  196. /* input state - page 0x13 */
  197. i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, INPUT_STATE_REG);
  198. /* Turning ON the required input of the switch */
  199. for (i = 0; i < num_con ; i++)
  200. i2c_reg_write(vsc_addr, con_arr[i][0], 0);
  201. /* Setting Global Input LOS threshold value */
  202. i2c_reg_write(vsc_addr, GLOBAL_INPUT_LOS, 0x60);
  203. /* config output mode - page 0x23 */
  204. i2c_reg_write(vsc_addr, CURRENT_PAGE_REGISTER, OUTPUT_MODE_PAGE);
  205. /* Turn ON the Output driver correspond to required output*/
  206. for (i = 0; i < num_con ; i++)
  207. i2c_reg_write(vsc_addr, con_arr[i][1], 0);
  208. /* configure global core control register, Turn on Global core power */
  209. i2c_reg_write(vsc_addr, GLOBAL_CORE_CNTRL, 0);
  210. vsc_wp_config(vsc_addr);
  211. return 0;
  212. }
  213. void vsc_wp_config(unsigned int vsc_addr)
  214. {
  215. debug("VSC:Configuring VSC at address:0x%x for WP\n", vsc_addr);
  216. /* For new crosspoint configuration to occur, WP bit of
  217. * CORE_CONFIG_REG should be set 1 and then reset to 0 */
  218. i2c_reg_write(vsc_addr, CORE_CONFIG_REG, 0x01);
  219. i2c_reg_write(vsc_addr, CORE_CONFIG_REG, 0x0);
  220. }