port.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997
  1. /*
  2. * Marvell 88E6xxx Switch Port 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 <linux/if_bridge.h>
  16. #include <linux/phy.h>
  17. #include <linux/phylink.h>
  18. #include "chip.h"
  19. #include "port.h"
  20. int mv88e6xxx_port_read(struct mv88e6xxx_chip *chip, int port, int reg,
  21. u16 *val)
  22. {
  23. int addr = chip->info->port_base_addr + port;
  24. return mv88e6xxx_read(chip, addr, reg, val);
  25. }
  26. int mv88e6xxx_port_write(struct mv88e6xxx_chip *chip, int port, int reg,
  27. u16 val)
  28. {
  29. int addr = chip->info->port_base_addr + port;
  30. return mv88e6xxx_write(chip, addr, reg, val);
  31. }
  32. /* Offset 0x01: MAC (or PCS or Physical) Control Register
  33. *
  34. * Link, Duplex and Flow Control have one force bit, one value bit.
  35. *
  36. * For port's MAC speed, ForceSpd (or SpdValue) bits 1:0 program the value.
  37. * Alternative values require the 200BASE (or AltSpeed) bit 12 set.
  38. * Newer chips need a ForcedSpd bit 13 set to consider the value.
  39. */
  40. static int mv88e6xxx_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port,
  41. phy_interface_t mode)
  42. {
  43. u16 reg;
  44. int err;
  45. err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_MAC_CTL, &reg);
  46. if (err)
  47. return err;
  48. reg &= ~(MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_RXCLK |
  49. MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_TXCLK);
  50. switch (mode) {
  51. case PHY_INTERFACE_MODE_RGMII_RXID:
  52. reg |= MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_RXCLK;
  53. break;
  54. case PHY_INTERFACE_MODE_RGMII_TXID:
  55. reg |= MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_TXCLK;
  56. break;
  57. case PHY_INTERFACE_MODE_RGMII_ID:
  58. reg |= MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_RXCLK |
  59. MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_TXCLK;
  60. break;
  61. case PHY_INTERFACE_MODE_RGMII:
  62. break;
  63. default:
  64. return 0;
  65. }
  66. err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_MAC_CTL, reg);
  67. if (err)
  68. return err;
  69. dev_dbg(chip->dev, "p%d: delay RXCLK %s, TXCLK %s\n", port,
  70. reg & MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_RXCLK ? "yes" : "no",
  71. reg & MV88E6XXX_PORT_MAC_CTL_RGMII_DELAY_TXCLK ? "yes" : "no");
  72. return 0;
  73. }
  74. int mv88e6352_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port,
  75. phy_interface_t mode)
  76. {
  77. if (port < 5)
  78. return -EOPNOTSUPP;
  79. return mv88e6xxx_port_set_rgmii_delay(chip, port, mode);
  80. }
  81. int mv88e6390_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port,
  82. phy_interface_t mode)
  83. {
  84. if (port != 0)
  85. return -EOPNOTSUPP;
  86. return mv88e6xxx_port_set_rgmii_delay(chip, port, mode);
  87. }
  88. int mv88e6xxx_port_set_link(struct mv88e6xxx_chip *chip, int port, int link)
  89. {
  90. u16 reg;
  91. int err;
  92. err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_MAC_CTL, &reg);
  93. if (err)
  94. return err;
  95. reg &= ~(MV88E6XXX_PORT_MAC_CTL_FORCE_LINK |
  96. MV88E6XXX_PORT_MAC_CTL_LINK_UP);
  97. switch (link) {
  98. case LINK_FORCED_DOWN:
  99. reg |= MV88E6XXX_PORT_MAC_CTL_FORCE_LINK;
  100. break;
  101. case LINK_FORCED_UP:
  102. reg |= MV88E6XXX_PORT_MAC_CTL_FORCE_LINK |
  103. MV88E6XXX_PORT_MAC_CTL_LINK_UP;
  104. break;
  105. case LINK_UNFORCED:
  106. /* normal link detection */
  107. break;
  108. default:
  109. return -EINVAL;
  110. }
  111. err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_MAC_CTL, reg);
  112. if (err)
  113. return err;
  114. dev_dbg(chip->dev, "p%d: %s link %s\n", port,
  115. reg & MV88E6XXX_PORT_MAC_CTL_FORCE_LINK ? "Force" : "Unforce",
  116. reg & MV88E6XXX_PORT_MAC_CTL_LINK_UP ? "up" : "down");
  117. return 0;
  118. }
  119. int mv88e6xxx_port_set_duplex(struct mv88e6xxx_chip *chip, int port, int dup)
  120. {
  121. u16 reg;
  122. int err;
  123. err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_MAC_CTL, &reg);
  124. if (err)
  125. return err;
  126. reg &= ~(MV88E6XXX_PORT_MAC_CTL_FORCE_DUPLEX |
  127. MV88E6XXX_PORT_MAC_CTL_DUPLEX_FULL);
  128. switch (dup) {
  129. case DUPLEX_HALF:
  130. reg |= MV88E6XXX_PORT_MAC_CTL_FORCE_DUPLEX;
  131. break;
  132. case DUPLEX_FULL:
  133. reg |= MV88E6XXX_PORT_MAC_CTL_FORCE_DUPLEX |
  134. MV88E6XXX_PORT_MAC_CTL_DUPLEX_FULL;
  135. break;
  136. case DUPLEX_UNFORCED:
  137. /* normal duplex detection */
  138. break;
  139. default:
  140. return -EINVAL;
  141. }
  142. err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_MAC_CTL, reg);
  143. if (err)
  144. return err;
  145. dev_dbg(chip->dev, "p%d: %s %s duplex\n", port,
  146. reg & MV88E6XXX_PORT_MAC_CTL_FORCE_DUPLEX ? "Force" : "Unforce",
  147. reg & MV88E6XXX_PORT_MAC_CTL_DUPLEX_FULL ? "full" : "half");
  148. return 0;
  149. }
  150. static int mv88e6xxx_port_set_speed(struct mv88e6xxx_chip *chip, int port,
  151. int speed, bool alt_bit, bool force_bit)
  152. {
  153. u16 reg, ctrl;
  154. int err;
  155. switch (speed) {
  156. case 10:
  157. ctrl = MV88E6XXX_PORT_MAC_CTL_SPEED_10;
  158. break;
  159. case 100:
  160. ctrl = MV88E6XXX_PORT_MAC_CTL_SPEED_100;
  161. break;
  162. case 200:
  163. if (alt_bit)
  164. ctrl = MV88E6XXX_PORT_MAC_CTL_SPEED_100 |
  165. MV88E6390_PORT_MAC_CTL_ALTSPEED;
  166. else
  167. ctrl = MV88E6065_PORT_MAC_CTL_SPEED_200;
  168. break;
  169. case 1000:
  170. ctrl = MV88E6XXX_PORT_MAC_CTL_SPEED_1000;
  171. break;
  172. case 2500:
  173. ctrl = MV88E6390_PORT_MAC_CTL_SPEED_10000 |
  174. MV88E6390_PORT_MAC_CTL_ALTSPEED;
  175. break;
  176. case 10000:
  177. /* all bits set, fall through... */
  178. case SPEED_UNFORCED:
  179. ctrl = MV88E6XXX_PORT_MAC_CTL_SPEED_UNFORCED;
  180. break;
  181. default:
  182. return -EOPNOTSUPP;
  183. }
  184. err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_MAC_CTL, &reg);
  185. if (err)
  186. return err;
  187. reg &= ~MV88E6XXX_PORT_MAC_CTL_SPEED_MASK;
  188. if (alt_bit)
  189. reg &= ~MV88E6390_PORT_MAC_CTL_ALTSPEED;
  190. if (force_bit) {
  191. reg &= ~MV88E6390_PORT_MAC_CTL_FORCE_SPEED;
  192. if (speed != SPEED_UNFORCED)
  193. ctrl |= MV88E6390_PORT_MAC_CTL_FORCE_SPEED;
  194. }
  195. reg |= ctrl;
  196. err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_MAC_CTL, reg);
  197. if (err)
  198. return err;
  199. if (speed)
  200. dev_dbg(chip->dev, "p%d: Speed set to %d Mbps\n", port, speed);
  201. else
  202. dev_dbg(chip->dev, "p%d: Speed unforced\n", port);
  203. return 0;
  204. }
  205. /* Support 10, 100, 200 Mbps (e.g. 88E6065 family) */
  206. int mv88e6065_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
  207. {
  208. if (speed == SPEED_MAX)
  209. speed = 200;
  210. if (speed > 200)
  211. return -EOPNOTSUPP;
  212. /* Setting 200 Mbps on port 0 to 3 selects 100 Mbps */
  213. return mv88e6xxx_port_set_speed(chip, port, speed, false, false);
  214. }
  215. /* Support 10, 100, 1000 Mbps (e.g. 88E6185 family) */
  216. int mv88e6185_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
  217. {
  218. if (speed == SPEED_MAX)
  219. speed = 1000;
  220. if (speed == 200 || speed > 1000)
  221. return -EOPNOTSUPP;
  222. return mv88e6xxx_port_set_speed(chip, port, speed, false, false);
  223. }
  224. /* Support 10, 100, 200, 1000 Mbps (e.g. 88E6352 family) */
  225. int mv88e6352_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
  226. {
  227. if (speed == SPEED_MAX)
  228. speed = 1000;
  229. if (speed > 1000)
  230. return -EOPNOTSUPP;
  231. if (speed == 200 && port < 5)
  232. return -EOPNOTSUPP;
  233. return mv88e6xxx_port_set_speed(chip, port, speed, true, false);
  234. }
  235. /* Support 10, 100, 200, 1000, 2500 Mbps (e.g. 88E6390) */
  236. int mv88e6390_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
  237. {
  238. if (speed == SPEED_MAX)
  239. speed = port < 9 ? 1000 : 2500;
  240. if (speed > 2500)
  241. return -EOPNOTSUPP;
  242. if (speed == 200 && port != 0)
  243. return -EOPNOTSUPP;
  244. if (speed == 2500 && port < 9)
  245. return -EOPNOTSUPP;
  246. return mv88e6xxx_port_set_speed(chip, port, speed, true, true);
  247. }
  248. /* Support 10, 100, 200, 1000, 2500, 10000 Mbps (e.g. 88E6190X) */
  249. int mv88e6390x_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
  250. {
  251. if (speed == SPEED_MAX)
  252. speed = port < 9 ? 1000 : 10000;
  253. if (speed == 200 && port != 0)
  254. return -EOPNOTSUPP;
  255. if (speed >= 2500 && port < 9)
  256. return -EOPNOTSUPP;
  257. return mv88e6xxx_port_set_speed(chip, port, speed, true, true);
  258. }
  259. int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
  260. phy_interface_t mode)
  261. {
  262. u16 reg;
  263. u16 cmode;
  264. int err;
  265. if (mode == PHY_INTERFACE_MODE_NA)
  266. return 0;
  267. if (port != 9 && port != 10)
  268. return -EOPNOTSUPP;
  269. switch (mode) {
  270. case PHY_INTERFACE_MODE_1000BASEX:
  271. cmode = MV88E6XXX_PORT_STS_CMODE_1000BASE_X;
  272. break;
  273. case PHY_INTERFACE_MODE_SGMII:
  274. cmode = MV88E6XXX_PORT_STS_CMODE_SGMII;
  275. break;
  276. case PHY_INTERFACE_MODE_2500BASEX:
  277. cmode = MV88E6XXX_PORT_STS_CMODE_2500BASEX;
  278. break;
  279. case PHY_INTERFACE_MODE_XGMII:
  280. case PHY_INTERFACE_MODE_XAUI:
  281. cmode = MV88E6XXX_PORT_STS_CMODE_XAUI;
  282. break;
  283. case PHY_INTERFACE_MODE_RXAUI:
  284. cmode = MV88E6XXX_PORT_STS_CMODE_RXAUI;
  285. break;
  286. default:
  287. cmode = 0;
  288. }
  289. if (cmode) {
  290. err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, &reg);
  291. if (err)
  292. return err;
  293. reg &= ~MV88E6XXX_PORT_STS_CMODE_MASK;
  294. reg |= cmode;
  295. err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_STS, reg);
  296. if (err)
  297. return err;
  298. }
  299. return 0;
  300. }
  301. int mv88e6xxx_port_get_cmode(struct mv88e6xxx_chip *chip, int port, u8 *cmode)
  302. {
  303. int err;
  304. u16 reg;
  305. err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, &reg);
  306. if (err)
  307. return err;
  308. *cmode = reg & MV88E6XXX_PORT_STS_CMODE_MASK;
  309. return 0;
  310. }
  311. int mv88e6xxx_port_link_state(struct mv88e6xxx_chip *chip, int port,
  312. struct phylink_link_state *state)
  313. {
  314. int err;
  315. u16 reg;
  316. err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, &reg);
  317. if (err)
  318. return err;
  319. switch (reg & MV88E6XXX_PORT_STS_SPEED_MASK) {
  320. case MV88E6XXX_PORT_STS_SPEED_10:
  321. state->speed = SPEED_10;
  322. break;
  323. case MV88E6XXX_PORT_STS_SPEED_100:
  324. state->speed = SPEED_100;
  325. break;
  326. case MV88E6XXX_PORT_STS_SPEED_1000:
  327. state->speed = SPEED_1000;
  328. break;
  329. case MV88E6XXX_PORT_STS_SPEED_10000:
  330. if ((reg &MV88E6XXX_PORT_STS_CMODE_MASK) ==
  331. MV88E6XXX_PORT_STS_CMODE_2500BASEX)
  332. state->speed = SPEED_2500;
  333. else
  334. state->speed = SPEED_10000;
  335. break;
  336. }
  337. state->duplex = reg & MV88E6XXX_PORT_STS_DUPLEX ?
  338. DUPLEX_FULL : DUPLEX_HALF;
  339. state->link = !!(reg & MV88E6XXX_PORT_STS_LINK);
  340. state->an_enabled = 1;
  341. state->an_complete = state->link;
  342. return 0;
  343. }
  344. /* Offset 0x02: Jamming Control
  345. *
  346. * Do not limit the period of time that this port can be paused for by
  347. * the remote end or the period of time that this port can pause the
  348. * remote end.
  349. */
  350. int mv88e6097_port_pause_limit(struct mv88e6xxx_chip *chip, int port, u8 in,
  351. u8 out)
  352. {
  353. return mv88e6xxx_port_write(chip, port, MV88E6097_PORT_JAM_CTL,
  354. out << 8 | in);
  355. }
  356. int mv88e6390_port_pause_limit(struct mv88e6xxx_chip *chip, int port, u8 in,
  357. u8 out)
  358. {
  359. int err;
  360. err = mv88e6xxx_port_write(chip, port, MV88E6390_PORT_FLOW_CTL,
  361. MV88E6390_PORT_FLOW_CTL_UPDATE |
  362. MV88E6390_PORT_FLOW_CTL_LIMIT_IN | in);
  363. if (err)
  364. return err;
  365. return mv88e6xxx_port_write(chip, port, MV88E6390_PORT_FLOW_CTL,
  366. MV88E6390_PORT_FLOW_CTL_UPDATE |
  367. MV88E6390_PORT_FLOW_CTL_LIMIT_OUT | out);
  368. }
  369. /* Offset 0x04: Port Control Register */
  370. static const char * const mv88e6xxx_port_state_names[] = {
  371. [MV88E6XXX_PORT_CTL0_STATE_DISABLED] = "Disabled",
  372. [MV88E6XXX_PORT_CTL0_STATE_BLOCKING] = "Blocking/Listening",
  373. [MV88E6XXX_PORT_CTL0_STATE_LEARNING] = "Learning",
  374. [MV88E6XXX_PORT_CTL0_STATE_FORWARDING] = "Forwarding",
  375. };
  376. int mv88e6xxx_port_set_state(struct mv88e6xxx_chip *chip, int port, u8 state)
  377. {
  378. u16 reg;
  379. int err;
  380. err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL0, &reg);
  381. if (err)
  382. return err;
  383. reg &= ~MV88E6XXX_PORT_CTL0_STATE_MASK;
  384. switch (state) {
  385. case BR_STATE_DISABLED:
  386. state = MV88E6XXX_PORT_CTL0_STATE_DISABLED;
  387. break;
  388. case BR_STATE_BLOCKING:
  389. case BR_STATE_LISTENING:
  390. state = MV88E6XXX_PORT_CTL0_STATE_BLOCKING;
  391. break;
  392. case BR_STATE_LEARNING:
  393. state = MV88E6XXX_PORT_CTL0_STATE_LEARNING;
  394. break;
  395. case BR_STATE_FORWARDING:
  396. state = MV88E6XXX_PORT_CTL0_STATE_FORWARDING;
  397. break;
  398. default:
  399. return -EINVAL;
  400. }
  401. reg |= state;
  402. err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg);
  403. if (err)
  404. return err;
  405. dev_dbg(chip->dev, "p%d: PortState set to %s\n", port,
  406. mv88e6xxx_port_state_names[state]);
  407. return 0;
  408. }
  409. int mv88e6xxx_port_set_egress_mode(struct mv88e6xxx_chip *chip, int port,
  410. enum mv88e6xxx_egress_mode mode)
  411. {
  412. int err;
  413. u16 reg;
  414. err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL0, &reg);
  415. if (err)
  416. return err;
  417. reg &= ~MV88E6XXX_PORT_CTL0_EGRESS_MODE_MASK;
  418. switch (mode) {
  419. case MV88E6XXX_EGRESS_MODE_UNMODIFIED:
  420. reg |= MV88E6XXX_PORT_CTL0_EGRESS_MODE_UNMODIFIED;
  421. break;
  422. case MV88E6XXX_EGRESS_MODE_UNTAGGED:
  423. reg |= MV88E6XXX_PORT_CTL0_EGRESS_MODE_UNTAGGED;
  424. break;
  425. case MV88E6XXX_EGRESS_MODE_TAGGED:
  426. reg |= MV88E6XXX_PORT_CTL0_EGRESS_MODE_TAGGED;
  427. break;
  428. case MV88E6XXX_EGRESS_MODE_ETHERTYPE:
  429. reg |= MV88E6XXX_PORT_CTL0_EGRESS_MODE_ETHER_TYPE_DSA;
  430. break;
  431. default:
  432. return -EINVAL;
  433. }
  434. return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg);
  435. }
  436. int mv88e6085_port_set_frame_mode(struct mv88e6xxx_chip *chip, int port,
  437. enum mv88e6xxx_frame_mode mode)
  438. {
  439. int err;
  440. u16 reg;
  441. err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL0, &reg);
  442. if (err)
  443. return err;
  444. reg &= ~MV88E6XXX_PORT_CTL0_FRAME_MODE_MASK;
  445. switch (mode) {
  446. case MV88E6XXX_FRAME_MODE_NORMAL:
  447. reg |= MV88E6XXX_PORT_CTL0_FRAME_MODE_NORMAL;
  448. break;
  449. case MV88E6XXX_FRAME_MODE_DSA:
  450. reg |= MV88E6XXX_PORT_CTL0_FRAME_MODE_DSA;
  451. break;
  452. default:
  453. return -EINVAL;
  454. }
  455. return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg);
  456. }
  457. int mv88e6351_port_set_frame_mode(struct mv88e6xxx_chip *chip, int port,
  458. enum mv88e6xxx_frame_mode mode)
  459. {
  460. int err;
  461. u16 reg;
  462. err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL0, &reg);
  463. if (err)
  464. return err;
  465. reg &= ~MV88E6XXX_PORT_CTL0_FRAME_MODE_MASK;
  466. switch (mode) {
  467. case MV88E6XXX_FRAME_MODE_NORMAL:
  468. reg |= MV88E6XXX_PORT_CTL0_FRAME_MODE_NORMAL;
  469. break;
  470. case MV88E6XXX_FRAME_MODE_DSA:
  471. reg |= MV88E6XXX_PORT_CTL0_FRAME_MODE_DSA;
  472. break;
  473. case MV88E6XXX_FRAME_MODE_PROVIDER:
  474. reg |= MV88E6XXX_PORT_CTL0_FRAME_MODE_PROVIDER;
  475. break;
  476. case MV88E6XXX_FRAME_MODE_ETHERTYPE:
  477. reg |= MV88E6XXX_PORT_CTL0_FRAME_MODE_ETHER_TYPE_DSA;
  478. break;
  479. default:
  480. return -EINVAL;
  481. }
  482. return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg);
  483. }
  484. static int mv88e6185_port_set_forward_unknown(struct mv88e6xxx_chip *chip,
  485. int port, bool unicast)
  486. {
  487. int err;
  488. u16 reg;
  489. err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL0, &reg);
  490. if (err)
  491. return err;
  492. if (unicast)
  493. reg |= MV88E6185_PORT_CTL0_FORWARD_UNKNOWN;
  494. else
  495. reg &= ~MV88E6185_PORT_CTL0_FORWARD_UNKNOWN;
  496. return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg);
  497. }
  498. int mv88e6352_port_set_egress_floods(struct mv88e6xxx_chip *chip, int port,
  499. bool unicast, bool multicast)
  500. {
  501. int err;
  502. u16 reg;
  503. err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL0, &reg);
  504. if (err)
  505. return err;
  506. reg &= ~MV88E6352_PORT_CTL0_EGRESS_FLOODS_MASK;
  507. if (unicast && multicast)
  508. reg |= MV88E6352_PORT_CTL0_EGRESS_FLOODS_ALL_UNKNOWN_DA;
  509. else if (unicast)
  510. reg |= MV88E6352_PORT_CTL0_EGRESS_FLOODS_NO_UNKNOWN_MC_DA;
  511. else if (multicast)
  512. reg |= MV88E6352_PORT_CTL0_EGRESS_FLOODS_NO_UNKNOWN_UC_DA;
  513. else
  514. reg |= MV88E6352_PORT_CTL0_EGRESS_FLOODS_NO_UNKNOWN_DA;
  515. return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg);
  516. }
  517. /* Offset 0x05: Port Control 1 */
  518. int mv88e6xxx_port_set_message_port(struct mv88e6xxx_chip *chip, int port,
  519. bool message_port)
  520. {
  521. u16 val;
  522. int err;
  523. err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL1, &val);
  524. if (err)
  525. return err;
  526. if (message_port)
  527. val |= MV88E6XXX_PORT_CTL1_MESSAGE_PORT;
  528. else
  529. val &= ~MV88E6XXX_PORT_CTL1_MESSAGE_PORT;
  530. return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL1, val);
  531. }
  532. /* Offset 0x06: Port Based VLAN Map */
  533. int mv88e6xxx_port_set_vlan_map(struct mv88e6xxx_chip *chip, int port, u16 map)
  534. {
  535. const u16 mask = mv88e6xxx_port_mask(chip);
  536. u16 reg;
  537. int err;
  538. err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_BASE_VLAN, &reg);
  539. if (err)
  540. return err;
  541. reg &= ~mask;
  542. reg |= map & mask;
  543. err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_BASE_VLAN, reg);
  544. if (err)
  545. return err;
  546. dev_dbg(chip->dev, "p%d: VLANTable set to %.3x\n", port, map);
  547. return 0;
  548. }
  549. int mv88e6xxx_port_get_fid(struct mv88e6xxx_chip *chip, int port, u16 *fid)
  550. {
  551. const u16 upper_mask = (mv88e6xxx_num_databases(chip) - 1) >> 4;
  552. u16 reg;
  553. int err;
  554. /* Port's default FID lower 4 bits are located in reg 0x06, offset 12 */
  555. err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_BASE_VLAN, &reg);
  556. if (err)
  557. return err;
  558. *fid = (reg & 0xf000) >> 12;
  559. /* Port's default FID upper bits are located in reg 0x05, offset 0 */
  560. if (upper_mask) {
  561. err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL1,
  562. &reg);
  563. if (err)
  564. return err;
  565. *fid |= (reg & upper_mask) << 4;
  566. }
  567. return 0;
  568. }
  569. int mv88e6xxx_port_set_fid(struct mv88e6xxx_chip *chip, int port, u16 fid)
  570. {
  571. const u16 upper_mask = (mv88e6xxx_num_databases(chip) - 1) >> 4;
  572. u16 reg;
  573. int err;
  574. if (fid >= mv88e6xxx_num_databases(chip))
  575. return -EINVAL;
  576. /* Port's default FID lower 4 bits are located in reg 0x06, offset 12 */
  577. err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_BASE_VLAN, &reg);
  578. if (err)
  579. return err;
  580. reg &= 0x0fff;
  581. reg |= (fid & 0x000f) << 12;
  582. err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_BASE_VLAN, reg);
  583. if (err)
  584. return err;
  585. /* Port's default FID upper bits are located in reg 0x05, offset 0 */
  586. if (upper_mask) {
  587. err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL1,
  588. &reg);
  589. if (err)
  590. return err;
  591. reg &= ~upper_mask;
  592. reg |= (fid >> 4) & upper_mask;
  593. err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL1,
  594. reg);
  595. if (err)
  596. return err;
  597. }
  598. dev_dbg(chip->dev, "p%d: FID set to %u\n", port, fid);
  599. return 0;
  600. }
  601. /* Offset 0x07: Default Port VLAN ID & Priority */
  602. int mv88e6xxx_port_get_pvid(struct mv88e6xxx_chip *chip, int port, u16 *pvid)
  603. {
  604. u16 reg;
  605. int err;
  606. err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_DEFAULT_VLAN,
  607. &reg);
  608. if (err)
  609. return err;
  610. *pvid = reg & MV88E6XXX_PORT_DEFAULT_VLAN_MASK;
  611. return 0;
  612. }
  613. int mv88e6xxx_port_set_pvid(struct mv88e6xxx_chip *chip, int port, u16 pvid)
  614. {
  615. u16 reg;
  616. int err;
  617. err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_DEFAULT_VLAN,
  618. &reg);
  619. if (err)
  620. return err;
  621. reg &= ~MV88E6XXX_PORT_DEFAULT_VLAN_MASK;
  622. reg |= pvid & MV88E6XXX_PORT_DEFAULT_VLAN_MASK;
  623. err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_DEFAULT_VLAN,
  624. reg);
  625. if (err)
  626. return err;
  627. dev_dbg(chip->dev, "p%d: DefaultVID set to %u\n", port, pvid);
  628. return 0;
  629. }
  630. /* Offset 0x08: Port Control 2 Register */
  631. static const char * const mv88e6xxx_port_8021q_mode_names[] = {
  632. [MV88E6XXX_PORT_CTL2_8021Q_MODE_DISABLED] = "Disabled",
  633. [MV88E6XXX_PORT_CTL2_8021Q_MODE_FALLBACK] = "Fallback",
  634. [MV88E6XXX_PORT_CTL2_8021Q_MODE_CHECK] = "Check",
  635. [MV88E6XXX_PORT_CTL2_8021Q_MODE_SECURE] = "Secure",
  636. };
  637. static int mv88e6185_port_set_default_forward(struct mv88e6xxx_chip *chip,
  638. int port, bool multicast)
  639. {
  640. int err;
  641. u16 reg;
  642. err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL2, &reg);
  643. if (err)
  644. return err;
  645. if (multicast)
  646. reg |= MV88E6XXX_PORT_CTL2_DEFAULT_FORWARD;
  647. else
  648. reg &= ~MV88E6XXX_PORT_CTL2_DEFAULT_FORWARD;
  649. return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL2, reg);
  650. }
  651. int mv88e6185_port_set_egress_floods(struct mv88e6xxx_chip *chip, int port,
  652. bool unicast, bool multicast)
  653. {
  654. int err;
  655. err = mv88e6185_port_set_forward_unknown(chip, port, unicast);
  656. if (err)
  657. return err;
  658. return mv88e6185_port_set_default_forward(chip, port, multicast);
  659. }
  660. int mv88e6095_port_set_upstream_port(struct mv88e6xxx_chip *chip, int port,
  661. int upstream_port)
  662. {
  663. int err;
  664. u16 reg;
  665. err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL2, &reg);
  666. if (err)
  667. return err;
  668. reg &= ~MV88E6095_PORT_CTL2_CPU_PORT_MASK;
  669. reg |= upstream_port;
  670. return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL2, reg);
  671. }
  672. int mv88e6xxx_port_set_8021q_mode(struct mv88e6xxx_chip *chip, int port,
  673. u16 mode)
  674. {
  675. u16 reg;
  676. int err;
  677. err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL2, &reg);
  678. if (err)
  679. return err;
  680. reg &= ~MV88E6XXX_PORT_CTL2_8021Q_MODE_MASK;
  681. reg |= mode & MV88E6XXX_PORT_CTL2_8021Q_MODE_MASK;
  682. err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL2, reg);
  683. if (err)
  684. return err;
  685. dev_dbg(chip->dev, "p%d: 802.1QMode set to %s\n", port,
  686. mv88e6xxx_port_8021q_mode_names[mode]);
  687. return 0;
  688. }
  689. int mv88e6xxx_port_set_map_da(struct mv88e6xxx_chip *chip, int port)
  690. {
  691. u16 reg;
  692. int err;
  693. err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL2, &reg);
  694. if (err)
  695. return err;
  696. reg |= MV88E6XXX_PORT_CTL2_MAP_DA;
  697. return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL2, reg);
  698. }
  699. int mv88e6165_port_set_jumbo_size(struct mv88e6xxx_chip *chip, int port,
  700. size_t size)
  701. {
  702. u16 reg;
  703. int err;
  704. err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL2, &reg);
  705. if (err)
  706. return err;
  707. reg &= ~MV88E6XXX_PORT_CTL2_JUMBO_MODE_MASK;
  708. if (size <= 1522)
  709. reg |= MV88E6XXX_PORT_CTL2_JUMBO_MODE_1522;
  710. else if (size <= 2048)
  711. reg |= MV88E6XXX_PORT_CTL2_JUMBO_MODE_2048;
  712. else if (size <= 10240)
  713. reg |= MV88E6XXX_PORT_CTL2_JUMBO_MODE_10240;
  714. else
  715. return -ERANGE;
  716. return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL2, reg);
  717. }
  718. /* Offset 0x09: Port Rate Control */
  719. int mv88e6095_port_egress_rate_limiting(struct mv88e6xxx_chip *chip, int port)
  720. {
  721. return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_EGRESS_RATE_CTL1,
  722. 0x0000);
  723. }
  724. int mv88e6097_port_egress_rate_limiting(struct mv88e6xxx_chip *chip, int port)
  725. {
  726. return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_EGRESS_RATE_CTL1,
  727. 0x0001);
  728. }
  729. /* Offset 0x0C: Port ATU Control */
  730. int mv88e6xxx_port_disable_learn_limit(struct mv88e6xxx_chip *chip, int port)
  731. {
  732. return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_ATU_CTL, 0);
  733. }
  734. /* Offset 0x0D: (Priority) Override Register */
  735. int mv88e6xxx_port_disable_pri_override(struct mv88e6xxx_chip *chip, int port)
  736. {
  737. return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_PRI_OVERRIDE, 0);
  738. }
  739. /* Offset 0x0f: Port Ether type */
  740. int mv88e6351_port_set_ether_type(struct mv88e6xxx_chip *chip, int port,
  741. u16 etype)
  742. {
  743. return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_ETH_TYPE, etype);
  744. }
  745. /* Offset 0x18: Port IEEE Priority Remapping Registers [0-3]
  746. * Offset 0x19: Port IEEE Priority Remapping Registers [4-7]
  747. */
  748. int mv88e6095_port_tag_remap(struct mv88e6xxx_chip *chip, int port)
  749. {
  750. int err;
  751. /* Use a direct priority mapping for all IEEE tagged frames */
  752. err = mv88e6xxx_port_write(chip, port,
  753. MV88E6095_PORT_IEEE_PRIO_REMAP_0123,
  754. 0x3210);
  755. if (err)
  756. return err;
  757. return mv88e6xxx_port_write(chip, port,
  758. MV88E6095_PORT_IEEE_PRIO_REMAP_4567,
  759. 0x7654);
  760. }
  761. static int mv88e6xxx_port_ieeepmt_write(struct mv88e6xxx_chip *chip,
  762. int port, u16 table, u8 ptr, u16 data)
  763. {
  764. u16 reg;
  765. reg = MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_UPDATE | table |
  766. (ptr << __bf_shf(MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_PTR_MASK)) |
  767. (data & MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_DATA_MASK);
  768. return mv88e6xxx_port_write(chip, port,
  769. MV88E6390_PORT_IEEE_PRIO_MAP_TABLE, reg);
  770. }
  771. int mv88e6390_port_tag_remap(struct mv88e6xxx_chip *chip, int port)
  772. {
  773. int err, i;
  774. u16 table;
  775. for (i = 0; i <= 7; i++) {
  776. table = MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_INGRESS_PCP;
  777. err = mv88e6xxx_port_ieeepmt_write(chip, port, table, i,
  778. (i | i << 4));
  779. if (err)
  780. return err;
  781. table = MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_EGRESS_GREEN_PCP;
  782. err = mv88e6xxx_port_ieeepmt_write(chip, port, table, i, i);
  783. if (err)
  784. return err;
  785. table = MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_EGRESS_YELLOW_PCP;
  786. err = mv88e6xxx_port_ieeepmt_write(chip, port, table, i, i);
  787. if (err)
  788. return err;
  789. table = MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_EGRESS_AVB_PCP;
  790. err = mv88e6xxx_port_ieeepmt_write(chip, port, table, i, i);
  791. if (err)
  792. return err;
  793. }
  794. return 0;
  795. }