global1.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  1. /*
  2. * Marvell 88E6xxx Switch Global (1) Registers support
  3. *
  4. * Copyright (c) 2008 Marvell Semiconductor
  5. *
  6. * Copyright (c) 2016 Vivien Didelot <vivien.didelot@savoirfairelinux.com>
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version.
  12. */
  13. #include "mv88e6xxx.h"
  14. #include "global1.h"
  15. int mv88e6xxx_g1_read(struct mv88e6xxx_chip *chip, int reg, u16 *val)
  16. {
  17. int addr = chip->info->global1_addr;
  18. return mv88e6xxx_read(chip, addr, reg, val);
  19. }
  20. int mv88e6xxx_g1_write(struct mv88e6xxx_chip *chip, int reg, u16 val)
  21. {
  22. int addr = chip->info->global1_addr;
  23. return mv88e6xxx_write(chip, addr, reg, val);
  24. }
  25. int mv88e6xxx_g1_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask)
  26. {
  27. return mv88e6xxx_wait(chip, chip->info->global1_addr, reg, mask);
  28. }
  29. /* Offset 0x00: Switch Global Status Register */
  30. static int mv88e6185_g1_wait_ppu_disabled(struct mv88e6xxx_chip *chip)
  31. {
  32. u16 state;
  33. int i, err;
  34. for (i = 0; i < 16; i++) {
  35. err = mv88e6xxx_g1_read(chip, GLOBAL_STATUS, &state);
  36. if (err)
  37. return err;
  38. /* Check the value of the PPUState bits 15:14 */
  39. state &= GLOBAL_STATUS_PPU_STATE_MASK;
  40. if (state != GLOBAL_STATUS_PPU_STATE_POLLING)
  41. return 0;
  42. usleep_range(1000, 2000);
  43. }
  44. return -ETIMEDOUT;
  45. }
  46. static int mv88e6185_g1_wait_ppu_polling(struct mv88e6xxx_chip *chip)
  47. {
  48. u16 state;
  49. int i, err;
  50. for (i = 0; i < 16; ++i) {
  51. err = mv88e6xxx_g1_read(chip, GLOBAL_STATUS, &state);
  52. if (err)
  53. return err;
  54. /* Check the value of the PPUState bits 15:14 */
  55. state &= GLOBAL_STATUS_PPU_STATE_MASK;
  56. if (state == GLOBAL_STATUS_PPU_STATE_POLLING)
  57. return 0;
  58. usleep_range(1000, 2000);
  59. }
  60. return -ETIMEDOUT;
  61. }
  62. static int mv88e6352_g1_wait_ppu_polling(struct mv88e6xxx_chip *chip)
  63. {
  64. u16 state;
  65. int i, err;
  66. for (i = 0; i < 16; ++i) {
  67. err = mv88e6xxx_g1_read(chip, GLOBAL_STATUS, &state);
  68. if (err)
  69. return err;
  70. /* Check the value of the PPUState (or InitState) bit 15 */
  71. if (state & GLOBAL_STATUS_PPU_STATE)
  72. return 0;
  73. usleep_range(1000, 2000);
  74. }
  75. return -ETIMEDOUT;
  76. }
  77. static int mv88e6xxx_g1_wait_init_ready(struct mv88e6xxx_chip *chip)
  78. {
  79. const unsigned long timeout = jiffies + 1 * HZ;
  80. u16 val;
  81. int err;
  82. /* Wait up to 1 second for the switch to be ready. The InitReady bit 11
  83. * is set to a one when all units inside the device (ATU, VTU, etc.)
  84. * have finished their initialization and are ready to accept frames.
  85. */
  86. while (time_before(jiffies, timeout)) {
  87. err = mv88e6xxx_g1_read(chip, GLOBAL_STATUS, &val);
  88. if (err)
  89. return err;
  90. if (val & GLOBAL_STATUS_INIT_READY)
  91. break;
  92. usleep_range(1000, 2000);
  93. }
  94. if (time_after(jiffies, timeout))
  95. return -ETIMEDOUT;
  96. return 0;
  97. }
  98. /* Offset 0x04: Switch Global Control Register */
  99. int mv88e6185_g1_reset(struct mv88e6xxx_chip *chip)
  100. {
  101. u16 val;
  102. int err;
  103. /* Set the SWReset bit 15 along with the PPUEn bit 14, to also restart
  104. * the PPU, including re-doing PHY detection and initialization
  105. */
  106. err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL, &val);
  107. if (err)
  108. return err;
  109. val |= GLOBAL_CONTROL_SW_RESET;
  110. val |= GLOBAL_CONTROL_PPU_ENABLE;
  111. err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL, val);
  112. if (err)
  113. return err;
  114. err = mv88e6xxx_g1_wait_init_ready(chip);
  115. if (err)
  116. return err;
  117. return mv88e6185_g1_wait_ppu_polling(chip);
  118. }
  119. int mv88e6352_g1_reset(struct mv88e6xxx_chip *chip)
  120. {
  121. u16 val;
  122. int err;
  123. /* Set the SWReset bit 15 */
  124. err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL, &val);
  125. if (err)
  126. return err;
  127. val |= GLOBAL_CONTROL_SW_RESET;
  128. err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL, val);
  129. if (err)
  130. return err;
  131. err = mv88e6xxx_g1_wait_init_ready(chip);
  132. if (err)
  133. return err;
  134. return mv88e6352_g1_wait_ppu_polling(chip);
  135. }
  136. int mv88e6185_g1_ppu_enable(struct mv88e6xxx_chip *chip)
  137. {
  138. u16 val;
  139. int err;
  140. err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL, &val);
  141. if (err)
  142. return err;
  143. val |= GLOBAL_CONTROL_PPU_ENABLE;
  144. err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL, val);
  145. if (err)
  146. return err;
  147. return mv88e6185_g1_wait_ppu_polling(chip);
  148. }
  149. int mv88e6185_g1_ppu_disable(struct mv88e6xxx_chip *chip)
  150. {
  151. u16 val;
  152. int err;
  153. err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL, &val);
  154. if (err)
  155. return err;
  156. val &= ~GLOBAL_CONTROL_PPU_ENABLE;
  157. err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL, val);
  158. if (err)
  159. return err;
  160. return mv88e6185_g1_wait_ppu_disabled(chip);
  161. }
  162. /* Offset 0x1a: Monitor Control */
  163. /* Offset 0x1a: Monitor & MGMT Control on some devices */
  164. int mv88e6095_g1_set_egress_port(struct mv88e6xxx_chip *chip, int port)
  165. {
  166. u16 reg;
  167. int err;
  168. err = mv88e6xxx_g1_read(chip, GLOBAL_MONITOR_CONTROL, &reg);
  169. if (err)
  170. return err;
  171. reg &= ~(GLOBAL_MONITOR_CONTROL_INGRESS_MASK |
  172. GLOBAL_MONITOR_CONTROL_EGRESS_MASK);
  173. reg |= port << GLOBAL_MONITOR_CONTROL_INGRESS_SHIFT |
  174. port << GLOBAL_MONITOR_CONTROL_EGRESS_SHIFT;
  175. return mv88e6xxx_g1_write(chip, GLOBAL_MONITOR_CONTROL, reg);
  176. }
  177. /* Older generations also call this the ARP destination. It has been
  178. * generalized in more modern devices such that more than ARP can
  179. * egress it
  180. */
  181. int mv88e6095_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port)
  182. {
  183. u16 reg;
  184. int err;
  185. err = mv88e6xxx_g1_read(chip, GLOBAL_MONITOR_CONTROL, &reg);
  186. if (err)
  187. return err;
  188. reg &= ~GLOBAL_MONITOR_CONTROL_ARP_MASK;
  189. reg |= port << GLOBAL_MONITOR_CONTROL_ARP_SHIFT;
  190. return mv88e6xxx_g1_write(chip, GLOBAL_MONITOR_CONTROL, reg);
  191. }
  192. static int mv88e6390_g1_monitor_write(struct mv88e6xxx_chip *chip,
  193. u16 pointer, u8 data)
  194. {
  195. u16 reg;
  196. reg = GLOBAL_MONITOR_CONTROL_UPDATE | pointer | data;
  197. return mv88e6xxx_g1_write(chip, GLOBAL_MONITOR_CONTROL, reg);
  198. }
  199. int mv88e6390_g1_set_egress_port(struct mv88e6xxx_chip *chip, int port)
  200. {
  201. int err;
  202. err = mv88e6390_g1_monitor_write(chip, GLOBAL_MONITOR_CONTROL_INGRESS,
  203. port);
  204. if (err)
  205. return err;
  206. return mv88e6390_g1_monitor_write(chip, GLOBAL_MONITOR_CONTROL_EGRESS,
  207. port);
  208. }
  209. int mv88e6390_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port)
  210. {
  211. return mv88e6390_g1_monitor_write(chip, GLOBAL_MONITOR_CONTROL_CPU_DEST,
  212. port);
  213. }
  214. int mv88e6390_g1_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip)
  215. {
  216. int err;
  217. /* 01:c2:80:00:00:00:00-01:c2:80:00:00:00:07 are Management */
  218. err = mv88e6390_g1_monitor_write(
  219. chip, GLOBAL_MONITOR_CONTROL_0180C280000000XLO, 0xff);
  220. if (err)
  221. return err;
  222. /* 01:c2:80:00:00:00:08-01:c2:80:00:00:00:0f are Management */
  223. err = mv88e6390_g1_monitor_write(
  224. chip, GLOBAL_MONITOR_CONTROL_0180C280000000XHI, 0xff);
  225. if (err)
  226. return err;
  227. /* 01:c2:80:00:00:00:20-01:c2:80:00:00:00:27 are Management */
  228. err = mv88e6390_g1_monitor_write(
  229. chip, GLOBAL_MONITOR_CONTROL_0180C280000002XLO, 0xff);
  230. if (err)
  231. return err;
  232. /* 01:c2:80:00:00:00:28-01:c2:80:00:00:00:2f are Management */
  233. return mv88e6390_g1_monitor_write(
  234. chip, GLOBAL_MONITOR_CONTROL_0180C280000002XHI, 0xff);
  235. }
  236. /* Offset 0x1c: Global Control 2 */
  237. int mv88e6390_g1_stats_set_histogram(struct mv88e6xxx_chip *chip)
  238. {
  239. u16 val;
  240. int err;
  241. err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL_2, &val);
  242. if (err)
  243. return err;
  244. val |= GLOBAL_CONTROL_2_HIST_RX_TX;
  245. err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL_2, val);
  246. return err;
  247. }
  248. /* Offset 0x1d: Statistics Operation 2 */
  249. int mv88e6xxx_g1_stats_wait(struct mv88e6xxx_chip *chip)
  250. {
  251. return mv88e6xxx_g1_wait(chip, GLOBAL_STATS_OP, GLOBAL_STATS_OP_BUSY);
  252. }
  253. int mv88e6xxx_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
  254. {
  255. int err;
  256. /* Snapshot the hardware statistics counters for this port. */
  257. err = mv88e6xxx_g1_write(chip, GLOBAL_STATS_OP,
  258. GLOBAL_STATS_OP_CAPTURE_PORT |
  259. GLOBAL_STATS_OP_HIST_RX_TX | port);
  260. if (err)
  261. return err;
  262. /* Wait for the snapshotting to complete. */
  263. return mv88e6xxx_g1_stats_wait(chip);
  264. }
  265. int mv88e6320_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
  266. {
  267. port = (port + 1) << 5;
  268. return mv88e6xxx_g1_stats_snapshot(chip, port);
  269. }
  270. int mv88e6390_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
  271. {
  272. int err;
  273. port = (port + 1) << 5;
  274. /* Snapshot the hardware statistics counters for this port. */
  275. err = mv88e6xxx_g1_write(chip, GLOBAL_STATS_OP,
  276. GLOBAL_STATS_OP_CAPTURE_PORT | port);
  277. if (err)
  278. return err;
  279. /* Wait for the snapshotting to complete. */
  280. return mv88e6xxx_g1_stats_wait(chip);
  281. }
  282. void mv88e6xxx_g1_stats_read(struct mv88e6xxx_chip *chip, int stat, u32 *val)
  283. {
  284. u32 value;
  285. u16 reg;
  286. int err;
  287. *val = 0;
  288. err = mv88e6xxx_g1_write(chip, GLOBAL_STATS_OP,
  289. GLOBAL_STATS_OP_READ_CAPTURED | stat);
  290. if (err)
  291. return;
  292. err = mv88e6xxx_g1_stats_wait(chip);
  293. if (err)
  294. return;
  295. err = mv88e6xxx_g1_read(chip, GLOBAL_STATS_COUNTER_32, &reg);
  296. if (err)
  297. return;
  298. value = reg << 16;
  299. err = mv88e6xxx_g1_read(chip, GLOBAL_STATS_COUNTER_01, &reg);
  300. if (err)
  301. return;
  302. *val = value | reg;
  303. }