global2.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492
  1. /*
  2. * Marvell 88E6xxx Switch Global 2 Registers support (device address 0x1C)
  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 "global2.h"
  15. #define ADDR_GLOBAL2 0x1c
  16. static int mv88e6xxx_g2_read(struct mv88e6xxx_chip *chip, int reg, u16 *val)
  17. {
  18. return mv88e6xxx_read(chip, ADDR_GLOBAL2, reg, val);
  19. }
  20. static int mv88e6xxx_g2_write(struct mv88e6xxx_chip *chip, int reg, u16 val)
  21. {
  22. return mv88e6xxx_write(chip, ADDR_GLOBAL2, reg, val);
  23. }
  24. static int mv88e6xxx_g2_update(struct mv88e6xxx_chip *chip, int reg, u16 update)
  25. {
  26. return mv88e6xxx_update(chip, ADDR_GLOBAL2, reg, update);
  27. }
  28. static int mv88e6xxx_g2_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask)
  29. {
  30. return mv88e6xxx_wait(chip, ADDR_GLOBAL2, reg, mask);
  31. }
  32. /* Offset 0x06: Device Mapping Table register */
  33. static int mv88e6xxx_g2_device_mapping_write(struct mv88e6xxx_chip *chip,
  34. int target, int port)
  35. {
  36. u16 val = (target << 8) | (port & 0xf);
  37. return mv88e6xxx_g2_update(chip, GLOBAL2_DEVICE_MAPPING, val);
  38. }
  39. static int mv88e6xxx_g2_set_device_mapping(struct mv88e6xxx_chip *chip)
  40. {
  41. int target, port;
  42. int err;
  43. /* Initialize the routing port to the 32 possible target devices */
  44. for (target = 0; target < 32; ++target) {
  45. port = 0xf;
  46. if (target < DSA_MAX_SWITCHES) {
  47. port = chip->ds->rtable[target];
  48. if (port == DSA_RTABLE_NONE)
  49. port = 0xf;
  50. }
  51. err = mv88e6xxx_g2_device_mapping_write(chip, target, port);
  52. if (err)
  53. break;
  54. }
  55. return err;
  56. }
  57. /* Offset 0x07: Trunk Mask Table register */
  58. static int mv88e6xxx_g2_trunk_mask_write(struct mv88e6xxx_chip *chip, int num,
  59. bool hask, u16 mask)
  60. {
  61. const u16 port_mask = BIT(mv88e6xxx_num_ports(chip)) - 1;
  62. u16 val = (num << 12) | (mask & port_mask);
  63. if (hask)
  64. val |= GLOBAL2_TRUNK_MASK_HASK;
  65. return mv88e6xxx_g2_update(chip, GLOBAL2_TRUNK_MASK, val);
  66. }
  67. /* Offset 0x08: Trunk Mapping Table register */
  68. static int mv88e6xxx_g2_trunk_mapping_write(struct mv88e6xxx_chip *chip, int id,
  69. u16 map)
  70. {
  71. const u16 port_mask = BIT(mv88e6xxx_num_ports(chip)) - 1;
  72. u16 val = (id << 11) | (map & port_mask);
  73. return mv88e6xxx_g2_update(chip, GLOBAL2_TRUNK_MAPPING, val);
  74. }
  75. static int mv88e6xxx_g2_clear_trunk(struct mv88e6xxx_chip *chip)
  76. {
  77. const u16 port_mask = BIT(mv88e6xxx_num_ports(chip)) - 1;
  78. int i, err;
  79. /* Clear all eight possible Trunk Mask vectors */
  80. for (i = 0; i < 8; ++i) {
  81. err = mv88e6xxx_g2_trunk_mask_write(chip, i, false, port_mask);
  82. if (err)
  83. return err;
  84. }
  85. /* Clear all sixteen possible Trunk ID routing vectors */
  86. for (i = 0; i < 16; ++i) {
  87. err = mv88e6xxx_g2_trunk_mapping_write(chip, i, 0);
  88. if (err)
  89. return err;
  90. }
  91. return 0;
  92. }
  93. /* Offset 0x09: Ingress Rate Command register
  94. * Offset 0x0A: Ingress Rate Data register
  95. */
  96. static int mv88e6xxx_g2_clear_irl(struct mv88e6xxx_chip *chip)
  97. {
  98. int port, err;
  99. /* Init all Ingress Rate Limit resources of all ports */
  100. for (port = 0; port < mv88e6xxx_num_ports(chip); ++port) {
  101. /* XXX newer chips (like 88E6390) have different 2-bit ops */
  102. err = mv88e6xxx_g2_write(chip, GLOBAL2_IRL_CMD,
  103. GLOBAL2_IRL_CMD_OP_INIT_ALL |
  104. (port << 8));
  105. if (err)
  106. break;
  107. /* Wait for the operation to complete */
  108. err = mv88e6xxx_g2_wait(chip, GLOBAL2_IRL_CMD,
  109. GLOBAL2_IRL_CMD_BUSY);
  110. if (err)
  111. break;
  112. }
  113. return err;
  114. }
  115. /* Offset 0x0D: Switch MAC/WoL/WoF register */
  116. static int mv88e6xxx_g2_switch_mac_write(struct mv88e6xxx_chip *chip,
  117. unsigned int pointer, u8 data)
  118. {
  119. u16 val = (pointer << 8) | data;
  120. return mv88e6xxx_g2_update(chip, GLOBAL2_SWITCH_MAC, val);
  121. }
  122. int mv88e6xxx_g2_set_switch_mac(struct mv88e6xxx_chip *chip, u8 *addr)
  123. {
  124. int i, err;
  125. for (i = 0; i < 6; i++) {
  126. err = mv88e6xxx_g2_switch_mac_write(chip, i, addr[i]);
  127. if (err)
  128. break;
  129. }
  130. return err;
  131. }
  132. /* Offset 0x0F: Priority Override Table */
  133. static int mv88e6xxx_g2_pot_write(struct mv88e6xxx_chip *chip, int pointer,
  134. u8 data)
  135. {
  136. u16 val = (pointer << 8) | (data & 0x7);
  137. return mv88e6xxx_g2_update(chip, GLOBAL2_PRIO_OVERRIDE, val);
  138. }
  139. static int mv88e6xxx_g2_clear_pot(struct mv88e6xxx_chip *chip)
  140. {
  141. int i, err;
  142. /* Clear all sixteen possible Priority Override entries */
  143. for (i = 0; i < 16; i++) {
  144. err = mv88e6xxx_g2_pot_write(chip, i, 0);
  145. if (err)
  146. break;
  147. }
  148. return err;
  149. }
  150. /* Offset 0x14: EEPROM Command
  151. * Offset 0x15: EEPROM Data
  152. */
  153. static int mv88e6xxx_g2_eeprom_wait(struct mv88e6xxx_chip *chip)
  154. {
  155. return mv88e6xxx_g2_wait(chip, GLOBAL2_EEPROM_CMD,
  156. GLOBAL2_EEPROM_CMD_BUSY |
  157. GLOBAL2_EEPROM_CMD_RUNNING);
  158. }
  159. static int mv88e6xxx_g2_eeprom_cmd(struct mv88e6xxx_chip *chip, u16 cmd)
  160. {
  161. int err;
  162. err = mv88e6xxx_g2_write(chip, GLOBAL2_EEPROM_CMD, cmd);
  163. if (err)
  164. return err;
  165. return mv88e6xxx_g2_eeprom_wait(chip);
  166. }
  167. static int mv88e6xxx_g2_eeprom_read16(struct mv88e6xxx_chip *chip,
  168. u8 addr, u16 *data)
  169. {
  170. u16 cmd = GLOBAL2_EEPROM_CMD_OP_READ | addr;
  171. int err;
  172. err = mv88e6xxx_g2_eeprom_wait(chip);
  173. if (err)
  174. return err;
  175. err = mv88e6xxx_g2_eeprom_cmd(chip, cmd);
  176. if (err)
  177. return err;
  178. return mv88e6xxx_g2_read(chip, GLOBAL2_EEPROM_DATA, data);
  179. }
  180. static int mv88e6xxx_g2_eeprom_write16(struct mv88e6xxx_chip *chip,
  181. u8 addr, u16 data)
  182. {
  183. u16 cmd = GLOBAL2_EEPROM_CMD_OP_WRITE | addr;
  184. int err;
  185. err = mv88e6xxx_g2_eeprom_wait(chip);
  186. if (err)
  187. return err;
  188. err = mv88e6xxx_g2_write(chip, GLOBAL2_EEPROM_DATA, data);
  189. if (err)
  190. return err;
  191. return mv88e6xxx_g2_eeprom_cmd(chip, cmd);
  192. }
  193. int mv88e6xxx_g2_get_eeprom16(struct mv88e6xxx_chip *chip,
  194. struct ethtool_eeprom *eeprom, u8 *data)
  195. {
  196. unsigned int offset = eeprom->offset;
  197. unsigned int len = eeprom->len;
  198. u16 val;
  199. int err;
  200. eeprom->len = 0;
  201. if (offset & 1) {
  202. err = mv88e6xxx_g2_eeprom_read16(chip, offset >> 1, &val);
  203. if (err)
  204. return err;
  205. *data++ = (val >> 8) & 0xff;
  206. offset++;
  207. len--;
  208. eeprom->len++;
  209. }
  210. while (len >= 2) {
  211. err = mv88e6xxx_g2_eeprom_read16(chip, offset >> 1, &val);
  212. if (err)
  213. return err;
  214. *data++ = val & 0xff;
  215. *data++ = (val >> 8) & 0xff;
  216. offset += 2;
  217. len -= 2;
  218. eeprom->len += 2;
  219. }
  220. if (len) {
  221. err = mv88e6xxx_g2_eeprom_read16(chip, offset >> 1, &val);
  222. if (err)
  223. return err;
  224. *data++ = val & 0xff;
  225. offset++;
  226. len--;
  227. eeprom->len++;
  228. }
  229. return 0;
  230. }
  231. int mv88e6xxx_g2_set_eeprom16(struct mv88e6xxx_chip *chip,
  232. struct ethtool_eeprom *eeprom, u8 *data)
  233. {
  234. unsigned int offset = eeprom->offset;
  235. unsigned int len = eeprom->len;
  236. u16 val;
  237. int err;
  238. /* Ensure the RO WriteEn bit is set */
  239. err = mv88e6xxx_g2_read(chip, GLOBAL2_EEPROM_CMD, &val);
  240. if (err)
  241. return err;
  242. if (!(val & GLOBAL2_EEPROM_CMD_WRITE_EN))
  243. return -EROFS;
  244. eeprom->len = 0;
  245. if (offset & 1) {
  246. err = mv88e6xxx_g2_eeprom_read16(chip, offset >> 1, &val);
  247. if (err)
  248. return err;
  249. val = (*data++ << 8) | (val & 0xff);
  250. err = mv88e6xxx_g2_eeprom_write16(chip, offset >> 1, val);
  251. if (err)
  252. return err;
  253. offset++;
  254. len--;
  255. eeprom->len++;
  256. }
  257. while (len >= 2) {
  258. val = *data++;
  259. val |= *data++ << 8;
  260. err = mv88e6xxx_g2_eeprom_write16(chip, offset >> 1, val);
  261. if (err)
  262. return err;
  263. offset += 2;
  264. len -= 2;
  265. eeprom->len += 2;
  266. }
  267. if (len) {
  268. err = mv88e6xxx_g2_eeprom_read16(chip, offset >> 1, &val);
  269. if (err)
  270. return err;
  271. val = (val & 0xff00) | *data++;
  272. err = mv88e6xxx_g2_eeprom_write16(chip, offset >> 1, val);
  273. if (err)
  274. return err;
  275. offset++;
  276. len--;
  277. eeprom->len++;
  278. }
  279. return 0;
  280. }
  281. /* Offset 0x18: SMI PHY Command Register
  282. * Offset 0x19: SMI PHY Data Register
  283. */
  284. static int mv88e6xxx_g2_smi_phy_wait(struct mv88e6xxx_chip *chip)
  285. {
  286. return mv88e6xxx_g2_wait(chip, GLOBAL2_SMI_PHY_CMD,
  287. GLOBAL2_SMI_PHY_CMD_BUSY);
  288. }
  289. static int mv88e6xxx_g2_smi_phy_cmd(struct mv88e6xxx_chip *chip, u16 cmd)
  290. {
  291. int err;
  292. err = mv88e6xxx_g2_write(chip, GLOBAL2_SMI_PHY_CMD, cmd);
  293. if (err)
  294. return err;
  295. return mv88e6xxx_g2_smi_phy_wait(chip);
  296. }
  297. int mv88e6xxx_g2_smi_phy_read(struct mv88e6xxx_chip *chip, int addr, int reg,
  298. u16 *val)
  299. {
  300. u16 cmd = GLOBAL2_SMI_PHY_CMD_OP_22_READ_DATA | (addr << 5) | reg;
  301. int err;
  302. err = mv88e6xxx_g2_smi_phy_wait(chip);
  303. if (err)
  304. return err;
  305. err = mv88e6xxx_g2_smi_phy_cmd(chip, cmd);
  306. if (err)
  307. return err;
  308. return mv88e6xxx_g2_read(chip, GLOBAL2_SMI_PHY_DATA, val);
  309. }
  310. int mv88e6xxx_g2_smi_phy_write(struct mv88e6xxx_chip *chip, int addr, int reg,
  311. u16 val)
  312. {
  313. u16 cmd = GLOBAL2_SMI_PHY_CMD_OP_22_WRITE_DATA | (addr << 5) | reg;
  314. int err;
  315. err = mv88e6xxx_g2_smi_phy_wait(chip);
  316. if (err)
  317. return err;
  318. err = mv88e6xxx_g2_write(chip, GLOBAL2_SMI_PHY_DATA, val);
  319. if (err)
  320. return err;
  321. return mv88e6xxx_g2_smi_phy_cmd(chip, cmd);
  322. }
  323. int mv88e6xxx_g2_setup(struct mv88e6xxx_chip *chip)
  324. {
  325. u16 reg;
  326. int err;
  327. if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_MGMT_EN_2X)) {
  328. /* Consider the frames with reserved multicast destination
  329. * addresses matching 01:80:c2:00:00:2x as MGMT.
  330. */
  331. err = mv88e6xxx_g2_write(chip, GLOBAL2_MGMT_EN_2X, 0xffff);
  332. if (err)
  333. return err;
  334. }
  335. if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_MGMT_EN_0X)) {
  336. /* Consider the frames with reserved multicast destination
  337. * addresses matching 01:80:c2:00:00:0x as MGMT.
  338. */
  339. err = mv88e6xxx_g2_write(chip, GLOBAL2_MGMT_EN_0X, 0xffff);
  340. if (err)
  341. return err;
  342. }
  343. /* Ignore removed tag data on doubly tagged packets, disable
  344. * flow control messages, force flow control priority to the
  345. * highest, and send all special multicast frames to the CPU
  346. * port at the highest priority.
  347. */
  348. reg = GLOBAL2_SWITCH_MGMT_FORCE_FLOW_CTRL_PRI | (0x7 << 4);
  349. if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_MGMT_EN_0X) ||
  350. mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_MGMT_EN_2X))
  351. reg |= GLOBAL2_SWITCH_MGMT_RSVD2CPU | 0x7;
  352. err = mv88e6xxx_g2_write(chip, GLOBAL2_SWITCH_MGMT, reg);
  353. if (err)
  354. return err;
  355. /* Program the DSA routing table. */
  356. err = mv88e6xxx_g2_set_device_mapping(chip);
  357. if (err)
  358. return err;
  359. /* Clear all trunk masks and mapping. */
  360. err = mv88e6xxx_g2_clear_trunk(chip);
  361. if (err)
  362. return err;
  363. if (mv88e6xxx_has(chip, MV88E6XXX_FLAGS_IRL)) {
  364. /* Disable ingress rate limiting by resetting all per port
  365. * ingress rate limit resources to their initial state.
  366. */
  367. err = mv88e6xxx_g2_clear_irl(chip);
  368. if (err)
  369. return err;
  370. }
  371. if (mv88e6xxx_has(chip, MV88E6XXX_FLAGS_PVT)) {
  372. /* Initialize Cross-chip Port VLAN Table to reset defaults */
  373. err = mv88e6xxx_g2_write(chip, GLOBAL2_PVT_ADDR,
  374. GLOBAL2_PVT_ADDR_OP_INIT_ONES);
  375. if (err)
  376. return err;
  377. }
  378. if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_POT)) {
  379. /* Clear the priority override table. */
  380. err = mv88e6xxx_g2_clear_pot(chip);
  381. if (err)
  382. return err;
  383. }
  384. return 0;
  385. }