1 /*   This program is free software; you can redistribute it and/or modify
2  *   it under the terms of the GNU General Public License as published by
3  *   the Free Software Foundation; version 2 of the License
4  *
5  *   This program is distributed in the hope that it will be useful,
6  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
7  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
8  *   GNU General Public License for more details.
9  *
10  *   Copyright (C) 2009-2016 John Crispin <blogic@openwrt.org>
11  *   Copyright (C) 2009-2016 Felix Fietkau <nbd@openwrt.org>
12  *   Copyright (C) 2013-2016 Michael Lee <igvtee@gmail.com>
13  */
14 
15 #include <linux/module.h>
16 #include <linux/kernel.h>
17 #include <linux/types.h>
18 #include <linux/platform_device.h>
19 #include <linux/of_device.h>
20 #include <linux/of_irq.h>
21 
22 #include <ralink_regs.h>
23 
24 #include "mtk_eth_soc.h"
25 #include "gsw_mt7620.h"
26 
mtk_switch_w32(struct mt7620_gsw * gsw,u32 val,unsigned int reg)27 void mtk_switch_w32(struct mt7620_gsw *gsw, u32 val, unsigned int reg)
28 {
29 	iowrite32(val, gsw->base + reg);
30 }
31 EXPORT_SYMBOL_GPL(mtk_switch_w32);
32 
mtk_switch_r32(struct mt7620_gsw * gsw,unsigned int reg)33 u32 mtk_switch_r32(struct mt7620_gsw *gsw, unsigned int reg)
34 {
35 	return ioread32(gsw->base + reg);
36 }
37 EXPORT_SYMBOL_GPL(mtk_switch_r32);
38 
gsw_interrupt_mt7621(int irq,void * _eth)39 static irqreturn_t gsw_interrupt_mt7621(int irq, void *_eth)
40 {
41 	struct mtk_eth *eth = (struct mtk_eth *)_eth;
42 	struct mt7620_gsw *gsw = (struct mt7620_gsw *)eth->sw_priv;
43 	u32 reg, i;
44 
45 	reg = mt7530_mdio_r32(gsw, MT7530_SYS_INT_STS);
46 
47 	for (i = 0; i < 5; i++) {
48 		unsigned int link;
49 
50 		if ((reg & BIT(i)) == 0)
51 			continue;
52 
53 		link = mt7530_mdio_r32(gsw, MT7530_PMSR_P(i)) & 0x1;
54 
55 		if (link == eth->link[i])
56 			continue;
57 
58 		eth->link[i] = link;
59 		if (link)
60 			netdev_info(*eth->netdev,
61 				    "port %d link up\n", i);
62 		else
63 			netdev_info(*eth->netdev,
64 				    "port %d link down\n", i);
65 	}
66 
67 	mt7530_mdio_w32(gsw, MT7530_SYS_INT_STS, 0x1f);
68 
69 	return IRQ_HANDLED;
70 }
71 
mt7621_hw_init(struct mtk_eth * eth,struct mt7620_gsw * gsw,struct device_node * np)72 static void mt7621_hw_init(struct mtk_eth *eth, struct mt7620_gsw *gsw,
73 			   struct device_node *np)
74 {
75 	u32 i;
76 	u32 val;
77 
78 	/* hardware reset the switch */
79 	mtk_reset(eth, RST_CTRL_MCM);
80 	mdelay(10);
81 
82 	/* reduce RGMII2 PAD driving strength */
83 	rt_sysc_m32(MT7621_MDIO_DRV_MASK, 0, SYSC_PAD_RGMII2_MDIO);
84 
85 	/* gpio mux - RGMII1=Normal mode */
86 	rt_sysc_m32(BIT(14), 0, SYSC_GPIO_MODE);
87 
88 	/* set GMAC1 RGMII mode */
89 	rt_sysc_m32(MT7621_GE1_MODE_MASK, 0, SYSC_REG_CFG1);
90 
91 	/* enable MDIO to control MT7530 */
92 	rt_sysc_m32(3 << 12, 0, SYSC_GPIO_MODE);
93 
94 	/* turn off all PHYs */
95 	for (i = 0; i <= 4; i++) {
96 		val = _mt7620_mii_read(gsw, i, 0x0);
97 		val |= BIT(11);
98 		_mt7620_mii_write(gsw, i, 0x0, val);
99 	}
100 
101 	/* reset the switch */
102 	mt7530_mdio_w32(gsw, MT7530_SYS_CTRL,
103 			SYS_CTRL_SW_RST | SYS_CTRL_REG_RST);
104 	usleep_range(10, 20);
105 
106 	if ((rt_sysc_r32(SYSC_REG_CHIP_REV_ID) & 0xFFFF) == 0x0101) {
107 		/* GE1, Force 1000M/FD, FC ON, MAX_RX_LENGTH 1536 */
108 		mtk_switch_w32(gsw, MAC_MCR_FIXED_LINK, MTK_MAC_P2_MCR);
109 		mt7530_mdio_w32(gsw, MT7530_PMCR_P(6), PMCR_FIXED_LINK);
110 	} else {
111 		/* GE1, Force 1000M/FD, FC ON, MAX_RX_LENGTH 1536 */
112 		mtk_switch_w32(gsw, MAC_MCR_FIXED_LINK_FC, MTK_MAC_P1_MCR);
113 		mt7530_mdio_w32(gsw, MT7530_PMCR_P(6), PMCR_FIXED_LINK_FC);
114 	}
115 
116 	/* GE2, Link down */
117 	mtk_switch_w32(gsw, MAC_MCR_FORCE_MODE, MTK_MAC_P2_MCR);
118 
119 	/* Enable Port 6, P5 as GMAC5, P5 disable */
120 	val = mt7530_mdio_r32(gsw, MT7530_MHWTRAP);
121 	/* Enable Port 6 */
122 	val &= ~MHWTRAP_P6_DIS;
123 	/* Disable Port 5 */
124 	val |= MHWTRAP_P5_DIS;
125 	/* manual override of HW-Trap */
126 	val |= MHWTRAP_MANUAL;
127 	mt7530_mdio_w32(gsw, MT7530_MHWTRAP, val);
128 
129 	val = rt_sysc_r32(SYSC_REG_CFG);
130 	val = (val >> MT7621_XTAL_SHIFT) & MT7621_XTAL_MASK;
131 	if (val < MT7621_XTAL_25 && val >= MT7621_XTAL_40) {
132 		/* 40Mhz */
133 
134 		/* disable MT7530 core clock */
135 		_mt7620_mii_write(gsw, 0, 13, 0x1f);
136 		_mt7620_mii_write(gsw, 0, 14, 0x410);
137 		_mt7620_mii_write(gsw, 0, 13, 0x401f);
138 		_mt7620_mii_write(gsw, 0, 14, 0x0);
139 
140 		/* disable MT7530 PLL */
141 		_mt7620_mii_write(gsw, 0, 13, 0x1f);
142 		_mt7620_mii_write(gsw, 0, 14, 0x40d);
143 		_mt7620_mii_write(gsw, 0, 13, 0x401f);
144 		_mt7620_mii_write(gsw, 0, 14, 0x2020);
145 
146 		/* for MT7530 core clock = 500Mhz */
147 		_mt7620_mii_write(gsw, 0, 13, 0x1f);
148 		_mt7620_mii_write(gsw, 0, 14, 0x40e);
149 		_mt7620_mii_write(gsw, 0, 13, 0x401f);
150 		_mt7620_mii_write(gsw, 0, 14, 0x119);
151 
152 		/* enable MT7530 PLL */
153 		_mt7620_mii_write(gsw, 0, 13, 0x1f);
154 		_mt7620_mii_write(gsw, 0, 14, 0x40d);
155 		_mt7620_mii_write(gsw, 0, 13, 0x401f);
156 		_mt7620_mii_write(gsw, 0, 14, 0x2820);
157 
158 		usleep_range(20, 40);
159 
160 		/* enable MT7530 core clock */
161 		_mt7620_mii_write(gsw, 0, 13, 0x1f);
162 		_mt7620_mii_write(gsw, 0, 14, 0x410);
163 		_mt7620_mii_write(gsw, 0, 13, 0x401f);
164 	}
165 
166 	/* RGMII */
167 	_mt7620_mii_write(gsw, 0, 14, 0x1);
168 
169 	/* set MT7530 central align */
170 	mt7530_mdio_m32(gsw, BIT(0), P6ECR_INTF_MODE_RGMII, MT7530_P6ECR);
171 	mt7530_mdio_m32(gsw, TRGMII_TXCTRL_TXC_INV, 0,
172 			MT7530_TRGMII_TXCTRL);
173 	mt7530_mdio_w32(gsw, MT7530_TRGMII_TCK_CTRL, 0x855);
174 
175 	/* delay setting for 10/1000M */
176 	mt7530_mdio_w32(gsw, MT7530_P5RGMIIRXCR,
177 			P5RGMIIRXCR_C_ALIGN | P5RGMIIRXCR_DELAY_2);
178 	mt7530_mdio_w32(gsw, MT7530_P5RGMIITXCR, 0x14);
179 
180 	/* lower Tx Driving*/
181 	mt7530_mdio_w32(gsw, MT7530_TRGMII_TD0_ODT, 0x44);
182 	mt7530_mdio_w32(gsw, MT7530_TRGMII_TD1_ODT, 0x44);
183 	mt7530_mdio_w32(gsw, MT7530_TRGMII_TD2_ODT, 0x44);
184 	mt7530_mdio_w32(gsw, MT7530_TRGMII_TD3_ODT, 0x44);
185 	mt7530_mdio_w32(gsw, MT7530_TRGMII_TD4_ODT, 0x44);
186 	mt7530_mdio_w32(gsw, MT7530_TRGMII_TD5_ODT, 0x44);
187 
188 	/* turn on all PHYs */
189 	for (i = 0; i <= 4; i++) {
190 		val = _mt7620_mii_read(gsw, i, 0);
191 		val &= ~BIT(11);
192 		_mt7620_mii_write(gsw, i, 0, val);
193 	}
194 
195 #define MT7530_NUM_PORTS 8
196 #define REG_ESW_PORT_PCR(x)    (0x2004 | ((x) << 8))
197 #define REG_ESW_PORT_PVC(x)    (0x2010 | ((x) << 8))
198 #define REG_ESW_PORT_PPBV1(x)  (0x2014 | ((x) << 8))
199 #define MT7530_CPU_PORT                6
200 
201 	/* This is copied from mt7530_apply_config in libreCMC driver */
202 	{
203 		int i;
204 
205 		for (i = 0; i < MT7530_NUM_PORTS; i++)
206 			mt7530_mdio_w32(gsw, REG_ESW_PORT_PCR(i), 0x00400000);
207 
208 		mt7530_mdio_w32(gsw, REG_ESW_PORT_PCR(MT7530_CPU_PORT),
209 				0x00ff0000);
210 
211 		for (i = 0; i < MT7530_NUM_PORTS; i++)
212 			mt7530_mdio_w32(gsw, REG_ESW_PORT_PVC(i), 0x810000c0);
213 	}
214 
215 	/* enable irq */
216 	mt7530_mdio_m32(gsw, 0, 3 << 16, MT7530_TOP_SIG_CTRL);
217 	mt7530_mdio_w32(gsw, MT7530_SYS_INT_EN, 0x1f);
218 }
219 
220 static const struct of_device_id mediatek_gsw_match[] = {
221 	{ .compatible = "mediatek,mt7621-gsw" },
222 	{},
223 };
224 MODULE_DEVICE_TABLE(of, mediatek_gsw_match);
225 
mtk_gsw_init(struct mtk_eth * eth)226 int mtk_gsw_init(struct mtk_eth *eth)
227 {
228 	struct device_node *np = eth->switch_np;
229 	struct platform_device *pdev = of_find_device_by_node(np);
230 	struct mt7620_gsw *gsw;
231 
232 	if (!pdev)
233 		return -ENODEV;
234 
235 	if (!of_device_is_compatible(np, mediatek_gsw_match->compatible))
236 		return -EINVAL;
237 
238 	gsw = platform_get_drvdata(pdev);
239 	eth->sw_priv = gsw;
240 
241 	if (!gsw->irq)
242 		return -EINVAL;
243 
244 	request_irq(gsw->irq, gsw_interrupt_mt7621, 0,
245 		    "gsw", eth);
246 	disable_irq(gsw->irq);
247 
248 	mt7621_hw_init(eth, gsw, np);
249 
250 	enable_irq(gsw->irq);
251 
252 	return 0;
253 }
254 EXPORT_SYMBOL_GPL(mtk_gsw_init);
255 
mt7621_gsw_probe(struct platform_device * pdev)256 static int mt7621_gsw_probe(struct platform_device *pdev)
257 {
258 	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
259 	struct mt7620_gsw *gsw;
260 
261 	gsw = devm_kzalloc(&pdev->dev, sizeof(struct mt7620_gsw), GFP_KERNEL);
262 	if (!gsw)
263 		return -ENOMEM;
264 
265 	gsw->base = devm_ioremap_resource(&pdev->dev, res);
266 	if (IS_ERR(gsw->base))
267 		return PTR_ERR(gsw->base);
268 
269 	gsw->dev = &pdev->dev;
270 	gsw->irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
271 
272 	platform_set_drvdata(pdev, gsw);
273 
274 	return 0;
275 }
276 
mt7621_gsw_remove(struct platform_device * pdev)277 static int mt7621_gsw_remove(struct platform_device *pdev)
278 {
279 	platform_set_drvdata(pdev, NULL);
280 
281 	return 0;
282 }
283 
284 static struct platform_driver gsw_driver = {
285 	.probe = mt7621_gsw_probe,
286 	.remove = mt7621_gsw_remove,
287 	.driver = {
288 		.name = "mt7621-gsw",
289 		.owner = THIS_MODULE,
290 		.of_match_table = mediatek_gsw_match,
291 	},
292 };
293 
294 module_platform_driver(gsw_driver);
295 
296 MODULE_LICENSE("GPL");
297 MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
298 MODULE_DESCRIPTION("GBit switch driver for Mediatek MT7621 SoC");
299