0502-net-next-mediatek-add-switch-driver-for-rt3050.patch 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691
  1. From 2c39ddc83452c34fedc86261ed1f96d7537adfd1 Mon Sep 17 00:00:00 2001
  2. From: John Crispin <blogic@openwrt.org>
  3. Date: Mon, 14 Dec 2015 21:28:10 +0100
  4. Subject: [PATCH 502/513] net-next: mediatek: add switch driver for rt3050
  5. This driver is very basic and only provides basic init and irq support.
  6. Switchdev support for this device will follow.
  7. Signed-off-by: John Crispin <blogic@openwrt.org>
  8. ---
  9. drivers/net/ethernet/mediatek/esw_rt3050.c | 640 ++++++++++++++++++++++++++++
  10. drivers/net/ethernet/mediatek/esw_rt3050.h | 29 ++
  11. 2 files changed, 669 insertions(+)
  12. create mode 100644 drivers/net/ethernet/mediatek/esw_rt3050.c
  13. create mode 100644 drivers/net/ethernet/mediatek/esw_rt3050.h
  14. --- /dev/null
  15. +++ b/drivers/net/ethernet/mediatek/esw_rt3050.c
  16. @@ -0,0 +1,640 @@
  17. +/* This program is free software; you can redistribute it and/or modify
  18. + * it under the terms of the GNU General Public License as published by
  19. + * the Free Software Foundation; version 2 of the License
  20. + *
  21. + * This program is distributed in the hope that it will be useful,
  22. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  23. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  24. + * GNU General Public License for more details.
  25. + *
  26. + * Copyright (C) 2009-2015 John Crispin <blogic@openwrt.org>
  27. + * Copyright (C) 2009-2015 Felix Fietkau <nbd@nbd.name>
  28. + * Copyright (C) 2013-2015 Michael Lee <igvtee@gmail.com>
  29. + */
  30. +
  31. +#include <linux/module.h>
  32. +#include <linux/kernel.h>
  33. +#include <linux/types.h>
  34. +#include <linux/dma-mapping.h>
  35. +#include <linux/init.h>
  36. +#include <linux/skbuff.h>
  37. +#include <linux/etherdevice.h>
  38. +#include <linux/ethtool.h>
  39. +#include <linux/platform_device.h>
  40. +#include <linux/of_device.h>
  41. +#include <linux/clk.h>
  42. +#include <linux/of_net.h>
  43. +#include <linux/of_mdio.h>
  44. +
  45. +#include <asm/mach-ralink/ralink_regs.h>
  46. +
  47. +#include "mtk_eth_soc.h"
  48. +
  49. +#include <linux/ioport.h>
  50. +#include <linux/mii.h>
  51. +
  52. +#include <ralink_regs.h>
  53. +
  54. +/* HW limitations for this switch:
  55. + * - No large frame support (PKT_MAX_LEN at most 1536)
  56. + * - Can't have untagged vlan and tagged vlan on one port at the same time,
  57. + * though this might be possible using the undocumented PPE.
  58. + */
  59. +
  60. +#define RT305X_ESW_REG_ISR 0x00
  61. +#define RT305X_ESW_REG_IMR 0x04
  62. +#define RT305X_ESW_REG_FCT0 0x08
  63. +#define RT305X_ESW_REG_PFC1 0x14
  64. +#define RT305X_ESW_REG_ATS 0x24
  65. +#define RT305X_ESW_REG_ATS0 0x28
  66. +#define RT305X_ESW_REG_ATS1 0x2c
  67. +#define RT305X_ESW_REG_ATS2 0x30
  68. +#define RT305X_ESW_REG_PVIDC(_n) (0x40 + 4 * (_n))
  69. +#define RT305X_ESW_REG_VLANI(_n) (0x50 + 4 * (_n))
  70. +#define RT305X_ESW_REG_VMSC(_n) (0x70 + 4 * (_n))
  71. +#define RT305X_ESW_REG_POA 0x80
  72. +#define RT305X_ESW_REG_FPA 0x84
  73. +#define RT305X_ESW_REG_SOCPC 0x8c
  74. +#define RT305X_ESW_REG_POC0 0x90
  75. +#define RT305X_ESW_REG_POC1 0x94
  76. +#define RT305X_ESW_REG_POC2 0x98
  77. +#define RT305X_ESW_REG_SGC 0x9c
  78. +#define RT305X_ESW_REG_STRT 0xa0
  79. +#define RT305X_ESW_REG_PCR0 0xc0
  80. +#define RT305X_ESW_REG_PCR1 0xc4
  81. +#define RT305X_ESW_REG_FPA2 0xc8
  82. +#define RT305X_ESW_REG_FCT2 0xcc
  83. +#define RT305X_ESW_REG_SGC2 0xe4
  84. +#define RT305X_ESW_REG_P0LED 0xa4
  85. +#define RT305X_ESW_REG_P1LED 0xa8
  86. +#define RT305X_ESW_REG_P2LED 0xac
  87. +#define RT305X_ESW_REG_P3LED 0xb0
  88. +#define RT305X_ESW_REG_P4LED 0xb4
  89. +#define RT305X_ESW_REG_PXPC(_x) (0xe8 + (4 * _x))
  90. +#define RT305X_ESW_REG_P1PC 0xec
  91. +#define RT305X_ESW_REG_P2PC 0xf0
  92. +#define RT305X_ESW_REG_P3PC 0xf4
  93. +#define RT305X_ESW_REG_P4PC 0xf8
  94. +#define RT305X_ESW_REG_P5PC 0xfc
  95. +
  96. +#define RT305X_ESW_LED_LINK 0
  97. +#define RT305X_ESW_LED_100M 1
  98. +#define RT305X_ESW_LED_DUPLEX 2
  99. +#define RT305X_ESW_LED_ACTIVITY 3
  100. +#define RT305X_ESW_LED_COLLISION 4
  101. +#define RT305X_ESW_LED_LINKACT 5
  102. +#define RT305X_ESW_LED_DUPLCOLL 6
  103. +#define RT305X_ESW_LED_10MACT 7
  104. +#define RT305X_ESW_LED_100MACT 8
  105. +/* Additional led states not in datasheet: */
  106. +#define RT305X_ESW_LED_BLINK 10
  107. +#define RT305X_ESW_LED_ON 12
  108. +
  109. +#define RT305X_ESW_LINK_S 25
  110. +#define RT305X_ESW_DUPLEX_S 9
  111. +#define RT305X_ESW_SPD_S 0
  112. +
  113. +#define RT305X_ESW_PCR0_WT_NWAY_DATA_S 16
  114. +#define RT305X_ESW_PCR0_WT_PHY_CMD BIT(13)
  115. +#define RT305X_ESW_PCR0_CPU_PHY_REG_S 8
  116. +
  117. +#define RT305X_ESW_PCR1_WT_DONE BIT(0)
  118. +
  119. +#define RT305X_ESW_ATS_TIMEOUT (5 * HZ)
  120. +#define RT305X_ESW_PHY_TIMEOUT (5 * HZ)
  121. +
  122. +#define RT305X_ESW_PVIDC_PVID_M 0xfff
  123. +#define RT305X_ESW_PVIDC_PVID_S 12
  124. +
  125. +#define RT305X_ESW_VLANI_VID_M 0xfff
  126. +#define RT305X_ESW_VLANI_VID_S 12
  127. +
  128. +#define RT305X_ESW_VMSC_MSC_M 0xff
  129. +#define RT305X_ESW_VMSC_MSC_S 8
  130. +
  131. +#define RT305X_ESW_SOCPC_DISUN2CPU_S 0
  132. +#define RT305X_ESW_SOCPC_DISMC2CPU_S 8
  133. +#define RT305X_ESW_SOCPC_DISBC2CPU_S 16
  134. +#define RT305X_ESW_SOCPC_CRC_PADDING BIT(25)
  135. +
  136. +#define RT305X_ESW_POC0_EN_BP_S 0
  137. +#define RT305X_ESW_POC0_EN_FC_S 8
  138. +#define RT305X_ESW_POC0_DIS_RMC2CPU_S 16
  139. +#define RT305X_ESW_POC0_DIS_PORT_M 0x7f
  140. +#define RT305X_ESW_POC0_DIS_PORT_S 23
  141. +
  142. +#define RT305X_ESW_POC2_UNTAG_EN_M 0xff
  143. +#define RT305X_ESW_POC2_UNTAG_EN_S 0
  144. +#define RT305X_ESW_POC2_ENAGING_S 8
  145. +#define RT305X_ESW_POC2_DIS_UC_PAUSE_S 16
  146. +
  147. +#define RT305X_ESW_SGC2_DOUBLE_TAG_M 0x7f
  148. +#define RT305X_ESW_SGC2_DOUBLE_TAG_S 0
  149. +#define RT305X_ESW_SGC2_LAN_PMAP_M 0x3f
  150. +#define RT305X_ESW_SGC2_LAN_PMAP_S 24
  151. +
  152. +#define RT305X_ESW_PFC1_EN_VLAN_M 0xff
  153. +#define RT305X_ESW_PFC1_EN_VLAN_S 16
  154. +#define RT305X_ESW_PFC1_EN_TOS_S 24
  155. +
  156. +#define RT305X_ESW_VLAN_NONE 0xfff
  157. +
  158. +#define RT305X_ESW_GSC_BC_STROM_MASK 0x3
  159. +#define RT305X_ESW_GSC_BC_STROM_SHIFT 4
  160. +
  161. +#define RT305X_ESW_GSC_LED_FREQ_MASK 0x3
  162. +#define RT305X_ESW_GSC_LED_FREQ_SHIFT 23
  163. +
  164. +#define RT305X_ESW_POA_LINK_MASK 0x1f
  165. +#define RT305X_ESW_POA_LINK_SHIFT 25
  166. +
  167. +#define RT305X_ESW_PORT_ST_CHG BIT(26)
  168. +#define RT305X_ESW_PORT0 0
  169. +#define RT305X_ESW_PORT1 1
  170. +#define RT305X_ESW_PORT2 2
  171. +#define RT305X_ESW_PORT3 3
  172. +#define RT305X_ESW_PORT4 4
  173. +#define RT305X_ESW_PORT5 5
  174. +#define RT305X_ESW_PORT6 6
  175. +
  176. +#define RT305X_ESW_PMAP_LLLLLL 0x3f
  177. +#define RT305X_ESW_PMAP_LLLLWL 0x2f
  178. +#define RT305X_ESW_PMAP_WLLLLL 0x3e
  179. +
  180. +#define RT305X_ESW_PORTS_INTERNAL \
  181. + (BIT(RT305X_ESW_PORT0) | BIT(RT305X_ESW_PORT1) | \
  182. + BIT(RT305X_ESW_PORT2) | BIT(RT305X_ESW_PORT3) | \
  183. + BIT(RT305X_ESW_PORT4))
  184. +
  185. +#define RT305X_ESW_PORTS_NOCPU \
  186. + (RT305X_ESW_PORTS_INTERNAL | BIT(RT305X_ESW_PORT5))
  187. +
  188. +#define RT305X_ESW_PORTS_CPU BIT(RT305X_ESW_PORT6)
  189. +
  190. +#define RT305X_ESW_PORTS_ALL \
  191. + (RT305X_ESW_PORTS_NOCPU | RT305X_ESW_PORTS_CPU)
  192. +
  193. +#define RT305X_ESW_NUM_PORTS 7
  194. +#define RT305X_ESW_NUM_LEDS 5
  195. +
  196. +#define RT5350_EWS_REG_LED_POLARITY 0x168
  197. +#define RT5350_RESET_EPHY BIT(24)
  198. +
  199. +struct esw_port {
  200. + bool disable;
  201. + u8 led;
  202. +};
  203. +
  204. +struct rt305x_esw {
  205. + struct device *dev;
  206. + void __iomem *base;
  207. + int irq;
  208. +
  209. + /* Protects against concurrent register r/w operations. */
  210. + spinlock_t reg_rw_lock;
  211. +
  212. + unsigned char port_map;
  213. + unsigned int reg_led_polarity;
  214. +
  215. + struct esw_port ports[RT305X_ESW_NUM_PORTS];
  216. +
  217. +};
  218. +
  219. +static inline void esw_w32(struct rt305x_esw *esw, u32 val, unsigned reg)
  220. +{
  221. + __raw_writel(val, esw->base + reg);
  222. +}
  223. +
  224. +static inline u32 esw_r32(struct rt305x_esw *esw, unsigned reg)
  225. +{
  226. + return __raw_readl(esw->base + reg);
  227. +}
  228. +
  229. +static inline void esw_rmw_raw(struct rt305x_esw *esw, unsigned reg,
  230. + unsigned long mask, unsigned long val)
  231. +{
  232. + unsigned long t;
  233. +
  234. + t = __raw_readl(esw->base + reg) & ~mask;
  235. + __raw_writel(t | val, esw->base + reg);
  236. +}
  237. +
  238. +static void esw_rmw(struct rt305x_esw *esw, unsigned reg,
  239. + unsigned long mask, unsigned long val)
  240. +{
  241. + unsigned long flags;
  242. +
  243. + spin_lock_irqsave(&esw->reg_rw_lock, flags);
  244. + esw_rmw_raw(esw, reg, mask, val);
  245. + spin_unlock_irqrestore(&esw->reg_rw_lock, flags);
  246. +}
  247. +
  248. +static u32 rt305x_mii_write(struct rt305x_esw *esw, u32 phy_addr,
  249. + u32 phy_register, u32 write_data)
  250. +{
  251. + unsigned long t_start = jiffies;
  252. + int ret = 0;
  253. +
  254. + while (1) {
  255. + if (!(esw_r32(esw, RT305X_ESW_REG_PCR1) &
  256. + RT305X_ESW_PCR1_WT_DONE))
  257. + break;
  258. + if (time_after(jiffies, t_start + RT305X_ESW_PHY_TIMEOUT)) {
  259. + ret = 1;
  260. + goto out;
  261. + }
  262. + }
  263. +
  264. + write_data &= 0xffff;
  265. + esw_w32(esw, (write_data << RT305X_ESW_PCR0_WT_NWAY_DATA_S) |
  266. + (phy_register << RT305X_ESW_PCR0_CPU_PHY_REG_S) |
  267. + (phy_addr) | RT305X_ESW_PCR0_WT_PHY_CMD,
  268. + RT305X_ESW_REG_PCR0);
  269. +
  270. + t_start = jiffies;
  271. + while (1) {
  272. + if (esw_r32(esw, RT305X_ESW_REG_PCR1) &
  273. + RT305X_ESW_PCR1_WT_DONE)
  274. + break;
  275. +
  276. + if (time_after(jiffies, t_start + RT305X_ESW_PHY_TIMEOUT)) {
  277. + ret = 1;
  278. + break;
  279. + }
  280. + }
  281. +out:
  282. + if (ret)
  283. + dev_err(esw->dev, "ramips_eth: MDIO timeout\n");
  284. + return ret;
  285. +}
  286. +
  287. +static unsigned esw_get_port_disable(struct rt305x_esw *esw)
  288. +{
  289. + unsigned reg;
  290. +
  291. + reg = esw_r32(esw, RT305X_ESW_REG_POC0);
  292. + return (reg >> RT305X_ESW_POC0_DIS_PORT_S) &
  293. + RT305X_ESW_POC0_DIS_PORT_M;
  294. +}
  295. +
  296. +static void esw_hw_init(struct rt305x_esw *esw)
  297. +{
  298. + int i;
  299. + u8 port_disable = 0;
  300. + u8 port_map = RT305X_ESW_PMAP_LLLLLL;
  301. +
  302. + /* vodoo from original driver */
  303. + esw_w32(esw, 0xC8A07850, RT305X_ESW_REG_FCT0);
  304. + esw_w32(esw, 0x00000000, RT305X_ESW_REG_SGC2);
  305. + /* Port priority 1 for all ports, vlan enabled. */
  306. + esw_w32(esw, 0x00005555 |
  307. + (RT305X_ESW_PORTS_ALL << RT305X_ESW_PFC1_EN_VLAN_S),
  308. + RT305X_ESW_REG_PFC1);
  309. +
  310. + /* Enable Back Pressure, and Flow Control */
  311. + esw_w32(esw, ((RT305X_ESW_PORTS_ALL << RT305X_ESW_POC0_EN_BP_S) |
  312. + (RT305X_ESW_PORTS_ALL << RT305X_ESW_POC0_EN_FC_S)),
  313. + RT305X_ESW_REG_POC0);
  314. +
  315. + /* Enable Aging, and VLAN TAG removal */
  316. + esw_w32(esw, ((RT305X_ESW_PORTS_ALL << RT305X_ESW_POC2_ENAGING_S) |
  317. + (RT305X_ESW_PORTS_NOCPU << RT305X_ESW_POC2_UNTAG_EN_S)),
  318. + RT305X_ESW_REG_POC2);
  319. +
  320. + esw_w32(esw, 0x00d6500c, RT305X_ESW_REG_FCT2);
  321. +
  322. + /* 300s aging timer, max packet len 1536, broadcast storm prevention
  323. + * disabled, disable collision abort, mac xor48 hash, 10 packet back
  324. + * pressure jam, GMII disable was_transmit, back pressure disabled,
  325. + * 30ms led flash, unmatched IGMP as broadcast, rmc tb fault to all
  326. + * ports.
  327. + */
  328. + esw_w32(esw, 0x0008a301, RT305X_ESW_REG_SGC);
  329. +
  330. + /* Setup SoC Port control register */
  331. + esw_w32(esw,
  332. + (RT305X_ESW_SOCPC_CRC_PADDING |
  333. + (RT305X_ESW_PORTS_CPU << RT305X_ESW_SOCPC_DISUN2CPU_S) |
  334. + (RT305X_ESW_PORTS_CPU << RT305X_ESW_SOCPC_DISMC2CPU_S) |
  335. + (RT305X_ESW_PORTS_CPU << RT305X_ESW_SOCPC_DISBC2CPU_S)),
  336. + RT305X_ESW_REG_SOCPC);
  337. +
  338. + /* ext phy base addr 31, enable port 5 polling, rx/tx clock skew 1,
  339. + * turbo mii off, rgmi 3.3v off
  340. + * port5: disabled
  341. + * port6: enabled, gige, full-duplex, rx/tx-flow-control
  342. + */
  343. + esw_w32(esw, 0x3f502b28, RT305X_ESW_REG_FPA2);
  344. + esw_w32(esw, 0x00000000, RT305X_ESW_REG_FPA);
  345. +
  346. + /* Force Link/Activity on ports */
  347. + esw_w32(esw, 0x00000005, RT305X_ESW_REG_P0LED);
  348. + esw_w32(esw, 0x00000005, RT305X_ESW_REG_P1LED);
  349. + esw_w32(esw, 0x00000005, RT305X_ESW_REG_P2LED);
  350. + esw_w32(esw, 0x00000005, RT305X_ESW_REG_P3LED);
  351. + esw_w32(esw, 0x00000005, RT305X_ESW_REG_P4LED);
  352. +
  353. + /* Copy disabled port configuration from bootloader setup */
  354. + port_disable = esw_get_port_disable(esw);
  355. + for (i = 0; i < 6; i++)
  356. + esw->ports[i].disable = (port_disable & (1 << i)) != 0;
  357. +
  358. + if (ralink_soc == RT305X_SOC_RT3352) {
  359. + /* reset EPHY */
  360. + fe_reset(RT5350_RESET_EPHY);
  361. +
  362. + rt305x_mii_write(esw, 0, 31, 0x8000);
  363. + for (i = 0; i < 5; i++) {
  364. + if (esw->ports[i].disable) {
  365. + rt305x_mii_write(esw, i, MII_BMCR, BMCR_PDOWN);
  366. + } else {
  367. + rt305x_mii_write(esw, i, MII_BMCR,
  368. + BMCR_FULLDPLX |
  369. + BMCR_ANENABLE |
  370. + BMCR_SPEED100);
  371. + }
  372. + /* TX10 waveform coefficient LSB=0 disable PHY */
  373. + rt305x_mii_write(esw, i, 26, 0x1601);
  374. + /* TX100/TX10 AD/DA current bias */
  375. + rt305x_mii_write(esw, i, 29, 0x7016);
  376. + /* TX100 slew rate control */
  377. + rt305x_mii_write(esw, i, 30, 0x0038);
  378. + }
  379. +
  380. + /* select global register */
  381. + rt305x_mii_write(esw, 0, 31, 0x0);
  382. + /* enlarge agcsel threshold 3 and threshold 2 */
  383. + rt305x_mii_write(esw, 0, 1, 0x4a40);
  384. + /* enlarge agcsel threshold 5 and threshold 4 */
  385. + rt305x_mii_write(esw, 0, 2, 0x6254);
  386. + /* enlarge agcsel threshold */
  387. + rt305x_mii_write(esw, 0, 3, 0xa17f);
  388. + rt305x_mii_write(esw, 0, 12, 0x7eaa);
  389. + /* longer TP_IDL tail length */
  390. + rt305x_mii_write(esw, 0, 14, 0x65);
  391. + /* increased squelch pulse count threshold. */
  392. + rt305x_mii_write(esw, 0, 16, 0x0684);
  393. + /* set TX10 signal amplitude threshold to minimum */
  394. + rt305x_mii_write(esw, 0, 17, 0x0fe0);
  395. + /* set squelch amplitude to higher threshold */
  396. + rt305x_mii_write(esw, 0, 18, 0x40ba);
  397. + /* tune TP_IDL tail and head waveform, enable power
  398. + * down slew rate control
  399. + */
  400. + rt305x_mii_write(esw, 0, 22, 0x253f);
  401. + /* set PLL/Receive bias current are calibrated */
  402. + rt305x_mii_write(esw, 0, 27, 0x2fda);
  403. + /* change PLL/Receive bias current to internal(RT3350) */
  404. + rt305x_mii_write(esw, 0, 28, 0xc410);
  405. + /* change PLL bias current to internal(RT3052_MP3) */
  406. + rt305x_mii_write(esw, 0, 29, 0x598b);
  407. + /* select local register */
  408. + rt305x_mii_write(esw, 0, 31, 0x8000);
  409. + } else if (ralink_soc == RT305X_SOC_RT5350) {
  410. + /* reset EPHY */
  411. + fe_reset(RT5350_RESET_EPHY);
  412. +
  413. + /* set the led polarity */
  414. + esw_w32(esw, esw->reg_led_polarity & 0x1F,
  415. + RT5350_EWS_REG_LED_POLARITY);
  416. +
  417. + /* local registers */
  418. + rt305x_mii_write(esw, 0, 31, 0x8000);
  419. + for (i = 0; i < 5; i++) {
  420. + if (esw->ports[i].disable) {
  421. + rt305x_mii_write(esw, i, MII_BMCR, BMCR_PDOWN);
  422. + } else {
  423. + rt305x_mii_write(esw, i, MII_BMCR,
  424. + BMCR_FULLDPLX |
  425. + BMCR_ANENABLE |
  426. + BMCR_SPEED100);
  427. + }
  428. + /* TX10 waveform coefficient LSB=0 disable PHY */
  429. + rt305x_mii_write(esw, i, 26, 0x1601);
  430. + /* TX100/TX10 AD/DA current bias */
  431. + rt305x_mii_write(esw, i, 29, 0x7015);
  432. + /* TX100 slew rate control */
  433. + rt305x_mii_write(esw, i, 30, 0x0038);
  434. + }
  435. +
  436. + /* global registers */
  437. + rt305x_mii_write(esw, 0, 31, 0x0);
  438. + /* enlarge agcsel threshold 3 and threshold 2 */
  439. + rt305x_mii_write(esw, 0, 1, 0x4a40);
  440. + /* enlarge agcsel threshold 5 and threshold 4 */
  441. + rt305x_mii_write(esw, 0, 2, 0x6254);
  442. + /* enlarge agcsel threshold 6 */
  443. + rt305x_mii_write(esw, 0, 3, 0xa17f);
  444. + rt305x_mii_write(esw, 0, 12, 0x7eaa);
  445. + /* longer TP_IDL tail length */
  446. + rt305x_mii_write(esw, 0, 14, 0x65);
  447. + /* increased squelch pulse count threshold. */
  448. + rt305x_mii_write(esw, 0, 16, 0x0684);
  449. + /* set TX10 signal amplitude threshold to minimum */
  450. + rt305x_mii_write(esw, 0, 17, 0x0fe0);
  451. + /* set squelch amplitude to higher threshold */
  452. + rt305x_mii_write(esw, 0, 18, 0x40ba);
  453. + /* tune TP_IDL tail and head waveform, enable power
  454. + * down slew rate control
  455. + */
  456. + rt305x_mii_write(esw, 0, 22, 0x253f);
  457. + /* set PLL/Receive bias current are calibrated */
  458. + rt305x_mii_write(esw, 0, 27, 0x2fda);
  459. + /* change PLL/Receive bias current to internal(RT3350) */
  460. + rt305x_mii_write(esw, 0, 28, 0xc410);
  461. + /* change PLL bias current to internal(RT3052_MP3) */
  462. + rt305x_mii_write(esw, 0, 29, 0x598b);
  463. + /* select local register */
  464. + rt305x_mii_write(esw, 0, 31, 0x8000);
  465. + } else if (ralink_soc == MT762X_SOC_MT7628AN || ralink_soc == MT762X_SOC_MT7688) {
  466. + int i;
  467. +
  468. + /* reset EPHY */
  469. + fe_reset(RT5350_RESET_EPHY);
  470. +
  471. + rt305x_mii_write(esw, 0, 31, 0x2000); /* change G2 page */
  472. + rt305x_mii_write(esw, 0, 26, 0x0020);
  473. +
  474. + for (i = 0; i < 5; i++) {
  475. + rt305x_mii_write(esw, i, 31, 0x8000);
  476. + rt305x_mii_write(esw, i, 0, 0x3100);
  477. + rt305x_mii_write(esw, i, 30, 0xa000);
  478. + rt305x_mii_write(esw, i, 31, 0xa000);
  479. + rt305x_mii_write(esw, i, 16, 0x0606);
  480. + rt305x_mii_write(esw, i, 23, 0x0f0e);
  481. + rt305x_mii_write(esw, i, 24, 0x1610);
  482. + rt305x_mii_write(esw, i, 30, 0x1f15);
  483. + rt305x_mii_write(esw, i, 28, 0x6111);
  484. + rt305x_mii_write(esw, i, 31, 0x2000);
  485. + rt305x_mii_write(esw, i, 26, 0x0000);
  486. + }
  487. +
  488. + /* 100Base AOI setting */
  489. + rt305x_mii_write(esw, 0, 31, 0x5000);
  490. + rt305x_mii_write(esw, 0, 19, 0x004a);
  491. + rt305x_mii_write(esw, 0, 20, 0x015a);
  492. + rt305x_mii_write(esw, 0, 21, 0x00ee);
  493. + rt305x_mii_write(esw, 0, 22, 0x0033);
  494. + rt305x_mii_write(esw, 0, 23, 0x020a);
  495. + rt305x_mii_write(esw, 0, 24, 0x0000);
  496. + rt305x_mii_write(esw, 0, 25, 0x024a);
  497. + rt305x_mii_write(esw, 0, 26, 0x035a);
  498. + rt305x_mii_write(esw, 0, 27, 0x02ee);
  499. + rt305x_mii_write(esw, 0, 28, 0x0233);
  500. + rt305x_mii_write(esw, 0, 29, 0x000a);
  501. + rt305x_mii_write(esw, 0, 30, 0x0000);
  502. + } else {
  503. + rt305x_mii_write(esw, 0, 31, 0x8000);
  504. + for (i = 0; i < 5; i++) {
  505. + if (esw->ports[i].disable) {
  506. + rt305x_mii_write(esw, i, MII_BMCR, BMCR_PDOWN);
  507. + } else {
  508. + rt305x_mii_write(esw, i, MII_BMCR,
  509. + BMCR_FULLDPLX |
  510. + BMCR_ANENABLE |
  511. + BMCR_SPEED100);
  512. + }
  513. + /* TX10 waveform coefficient */
  514. + rt305x_mii_write(esw, i, 26, 0x1601);
  515. + /* TX100/TX10 AD/DA current bias */
  516. + rt305x_mii_write(esw, i, 29, 0x7058);
  517. + /* TX100 slew rate control */
  518. + rt305x_mii_write(esw, i, 30, 0x0018);
  519. + }
  520. +
  521. + /* PHY IOT */
  522. + /* select global register */
  523. + rt305x_mii_write(esw, 0, 31, 0x0);
  524. + /* tune TP_IDL tail and head waveform */
  525. + rt305x_mii_write(esw, 0, 22, 0x052f);
  526. + /* set TX10 signal amplitude threshold to minimum */
  527. + rt305x_mii_write(esw, 0, 17, 0x0fe0);
  528. + /* set squelch amplitude to higher threshold */
  529. + rt305x_mii_write(esw, 0, 18, 0x40ba);
  530. + /* longer TP_IDL tail length */
  531. + rt305x_mii_write(esw, 0, 14, 0x65);
  532. + /* select local register */
  533. + rt305x_mii_write(esw, 0, 31, 0x8000);
  534. + }
  535. +
  536. + if (esw->port_map)
  537. + port_map = esw->port_map;
  538. + else
  539. + port_map = RT305X_ESW_PMAP_LLLLLL;
  540. +
  541. + /* Unused HW feature, but still nice to be consistent here...
  542. + * This is also exported to userspace ('lan' attribute) so it's
  543. + * conveniently usable to decide which ports go into the wan vlan by
  544. + * default.
  545. + */
  546. + esw_rmw(esw, RT305X_ESW_REG_SGC2,
  547. + RT305X_ESW_SGC2_LAN_PMAP_M << RT305X_ESW_SGC2_LAN_PMAP_S,
  548. + port_map << RT305X_ESW_SGC2_LAN_PMAP_S);
  549. +
  550. + /* make the switch leds blink */
  551. + for (i = 0; i < RT305X_ESW_NUM_LEDS; i++)
  552. + esw->ports[i].led = 0x05;
  553. +
  554. + /* Only unmask the port change interrupt */
  555. + esw_w32(esw, ~RT305X_ESW_PORT_ST_CHG, RT305X_ESW_REG_IMR);
  556. +}
  557. +
  558. +static irqreturn_t esw_interrupt(int irq, void *_esw)
  559. +{
  560. + struct rt305x_esw *esw = (struct rt305x_esw *)_esw;
  561. + u32 status;
  562. +
  563. + status = esw_r32(esw, RT305X_ESW_REG_ISR);
  564. + if (status & RT305X_ESW_PORT_ST_CHG) {
  565. + u32 link = esw_r32(esw, RT305X_ESW_REG_POA);
  566. +
  567. + link >>= RT305X_ESW_POA_LINK_SHIFT;
  568. + link &= RT305X_ESW_POA_LINK_MASK;
  569. + dev_info(esw->dev, "link changed 0x%02X\n", link);
  570. + }
  571. + esw_w32(esw, status, RT305X_ESW_REG_ISR);
  572. +
  573. + return IRQ_HANDLED;
  574. +}
  575. +
  576. +static int esw_probe(struct platform_device *pdev)
  577. +{
  578. + struct resource *res = platform_get_resource(p, IORESOURCE_MEM, 0);
  579. + struct device_node *np = pdev->dev.of_node;
  580. + const __be32 *port_map, *reg_init;
  581. + struct rt305x_esw *esw;
  582. + struct resource *irq;
  583. + int ret;
  584. +
  585. + esw = devm_kzalloc(&pdev->dev, sizeof(*esw), GFP_KERNEL);
  586. + if (!esw)
  587. + return -ENOMEM;
  588. +
  589. + esw->dev = &pdev->dev;
  590. + esw->irq = irq->start;
  591. + esw->base = devm_ioremap_resource(&pdev->dev, res);
  592. + if (!esw->base)
  593. + return -EADDRNOTAVAIL;
  594. +
  595. + port_map = of_get_property(np, "mediatek,portmap", NULL);
  596. + if (port_map)
  597. + esw->port_map = be32_to_cpu(*port_map);
  598. +
  599. + reg_init = of_get_property(np, "mediatek,led_polarity", NULL);
  600. + if (reg_init)
  601. + esw->reg_led_polarity = be32_to_cpu(*reg_init);
  602. +
  603. + platform_set_drvdata(pdev, esw);
  604. +
  605. + spin_lock_init(&esw->reg_rw_lock);
  606. +
  607. + esw_hw_init(esw);
  608. +
  609. + ret = devm_request_irq(&pdev->dev, esw->irq, esw_interrupt, 0, "esw",
  610. + esw);
  611. +
  612. + if (!ret) {
  613. + esw_w32(esw, RT305X_ESW_PORT_ST_CHG, RT305X_ESW_REG_ISR);
  614. + esw_w32(esw, ~RT305X_ESW_PORT_ST_CHG, RT305X_ESW_REG_IMR);
  615. + }
  616. +
  617. + return ret;
  618. +}
  619. +
  620. +static int esw_remove(struct platform_device *pdev)
  621. +{
  622. + struct rt305x_esw *esw = platform_get_drvdata(pdev);
  623. +
  624. + if (esw) {
  625. + esw_w32(esw, ~0, RT305X_ESW_REG_IMR);
  626. + platform_set_drvdata(pdev, NULL);
  627. + }
  628. +
  629. + return 0;
  630. +}
  631. +
  632. +static const struct of_device_id ralink_esw_match[] = {
  633. + { .compatible = "ralink,rt3050-esw" },
  634. + {},
  635. +};
  636. +MODULE_DEVICE_TABLE(of, ralink_esw_match);
  637. +
  638. +static struct platform_driver esw_driver = {
  639. + .probe = esw_probe,
  640. + .remove = esw_remove,
  641. + .driver = {
  642. + .name = "rt3050-esw",
  643. + .owner = THIS_MODULE,
  644. + .of_match_table = ralink_esw_match,
  645. + },
  646. +};
  647. +
  648. +int __init mtk_switch_init(void)
  649. +{
  650. + return platform_driver_register(&esw_driver);
  651. +}
  652. +
  653. +void mtk_switch_exit(void)
  654. +{
  655. + platform_driver_unregister(&esw_driver);
  656. +}
  657. --- /dev/null
  658. +++ b/drivers/net/ethernet/mediatek/esw_rt3050.h
  659. @@ -0,0 +1,29 @@
  660. +/* This program is free software; you can redistribute it and/or modify
  661. + * it under the terms of the GNU General Public License as published by
  662. + * the Free Software Foundation; version 2 of the License
  663. + *
  664. + * This program is distributed in the hope that it will be useful,
  665. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  666. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  667. + * GNU General Public License for more details.
  668. + *
  669. + * Copyright (C) 2009-2015 John Crispin <blogic@openwrt.org>
  670. + * Copyright (C) 2009-2015 Felix Fietkau <nbd@nbd.name>
  671. + * Copyright (C) 2013-2015 Michael Lee <igvtee@gmail.com>
  672. + */
  673. +
  674. +#ifndef _RALINK_ESW_RT3052_H__
  675. +#define _RALINK_ESW_RT3052_H__
  676. +
  677. +#ifdef CONFIG_NET_MEDIATEK_ESW_RT3052
  678. +
  679. +int __init mtk_switch_init(void);
  680. +void mtk_switch_exit(void);
  681. +
  682. +#else
  683. +
  684. +static inline int __init mtk_switch_init(void) { return 0; }
  685. +static inline void mtk_switch_exit(void) { }
  686. +
  687. +#endif
  688. +#endif