global1.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481
  1. /*
  2. * Marvell 88E6xxx Switch Global (1) Registers support
  3. *
  4. * Copyright (c) 2008 Marvell Semiconductor
  5. *
  6. * Copyright (c) 2016-2017 Savoir-faire Linux Inc.
  7. * Vivien Didelot <vivien.didelot@savoirfairelinux.com>
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation; either version 2 of the License, or
  12. * (at your option) any later version.
  13. */
  14. #include <linux/bitfield.h>
  15. #include "chip.h"
  16. #include "global1.h"
  17. int mv88e6xxx_g1_read(struct mv88e6xxx_chip *chip, int reg, u16 *val)
  18. {
  19. int addr = chip->info->global1_addr;
  20. return mv88e6xxx_read(chip, addr, reg, val);
  21. }
  22. int mv88e6xxx_g1_write(struct mv88e6xxx_chip *chip, int reg, u16 val)
  23. {
  24. int addr = chip->info->global1_addr;
  25. return mv88e6xxx_write(chip, addr, reg, val);
  26. }
  27. int mv88e6xxx_g1_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask)
  28. {
  29. return mv88e6xxx_wait(chip, chip->info->global1_addr, reg, mask);
  30. }
  31. /* Offset 0x00: Switch Global Status Register */
  32. static int mv88e6185_g1_wait_ppu_disabled(struct mv88e6xxx_chip *chip)
  33. {
  34. u16 state;
  35. int i, err;
  36. for (i = 0; i < 16; i++) {
  37. err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, &state);
  38. if (err)
  39. return err;
  40. /* Check the value of the PPUState bits 15:14 */
  41. state &= MV88E6185_G1_STS_PPU_STATE_MASK;
  42. if (state != MV88E6185_G1_STS_PPU_STATE_POLLING)
  43. return 0;
  44. usleep_range(1000, 2000);
  45. }
  46. return -ETIMEDOUT;
  47. }
  48. static int mv88e6185_g1_wait_ppu_polling(struct mv88e6xxx_chip *chip)
  49. {
  50. u16 state;
  51. int i, err;
  52. for (i = 0; i < 16; ++i) {
  53. err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, &state);
  54. if (err)
  55. return err;
  56. /* Check the value of the PPUState bits 15:14 */
  57. state &= MV88E6185_G1_STS_PPU_STATE_MASK;
  58. if (state == MV88E6185_G1_STS_PPU_STATE_POLLING)
  59. return 0;
  60. usleep_range(1000, 2000);
  61. }
  62. return -ETIMEDOUT;
  63. }
  64. static int mv88e6352_g1_wait_ppu_polling(struct mv88e6xxx_chip *chip)
  65. {
  66. u16 state;
  67. int i, err;
  68. for (i = 0; i < 16; ++i) {
  69. err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, &state);
  70. if (err)
  71. return err;
  72. /* Check the value of the PPUState (or InitState) bit 15 */
  73. if (state & MV88E6352_G1_STS_PPU_STATE)
  74. return 0;
  75. usleep_range(1000, 2000);
  76. }
  77. return -ETIMEDOUT;
  78. }
  79. static int mv88e6xxx_g1_wait_init_ready(struct mv88e6xxx_chip *chip)
  80. {
  81. const unsigned long timeout = jiffies + 1 * HZ;
  82. u16 val;
  83. int err;
  84. /* Wait up to 1 second for the switch to be ready. The InitReady bit 11
  85. * is set to a one when all units inside the device (ATU, VTU, etc.)
  86. * have finished their initialization and are ready to accept frames.
  87. */
  88. while (time_before(jiffies, timeout)) {
  89. err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, &val);
  90. if (err)
  91. return err;
  92. if (val & MV88E6XXX_G1_STS_INIT_READY)
  93. break;
  94. usleep_range(1000, 2000);
  95. }
  96. if (time_after(jiffies, timeout))
  97. return -ETIMEDOUT;
  98. return 0;
  99. }
  100. /* Offset 0x01: Switch MAC Address Register Bytes 0 & 1
  101. * Offset 0x02: Switch MAC Address Register Bytes 2 & 3
  102. * Offset 0x03: Switch MAC Address Register Bytes 4 & 5
  103. */
  104. int mv88e6xxx_g1_set_switch_mac(struct mv88e6xxx_chip *chip, u8 *addr)
  105. {
  106. u16 reg;
  107. int err;
  108. reg = (addr[0] << 8) | addr[1];
  109. err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_MAC_01, reg);
  110. if (err)
  111. return err;
  112. reg = (addr[2] << 8) | addr[3];
  113. err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_MAC_23, reg);
  114. if (err)
  115. return err;
  116. reg = (addr[4] << 8) | addr[5];
  117. err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_MAC_45, reg);
  118. if (err)
  119. return err;
  120. return 0;
  121. }
  122. /* Offset 0x04: Switch Global Control Register */
  123. int mv88e6185_g1_reset(struct mv88e6xxx_chip *chip)
  124. {
  125. u16 val;
  126. int err;
  127. /* Set the SWReset bit 15 along with the PPUEn bit 14, to also restart
  128. * the PPU, including re-doing PHY detection and initialization
  129. */
  130. err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, &val);
  131. if (err)
  132. return err;
  133. val |= MV88E6XXX_G1_CTL1_SW_RESET;
  134. val |= MV88E6XXX_G1_CTL1_PPU_ENABLE;
  135. err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL1, val);
  136. if (err)
  137. return err;
  138. err = mv88e6xxx_g1_wait_init_ready(chip);
  139. if (err)
  140. return err;
  141. return mv88e6185_g1_wait_ppu_polling(chip);
  142. }
  143. int mv88e6352_g1_reset(struct mv88e6xxx_chip *chip)
  144. {
  145. u16 val;
  146. int err;
  147. /* Set the SWReset bit 15 */
  148. err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, &val);
  149. if (err)
  150. return err;
  151. val |= MV88E6XXX_G1_CTL1_SW_RESET;
  152. err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL1, val);
  153. if (err)
  154. return err;
  155. err = mv88e6xxx_g1_wait_init_ready(chip);
  156. if (err)
  157. return err;
  158. return mv88e6352_g1_wait_ppu_polling(chip);
  159. }
  160. int mv88e6185_g1_ppu_enable(struct mv88e6xxx_chip *chip)
  161. {
  162. u16 val;
  163. int err;
  164. err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, &val);
  165. if (err)
  166. return err;
  167. val |= MV88E6XXX_G1_CTL1_PPU_ENABLE;
  168. err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL1, val);
  169. if (err)
  170. return err;
  171. return mv88e6185_g1_wait_ppu_polling(chip);
  172. }
  173. int mv88e6185_g1_ppu_disable(struct mv88e6xxx_chip *chip)
  174. {
  175. u16 val;
  176. int err;
  177. err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, &val);
  178. if (err)
  179. return err;
  180. val &= ~MV88E6XXX_G1_CTL1_PPU_ENABLE;
  181. err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL1, val);
  182. if (err)
  183. return err;
  184. return mv88e6185_g1_wait_ppu_disabled(chip);
  185. }
  186. /* Offset 0x1a: Monitor Control */
  187. /* Offset 0x1a: Monitor & MGMT Control on some devices */
  188. int mv88e6095_g1_set_egress_port(struct mv88e6xxx_chip *chip, int port)
  189. {
  190. u16 reg;
  191. int err;
  192. err = mv88e6xxx_g1_read(chip, MV88E6185_G1_MONITOR_CTL, &reg);
  193. if (err)
  194. return err;
  195. reg &= ~(MV88E6185_G1_MONITOR_CTL_INGRESS_DEST_MASK |
  196. MV88E6185_G1_MONITOR_CTL_EGRESS_DEST_MASK);
  197. reg |= port << __bf_shf(MV88E6185_G1_MONITOR_CTL_INGRESS_DEST_MASK) |
  198. port << __bf_shf(MV88E6185_G1_MONITOR_CTL_EGRESS_DEST_MASK);
  199. return mv88e6xxx_g1_write(chip, MV88E6185_G1_MONITOR_CTL, reg);
  200. }
  201. /* Older generations also call this the ARP destination. It has been
  202. * generalized in more modern devices such that more than ARP can
  203. * egress it
  204. */
  205. int mv88e6095_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port)
  206. {
  207. u16 reg;
  208. int err;
  209. err = mv88e6xxx_g1_read(chip, MV88E6185_G1_MONITOR_CTL, &reg);
  210. if (err)
  211. return err;
  212. reg &= ~MV88E6185_G1_MONITOR_CTL_ARP_DEST_MASK;
  213. reg |= port << __bf_shf(MV88E6185_G1_MONITOR_CTL_ARP_DEST_MASK);
  214. return mv88e6xxx_g1_write(chip, MV88E6185_G1_MONITOR_CTL, reg);
  215. }
  216. static int mv88e6390_g1_monitor_write(struct mv88e6xxx_chip *chip,
  217. u16 pointer, u8 data)
  218. {
  219. u16 reg;
  220. reg = MV88E6390_G1_MONITOR_MGMT_CTL_UPDATE | pointer | data;
  221. return mv88e6xxx_g1_write(chip, MV88E6390_G1_MONITOR_MGMT_CTL, reg);
  222. }
  223. int mv88e6390_g1_set_egress_port(struct mv88e6xxx_chip *chip, int port)
  224. {
  225. u16 ptr;
  226. int err;
  227. ptr = MV88E6390_G1_MONITOR_MGMT_CTL_PTR_INGRESS_DEST;
  228. err = mv88e6390_g1_monitor_write(chip, ptr, port);
  229. if (err)
  230. return err;
  231. ptr = MV88E6390_G1_MONITOR_MGMT_CTL_PTR_EGRESS_DEST;
  232. err = mv88e6390_g1_monitor_write(chip, ptr, port);
  233. if (err)
  234. return err;
  235. return 0;
  236. }
  237. int mv88e6390_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port)
  238. {
  239. u16 ptr = MV88E6390_G1_MONITOR_MGMT_CTL_PTR_CPU_DEST;
  240. return mv88e6390_g1_monitor_write(chip, ptr, port);
  241. }
  242. int mv88e6390_g1_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip)
  243. {
  244. u16 ptr;
  245. int err;
  246. /* 01:c2:80:00:00:00:00-01:c2:80:00:00:00:07 are Management */
  247. ptr = MV88E6390_G1_MONITOR_MGMT_CTL_PTR_0180C280000000XLO;
  248. err = mv88e6390_g1_monitor_write(chip, ptr, 0xff);
  249. if (err)
  250. return err;
  251. /* 01:c2:80:00:00:00:08-01:c2:80:00:00:00:0f are Management */
  252. ptr = MV88E6390_G1_MONITOR_MGMT_CTL_PTR_0180C280000000XHI;
  253. err = mv88e6390_g1_monitor_write(chip, ptr, 0xff);
  254. if (err)
  255. return err;
  256. /* 01:c2:80:00:00:00:20-01:c2:80:00:00:00:27 are Management */
  257. ptr = MV88E6390_G1_MONITOR_MGMT_CTL_PTR_0180C280000002XLO;
  258. err = mv88e6390_g1_monitor_write(chip, ptr, 0xff);
  259. if (err)
  260. return err;
  261. /* 01:c2:80:00:00:00:28-01:c2:80:00:00:00:2f are Management */
  262. ptr = MV88E6390_G1_MONITOR_MGMT_CTL_PTR_0180C280000002XHI;
  263. err = mv88e6390_g1_monitor_write(chip, ptr, 0xff);
  264. if (err)
  265. return err;
  266. return 0;
  267. }
  268. /* Offset 0x1c: Global Control 2 */
  269. int mv88e6390_g1_stats_set_histogram(struct mv88e6xxx_chip *chip)
  270. {
  271. u16 val;
  272. int err;
  273. err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL2, &val);
  274. if (err)
  275. return err;
  276. val |= MV88E6XXX_G1_CTL2_HIST_RX_TX;
  277. err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL2, val);
  278. return err;
  279. }
  280. /* Offset 0x1d: Statistics Operation 2 */
  281. int mv88e6xxx_g1_stats_wait(struct mv88e6xxx_chip *chip)
  282. {
  283. return mv88e6xxx_g1_wait(chip, MV88E6XXX_G1_STATS_OP,
  284. MV88E6XXX_G1_STATS_OP_BUSY);
  285. }
  286. int mv88e6095_g1_stats_set_histogram(struct mv88e6xxx_chip *chip)
  287. {
  288. u16 val;
  289. int err;
  290. err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STATS_OP, &val);
  291. if (err)
  292. return err;
  293. val |= MV88E6XXX_G1_STATS_OP_HIST_RX_TX;
  294. err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_STATS_OP, val);
  295. return err;
  296. }
  297. int mv88e6xxx_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
  298. {
  299. int err;
  300. /* Snapshot the hardware statistics counters for this port. */
  301. err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_STATS_OP,
  302. MV88E6XXX_G1_STATS_OP_BUSY |
  303. MV88E6XXX_G1_STATS_OP_CAPTURE_PORT |
  304. MV88E6XXX_G1_STATS_OP_HIST_RX_TX | port);
  305. if (err)
  306. return err;
  307. /* Wait for the snapshotting to complete. */
  308. return mv88e6xxx_g1_stats_wait(chip);
  309. }
  310. int mv88e6320_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
  311. {
  312. port = (port + 1) << 5;
  313. return mv88e6xxx_g1_stats_snapshot(chip, port);
  314. }
  315. int mv88e6390_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
  316. {
  317. int err;
  318. port = (port + 1) << 5;
  319. /* Snapshot the hardware statistics counters for this port. */
  320. err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_STATS_OP,
  321. MV88E6XXX_G1_STATS_OP_BUSY |
  322. MV88E6XXX_G1_STATS_OP_CAPTURE_PORT | port);
  323. if (err)
  324. return err;
  325. /* Wait for the snapshotting to complete. */
  326. return mv88e6xxx_g1_stats_wait(chip);
  327. }
  328. void mv88e6xxx_g1_stats_read(struct mv88e6xxx_chip *chip, int stat, u32 *val)
  329. {
  330. u32 value;
  331. u16 reg;
  332. int err;
  333. *val = 0;
  334. err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_STATS_OP,
  335. MV88E6XXX_G1_STATS_OP_BUSY |
  336. MV88E6XXX_G1_STATS_OP_READ_CAPTURED | stat);
  337. if (err)
  338. return;
  339. err = mv88e6xxx_g1_stats_wait(chip);
  340. if (err)
  341. return;
  342. err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STATS_COUNTER_32, &reg);
  343. if (err)
  344. return;
  345. value = reg << 16;
  346. err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STATS_COUNTER_01, &reg);
  347. if (err)
  348. return;
  349. *val = value | reg;
  350. }
  351. int mv88e6xxx_g1_stats_clear(struct mv88e6xxx_chip *chip)
  352. {
  353. int err;
  354. u16 val;
  355. err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STATS_OP, &val);
  356. if (err)
  357. return err;
  358. val |= MV88E6XXX_G1_STATS_OP_BUSY | MV88E6XXX_G1_STATS_OP_FLUSH_ALL;
  359. err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_STATS_OP, val);
  360. if (err)
  361. return err;
  362. /* Wait for the flush to complete. */
  363. return mv88e6xxx_g1_stats_wait(chip);
  364. }