mclink.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * (C) Copyright 2012
  4. * Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
  5. */
  6. #include <common.h>
  7. #include <asm/io.h>
  8. #include <errno.h>
  9. #include <gdsys_fpga.h>
  10. enum {
  11. MCINT_SLAVE_LINK_CHANGED_EV = 1 << 7,
  12. MCINT_TX_ERROR_EV = 1 << 9,
  13. MCINT_TX_BUFFER_FREE = 1 << 10,
  14. MCINT_TX_PACKET_TRANSMITTED_EV = 1 << 11,
  15. MCINT_RX_ERROR_EV = 1 << 13,
  16. MCINT_RX_CONTENT_AVAILABLE = 1 << 14,
  17. MCINT_RX_PACKET_RECEIVED_EV = 1 << 15,
  18. };
  19. int mclink_probe(void)
  20. {
  21. unsigned int k;
  22. int slaves = 0;
  23. for (k = 0; k < CONFIG_SYS_MCLINK_MAX; ++k) {
  24. int timeout = 0;
  25. unsigned int ctr = 0;
  26. u16 mc_status;
  27. FPGA_GET_REG(k, mc_status, &mc_status);
  28. if (!(mc_status & (1 << 15)))
  29. break;
  30. FPGA_SET_REG(k, mc_control, 0x8000);
  31. FPGA_GET_REG(k, mc_status, &mc_status);
  32. while (!(mc_status & (1 << 14))) {
  33. udelay(100);
  34. if (ctr++ > 500) {
  35. timeout = 1;
  36. break;
  37. }
  38. FPGA_GET_REG(k, mc_status, &mc_status);
  39. }
  40. if (timeout)
  41. break;
  42. printf("waited %d us for mclink %d to come up\n", ctr * 100, k);
  43. slaves++;
  44. }
  45. return slaves;
  46. }
  47. int mclink_send(u8 slave, u16 addr, u16 data)
  48. {
  49. unsigned int ctr = 0;
  50. u16 int_status;
  51. u16 rx_cmd_status;
  52. u16 rx_cmd;
  53. /* reset interrupt status */
  54. FPGA_GET_REG(0, mc_int, &int_status);
  55. FPGA_SET_REG(0, mc_int, int_status);
  56. /* send */
  57. FPGA_SET_REG(0, mc_tx_address, addr);
  58. FPGA_SET_REG(0, mc_tx_data, data);
  59. FPGA_SET_REG(0, mc_tx_cmd, (slave & 0x03) << 14);
  60. FPGA_SET_REG(0, mc_control, 0x8001);
  61. /* wait for reply */
  62. FPGA_GET_REG(0, mc_int, &int_status);
  63. while (!(int_status & MCINT_RX_PACKET_RECEIVED_EV)) {
  64. udelay(100);
  65. if (ctr++ > 3)
  66. return -ETIMEDOUT;
  67. FPGA_GET_REG(0, mc_int, &int_status);
  68. }
  69. FPGA_GET_REG(0, mc_rx_cmd_status, &rx_cmd_status);
  70. rx_cmd = (rx_cmd_status >> 12) & 0x03;
  71. if (rx_cmd != 0)
  72. printf("mclink_send: received cmd %d, expected %d\n", rx_cmd,
  73. 0);
  74. return 0;
  75. }
  76. int mclink_receive(u8 slave, u16 addr, u16 *data)
  77. {
  78. u16 rx_cmd_status;
  79. u16 rx_cmd;
  80. u16 int_status;
  81. unsigned int ctr = 0;
  82. /* send read request */
  83. FPGA_SET_REG(0, mc_tx_address, addr);
  84. FPGA_SET_REG(0, mc_tx_cmd,
  85. ((slave & 0x03) << 14) | (1 << 12) | (1 << 0));
  86. FPGA_SET_REG(0, mc_control, 0x8001);
  87. /* wait for reply */
  88. FPGA_GET_REG(0, mc_int, &int_status);
  89. while (!(int_status & MCINT_RX_CONTENT_AVAILABLE)) {
  90. udelay(100);
  91. if (ctr++ > 3)
  92. return -ETIMEDOUT;
  93. FPGA_GET_REG(0, mc_int, &int_status);
  94. }
  95. /* check reply */
  96. FPGA_GET_REG(0, mc_rx_cmd_status, &rx_cmd_status);
  97. if ((rx_cmd_status >> 14) != slave) {
  98. printf("mclink_receive: reply from slave %d, expected %d\n",
  99. rx_cmd_status >> 14, slave);
  100. return -EINVAL;
  101. }
  102. rx_cmd = (rx_cmd_status >> 12) & 0x03;
  103. if (rx_cmd != 1) {
  104. printf("mclink_send: received cmd %d, expected %d\n",
  105. rx_cmd, 1);
  106. return -EIO;
  107. }
  108. FPGA_GET_REG(0, mc_rx_data, data);
  109. return 0;
  110. }