0512-net-mediatek-add-swconfig-driver-for-esw_rt3050.patch 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901
  1. From 4473f30809eed09037e1932a0c1805172cd997f7 Mon Sep 17 00:00:00 2001
  2. From: John Crispin <blogic@openwrt.org>
  3. Date: Mon, 14 Dec 2015 22:07:31 +0100
  4. Subject: [PATCH 512/513] net: mediatek: add swconfig driver for esw_rt3050
  5. Signed-off-by: John Crispin <blogic@openwrt.org>
  6. ---
  7. drivers/net/ethernet/mediatek/esw_rt3050.c | 805 ++++++++++++++++++++++++++++
  8. 1 file changed, 805 insertions(+)
  9. --- a/drivers/net/ethernet/mediatek/esw_rt3050.c
  10. +++ b/drivers/net/ethernet/mediatek/esw_rt3050.c
  11. @@ -17,6 +17,8 @@
  12. #include <linux/platform_device.h>
  13. #include <asm/mach-ralink/ralink_regs.h>
  14. +#include <linux/switch.h>
  15. +
  16. #include "mtk_eth_soc.h"
  17. /* HW limitations for this switch:
  18. @@ -141,6 +143,8 @@
  19. #define RT305X_ESW_PORT5 5
  20. #define RT305X_ESW_PORT6 6
  21. +#define RT305X_ESW_PORTS_NONE 0
  22. +
  23. #define RT305X_ESW_PMAP_LLLLLL 0x3f
  24. #define RT305X_ESW_PMAP_LLLLWL 0x2f
  25. #define RT305X_ESW_PMAP_WLLLLL 0x3e
  26. @@ -158,15 +162,51 @@
  27. #define RT305X_ESW_PORTS_ALL \
  28. (RT305X_ESW_PORTS_NOCPU | RT305X_ESW_PORTS_CPU)
  29. +#define RT305X_ESW_NUM_VLANS 16
  30. +#define RT305X_ESW_NUM_VIDS 4096
  31. #define RT305X_ESW_NUM_PORTS 7
  32. +#define RT305X_ESW_NUM_LANWAN 6
  33. #define RT305X_ESW_NUM_LEDS 5
  34. +#define RT5350_ESW_REG_PXTPC(_x) (0x150 + (4 * _x))
  35. #define RT5350_EWS_REG_LED_POLARITY 0x168
  36. #define RT5350_RESET_EPHY BIT(24)
  37. +enum {
  38. + /* Global attributes. */
  39. + RT305X_ESW_ATTR_ENABLE_VLAN,
  40. + RT305X_ESW_ATTR_ALT_VLAN_DISABLE,
  41. + RT305X_ESW_ATTR_BC_STATUS,
  42. + RT305X_ESW_ATTR_LED_FREQ,
  43. + /* Port attributes. */
  44. + RT305X_ESW_ATTR_PORT_DISABLE,
  45. + RT305X_ESW_ATTR_PORT_DOUBLETAG,
  46. + RT305X_ESW_ATTR_PORT_UNTAG,
  47. + RT305X_ESW_ATTR_PORT_LED,
  48. + RT305X_ESW_ATTR_PORT_LAN,
  49. + RT305X_ESW_ATTR_PORT_RECV_BAD,
  50. + RT305X_ESW_ATTR_PORT_RECV_GOOD,
  51. + RT5350_ESW_ATTR_PORT_TR_BAD,
  52. + RT5350_ESW_ATTR_PORT_TR_GOOD,
  53. +};
  54. +
  55. struct esw_port {
  56. bool disable;
  57. + bool doubletag;
  58. + bool untag;
  59. u8 led;
  60. + u16 pvid;
  61. +};
  62. +
  63. +struct esw_vlan {
  64. + u8 ports;
  65. + u16 vid;
  66. +};
  67. +
  68. +enum {
  69. + RT305X_ESW_VLAN_CONFIG_NONE = 0,
  70. + RT305X_ESW_VLAN_CONFIG_LLLLW,
  71. + RT305X_ESW_VLAN_CONFIG_WLLLL,
  72. };
  73. struct rt305x_esw {
  74. @@ -180,6 +220,12 @@ struct rt305x_esw {
  75. unsigned char port_map;
  76. unsigned int reg_led_polarity;
  77. + struct switch_dev swdev;
  78. + bool global_vlan_enable;
  79. + bool alt_vlan_disable;
  80. + int bc_storm_protect;
  81. + int led_frequency;
  82. + struct esw_vlan vlans[RT305X_ESW_NUM_VLANS];
  83. struct esw_port ports[RT305X_ESW_NUM_PORTS];
  84. };
  85. @@ -252,6 +298,71 @@ out:
  86. return ret;
  87. }
  88. +static unsigned esw_get_vlan_id(struct rt305x_esw *esw, unsigned vlan)
  89. +{
  90. + unsigned s;
  91. + unsigned val;
  92. +
  93. + s = RT305X_ESW_VLANI_VID_S * (vlan % 2);
  94. + val = esw_r32(esw, RT305X_ESW_REG_VLANI(vlan / 2));
  95. + val = (val >> s) & RT305X_ESW_VLANI_VID_M;
  96. +
  97. + return val;
  98. +}
  99. +
  100. +static void esw_set_vlan_id(struct rt305x_esw *esw, unsigned vlan, unsigned vid)
  101. +{
  102. + unsigned s;
  103. +
  104. + s = RT305X_ESW_VLANI_VID_S * (vlan % 2);
  105. + esw_rmw(esw,
  106. + RT305X_ESW_REG_VLANI(vlan / 2),
  107. + RT305X_ESW_VLANI_VID_M << s,
  108. + (vid & RT305X_ESW_VLANI_VID_M) << s);
  109. +}
  110. +
  111. +static unsigned esw_get_pvid(struct rt305x_esw *esw, unsigned port)
  112. +{
  113. + unsigned s, val;
  114. +
  115. + s = RT305X_ESW_PVIDC_PVID_S * (port % 2);
  116. + val = esw_r32(esw, RT305X_ESW_REG_PVIDC(port / 2));
  117. + return (val >> s) & RT305X_ESW_PVIDC_PVID_M;
  118. +}
  119. +
  120. +static void esw_set_pvid(struct rt305x_esw *esw, unsigned port, unsigned pvid)
  121. +{
  122. + unsigned s;
  123. +
  124. + s = RT305X_ESW_PVIDC_PVID_S * (port % 2);
  125. + esw_rmw(esw,
  126. + RT305X_ESW_REG_PVIDC(port / 2),
  127. + RT305X_ESW_PVIDC_PVID_M << s,
  128. + (pvid & RT305X_ESW_PVIDC_PVID_M) << s);
  129. +}
  130. +
  131. +static unsigned esw_get_vmsc(struct rt305x_esw *esw, unsigned vlan)
  132. +{
  133. + unsigned s, val;
  134. +
  135. + s = RT305X_ESW_VMSC_MSC_S * (vlan % 4);
  136. + val = esw_r32(esw, RT305X_ESW_REG_VMSC(vlan / 4));
  137. + val = (val >> s) & RT305X_ESW_VMSC_MSC_M;
  138. +
  139. + return val;
  140. +}
  141. +
  142. +static void esw_set_vmsc(struct rt305x_esw *esw, unsigned vlan, unsigned msc)
  143. +{
  144. + unsigned s;
  145. +
  146. + s = RT305X_ESW_VMSC_MSC_S * (vlan % 4);
  147. + esw_rmw(esw,
  148. + RT305X_ESW_REG_VMSC(vlan / 4),
  149. + RT305X_ESW_VMSC_MSC_M << s,
  150. + (msc & RT305X_ESW_VMSC_MSC_M) << s);
  151. +}
  152. +
  153. static unsigned esw_get_port_disable(struct rt305x_esw *esw)
  154. {
  155. unsigned reg;
  156. @@ -261,6 +372,59 @@ static unsigned esw_get_port_disable(str
  157. RT305X_ESW_POC0_DIS_PORT_M;
  158. }
  159. +static void esw_set_port_disable(struct rt305x_esw *esw, unsigned disable_mask)
  160. +{
  161. + unsigned old_mask;
  162. + unsigned enable_mask;
  163. + unsigned changed;
  164. + int i;
  165. +
  166. + old_mask = esw_get_port_disable(esw);
  167. + changed = old_mask ^ disable_mask;
  168. + enable_mask = old_mask & disable_mask;
  169. +
  170. + /* enable before writing to MII */
  171. + esw_rmw(esw, RT305X_ESW_REG_POC0,
  172. + (RT305X_ESW_POC0_DIS_PORT_M <<
  173. + RT305X_ESW_POC0_DIS_PORT_S),
  174. + enable_mask << RT305X_ESW_POC0_DIS_PORT_S);
  175. +
  176. + for (i = 0; i < RT305X_ESW_NUM_LEDS; i++) {
  177. + if (!(changed & (1 << i)))
  178. + continue;
  179. + if (disable_mask & (1 << i)) {
  180. + /* disable */
  181. + rt305x_mii_write(esw, i, MII_BMCR,
  182. + BMCR_PDOWN);
  183. + } else {
  184. + /* enable */
  185. + rt305x_mii_write(esw, i, MII_BMCR,
  186. + BMCR_FULLDPLX |
  187. + BMCR_ANENABLE |
  188. + BMCR_ANRESTART |
  189. + BMCR_SPEED100);
  190. + }
  191. + }
  192. +
  193. + /* disable after writing to MII */
  194. + esw_rmw(esw, RT305X_ESW_REG_POC0,
  195. + (RT305X_ESW_POC0_DIS_PORT_M <<
  196. + RT305X_ESW_POC0_DIS_PORT_S),
  197. + disable_mask << RT305X_ESW_POC0_DIS_PORT_S);
  198. +}
  199. +
  200. +static void esw_set_gsc(struct rt305x_esw *esw)
  201. +{
  202. + esw_rmw(esw, RT305X_ESW_REG_SGC,
  203. + RT305X_ESW_GSC_BC_STROM_MASK << RT305X_ESW_GSC_BC_STROM_SHIFT,
  204. + esw->bc_storm_protect << RT305X_ESW_GSC_BC_STROM_SHIFT);
  205. + esw_rmw(esw, RT305X_ESW_REG_SGC,
  206. + RT305X_ESW_GSC_LED_FREQ_MASK << RT305X_ESW_GSC_LED_FREQ_SHIFT,
  207. + esw->led_frequency << RT305X_ESW_GSC_LED_FREQ_SHIFT);
  208. +}
  209. +
  210. +static int esw_apply_config(struct switch_dev *dev);
  211. +
  212. static void esw_hw_init(struct rt305x_esw *esw)
  213. {
  214. int i;
  215. @@ -519,6 +683,9 @@ static void esw_hw_init(struct rt305x_es
  216. for (i = 0; i < RT305X_ESW_NUM_LEDS; i++)
  217. esw->ports[i].led = 0x05;
  218. + /* Apply the empty config. */
  219. + esw_apply_config(&esw->swdev);
  220. +
  221. /* Only unmask the port change interrupt */
  222. esw_w32(esw, ~RT305X_ESW_PORT_ST_CHG, RT305X_ESW_REG_IMR);
  223. }
  224. @@ -541,11 +708,629 @@ static irqreturn_t esw_interrupt(int irq
  225. return IRQ_HANDLED;
  226. }
  227. +static int esw_apply_config(struct switch_dev *dev)
  228. +{
  229. + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev);
  230. + int i;
  231. + u8 disable = 0;
  232. + u8 doubletag = 0;
  233. + u8 en_vlan = 0;
  234. + u8 untag = 0;
  235. +
  236. + for (i = 0; i < RT305X_ESW_NUM_VLANS; i++) {
  237. + u32 vid, vmsc;
  238. + if (esw->global_vlan_enable) {
  239. + vid = esw->vlans[i].vid;
  240. + vmsc = esw->vlans[i].ports;
  241. + } else {
  242. + vid = RT305X_ESW_VLAN_NONE;
  243. + vmsc = RT305X_ESW_PORTS_NONE;
  244. + }
  245. + esw_set_vlan_id(esw, i, vid);
  246. + esw_set_vmsc(esw, i, vmsc);
  247. + }
  248. +
  249. + for (i = 0; i < RT305X_ESW_NUM_PORTS; i++) {
  250. + u32 pvid;
  251. + disable |= esw->ports[i].disable << i;
  252. + if (esw->global_vlan_enable) {
  253. + doubletag |= esw->ports[i].doubletag << i;
  254. + en_vlan |= 1 << i;
  255. + untag |= esw->ports[i].untag << i;
  256. + pvid = esw->ports[i].pvid;
  257. + } else {
  258. + int x = esw->alt_vlan_disable ? 0 : 1;
  259. + doubletag |= x << i;
  260. + en_vlan |= x << i;
  261. + untag |= x << i;
  262. + pvid = 0;
  263. + }
  264. + esw_set_pvid(esw, i, pvid);
  265. + if (i < RT305X_ESW_NUM_LEDS)
  266. + esw_w32(esw, esw->ports[i].led,
  267. + RT305X_ESW_REG_P0LED + 4*i);
  268. + }
  269. +
  270. + esw_set_gsc(esw);
  271. + esw_set_port_disable(esw, disable);
  272. + esw_rmw(esw, RT305X_ESW_REG_SGC2,
  273. + (RT305X_ESW_SGC2_DOUBLE_TAG_M <<
  274. + RT305X_ESW_SGC2_DOUBLE_TAG_S),
  275. + doubletag << RT305X_ESW_SGC2_DOUBLE_TAG_S);
  276. + esw_rmw(esw, RT305X_ESW_REG_PFC1,
  277. + RT305X_ESW_PFC1_EN_VLAN_M << RT305X_ESW_PFC1_EN_VLAN_S,
  278. + en_vlan << RT305X_ESW_PFC1_EN_VLAN_S);
  279. + esw_rmw(esw, RT305X_ESW_REG_POC2,
  280. + RT305X_ESW_POC2_UNTAG_EN_M << RT305X_ESW_POC2_UNTAG_EN_S,
  281. + untag << RT305X_ESW_POC2_UNTAG_EN_S);
  282. +
  283. + if (!esw->global_vlan_enable) {
  284. + /*
  285. + * Still need to put all ports into vlan 0 or they'll be
  286. + * isolated.
  287. + * NOTE: vlan 0 is special, no vlan tag is prepended
  288. + */
  289. + esw_set_vlan_id(esw, 0, 0);
  290. + esw_set_vmsc(esw, 0, RT305X_ESW_PORTS_ALL);
  291. + }
  292. +
  293. + return 0;
  294. +}
  295. +
  296. +static int esw_reset_switch(struct switch_dev *dev)
  297. +{
  298. + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev);
  299. +
  300. + esw->global_vlan_enable = 0;
  301. + memset(esw->ports, 0, sizeof(esw->ports));
  302. + memset(esw->vlans, 0, sizeof(esw->vlans));
  303. + esw_hw_init(esw);
  304. +
  305. + return 0;
  306. +}
  307. +
  308. +static int esw_get_vlan_enable(struct switch_dev *dev,
  309. + const struct switch_attr *attr,
  310. + struct switch_val *val)
  311. +{
  312. + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev);
  313. +
  314. + val->value.i = esw->global_vlan_enable;
  315. +
  316. + return 0;
  317. +}
  318. +
  319. +static int esw_set_vlan_enable(struct switch_dev *dev,
  320. + const struct switch_attr *attr,
  321. + struct switch_val *val)
  322. +{
  323. + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev);
  324. +
  325. + esw->global_vlan_enable = val->value.i != 0;
  326. +
  327. + return 0;
  328. +}
  329. +
  330. +static int esw_get_alt_vlan_disable(struct switch_dev *dev,
  331. + const struct switch_attr *attr,
  332. + struct switch_val *val)
  333. +{
  334. + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev);
  335. +
  336. + val->value.i = esw->alt_vlan_disable;
  337. +
  338. + return 0;
  339. +}
  340. +
  341. +static int esw_set_alt_vlan_disable(struct switch_dev *dev,
  342. + const struct switch_attr *attr,
  343. + struct switch_val *val)
  344. +{
  345. + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev);
  346. +
  347. + esw->alt_vlan_disable = val->value.i != 0;
  348. +
  349. + return 0;
  350. +}
  351. +
  352. +static int
  353. +rt305x_esw_set_bc_status(struct switch_dev *dev,
  354. + const struct switch_attr *attr,
  355. + struct switch_val *val)
  356. +{
  357. + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev);
  358. +
  359. + esw->bc_storm_protect = val->value.i & RT305X_ESW_GSC_BC_STROM_MASK;
  360. +
  361. + return 0;
  362. +}
  363. +
  364. +static int
  365. +rt305x_esw_get_bc_status(struct switch_dev *dev,
  366. + const struct switch_attr *attr,
  367. + struct switch_val *val)
  368. +{
  369. + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev);
  370. +
  371. + val->value.i = esw->bc_storm_protect;
  372. +
  373. + return 0;
  374. +}
  375. +
  376. +static int
  377. +rt305x_esw_set_led_freq(struct switch_dev *dev,
  378. + const struct switch_attr *attr,
  379. + struct switch_val *val)
  380. +{
  381. + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev);
  382. +
  383. + esw->led_frequency = val->value.i & RT305X_ESW_GSC_LED_FREQ_MASK;
  384. +
  385. + return 0;
  386. +}
  387. +
  388. +static int
  389. +rt305x_esw_get_led_freq(struct switch_dev *dev,
  390. + const struct switch_attr *attr,
  391. + struct switch_val *val)
  392. +{
  393. + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev);
  394. +
  395. + val->value.i = esw->led_frequency;
  396. +
  397. + return 0;
  398. +}
  399. +
  400. +static int esw_get_port_link(struct switch_dev *dev,
  401. + int port,
  402. + struct switch_port_link *link)
  403. +{
  404. + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev);
  405. + u32 speed, poa;
  406. +
  407. + if (port < 0 || port >= RT305X_ESW_NUM_PORTS)
  408. + return -EINVAL;
  409. +
  410. + poa = esw_r32(esw, RT305X_ESW_REG_POA) >> port;
  411. +
  412. + link->link = (poa >> RT305X_ESW_LINK_S) & 1;
  413. + link->duplex = (poa >> RT305X_ESW_DUPLEX_S) & 1;
  414. + if (port < RT305X_ESW_NUM_LEDS) {
  415. + speed = (poa >> RT305X_ESW_SPD_S) & 1;
  416. + } else {
  417. + if (port == RT305X_ESW_NUM_PORTS - 1)
  418. + poa >>= 1;
  419. + speed = (poa >> RT305X_ESW_SPD_S) & 3;
  420. + }
  421. + switch (speed) {
  422. + case 0:
  423. + link->speed = SWITCH_PORT_SPEED_10;
  424. + break;
  425. + case 1:
  426. + link->speed = SWITCH_PORT_SPEED_100;
  427. + break;
  428. + case 2:
  429. + case 3: /* forced gige speed can be 2 or 3 */
  430. + link->speed = SWITCH_PORT_SPEED_1000;
  431. + break;
  432. + default:
  433. + link->speed = SWITCH_PORT_SPEED_UNKNOWN;
  434. + break;
  435. + }
  436. +
  437. + return 0;
  438. +}
  439. +
  440. +static int esw_get_port_bool(struct switch_dev *dev,
  441. + const struct switch_attr *attr,
  442. + struct switch_val *val)
  443. +{
  444. + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev);
  445. + int idx = val->port_vlan;
  446. + u32 x, reg, shift;
  447. +
  448. + if (idx < 0 || idx >= RT305X_ESW_NUM_PORTS)
  449. + return -EINVAL;
  450. +
  451. + switch (attr->id) {
  452. + case RT305X_ESW_ATTR_PORT_DISABLE:
  453. + reg = RT305X_ESW_REG_POC0;
  454. + shift = RT305X_ESW_POC0_DIS_PORT_S;
  455. + break;
  456. + case RT305X_ESW_ATTR_PORT_DOUBLETAG:
  457. + reg = RT305X_ESW_REG_SGC2;
  458. + shift = RT305X_ESW_SGC2_DOUBLE_TAG_S;
  459. + break;
  460. + case RT305X_ESW_ATTR_PORT_UNTAG:
  461. + reg = RT305X_ESW_REG_POC2;
  462. + shift = RT305X_ESW_POC2_UNTAG_EN_S;
  463. + break;
  464. + case RT305X_ESW_ATTR_PORT_LAN:
  465. + reg = RT305X_ESW_REG_SGC2;
  466. + shift = RT305X_ESW_SGC2_LAN_PMAP_S;
  467. + if (idx >= RT305X_ESW_NUM_LANWAN)
  468. + return -EINVAL;
  469. + break;
  470. + default:
  471. + return -EINVAL;
  472. + }
  473. +
  474. + x = esw_r32(esw, reg);
  475. + val->value.i = (x >> (idx + shift)) & 1;
  476. +
  477. + return 0;
  478. +}
  479. +
  480. +static int esw_set_port_bool(struct switch_dev *dev,
  481. + const struct switch_attr *attr,
  482. + struct switch_val *val)
  483. +{
  484. + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev);
  485. + int idx = val->port_vlan;
  486. +
  487. + if (idx < 0 || idx >= RT305X_ESW_NUM_PORTS ||
  488. + val->value.i < 0 || val->value.i > 1)
  489. + return -EINVAL;
  490. +
  491. + switch (attr->id) {
  492. + case RT305X_ESW_ATTR_PORT_DISABLE:
  493. + esw->ports[idx].disable = val->value.i;
  494. + break;
  495. + case RT305X_ESW_ATTR_PORT_DOUBLETAG:
  496. + esw->ports[idx].doubletag = val->value.i;
  497. + break;
  498. + case RT305X_ESW_ATTR_PORT_UNTAG:
  499. + esw->ports[idx].untag = val->value.i;
  500. + break;
  501. + default:
  502. + return -EINVAL;
  503. + }
  504. +
  505. + return 0;
  506. +}
  507. +
  508. +static int esw_get_port_recv_badgood(struct switch_dev *dev,
  509. + const struct switch_attr *attr,
  510. + struct switch_val *val)
  511. +{
  512. + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev);
  513. + int idx = val->port_vlan;
  514. + int shift = attr->id == RT305X_ESW_ATTR_PORT_RECV_GOOD ? 0 : 16;
  515. + u32 reg;
  516. +
  517. + if (idx < 0 || idx >= RT305X_ESW_NUM_LANWAN)
  518. + return -EINVAL;
  519. + reg = esw_r32(esw, RT305X_ESW_REG_PXPC(idx));
  520. + val->value.i = (reg >> shift) & 0xffff;
  521. +
  522. + return 0;
  523. +}
  524. +
  525. +static int
  526. +esw_get_port_tr_badgood(struct switch_dev *dev,
  527. + const struct switch_attr *attr,
  528. + struct switch_val *val)
  529. +{
  530. + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev);
  531. +
  532. + int idx = val->port_vlan;
  533. + int shift = attr->id == RT5350_ESW_ATTR_PORT_TR_GOOD ? 0 : 16;
  534. + u32 reg;
  535. +
  536. + if ((ralink_soc != RT305X_SOC_RT5350) && (ralink_soc != MT762X_SOC_MT7628AN) && (ralink_soc != MT762X_SOC_MT7688))
  537. + return -EINVAL;
  538. +
  539. + if (idx < 0 || idx >= RT305X_ESW_NUM_LANWAN)
  540. + return -EINVAL;
  541. +
  542. + reg = esw_r32(esw, RT5350_ESW_REG_PXTPC(idx));
  543. + val->value.i = (reg >> shift) & 0xffff;
  544. +
  545. + return 0;
  546. +}
  547. +
  548. +static int esw_get_port_led(struct switch_dev *dev,
  549. + const struct switch_attr *attr,
  550. + struct switch_val *val)
  551. +{
  552. + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev);
  553. + int idx = val->port_vlan;
  554. +
  555. + if (idx < 0 || idx >= RT305X_ESW_NUM_PORTS ||
  556. + idx >= RT305X_ESW_NUM_LEDS)
  557. + return -EINVAL;
  558. +
  559. + val->value.i = esw_r32(esw, RT305X_ESW_REG_P0LED + 4*idx);
  560. +
  561. + return 0;
  562. +}
  563. +
  564. +static int esw_set_port_led(struct switch_dev *dev,
  565. + const struct switch_attr *attr,
  566. + struct switch_val *val)
  567. +{
  568. + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev);
  569. + int idx = val->port_vlan;
  570. +
  571. + if (idx < 0 || idx >= RT305X_ESW_NUM_LEDS)
  572. + return -EINVAL;
  573. +
  574. + esw->ports[idx].led = val->value.i;
  575. +
  576. + return 0;
  577. +}
  578. +
  579. +static int esw_get_port_pvid(struct switch_dev *dev, int port, int *val)
  580. +{
  581. + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev);
  582. +
  583. + if (port >= RT305X_ESW_NUM_PORTS)
  584. + return -EINVAL;
  585. +
  586. + *val = esw_get_pvid(esw, port);
  587. +
  588. + return 0;
  589. +}
  590. +
  591. +static int esw_set_port_pvid(struct switch_dev *dev, int port, int val)
  592. +{
  593. + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev);
  594. +
  595. + if (port >= RT305X_ESW_NUM_PORTS)
  596. + return -EINVAL;
  597. +
  598. + esw->ports[port].pvid = val;
  599. +
  600. + return 0;
  601. +}
  602. +
  603. +static int esw_get_vlan_ports(struct switch_dev *dev, struct switch_val *val)
  604. +{
  605. + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev);
  606. + u32 vmsc, poc2;
  607. + int vlan_idx = -1;
  608. + int i;
  609. +
  610. + val->len = 0;
  611. +
  612. + if (val->port_vlan < 0 || val->port_vlan >= RT305X_ESW_NUM_VIDS)
  613. + return -EINVAL;
  614. +
  615. + /* valid vlan? */
  616. + for (i = 0; i < RT305X_ESW_NUM_VLANS; i++) {
  617. + if (esw_get_vlan_id(esw, i) == val->port_vlan &&
  618. + esw_get_vmsc(esw, i) != RT305X_ESW_PORTS_NONE) {
  619. + vlan_idx = i;
  620. + break;
  621. + }
  622. + }
  623. +
  624. + if (vlan_idx == -1)
  625. + return -EINVAL;
  626. +
  627. + vmsc = esw_get_vmsc(esw, vlan_idx);
  628. + poc2 = esw_r32(esw, RT305X_ESW_REG_POC2);
  629. +
  630. + for (i = 0; i < RT305X_ESW_NUM_PORTS; i++) {
  631. + struct switch_port *p;
  632. + int port_mask = 1 << i;
  633. +
  634. + if (!(vmsc & port_mask))
  635. + continue;
  636. +
  637. + p = &val->value.ports[val->len++];
  638. + p->id = i;
  639. + if (poc2 & (port_mask << RT305X_ESW_POC2_UNTAG_EN_S))
  640. + p->flags = 0;
  641. + else
  642. + p->flags = 1 << SWITCH_PORT_FLAG_TAGGED;
  643. + }
  644. +
  645. + return 0;
  646. +}
  647. +
  648. +static int esw_set_vlan_ports(struct switch_dev *dev, struct switch_val *val)
  649. +{
  650. + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev);
  651. + int ports;
  652. + int vlan_idx = -1;
  653. + int i;
  654. +
  655. + if (val->port_vlan < 0 || val->port_vlan >= RT305X_ESW_NUM_VIDS ||
  656. + val->len > RT305X_ESW_NUM_PORTS)
  657. + return -EINVAL;
  658. +
  659. + /* one of the already defined vlans? */
  660. + for (i = 0; i < RT305X_ESW_NUM_VLANS; i++) {
  661. + if (esw->vlans[i].vid == val->port_vlan &&
  662. + esw->vlans[i].ports != RT305X_ESW_PORTS_NONE) {
  663. + vlan_idx = i;
  664. + break;
  665. + }
  666. + }
  667. +
  668. + /* select a free slot */
  669. + for (i = 0; vlan_idx == -1 && i < RT305X_ESW_NUM_VLANS; i++) {
  670. + if (esw->vlans[i].ports == RT305X_ESW_PORTS_NONE)
  671. + vlan_idx = i;
  672. + }
  673. +
  674. + /* bail if all slots are in use */
  675. + if (vlan_idx == -1)
  676. + return -EINVAL;
  677. +
  678. + ports = RT305X_ESW_PORTS_NONE;
  679. + for (i = 0; i < val->len; i++) {
  680. + struct switch_port *p = &val->value.ports[i];
  681. + int port_mask = 1 << p->id;
  682. + bool untagged = !(p->flags & (1 << SWITCH_PORT_FLAG_TAGGED));
  683. +
  684. + if (p->id >= RT305X_ESW_NUM_PORTS)
  685. + return -EINVAL;
  686. +
  687. + ports |= port_mask;
  688. + esw->ports[p->id].untag = untagged;
  689. + }
  690. + esw->vlans[vlan_idx].ports = ports;
  691. + if (ports == RT305X_ESW_PORTS_NONE)
  692. + esw->vlans[vlan_idx].vid = RT305X_ESW_VLAN_NONE;
  693. + else
  694. + esw->vlans[vlan_idx].vid = val->port_vlan;
  695. +
  696. + return 0;
  697. +}
  698. +
  699. +static const struct switch_attr esw_global[] = {
  700. + {
  701. + .type = SWITCH_TYPE_INT,
  702. + .name = "enable_vlan",
  703. + .description = "VLAN mode (1:enabled)",
  704. + .max = 1,
  705. + .id = RT305X_ESW_ATTR_ENABLE_VLAN,
  706. + .get = esw_get_vlan_enable,
  707. + .set = esw_set_vlan_enable,
  708. + },
  709. + {
  710. + .type = SWITCH_TYPE_INT,
  711. + .name = "alternate_vlan_disable",
  712. + .description = "Use en_vlan instead of doubletag to disable"
  713. + " VLAN mode",
  714. + .max = 1,
  715. + .id = RT305X_ESW_ATTR_ALT_VLAN_DISABLE,
  716. + .get = esw_get_alt_vlan_disable,
  717. + .set = esw_set_alt_vlan_disable,
  718. + },
  719. + {
  720. + .type = SWITCH_TYPE_INT,
  721. + .name = "bc_storm_protect",
  722. + .description = "Global broadcast storm protection (0:Disable, 1:64 blocks, 2:96 blocks, 3:128 blocks)",
  723. + .max = 3,
  724. + .id = RT305X_ESW_ATTR_BC_STATUS,
  725. + .get = rt305x_esw_get_bc_status,
  726. + .set = rt305x_esw_set_bc_status,
  727. + },
  728. + {
  729. + .type = SWITCH_TYPE_INT,
  730. + .name = "led_frequency",
  731. + .description = "LED Flash frequency (0:30mS, 1:60mS, 2:240mS, 3:480mS)",
  732. + .max = 3,
  733. + .id = RT305X_ESW_ATTR_LED_FREQ,
  734. + .get = rt305x_esw_get_led_freq,
  735. + .set = rt305x_esw_set_led_freq,
  736. + }
  737. +};
  738. +
  739. +static const struct switch_attr esw_port[] = {
  740. + {
  741. + .type = SWITCH_TYPE_INT,
  742. + .name = "disable",
  743. + .description = "Port state (1:disabled)",
  744. + .max = 1,
  745. + .id = RT305X_ESW_ATTR_PORT_DISABLE,
  746. + .get = esw_get_port_bool,
  747. + .set = esw_set_port_bool,
  748. + },
  749. + {
  750. + .type = SWITCH_TYPE_INT,
  751. + .name = "doubletag",
  752. + .description = "Double tagging for incoming vlan packets "
  753. + "(1:enabled)",
  754. + .max = 1,
  755. + .id = RT305X_ESW_ATTR_PORT_DOUBLETAG,
  756. + .get = esw_get_port_bool,
  757. + .set = esw_set_port_bool,
  758. + },
  759. + {
  760. + .type = SWITCH_TYPE_INT,
  761. + .name = "untag",
  762. + .description = "Untag (1:strip outgoing vlan tag)",
  763. + .max = 1,
  764. + .id = RT305X_ESW_ATTR_PORT_UNTAG,
  765. + .get = esw_get_port_bool,
  766. + .set = esw_set_port_bool,
  767. + },
  768. + {
  769. + .type = SWITCH_TYPE_INT,
  770. + .name = "led",
  771. + .description = "LED mode (0:link, 1:100m, 2:duplex, 3:activity,"
  772. + " 4:collision, 5:linkact, 6:duplcoll, 7:10mact,"
  773. + " 8:100mact, 10:blink, 11:off, 12:on)",
  774. + .max = 15,
  775. + .id = RT305X_ESW_ATTR_PORT_LED,
  776. + .get = esw_get_port_led,
  777. + .set = esw_set_port_led,
  778. + },
  779. + {
  780. + .type = SWITCH_TYPE_INT,
  781. + .name = "lan",
  782. + .description = "HW port group (0:wan, 1:lan)",
  783. + .max = 1,
  784. + .id = RT305X_ESW_ATTR_PORT_LAN,
  785. + .get = esw_get_port_bool,
  786. + },
  787. + {
  788. + .type = SWITCH_TYPE_INT,
  789. + .name = "recv_bad",
  790. + .description = "Receive bad packet counter",
  791. + .id = RT305X_ESW_ATTR_PORT_RECV_BAD,
  792. + .get = esw_get_port_recv_badgood,
  793. + },
  794. + {
  795. + .type = SWITCH_TYPE_INT,
  796. + .name = "recv_good",
  797. + .description = "Receive good packet counter",
  798. + .id = RT305X_ESW_ATTR_PORT_RECV_GOOD,
  799. + .get = esw_get_port_recv_badgood,
  800. + },
  801. + {
  802. + .type = SWITCH_TYPE_INT,
  803. + .name = "tr_bad",
  804. +
  805. + .description = "Transmit bad packet counter. rt5350 only",
  806. + .id = RT5350_ESW_ATTR_PORT_TR_BAD,
  807. + .get = esw_get_port_tr_badgood,
  808. + },
  809. + {
  810. + .type = SWITCH_TYPE_INT,
  811. + .name = "tr_good",
  812. +
  813. + .description = "Transmit good packet counter. rt5350 only",
  814. + .id = RT5350_ESW_ATTR_PORT_TR_GOOD,
  815. + .get = esw_get_port_tr_badgood,
  816. + },
  817. +};
  818. +
  819. +static const struct switch_attr esw_vlan[] = {
  820. +};
  821. +
  822. +static const struct switch_dev_ops esw_ops = {
  823. + .attr_global = {
  824. + .attr = esw_global,
  825. + .n_attr = ARRAY_SIZE(esw_global),
  826. + },
  827. + .attr_port = {
  828. + .attr = esw_port,
  829. + .n_attr = ARRAY_SIZE(esw_port),
  830. + },
  831. + .attr_vlan = {
  832. + .attr = esw_vlan,
  833. + .n_attr = ARRAY_SIZE(esw_vlan),
  834. + },
  835. + .get_vlan_ports = esw_get_vlan_ports,
  836. + .set_vlan_ports = esw_set_vlan_ports,
  837. + .get_port_pvid = esw_get_port_pvid,
  838. + .set_port_pvid = esw_set_port_pvid,
  839. + .get_port_link = esw_get_port_link,
  840. + .apply_config = esw_apply_config,
  841. + .reset_switch = esw_reset_switch,
  842. +};
  843. +
  844. static int esw_probe(struct platform_device *pdev)
  845. {
  846. struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  847. struct device_node *np = pdev->dev.of_node;
  848. const __be32 *port_map, *reg_init;
  849. + struct switch_dev *swdev;
  850. struct rt305x_esw *esw;
  851. struct resource *irq;
  852. int ret;
  853. @@ -568,6 +1353,21 @@ static int esw_probe(struct platform_dev
  854. if (reg_init)
  855. esw->reg_led_polarity = be32_to_cpu(*reg_init);
  856. + swdev = &esw->swdev;
  857. + swdev->of_node = pdev->dev.of_node;
  858. + swdev->name = "rt305x-esw";
  859. + swdev->alias = "rt305x";
  860. + swdev->cpu_port = RT305X_ESW_PORT6;
  861. + swdev->ports = RT305X_ESW_NUM_PORTS;
  862. + swdev->vlans = RT305X_ESW_NUM_VIDS;
  863. + swdev->ops = &esw_ops;
  864. +
  865. + ret = register_switch(swdev, NULL);
  866. + if (ret < 0) {
  867. + dev_err(&pdev->dev, "register_switch failed\n");
  868. + goto unmap_base;
  869. + }
  870. +
  871. platform_set_drvdata(pdev, esw);
  872. spin_lock_init(&esw->reg_rw_lock);
  873. @@ -583,6 +1383,11 @@ static int esw_probe(struct platform_dev
  874. }
  875. return ret;
  876. +
  877. +unmap_base:
  878. + iounmap(esw->base);
  879. + kfree(esw);
  880. + return ret;
  881. }
  882. static int esw_remove(struct platform_device *pdev)