global1.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585
  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. /* Use the default high priority for management frames sent to
  286. * the CPU.
  287. */
  288. port |= MV88E6390_G1_MONITOR_MGMT_CTL_PTR_CPU_DEST_MGMTPRI;
  289. return mv88e6390_g1_monitor_write(chip, ptr, port);
  290. }
  291. int mv88e6390_g1_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip)
  292. {
  293. u16 ptr;
  294. int err;
  295. /* 01:c2:80:00:00:00:00-01:c2:80:00:00:00:07 are Management */
  296. ptr = MV88E6390_G1_MONITOR_MGMT_CTL_PTR_0180C280000000XLO;
  297. err = mv88e6390_g1_monitor_write(chip, ptr, 0xff);
  298. if (err)
  299. return err;
  300. /* 01:c2:80:00:00:00:08-01:c2:80:00:00:00:0f are Management */
  301. ptr = MV88E6390_G1_MONITOR_MGMT_CTL_PTR_0180C280000000XHI;
  302. err = mv88e6390_g1_monitor_write(chip, ptr, 0xff);
  303. if (err)
  304. return err;
  305. /* 01:c2:80:00:00:00:20-01:c2:80:00:00:00:27 are Management */
  306. ptr = MV88E6390_G1_MONITOR_MGMT_CTL_PTR_0180C280000002XLO;
  307. err = mv88e6390_g1_monitor_write(chip, ptr, 0xff);
  308. if (err)
  309. return err;
  310. /* 01:c2:80:00:00:00:28-01:c2:80:00:00:00:2f are Management */
  311. ptr = MV88E6390_G1_MONITOR_MGMT_CTL_PTR_0180C280000002XHI;
  312. err = mv88e6390_g1_monitor_write(chip, ptr, 0xff);
  313. if (err)
  314. return err;
  315. return 0;
  316. }
  317. /* Offset 0x1c: Global Control 2 */
  318. static int mv88e6xxx_g1_ctl2_mask(struct mv88e6xxx_chip *chip, u16 mask,
  319. u16 val)
  320. {
  321. u16 reg;
  322. int err;
  323. err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL2, &reg);
  324. if (err)
  325. return err;
  326. reg &= ~mask;
  327. reg |= val & mask;
  328. return mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL2, reg);
  329. }
  330. int mv88e6185_g1_set_cascade_port(struct mv88e6xxx_chip *chip, int port)
  331. {
  332. const u16 mask = MV88E6185_G1_CTL2_CASCADE_PORT_MASK;
  333. return mv88e6xxx_g1_ctl2_mask(chip, mask, port << __bf_shf(mask));
  334. }
  335. int mv88e6085_g1_rmu_disable(struct mv88e6xxx_chip *chip)
  336. {
  337. return mv88e6xxx_g1_ctl2_mask(chip, MV88E6085_G1_CTL2_P10RM |
  338. MV88E6085_G1_CTL2_RM_ENABLE, 0);
  339. }
  340. int mv88e6352_g1_rmu_disable(struct mv88e6xxx_chip *chip)
  341. {
  342. return mv88e6xxx_g1_ctl2_mask(chip, MV88E6352_G1_CTL2_RMU_MODE_MASK,
  343. MV88E6352_G1_CTL2_RMU_MODE_DISABLED);
  344. }
  345. int mv88e6390_g1_rmu_disable(struct mv88e6xxx_chip *chip)
  346. {
  347. return mv88e6xxx_g1_ctl2_mask(chip, MV88E6390_G1_CTL2_RMU_MODE_MASK,
  348. MV88E6390_G1_CTL2_RMU_MODE_DISABLED);
  349. }
  350. int mv88e6390_g1_stats_set_histogram(struct mv88e6xxx_chip *chip)
  351. {
  352. return mv88e6xxx_g1_ctl2_mask(chip, MV88E6390_G1_CTL2_HIST_MODE_MASK,
  353. MV88E6390_G1_CTL2_HIST_MODE_RX |
  354. MV88E6390_G1_CTL2_HIST_MODE_TX);
  355. }
  356. int mv88e6xxx_g1_set_device_number(struct mv88e6xxx_chip *chip, int index)
  357. {
  358. return mv88e6xxx_g1_ctl2_mask(chip,
  359. MV88E6XXX_G1_CTL2_DEVICE_NUMBER_MASK,
  360. index);
  361. }
  362. /* Offset 0x1d: Statistics Operation 2 */
  363. int mv88e6xxx_g1_stats_wait(struct mv88e6xxx_chip *chip)
  364. {
  365. return mv88e6xxx_g1_wait(chip, MV88E6XXX_G1_STATS_OP,
  366. MV88E6XXX_G1_STATS_OP_BUSY);
  367. }
  368. int mv88e6095_g1_stats_set_histogram(struct mv88e6xxx_chip *chip)
  369. {
  370. u16 val;
  371. int err;
  372. err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STATS_OP, &val);
  373. if (err)
  374. return err;
  375. val |= MV88E6XXX_G1_STATS_OP_HIST_RX_TX;
  376. err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_STATS_OP, val);
  377. return err;
  378. }
  379. int mv88e6xxx_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
  380. {
  381. int err;
  382. /* Snapshot the hardware statistics counters for this port. */
  383. err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_STATS_OP,
  384. MV88E6XXX_G1_STATS_OP_BUSY |
  385. MV88E6XXX_G1_STATS_OP_CAPTURE_PORT |
  386. MV88E6XXX_G1_STATS_OP_HIST_RX_TX | port);
  387. if (err)
  388. return err;
  389. /* Wait for the snapshotting to complete. */
  390. return mv88e6xxx_g1_stats_wait(chip);
  391. }
  392. int mv88e6320_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
  393. {
  394. port = (port + 1) << 5;
  395. return mv88e6xxx_g1_stats_snapshot(chip, port);
  396. }
  397. int mv88e6390_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
  398. {
  399. int err;
  400. port = (port + 1) << 5;
  401. /* Snapshot the hardware statistics counters for this port. */
  402. err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_STATS_OP,
  403. MV88E6XXX_G1_STATS_OP_BUSY |
  404. MV88E6XXX_G1_STATS_OP_CAPTURE_PORT | port);
  405. if (err)
  406. return err;
  407. /* Wait for the snapshotting to complete. */
  408. return mv88e6xxx_g1_stats_wait(chip);
  409. }
  410. void mv88e6xxx_g1_stats_read(struct mv88e6xxx_chip *chip, int stat, u32 *val)
  411. {
  412. u32 value;
  413. u16 reg;
  414. int err;
  415. *val = 0;
  416. err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_STATS_OP,
  417. MV88E6XXX_G1_STATS_OP_BUSY |
  418. MV88E6XXX_G1_STATS_OP_READ_CAPTURED | stat);
  419. if (err)
  420. return;
  421. err = mv88e6xxx_g1_stats_wait(chip);
  422. if (err)
  423. return;
  424. err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STATS_COUNTER_32, &reg);
  425. if (err)
  426. return;
  427. value = reg << 16;
  428. err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STATS_COUNTER_01, &reg);
  429. if (err)
  430. return;
  431. *val = value | reg;
  432. }
  433. int mv88e6xxx_g1_stats_clear(struct mv88e6xxx_chip *chip)
  434. {
  435. int err;
  436. u16 val;
  437. err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STATS_OP, &val);
  438. if (err)
  439. return err;
  440. /* Keep the histogram mode bits */
  441. val &= MV88E6XXX_G1_STATS_OP_HIST_RX_TX;
  442. val |= MV88E6XXX_G1_STATS_OP_BUSY | MV88E6XXX_G1_STATS_OP_FLUSH_ALL;
  443. err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_STATS_OP, val);
  444. if (err)
  445. return err;
  446. /* Wait for the flush to complete. */
  447. return mv88e6xxx_g1_stats_wait(chip);
  448. }