global1.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578
  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 0x10: IP-PRI Mapping Register 0
  187. * Offset 0x11: IP-PRI Mapping Register 1
  188. * Offset 0x12: IP-PRI Mapping Register 2
  189. * Offset 0x13: IP-PRI Mapping Register 3
  190. * Offset 0x14: IP-PRI Mapping Register 4
  191. * Offset 0x15: IP-PRI Mapping Register 5
  192. * Offset 0x16: IP-PRI Mapping Register 6
  193. * Offset 0x17: IP-PRI Mapping Register 7
  194. */
  195. int mv88e6085_g1_ip_pri_map(struct mv88e6xxx_chip *chip)
  196. {
  197. int err;
  198. /* Reset the IP TOS/DiffServ/Traffic priorities to defaults */
  199. err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_IP_PRI_0, 0x0000);
  200. if (err)
  201. return err;
  202. err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_IP_PRI_1, 0x0000);
  203. if (err)
  204. return err;
  205. err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_IP_PRI_2, 0x5555);
  206. if (err)
  207. return err;
  208. err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_IP_PRI_3, 0x5555);
  209. if (err)
  210. return err;
  211. err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_IP_PRI_4, 0xaaaa);
  212. if (err)
  213. return err;
  214. err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_IP_PRI_5, 0xaaaa);
  215. if (err)
  216. return err;
  217. err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_IP_PRI_6, 0xffff);
  218. if (err)
  219. return err;
  220. err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_IP_PRI_7, 0xffff);
  221. if (err)
  222. return err;
  223. return 0;
  224. }
  225. /* Offset 0x18: IEEE-PRI Register */
  226. int mv88e6085_g1_ieee_pri_map(struct mv88e6xxx_chip *chip)
  227. {
  228. /* Reset the IEEE Tag priorities to defaults */
  229. return mv88e6xxx_g1_write(chip, MV88E6XXX_G1_IEEE_PRI, 0xfa41);
  230. }
  231. /* Offset 0x1a: Monitor Control */
  232. /* Offset 0x1a: Monitor & MGMT Control on some devices */
  233. int mv88e6095_g1_set_egress_port(struct mv88e6xxx_chip *chip, int port)
  234. {
  235. u16 reg;
  236. int err;
  237. err = mv88e6xxx_g1_read(chip, MV88E6185_G1_MONITOR_CTL, &reg);
  238. if (err)
  239. return err;
  240. reg &= ~(MV88E6185_G1_MONITOR_CTL_INGRESS_DEST_MASK |
  241. MV88E6185_G1_MONITOR_CTL_EGRESS_DEST_MASK);
  242. reg |= port << __bf_shf(MV88E6185_G1_MONITOR_CTL_INGRESS_DEST_MASK) |
  243. port << __bf_shf(MV88E6185_G1_MONITOR_CTL_EGRESS_DEST_MASK);
  244. return mv88e6xxx_g1_write(chip, MV88E6185_G1_MONITOR_CTL, reg);
  245. }
  246. /* Older generations also call this the ARP destination. It has been
  247. * generalized in more modern devices such that more than ARP can
  248. * egress it
  249. */
  250. int mv88e6095_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port)
  251. {
  252. u16 reg;
  253. int err;
  254. err = mv88e6xxx_g1_read(chip, MV88E6185_G1_MONITOR_CTL, &reg);
  255. if (err)
  256. return err;
  257. reg &= ~MV88E6185_G1_MONITOR_CTL_ARP_DEST_MASK;
  258. reg |= port << __bf_shf(MV88E6185_G1_MONITOR_CTL_ARP_DEST_MASK);
  259. return mv88e6xxx_g1_write(chip, MV88E6185_G1_MONITOR_CTL, reg);
  260. }
  261. static int mv88e6390_g1_monitor_write(struct mv88e6xxx_chip *chip,
  262. u16 pointer, u8 data)
  263. {
  264. u16 reg;
  265. reg = MV88E6390_G1_MONITOR_MGMT_CTL_UPDATE | pointer | data;
  266. return mv88e6xxx_g1_write(chip, MV88E6390_G1_MONITOR_MGMT_CTL, reg);
  267. }
  268. int mv88e6390_g1_set_egress_port(struct mv88e6xxx_chip *chip, int port)
  269. {
  270. u16 ptr;
  271. int err;
  272. ptr = MV88E6390_G1_MONITOR_MGMT_CTL_PTR_INGRESS_DEST;
  273. err = mv88e6390_g1_monitor_write(chip, ptr, port);
  274. if (err)
  275. return err;
  276. ptr = MV88E6390_G1_MONITOR_MGMT_CTL_PTR_EGRESS_DEST;
  277. err = mv88e6390_g1_monitor_write(chip, ptr, port);
  278. if (err)
  279. return err;
  280. return 0;
  281. }
  282. int mv88e6390_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port)
  283. {
  284. u16 ptr = MV88E6390_G1_MONITOR_MGMT_CTL_PTR_CPU_DEST;
  285. return mv88e6390_g1_monitor_write(chip, ptr, port);
  286. }
  287. int mv88e6390_g1_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip)
  288. {
  289. u16 ptr;
  290. int err;
  291. /* 01:c2:80:00:00:00:00-01:c2:80:00:00:00:07 are Management */
  292. ptr = MV88E6390_G1_MONITOR_MGMT_CTL_PTR_0180C280000000XLO;
  293. err = mv88e6390_g1_monitor_write(chip, ptr, 0xff);
  294. if (err)
  295. return err;
  296. /* 01:c2:80:00:00:00:08-01:c2:80:00:00:00:0f are Management */
  297. ptr = MV88E6390_G1_MONITOR_MGMT_CTL_PTR_0180C280000000XHI;
  298. err = mv88e6390_g1_monitor_write(chip, ptr, 0xff);
  299. if (err)
  300. return err;
  301. /* 01:c2:80:00:00:00:20-01:c2:80:00:00:00:27 are Management */
  302. ptr = MV88E6390_G1_MONITOR_MGMT_CTL_PTR_0180C280000002XLO;
  303. err = mv88e6390_g1_monitor_write(chip, ptr, 0xff);
  304. if (err)
  305. return err;
  306. /* 01:c2:80:00:00:00:28-01:c2:80:00:00:00:2f are Management */
  307. ptr = MV88E6390_G1_MONITOR_MGMT_CTL_PTR_0180C280000002XHI;
  308. err = mv88e6390_g1_monitor_write(chip, ptr, 0xff);
  309. if (err)
  310. return err;
  311. return 0;
  312. }
  313. /* Offset 0x1c: Global Control 2 */
  314. static int mv88e6xxx_g1_ctl2_mask(struct mv88e6xxx_chip *chip, u16 mask,
  315. u16 val)
  316. {
  317. u16 reg;
  318. int err;
  319. err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL2, &reg);
  320. if (err)
  321. return err;
  322. reg &= ~mask;
  323. reg |= val & mask;
  324. return mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL2, reg);
  325. }
  326. int mv88e6185_g1_set_cascade_port(struct mv88e6xxx_chip *chip, int port)
  327. {
  328. const u16 mask = MV88E6185_G1_CTL2_CASCADE_PORT_MASK;
  329. return mv88e6xxx_g1_ctl2_mask(chip, mask, port << __bf_shf(mask));
  330. }
  331. int mv88e6085_g1_rmu_disable(struct mv88e6xxx_chip *chip)
  332. {
  333. return mv88e6xxx_g1_ctl2_mask(chip, MV88E6085_G1_CTL2_P10RM |
  334. MV88E6085_G1_CTL2_RM_ENABLE, 0);
  335. }
  336. int mv88e6352_g1_rmu_disable(struct mv88e6xxx_chip *chip)
  337. {
  338. return mv88e6xxx_g1_ctl2_mask(chip, MV88E6352_G1_CTL2_RMU_MODE_MASK,
  339. MV88E6352_G1_CTL2_RMU_MODE_DISABLED);
  340. }
  341. int mv88e6390_g1_rmu_disable(struct mv88e6xxx_chip *chip)
  342. {
  343. return mv88e6xxx_g1_ctl2_mask(chip, MV88E6390_G1_CTL2_RMU_MODE_MASK,
  344. MV88E6390_G1_CTL2_RMU_MODE_DISABLED);
  345. }
  346. int mv88e6390_g1_stats_set_histogram(struct mv88e6xxx_chip *chip)
  347. {
  348. return mv88e6xxx_g1_ctl2_mask(chip, MV88E6390_G1_CTL2_HIST_MODE_MASK,
  349. MV88E6390_G1_CTL2_HIST_MODE_RX |
  350. MV88E6390_G1_CTL2_HIST_MODE_TX);
  351. }
  352. int mv88e6xxx_g1_set_device_number(struct mv88e6xxx_chip *chip, int index)
  353. {
  354. return mv88e6xxx_g1_ctl2_mask(chip,
  355. MV88E6XXX_G1_CTL2_DEVICE_NUMBER_MASK,
  356. index);
  357. }
  358. /* Offset 0x1d: Statistics Operation 2 */
  359. int mv88e6xxx_g1_stats_wait(struct mv88e6xxx_chip *chip)
  360. {
  361. return mv88e6xxx_g1_wait(chip, MV88E6XXX_G1_STATS_OP,
  362. MV88E6XXX_G1_STATS_OP_BUSY);
  363. }
  364. int mv88e6095_g1_stats_set_histogram(struct mv88e6xxx_chip *chip)
  365. {
  366. u16 val;
  367. int err;
  368. err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STATS_OP, &val);
  369. if (err)
  370. return err;
  371. val |= MV88E6XXX_G1_STATS_OP_HIST_RX_TX;
  372. err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_STATS_OP, val);
  373. return err;
  374. }
  375. int mv88e6xxx_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
  376. {
  377. int err;
  378. /* Snapshot the hardware statistics counters for this port. */
  379. err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_STATS_OP,
  380. MV88E6XXX_G1_STATS_OP_BUSY |
  381. MV88E6XXX_G1_STATS_OP_CAPTURE_PORT |
  382. MV88E6XXX_G1_STATS_OP_HIST_RX_TX | port);
  383. if (err)
  384. return err;
  385. /* Wait for the snapshotting to complete. */
  386. return mv88e6xxx_g1_stats_wait(chip);
  387. }
  388. int mv88e6320_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
  389. {
  390. port = (port + 1) << 5;
  391. return mv88e6xxx_g1_stats_snapshot(chip, port);
  392. }
  393. int mv88e6390_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
  394. {
  395. int err;
  396. port = (port + 1) << 5;
  397. /* Snapshot the hardware statistics counters for this port. */
  398. err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_STATS_OP,
  399. MV88E6XXX_G1_STATS_OP_BUSY |
  400. MV88E6XXX_G1_STATS_OP_CAPTURE_PORT | port);
  401. if (err)
  402. return err;
  403. /* Wait for the snapshotting to complete. */
  404. return mv88e6xxx_g1_stats_wait(chip);
  405. }
  406. void mv88e6xxx_g1_stats_read(struct mv88e6xxx_chip *chip, int stat, u32 *val)
  407. {
  408. u32 value;
  409. u16 reg;
  410. int err;
  411. *val = 0;
  412. err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_STATS_OP,
  413. MV88E6XXX_G1_STATS_OP_BUSY |
  414. MV88E6XXX_G1_STATS_OP_READ_CAPTURED | stat);
  415. if (err)
  416. return;
  417. err = mv88e6xxx_g1_stats_wait(chip);
  418. if (err)
  419. return;
  420. err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STATS_COUNTER_32, &reg);
  421. if (err)
  422. return;
  423. value = reg << 16;
  424. err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STATS_COUNTER_01, &reg);
  425. if (err)
  426. return;
  427. *val = value | reg;
  428. }
  429. int mv88e6xxx_g1_stats_clear(struct mv88e6xxx_chip *chip)
  430. {
  431. int err;
  432. u16 val;
  433. err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STATS_OP, &val);
  434. if (err)
  435. return err;
  436. val |= MV88E6XXX_G1_STATS_OP_BUSY | MV88E6XXX_G1_STATS_OP_FLUSH_ALL;
  437. err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_STATS_OP, val);
  438. if (err)
  439. return err;
  440. /* Wait for the flush to complete. */
  441. return mv88e6xxx_g1_stats_wait(chip);
  442. }