mvsw61xx.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903
  1. /*
  2. * Marvell 88E61xx switch driver
  3. *
  4. * Copyright (c) 2014 Claudio Leite <leitec@staticky.com>
  5. * Copyright (c) 2014 Nikita Nazarenko <nnazarenko@radiofid.com>
  6. *
  7. * Based on code (c) 2008 Felix Fietkau <nbd@openwrt.org>
  8. *
  9. * This program is free software; you can redistribute it and/or modify it
  10. * under the terms of the GNU General Public License v2 as published by the
  11. * Free Software Foundation
  12. */
  13. #include <linux/kernel.h>
  14. #include <linux/module.h>
  15. #include <linux/init.h>
  16. #include <linux/list.h>
  17. #include <linux/mii.h>
  18. #include <linux/phy.h>
  19. #include <linux/of.h>
  20. #include <linux/of_mdio.h>
  21. #include <linux/delay.h>
  22. #include <linux/switch.h>
  23. #include <linux/device.h>
  24. #include <linux/platform_device.h>
  25. #include "mvsw61xx.h"
  26. MODULE_DESCRIPTION("Marvell 88E61xx Switch driver");
  27. MODULE_AUTHOR("Claudio Leite <leitec@staticky.com>");
  28. MODULE_AUTHOR("Nikita Nazarenko <nnazarenko@radiofid.com>");
  29. MODULE_LICENSE("GPL v2");
  30. MODULE_ALIAS("platform:mvsw61xx");
  31. /*
  32. * Register access is done through direct or indirect addressing,
  33. * depending on how the switch is physically connected.
  34. *
  35. * Direct addressing: all port and global registers directly
  36. * accessible via an address/register pair
  37. *
  38. * Indirect addressing: switch is mapped at a single address,
  39. * port and global registers accessible via a single command/data
  40. * register pair
  41. */
  42. static int
  43. mvsw61xx_wait_mask_raw(struct mii_bus *bus, int addr,
  44. int reg, u16 mask, u16 val)
  45. {
  46. int i = 100;
  47. u16 r;
  48. do {
  49. r = bus->read(bus, addr, reg);
  50. if ((r & mask) == val)
  51. return 0;
  52. } while (--i > 0);
  53. return -ETIMEDOUT;
  54. }
  55. static u16
  56. r16(struct mii_bus *bus, bool indirect, int base_addr, int addr, int reg)
  57. {
  58. u16 ind_addr;
  59. if (!indirect)
  60. return bus->read(bus, addr, reg);
  61. /* Indirect read: First, make sure switch is free */
  62. mvsw61xx_wait_mask_raw(bus, base_addr, MV_INDIRECT_REG_CMD,
  63. MV_INDIRECT_INPROGRESS, 0);
  64. /* Load address and request read */
  65. ind_addr = MV_INDIRECT_READ | (addr << MV_INDIRECT_ADDR_S) | reg;
  66. bus->write(bus, base_addr, MV_INDIRECT_REG_CMD,
  67. ind_addr);
  68. /* Wait until it's ready */
  69. mvsw61xx_wait_mask_raw(bus, base_addr, MV_INDIRECT_REG_CMD,
  70. MV_INDIRECT_INPROGRESS, 0);
  71. /* Read the requested data */
  72. return bus->read(bus, base_addr, MV_INDIRECT_REG_DATA);
  73. }
  74. static void
  75. w16(struct mii_bus *bus, bool indirect, int base_addr, int addr,
  76. int reg, u16 val)
  77. {
  78. u16 ind_addr;
  79. if (!indirect) {
  80. bus->write(bus, addr, reg, val);
  81. return;
  82. }
  83. /* Indirect write: First, make sure switch is free */
  84. mvsw61xx_wait_mask_raw(bus, base_addr, MV_INDIRECT_REG_CMD,
  85. MV_INDIRECT_INPROGRESS, 0);
  86. /* Load the data to be written */
  87. bus->write(bus, base_addr, MV_INDIRECT_REG_DATA, val);
  88. /* Wait again for switch to be free */
  89. mvsw61xx_wait_mask_raw(bus, base_addr, MV_INDIRECT_REG_CMD,
  90. MV_INDIRECT_INPROGRESS, 0);
  91. /* Load address, and issue write command */
  92. ind_addr = MV_INDIRECT_WRITE | (addr << MV_INDIRECT_ADDR_S) | reg;
  93. bus->write(bus, base_addr, MV_INDIRECT_REG_CMD,
  94. ind_addr);
  95. }
  96. /* swconfig support */
  97. static inline u16
  98. sr16(struct switch_dev *dev, int addr, int reg)
  99. {
  100. struct mvsw61xx_state *state = get_state(dev);
  101. return r16(state->bus, state->is_indirect, state->base_addr, addr, reg);
  102. }
  103. static inline void
  104. sw16(struct switch_dev *dev, int addr, int reg, u16 val)
  105. {
  106. struct mvsw61xx_state *state = get_state(dev);
  107. w16(state->bus, state->is_indirect, state->base_addr, addr, reg, val);
  108. }
  109. static int
  110. mvsw61xx_wait_mask_s(struct switch_dev *dev, int addr,
  111. int reg, u16 mask, u16 val)
  112. {
  113. int i = 100;
  114. u16 r;
  115. do {
  116. r = sr16(dev, addr, reg) & mask;
  117. if (r == val)
  118. return 0;
  119. } while (--i > 0);
  120. return -ETIMEDOUT;
  121. }
  122. static int
  123. mvsw61xx_get_port_mask(struct switch_dev *dev,
  124. const struct switch_attr *attr, struct switch_val *val)
  125. {
  126. struct mvsw61xx_state *state = get_state(dev);
  127. char *buf = state->buf;
  128. int port, len, i;
  129. u16 reg;
  130. port = val->port_vlan;
  131. reg = sr16(dev, MV_PORTREG(VLANMAP, port)) & MV_PORTS_MASK;
  132. len = sprintf(buf, "0x%04x: ", reg);
  133. for (i = 0; i < MV_PORTS; i++) {
  134. if (reg & (1 << i))
  135. len += sprintf(buf + len, "%d ", i);
  136. else if (i == port)
  137. len += sprintf(buf + len, "(%d) ", i);
  138. }
  139. val->value.s = buf;
  140. return 0;
  141. }
  142. static int
  143. mvsw61xx_get_port_qmode(struct switch_dev *dev,
  144. const struct switch_attr *attr, struct switch_val *val)
  145. {
  146. struct mvsw61xx_state *state = get_state(dev);
  147. val->value.i = state->ports[val->port_vlan].qmode;
  148. return 0;
  149. }
  150. static int
  151. mvsw61xx_set_port_qmode(struct switch_dev *dev,
  152. const struct switch_attr *attr, struct switch_val *val)
  153. {
  154. struct mvsw61xx_state *state = get_state(dev);
  155. state->ports[val->port_vlan].qmode = val->value.i;
  156. return 0;
  157. }
  158. static int
  159. mvsw61xx_get_pvid(struct switch_dev *dev, int port, int *val)
  160. {
  161. struct mvsw61xx_state *state = get_state(dev);
  162. *val = state->ports[port].pvid;
  163. return 0;
  164. }
  165. static int
  166. mvsw61xx_set_pvid(struct switch_dev *dev, int port, int val)
  167. {
  168. struct mvsw61xx_state *state = get_state(dev);
  169. if (val < 0 || val >= MV_VLANS)
  170. return -EINVAL;
  171. state->ports[port].pvid = (u16)val;
  172. return 0;
  173. }
  174. static int
  175. mvsw61xx_get_port_status(struct switch_dev *dev,
  176. const struct switch_attr *attr, struct switch_val *val)
  177. {
  178. struct mvsw61xx_state *state = get_state(dev);
  179. char *buf = state->buf;
  180. u16 status, speed;
  181. int len;
  182. status = sr16(dev, MV_PORTREG(STATUS, val->port_vlan));
  183. speed = (status & MV_PORT_STATUS_SPEED_MASK) >>
  184. MV_PORT_STATUS_SPEED_SHIFT;
  185. len = sprintf(buf, "link: ");
  186. if (status & MV_PORT_STATUS_LINK) {
  187. len += sprintf(buf + len, "up, speed: ");
  188. switch (speed) {
  189. case MV_PORT_STATUS_SPEED_10:
  190. len += sprintf(buf + len, "10");
  191. break;
  192. case MV_PORT_STATUS_SPEED_100:
  193. len += sprintf(buf + len, "100");
  194. break;
  195. case MV_PORT_STATUS_SPEED_1000:
  196. len += sprintf(buf + len, "1000");
  197. break;
  198. }
  199. len += sprintf(buf + len, " Mbps, duplex: ");
  200. if (status & MV_PORT_STATUS_FDX)
  201. len += sprintf(buf + len, "full");
  202. else
  203. len += sprintf(buf + len, "half");
  204. } else {
  205. len += sprintf(buf + len, "down");
  206. }
  207. val->value.s = buf;
  208. return 0;
  209. }
  210. static int
  211. mvsw61xx_get_port_speed(struct switch_dev *dev,
  212. const struct switch_attr *attr, struct switch_val *val)
  213. {
  214. u16 status, speed;
  215. status = sr16(dev, MV_PORTREG(STATUS, val->port_vlan));
  216. speed = (status & MV_PORT_STATUS_SPEED_MASK) >>
  217. MV_PORT_STATUS_SPEED_SHIFT;
  218. val->value.i = 0;
  219. if (status & MV_PORT_STATUS_LINK) {
  220. switch (speed) {
  221. case MV_PORT_STATUS_SPEED_10:
  222. val->value.i = 10;
  223. break;
  224. case MV_PORT_STATUS_SPEED_100:
  225. val->value.i = 100;
  226. break;
  227. case MV_PORT_STATUS_SPEED_1000:
  228. val->value.i = 1000;
  229. break;
  230. }
  231. }
  232. return 0;
  233. }
  234. static int mvsw61xx_get_vlan_ports(struct switch_dev *dev,
  235. struct switch_val *val)
  236. {
  237. struct mvsw61xx_state *state = get_state(dev);
  238. int i, j, mode, vno;
  239. vno = val->port_vlan;
  240. if (vno <= 0 || vno >= dev->vlans)
  241. return -EINVAL;
  242. for (i = 0, j = 0; i < dev->ports; i++) {
  243. if (state->vlans[vno].mask & (1 << i)) {
  244. val->value.ports[j].id = i;
  245. mode = (state->vlans[vno].port_mode >> (i * 4)) & 0xf;
  246. if (mode == MV_VTUCTL_EGRESS_TAGGED)
  247. val->value.ports[j].flags =
  248. (1 << SWITCH_PORT_FLAG_TAGGED);
  249. else
  250. val->value.ports[j].flags = 0;
  251. j++;
  252. }
  253. }
  254. val->len = j;
  255. return 0;
  256. }
  257. static int mvsw61xx_set_vlan_ports(struct switch_dev *dev,
  258. struct switch_val *val)
  259. {
  260. struct mvsw61xx_state *state = get_state(dev);
  261. int i, mode, pno, vno;
  262. vno = val->port_vlan;
  263. if (vno <= 0 || vno >= dev->vlans)
  264. return -EINVAL;
  265. state->vlans[vno].mask = 0;
  266. state->vlans[vno].port_mode = 0;
  267. state->vlans[vno].port_sstate = 0;
  268. if(state->vlans[vno].vid == 0)
  269. state->vlans[vno].vid = vno;
  270. for (i = 0; i < val->len; i++) {
  271. pno = val->value.ports[i].id;
  272. state->vlans[vno].mask |= (1 << pno);
  273. if (val->value.ports[i].flags &
  274. (1 << SWITCH_PORT_FLAG_TAGGED))
  275. mode = MV_VTUCTL_EGRESS_TAGGED;
  276. else
  277. mode = MV_VTUCTL_EGRESS_UNTAGGED;
  278. state->vlans[vno].port_mode |= mode << (pno * 4);
  279. state->vlans[vno].port_sstate |=
  280. MV_STUCTL_STATE_FORWARDING << (pno * 4 + 2);
  281. }
  282. /*
  283. * DISCARD is nonzero, so it must be explicitly
  284. * set on ports not in the VLAN.
  285. */
  286. for (i = 0; i < dev->ports; i++)
  287. if (!(state->vlans[vno].mask & (1 << i)))
  288. state->vlans[vno].port_mode |=
  289. MV_VTUCTL_DISCARD << (i * 4);
  290. return 0;
  291. }
  292. static int mvsw61xx_get_vlan_port_based(struct switch_dev *dev,
  293. const struct switch_attr *attr, struct switch_val *val)
  294. {
  295. struct mvsw61xx_state *state = get_state(dev);
  296. int vno = val->port_vlan;
  297. if (vno <= 0 || vno >= dev->vlans)
  298. return -EINVAL;
  299. if (state->vlans[vno].port_based)
  300. val->value.i = 1;
  301. else
  302. val->value.i = 0;
  303. return 0;
  304. }
  305. static int mvsw61xx_set_vlan_port_based(struct switch_dev *dev,
  306. const struct switch_attr *attr, struct switch_val *val)
  307. {
  308. struct mvsw61xx_state *state = get_state(dev);
  309. int vno = val->port_vlan;
  310. if (vno <= 0 || vno >= dev->vlans)
  311. return -EINVAL;
  312. if (val->value.i == 1)
  313. state->vlans[vno].port_based = true;
  314. else
  315. state->vlans[vno].port_based = false;
  316. return 0;
  317. }
  318. static int mvsw61xx_get_vid(struct switch_dev *dev,
  319. const struct switch_attr *attr, struct switch_val *val)
  320. {
  321. struct mvsw61xx_state *state = get_state(dev);
  322. int vno = val->port_vlan;
  323. if (vno <= 0 || vno >= dev->vlans)
  324. return -EINVAL;
  325. val->value.i = state->vlans[vno].vid;
  326. return 0;
  327. }
  328. static int mvsw61xx_set_vid(struct switch_dev *dev,
  329. const struct switch_attr *attr, struct switch_val *val)
  330. {
  331. struct mvsw61xx_state *state = get_state(dev);
  332. int vno = val->port_vlan;
  333. if (vno <= 0 || vno >= dev->vlans)
  334. return -EINVAL;
  335. state->vlans[vno].vid = val->value.i;
  336. return 0;
  337. }
  338. static int mvsw61xx_get_enable_vlan(struct switch_dev *dev,
  339. const struct switch_attr *attr, struct switch_val *val)
  340. {
  341. struct mvsw61xx_state *state = get_state(dev);
  342. val->value.i = state->vlan_enabled;
  343. return 0;
  344. }
  345. static int mvsw61xx_set_enable_vlan(struct switch_dev *dev,
  346. const struct switch_attr *attr, struct switch_val *val)
  347. {
  348. struct mvsw61xx_state *state = get_state(dev);
  349. state->vlan_enabled = val->value.i;
  350. return 0;
  351. }
  352. static int mvsw61xx_vtu_program(struct switch_dev *dev)
  353. {
  354. struct mvsw61xx_state *state = get_state(dev);
  355. u16 v1, v2, s1, s2;
  356. int i;
  357. /* Flush */
  358. mvsw61xx_wait_mask_s(dev, MV_GLOBALREG(VTU_OP),
  359. MV_VTUOP_INPROGRESS, 0);
  360. sw16(dev, MV_GLOBALREG(VTU_OP),
  361. MV_VTUOP_INPROGRESS | MV_VTUOP_PURGE);
  362. /* Write VLAN table */
  363. for (i = 1; i < dev->vlans; i++) {
  364. if (state->vlans[i].mask == 0 ||
  365. state->vlans[i].vid == 0 ||
  366. state->vlans[i].port_based == true)
  367. continue;
  368. mvsw61xx_wait_mask_s(dev, MV_GLOBALREG(VTU_OP),
  369. MV_VTUOP_INPROGRESS, 0);
  370. /* Write per-VLAN port state into STU */
  371. s1 = (u16) (state->vlans[i].port_sstate & 0xffff);
  372. s2 = (u16) ((state->vlans[i].port_sstate >> 16) & 0xffff);
  373. sw16(dev, MV_GLOBALREG(VTU_VID), MV_VTU_VID_VALID);
  374. sw16(dev, MV_GLOBALREG(VTU_SID), i);
  375. sw16(dev, MV_GLOBALREG(VTU_DATA1), s1);
  376. sw16(dev, MV_GLOBALREG(VTU_DATA2), s2);
  377. sw16(dev, MV_GLOBALREG(VTU_DATA3), 0);
  378. sw16(dev, MV_GLOBALREG(VTU_OP),
  379. MV_VTUOP_INPROGRESS | MV_VTUOP_STULOAD);
  380. mvsw61xx_wait_mask_s(dev, MV_GLOBALREG(VTU_OP),
  381. MV_VTUOP_INPROGRESS, 0);
  382. /* Write VLAN information into VTU */
  383. v1 = (u16) (state->vlans[i].port_mode & 0xffff);
  384. v2 = (u16) ((state->vlans[i].port_mode >> 16) & 0xffff);
  385. sw16(dev, MV_GLOBALREG(VTU_VID),
  386. MV_VTU_VID_VALID | state->vlans[i].vid);
  387. sw16(dev, MV_GLOBALREG(VTU_SID), i);
  388. sw16(dev, MV_GLOBALREG(VTU_FID), 0);
  389. sw16(dev, MV_GLOBALREG(VTU_DATA1), v1);
  390. sw16(dev, MV_GLOBALREG(VTU_DATA2), v2);
  391. sw16(dev, MV_GLOBALREG(VTU_DATA3), 0);
  392. sw16(dev, MV_GLOBALREG(VTU_OP),
  393. MV_VTUOP_INPROGRESS | MV_VTUOP_LOAD);
  394. mvsw61xx_wait_mask_s(dev, MV_GLOBALREG(VTU_OP),
  395. MV_VTUOP_INPROGRESS, 0);
  396. }
  397. return 0;
  398. }
  399. static void mvsw61xx_vlan_port_config(struct switch_dev *dev, int vno)
  400. {
  401. struct mvsw61xx_state *state = get_state(dev);
  402. int i, mode;
  403. for (i = 0; i < dev->ports; i++) {
  404. if (!(state->vlans[vno].mask & (1 << i)))
  405. continue;
  406. mode = (state->vlans[vno].port_mode >> (i * 4)) & 0xf;
  407. if(mode != MV_VTUCTL_EGRESS_TAGGED)
  408. state->ports[i].pvid = state->vlans[vno].vid;
  409. if (state->vlans[vno].port_based)
  410. state->ports[i].mask |= state->vlans[vno].mask;
  411. else
  412. state->ports[i].qmode = MV_8021Q_MODE_SECURE;
  413. }
  414. }
  415. static int mvsw61xx_update_state(struct switch_dev *dev)
  416. {
  417. struct mvsw61xx_state *state = get_state(dev);
  418. int i;
  419. u16 reg;
  420. if (!state->registered)
  421. return -EINVAL;
  422. /*
  423. * Set 802.1q-only mode if vlan_enabled is true.
  424. *
  425. * Without this, even if 802.1q is enabled for
  426. * a port/VLAN, it still depends on the port-based
  427. * VLAN mask being set.
  428. *
  429. * With this setting, port-based VLANs are still
  430. * functional, provided the VID is not in the VTU.
  431. */
  432. reg = sr16(dev, MV_GLOBAL2REG(SDET_POLARITY));
  433. if (state->vlan_enabled)
  434. reg |= MV_8021Q_VLAN_ONLY;
  435. else
  436. reg &= ~MV_8021Q_VLAN_ONLY;
  437. sw16(dev, MV_GLOBAL2REG(SDET_POLARITY), reg);
  438. /*
  439. * Set port-based VLAN masks on each port
  440. * based only on VLAN definitions known to
  441. * the driver (i.e. in state).
  442. *
  443. * This means any pre-existing port mapping is
  444. * wiped out once our driver is initialized.
  445. */
  446. for (i = 0; i < dev->ports; i++) {
  447. state->ports[i].mask = 0;
  448. state->ports[i].qmode = MV_8021Q_MODE_DISABLE;
  449. }
  450. for (i = 0; i < dev->vlans; i++)
  451. mvsw61xx_vlan_port_config(dev, i);
  452. for (i = 0; i < dev->ports; i++) {
  453. reg = sr16(dev, MV_PORTREG(VLANID, i)) & ~MV_PVID_MASK;
  454. reg |= state->ports[i].pvid;
  455. sw16(dev, MV_PORTREG(VLANID, i), reg);
  456. state->ports[i].mask &= ~(1 << i);
  457. reg = sr16(dev, MV_PORTREG(VLANMAP, i)) & ~MV_PORTS_MASK;
  458. reg |= state->ports[i].mask;
  459. sw16(dev, MV_PORTREG(VLANMAP, i), reg);
  460. reg = sr16(dev, MV_PORTREG(CONTROL2, i)) &
  461. ~MV_8021Q_MODE_MASK;
  462. reg |= state->ports[i].qmode << MV_8021Q_MODE_SHIFT;
  463. sw16(dev, MV_PORTREG(CONTROL2, i), reg);
  464. }
  465. mvsw61xx_vtu_program(dev);
  466. return 0;
  467. }
  468. static int mvsw61xx_apply(struct switch_dev *dev)
  469. {
  470. return mvsw61xx_update_state(dev);
  471. }
  472. static int mvsw61xx_reset(struct switch_dev *dev)
  473. {
  474. struct mvsw61xx_state *state = get_state(dev);
  475. int i;
  476. u16 reg;
  477. /* Disable all ports before reset */
  478. for (i = 0; i < dev->ports; i++) {
  479. reg = sr16(dev, MV_PORTREG(CONTROL, i)) &
  480. ~MV_PORTCTRL_FORWARDING;
  481. sw16(dev, MV_PORTREG(CONTROL, i), reg);
  482. }
  483. reg = sr16(dev, MV_GLOBALREG(CONTROL)) | MV_CONTROL_RESET;
  484. sw16(dev, MV_GLOBALREG(CONTROL), reg);
  485. if (mvsw61xx_wait_mask_s(dev, MV_GLOBALREG(CONTROL),
  486. MV_CONTROL_RESET, 0) < 0)
  487. return -ETIMEDOUT;
  488. for (i = 0; i < dev->ports; i++) {
  489. state->ports[i].qmode = 0;
  490. state->ports[i].mask = 0;
  491. state->ports[i].pvid = 0;
  492. /* Force flow control off */
  493. reg = sr16(dev, MV_PORTREG(PHYCTL, i)) & ~MV_PHYCTL_FC_MASK;
  494. reg |= MV_PHYCTL_FC_DISABLE;
  495. sw16(dev, MV_PORTREG(PHYCTL, i), reg);
  496. /* Set port association vector */
  497. sw16(dev, MV_PORTREG(ASSOC, i), (1 << i));
  498. }
  499. for (i = 0; i < dev->vlans; i++) {
  500. state->vlans[i].port_based = false;
  501. state->vlans[i].mask = 0;
  502. state->vlans[i].vid = 0;
  503. state->vlans[i].port_mode = 0;
  504. state->vlans[i].port_sstate = 0;
  505. }
  506. state->vlan_enabled = 0;
  507. mvsw61xx_update_state(dev);
  508. /* Re-enable ports */
  509. for (i = 0; i < dev->ports; i++) {
  510. reg = sr16(dev, MV_PORTREG(CONTROL, i)) |
  511. MV_PORTCTRL_FORWARDING;
  512. sw16(dev, MV_PORTREG(CONTROL, i), reg);
  513. }
  514. return 0;
  515. }
  516. enum {
  517. MVSW61XX_ENABLE_VLAN,
  518. };
  519. enum {
  520. MVSW61XX_VLAN_PORT_BASED,
  521. MVSW61XX_VLAN_ID,
  522. };
  523. enum {
  524. MVSW61XX_PORT_MASK,
  525. MVSW61XX_PORT_QMODE,
  526. MVSW61XX_PORT_STATUS,
  527. MVSW61XX_PORT_LINK,
  528. };
  529. static const struct switch_attr mvsw61xx_global[] = {
  530. [MVSW61XX_ENABLE_VLAN] = {
  531. .id = MVSW61XX_ENABLE_VLAN,
  532. .type = SWITCH_TYPE_INT,
  533. .name = "enable_vlan",
  534. .description = "Enable 802.1q VLAN support",
  535. .get = mvsw61xx_get_enable_vlan,
  536. .set = mvsw61xx_set_enable_vlan,
  537. },
  538. };
  539. static const struct switch_attr mvsw61xx_vlan[] = {
  540. [MVSW61XX_VLAN_PORT_BASED] = {
  541. .id = MVSW61XX_VLAN_PORT_BASED,
  542. .type = SWITCH_TYPE_INT,
  543. .name = "port_based",
  544. .description = "Use port-based (non-802.1q) VLAN only",
  545. .get = mvsw61xx_get_vlan_port_based,
  546. .set = mvsw61xx_set_vlan_port_based,
  547. },
  548. [MVSW61XX_VLAN_ID] = {
  549. .id = MVSW61XX_VLAN_ID,
  550. .type = SWITCH_TYPE_INT,
  551. .name = "vid",
  552. .description = "Get/set VLAN ID",
  553. .get = mvsw61xx_get_vid,
  554. .set = mvsw61xx_set_vid,
  555. },
  556. };
  557. static const struct switch_attr mvsw61xx_port[] = {
  558. [MVSW61XX_PORT_MASK] = {
  559. .id = MVSW61XX_PORT_MASK,
  560. .type = SWITCH_TYPE_STRING,
  561. .description = "Port-based VLAN mask",
  562. .name = "mask",
  563. .get = mvsw61xx_get_port_mask,
  564. .set = NULL,
  565. },
  566. [MVSW61XX_PORT_QMODE] = {
  567. .id = MVSW61XX_PORT_QMODE,
  568. .type = SWITCH_TYPE_INT,
  569. .description = "802.1q mode: 0=off/1=fallback/2=check/3=secure",
  570. .name = "qmode",
  571. .get = mvsw61xx_get_port_qmode,
  572. .set = mvsw61xx_set_port_qmode,
  573. },
  574. [MVSW61XX_PORT_STATUS] = {
  575. .id = MVSW61XX_PORT_STATUS,
  576. .type = SWITCH_TYPE_STRING,
  577. .description = "Return port status",
  578. .name = "status",
  579. .get = mvsw61xx_get_port_status,
  580. .set = NULL,
  581. },
  582. [MVSW61XX_PORT_LINK] = {
  583. .id = MVSW61XX_PORT_LINK,
  584. .type = SWITCH_TYPE_INT,
  585. .description = "Get link speed",
  586. .name = "link",
  587. .get = mvsw61xx_get_port_speed,
  588. .set = NULL,
  589. },
  590. };
  591. static const struct switch_dev_ops mvsw61xx_ops = {
  592. .attr_global = {
  593. .attr = mvsw61xx_global,
  594. .n_attr = ARRAY_SIZE(mvsw61xx_global),
  595. },
  596. .attr_vlan = {
  597. .attr = mvsw61xx_vlan,
  598. .n_attr = ARRAY_SIZE(mvsw61xx_vlan),
  599. },
  600. .attr_port = {
  601. .attr = mvsw61xx_port,
  602. .n_attr = ARRAY_SIZE(mvsw61xx_port),
  603. },
  604. .get_port_pvid = mvsw61xx_get_pvid,
  605. .set_port_pvid = mvsw61xx_set_pvid,
  606. .get_vlan_ports = mvsw61xx_get_vlan_ports,
  607. .set_vlan_ports = mvsw61xx_set_vlan_ports,
  608. .apply_config = mvsw61xx_apply,
  609. .reset_switch = mvsw61xx_reset,
  610. };
  611. /* end swconfig stuff */
  612. static int mvsw61xx_probe(struct platform_device *pdev)
  613. {
  614. struct mvsw61xx_state *state;
  615. struct device_node *np = pdev->dev.of_node;
  616. struct device_node *mdio;
  617. char *model_str;
  618. u32 val;
  619. int err;
  620. state = kzalloc(sizeof(*state), GFP_KERNEL);
  621. if (!state)
  622. return -ENOMEM;
  623. mdio = of_parse_phandle(np, "mii-bus", 0);
  624. if (!mdio) {
  625. dev_err(&pdev->dev, "Couldn't get MII bus handle\n");
  626. err = -ENODEV;
  627. goto out_err;
  628. }
  629. state->bus = of_mdio_find_bus(mdio);
  630. if (!state->bus) {
  631. dev_err(&pdev->dev, "Couldn't find MII bus from handle\n");
  632. err = -ENODEV;
  633. goto out_err;
  634. }
  635. state->is_indirect = of_property_read_bool(np, "is-indirect");
  636. if (state->is_indirect) {
  637. if (of_property_read_u32(np, "reg", &val)) {
  638. dev_err(&pdev->dev, "Switch address not specified\n");
  639. err = -ENODEV;
  640. goto out_err;
  641. }
  642. state->base_addr = val;
  643. } else {
  644. state->base_addr = MV_BASE;
  645. }
  646. state->model = r16(state->bus, state->is_indirect, state->base_addr,
  647. MV_PORTREG(IDENT, 0)) & MV_IDENT_MASK;
  648. switch(state->model) {
  649. case MV_IDENT_VALUE_6171:
  650. model_str = MV_IDENT_STR_6171;
  651. break;
  652. case MV_IDENT_VALUE_6172:
  653. model_str = MV_IDENT_STR_6172;
  654. break;
  655. case MV_IDENT_VALUE_6176:
  656. model_str = MV_IDENT_STR_6176;
  657. break;
  658. default:
  659. dev_err(&pdev->dev, "No compatible switch found at 0x%02x\n",
  660. state->base_addr);
  661. err = -ENODEV;
  662. goto out_err;
  663. }
  664. platform_set_drvdata(pdev, state);
  665. dev_info(&pdev->dev, "Found %s at %s:%02x\n", model_str,
  666. state->bus->id, state->base_addr);
  667. dev_info(&pdev->dev, "Using %sdirect addressing\n",
  668. (state->is_indirect ? "in" : ""));
  669. if (of_property_read_u32(np, "cpu-port-0", &val)) {
  670. dev_err(&pdev->dev, "CPU port not set\n");
  671. err = -ENODEV;
  672. goto out_err;
  673. }
  674. state->cpu_port0 = val;
  675. if (!of_property_read_u32(np, "cpu-port-1", &val))
  676. state->cpu_port1 = val;
  677. else
  678. state->cpu_port1 = -1;
  679. state->dev.vlans = MV_VLANS;
  680. state->dev.cpu_port = state->cpu_port0;
  681. state->dev.ports = MV_PORTS;
  682. state->dev.name = model_str;
  683. state->dev.ops = &mvsw61xx_ops;
  684. state->dev.alias = dev_name(&pdev->dev);
  685. err = register_switch(&state->dev, NULL);
  686. if (err < 0)
  687. goto out_err;
  688. state->registered = true;
  689. return 0;
  690. out_err:
  691. kfree(state);
  692. return err;
  693. }
  694. static int
  695. mvsw61xx_remove(struct platform_device *pdev)
  696. {
  697. struct mvsw61xx_state *state = platform_get_drvdata(pdev);
  698. if (state->registered)
  699. unregister_switch(&state->dev);
  700. kfree(state);
  701. return 0;
  702. }
  703. static const struct of_device_id mvsw61xx_match[] = {
  704. { .compatible = "marvell,88e6171" },
  705. { .compatible = "marvell,88e6172" },
  706. { .compatible = "marvell,88e6176" },
  707. { }
  708. };
  709. MODULE_DEVICE_TABLE(of, mvsw61xx_match);
  710. static struct platform_driver mvsw61xx_driver = {
  711. .probe = mvsw61xx_probe,
  712. .remove = mvsw61xx_remove,
  713. .driver = {
  714. .name = "mvsw61xx",
  715. .of_match_table = of_match_ptr(mvsw61xx_match),
  716. .owner = THIS_MODULE,
  717. },
  718. };
  719. static int __init mvsw61xx_module_init(void)
  720. {
  721. return platform_driver_register(&mvsw61xx_driver);
  722. }
  723. late_initcall(mvsw61xx_module_init);
  724. static void __exit mvsw61xx_module_exit(void)
  725. {
  726. platform_driver_unregister(&mvsw61xx_driver);
  727. }
  728. module_exit(mvsw61xx_module_exit);