global2_avb.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Marvell 88E6xxx Switch Global 2 Registers support
  4. *
  5. * Copyright (c) 2008 Marvell Semiconductor
  6. *
  7. * Copyright (c) 2016-2017 Savoir-faire Linux Inc.
  8. * Vivien Didelot <[email protected]>
  9. *
  10. * Copyright (c) 2017 National Instruments
  11. * Brandon Streiff <[email protected]>
  12. */
  13. #include <linux/bitfield.h>
  14. #include "global2.h"
  15. /* Offset 0x16: AVB Command Register
  16. * Offset 0x17: AVB Data Register
  17. *
  18. * There are two different versions of this register interface:
  19. * "6352": 3-bit "op" field, 4-bit "port" field.
  20. * "6390": 2-bit "op" field, 5-bit "port" field.
  21. *
  22. * The "op" codes are different between the two, as well as the special
  23. * port fields for global PTP and TAI configuration.
  24. */
  25. /* mv88e6xxx_g2_avb_read -- Read one or multiple 16-bit words.
  26. * The hardware supports snapshotting up to four contiguous registers.
  27. */
  28. static int mv88e6xxx_g2_avb_wait(struct mv88e6xxx_chip *chip)
  29. {
  30. int bit = __bf_shf(MV88E6352_G2_AVB_CMD_BUSY);
  31. return mv88e6xxx_g2_wait_bit(chip, MV88E6352_G2_AVB_CMD, bit, 0);
  32. }
  33. static int mv88e6xxx_g2_avb_read(struct mv88e6xxx_chip *chip, u16 readop,
  34. u16 *data, int len)
  35. {
  36. int err;
  37. int i;
  38. err = mv88e6xxx_g2_avb_wait(chip);
  39. if (err)
  40. return err;
  41. /* Hardware can only snapshot four words. */
  42. if (len > 4)
  43. return -E2BIG;
  44. err = mv88e6xxx_g2_write(chip, MV88E6352_G2_AVB_CMD,
  45. MV88E6352_G2_AVB_CMD_BUSY | readop);
  46. if (err)
  47. return err;
  48. err = mv88e6xxx_g2_avb_wait(chip);
  49. if (err)
  50. return err;
  51. for (i = 0; i < len; ++i) {
  52. err = mv88e6xxx_g2_read(chip, MV88E6352_G2_AVB_DATA,
  53. &data[i]);
  54. if (err)
  55. return err;
  56. }
  57. return 0;
  58. }
  59. /* mv88e6xxx_g2_avb_write -- Write one 16-bit word. */
  60. static int mv88e6xxx_g2_avb_write(struct mv88e6xxx_chip *chip, u16 writeop,
  61. u16 data)
  62. {
  63. int err;
  64. err = mv88e6xxx_g2_avb_wait(chip);
  65. if (err)
  66. return err;
  67. err = mv88e6xxx_g2_write(chip, MV88E6352_G2_AVB_DATA, data);
  68. if (err)
  69. return err;
  70. err = mv88e6xxx_g2_write(chip, MV88E6352_G2_AVB_CMD,
  71. MV88E6352_G2_AVB_CMD_BUSY | writeop);
  72. return mv88e6xxx_g2_avb_wait(chip);
  73. }
  74. static int mv88e6352_g2_avb_port_ptp_read(struct mv88e6xxx_chip *chip,
  75. int port, int addr, u16 *data,
  76. int len)
  77. {
  78. u16 readop = (len == 1 ? MV88E6352_G2_AVB_CMD_OP_READ :
  79. MV88E6352_G2_AVB_CMD_OP_READ_INCR) |
  80. (port << 8) | (MV88E6352_G2_AVB_CMD_BLOCK_PTP << 5) |
  81. addr;
  82. return mv88e6xxx_g2_avb_read(chip, readop, data, len);
  83. }
  84. static int mv88e6352_g2_avb_port_ptp_write(struct mv88e6xxx_chip *chip,
  85. int port, int addr, u16 data)
  86. {
  87. u16 writeop = MV88E6352_G2_AVB_CMD_OP_WRITE | (port << 8) |
  88. (MV88E6352_G2_AVB_CMD_BLOCK_PTP << 5) | addr;
  89. return mv88e6xxx_g2_avb_write(chip, writeop, data);
  90. }
  91. static int mv88e6352_g2_avb_ptp_read(struct mv88e6xxx_chip *chip, int addr,
  92. u16 *data, int len)
  93. {
  94. return mv88e6352_g2_avb_port_ptp_read(chip,
  95. MV88E6352_G2_AVB_CMD_PORT_PTPGLOBAL,
  96. addr, data, len);
  97. }
  98. static int mv88e6352_g2_avb_ptp_write(struct mv88e6xxx_chip *chip, int addr,
  99. u16 data)
  100. {
  101. return mv88e6352_g2_avb_port_ptp_write(chip,
  102. MV88E6352_G2_AVB_CMD_PORT_PTPGLOBAL,
  103. addr, data);
  104. }
  105. static int mv88e6352_g2_avb_tai_read(struct mv88e6xxx_chip *chip, int addr,
  106. u16 *data, int len)
  107. {
  108. return mv88e6352_g2_avb_port_ptp_read(chip,
  109. MV88E6352_G2_AVB_CMD_PORT_TAIGLOBAL,
  110. addr, data, len);
  111. }
  112. static int mv88e6352_g2_avb_tai_write(struct mv88e6xxx_chip *chip, int addr,
  113. u16 data)
  114. {
  115. return mv88e6352_g2_avb_port_ptp_write(chip,
  116. MV88E6352_G2_AVB_CMD_PORT_TAIGLOBAL,
  117. addr, data);
  118. }
  119. const struct mv88e6xxx_avb_ops mv88e6352_avb_ops = {
  120. .port_ptp_read = mv88e6352_g2_avb_port_ptp_read,
  121. .port_ptp_write = mv88e6352_g2_avb_port_ptp_write,
  122. .ptp_read = mv88e6352_g2_avb_ptp_read,
  123. .ptp_write = mv88e6352_g2_avb_ptp_write,
  124. .tai_read = mv88e6352_g2_avb_tai_read,
  125. .tai_write = mv88e6352_g2_avb_tai_write,
  126. };
  127. static int mv88e6165_g2_avb_tai_read(struct mv88e6xxx_chip *chip, int addr,
  128. u16 *data, int len)
  129. {
  130. return mv88e6352_g2_avb_port_ptp_read(chip,
  131. MV88E6165_G2_AVB_CMD_PORT_PTPGLOBAL,
  132. addr, data, len);
  133. }
  134. static int mv88e6165_g2_avb_tai_write(struct mv88e6xxx_chip *chip, int addr,
  135. u16 data)
  136. {
  137. return mv88e6352_g2_avb_port_ptp_write(chip,
  138. MV88E6165_G2_AVB_CMD_PORT_PTPGLOBAL,
  139. addr, data);
  140. }
  141. const struct mv88e6xxx_avb_ops mv88e6165_avb_ops = {
  142. .port_ptp_read = mv88e6352_g2_avb_port_ptp_read,
  143. .port_ptp_write = mv88e6352_g2_avb_port_ptp_write,
  144. .ptp_read = mv88e6352_g2_avb_ptp_read,
  145. .ptp_write = mv88e6352_g2_avb_ptp_write,
  146. .tai_read = mv88e6165_g2_avb_tai_read,
  147. .tai_write = mv88e6165_g2_avb_tai_write,
  148. };
  149. static int mv88e6390_g2_avb_port_ptp_read(struct mv88e6xxx_chip *chip,
  150. int port, int addr, u16 *data,
  151. int len)
  152. {
  153. u16 readop = (len == 1 ? MV88E6390_G2_AVB_CMD_OP_READ :
  154. MV88E6390_G2_AVB_CMD_OP_READ_INCR) |
  155. (port << 8) | (MV88E6352_G2_AVB_CMD_BLOCK_PTP << 5) |
  156. addr;
  157. return mv88e6xxx_g2_avb_read(chip, readop, data, len);
  158. }
  159. static int mv88e6390_g2_avb_port_ptp_write(struct mv88e6xxx_chip *chip,
  160. int port, int addr, u16 data)
  161. {
  162. u16 writeop = MV88E6390_G2_AVB_CMD_OP_WRITE | (port << 8) |
  163. (MV88E6352_G2_AVB_CMD_BLOCK_PTP << 5) | addr;
  164. return mv88e6xxx_g2_avb_write(chip, writeop, data);
  165. }
  166. static int mv88e6390_g2_avb_ptp_read(struct mv88e6xxx_chip *chip, int addr,
  167. u16 *data, int len)
  168. {
  169. return mv88e6390_g2_avb_port_ptp_read(chip,
  170. MV88E6390_G2_AVB_CMD_PORT_PTPGLOBAL,
  171. addr, data, len);
  172. }
  173. static int mv88e6390_g2_avb_ptp_write(struct mv88e6xxx_chip *chip, int addr,
  174. u16 data)
  175. {
  176. return mv88e6390_g2_avb_port_ptp_write(chip,
  177. MV88E6390_G2_AVB_CMD_PORT_PTPGLOBAL,
  178. addr, data);
  179. }
  180. static int mv88e6390_g2_avb_tai_read(struct mv88e6xxx_chip *chip, int addr,
  181. u16 *data, int len)
  182. {
  183. return mv88e6390_g2_avb_port_ptp_read(chip,
  184. MV88E6390_G2_AVB_CMD_PORT_TAIGLOBAL,
  185. addr, data, len);
  186. }
  187. static int mv88e6390_g2_avb_tai_write(struct mv88e6xxx_chip *chip, int addr,
  188. u16 data)
  189. {
  190. return mv88e6390_g2_avb_port_ptp_write(chip,
  191. MV88E6390_G2_AVB_CMD_PORT_TAIGLOBAL,
  192. addr, data);
  193. }
  194. const struct mv88e6xxx_avb_ops mv88e6390_avb_ops = {
  195. .port_ptp_read = mv88e6390_g2_avb_port_ptp_read,
  196. .port_ptp_write = mv88e6390_g2_avb_port_ptp_write,
  197. .ptp_read = mv88e6390_g2_avb_ptp_read,
  198. .ptp_write = mv88e6390_g2_avb_ptp_write,
  199. .tai_read = mv88e6390_g2_avb_tai_read,
  200. .tai_write = mv88e6390_g2_avb_tai_write,
  201. };