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
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.
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>
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>
22 #include <ralink_regs.h>
24 #include "mtk_eth_soc.h"
25 #include "gsw_mt7620.h"
27 void mtk_switch_w32(struct mt7620_gsw *gsw, u32 val, unsigned int reg)
29 iowrite32(val, gsw->base + reg);
31 EXPORT_SYMBOL_GPL(mtk_switch_w32);
33 u32 mtk_switch_r32(struct mt7620_gsw *gsw, unsigned int reg)
35 return ioread32(gsw->base + reg);
37 EXPORT_SYMBOL_GPL(mtk_switch_r32);
39 static irqreturn_t gsw_interrupt_mt7621(int irq, void *_eth)
41 struct mtk_eth *eth = (struct mtk_eth *)_eth;
42 struct mt7620_gsw *gsw = (struct mt7620_gsw *)eth->sw_priv;
45 reg = mt7530_mdio_r32(gsw, MT7530_SYS_INT_STS);
47 for (i = 0; i < 5; i++) {
50 if ((reg & BIT(i)) == 0)
53 link = mt7530_mdio_r32(gsw, MT7530_PMSR_P(i)) & 0x1;
55 if (link == eth->link[i])
60 netdev_info(*eth->netdev,
61 "port %d link up\n", i);
63 netdev_info(*eth->netdev,
64 "port %d link down\n", i);
67 mt7530_mdio_w32(gsw, MT7530_SYS_INT_STS, 0x1f);
72 static void mt7621_hw_init(struct mtk_eth *eth, struct mt7620_gsw *gsw,
73 struct device_node *np)
78 /* hardware reset the switch */
79 mtk_reset(eth, RST_CTRL_MCM);
82 /* reduce RGMII2 PAD driving strength */
83 rt_sysc_m32(MT7621_MDIO_DRV_MASK, 0, SYSC_PAD_RGMII2_MDIO);
85 /* gpio mux - RGMII1=Normal mode */
86 rt_sysc_m32(BIT(14), 0, SYSC_GPIO_MODE);
88 /* set GMAC1 RGMII mode */
89 rt_sysc_m32(MT7621_GE1_MODE_MASK, 0, SYSC_REG_CFG1);
91 /* enable MDIO to control MT7530 */
92 rt_sysc_m32(3 << 12, 0, SYSC_GPIO_MODE);
94 /* turn off all PHYs */
95 for (i = 0; i <= 4; i++) {
96 val = _mt7620_mii_read(gsw, i, 0x0);
98 _mt7620_mii_write(gsw, i, 0x0, val);
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);
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);
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);
117 mtk_switch_w32(gsw, MAC_MCR_FORCE_MODE, MTK_MAC_P2_MCR);
119 /* Enable Port 6, P5 as GMAC5, P5 disable */
120 val = mt7530_mdio_r32(gsw, MT7530_MHWTRAP);
122 val &= ~MHWTRAP_P6_DIS;
124 val |= MHWTRAP_P5_DIS;
125 /* manual override of HW-Trap */
126 val |= MHWTRAP_MANUAL;
127 mt7530_mdio_w32(gsw, MT7530_MHWTRAP, val);
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) {
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);
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);
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);
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);
158 usleep_range(20, 40);
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);
167 _mt7620_mii_write(gsw, 0, 14, 0x1);
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);
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);
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);
188 /* turn on all PHYs */
189 for (i = 0; i <= 4; i++) {
190 val = _mt7620_mii_read(gsw, i, 0);
192 _mt7620_mii_write(gsw, i, 0, val);
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
201 /* This is copied from mt7530_apply_config in libreCMC driver */
205 for (i = 0; i < MT7530_NUM_PORTS; i++)
206 mt7530_mdio_w32(gsw, REG_ESW_PORT_PCR(i), 0x00400000);
208 mt7530_mdio_w32(gsw, REG_ESW_PORT_PCR(MT7530_CPU_PORT),
211 for (i = 0; i < MT7530_NUM_PORTS; i++)
212 mt7530_mdio_w32(gsw, REG_ESW_PORT_PVC(i), 0x810000c0);
216 mt7530_mdio_m32(gsw, 0, 3 << 16, MT7530_TOP_SIG_CTRL);
217 mt7530_mdio_w32(gsw, MT7530_SYS_INT_EN, 0x1f);
220 static const struct of_device_id mediatek_gsw_match[] = {
221 { .compatible = "mediatek,mt7621-gsw" },
224 MODULE_DEVICE_TABLE(of, mediatek_gsw_match);
226 int mtk_gsw_init(struct mtk_eth *eth)
228 struct device_node *np = eth->switch_np;
229 struct platform_device *pdev = of_find_device_by_node(np);
230 struct mt7620_gsw *gsw;
235 if (!of_device_is_compatible(np, mediatek_gsw_match->compatible))
238 gsw = platform_get_drvdata(pdev);
244 request_irq(gsw->irq, gsw_interrupt_mt7621, 0,
246 disable_irq(gsw->irq);
248 mt7621_hw_init(eth, gsw, np);
250 enable_irq(gsw->irq);
254 EXPORT_SYMBOL_GPL(mtk_gsw_init);
256 static int mt7621_gsw_probe(struct platform_device *pdev)
258 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
259 struct mt7620_gsw *gsw;
261 gsw = devm_kzalloc(&pdev->dev, sizeof(struct mt7620_gsw), GFP_KERNEL);
265 gsw->base = devm_ioremap_resource(&pdev->dev, res);
266 if (IS_ERR(gsw->base))
267 return PTR_ERR(gsw->base);
269 gsw->dev = &pdev->dev;
270 gsw->irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
272 platform_set_drvdata(pdev, gsw);
277 static int mt7621_gsw_remove(struct platform_device *pdev)
279 platform_set_drvdata(pdev, NULL);
284 static struct platform_driver gsw_driver = {
285 .probe = mt7621_gsw_probe,
286 .remove = mt7621_gsw_remove,
288 .name = "mt7621-gsw",
289 .of_match_table = mediatek_gsw_match,
293 module_platform_driver(gsw_driver);
295 MODULE_LICENSE("GPL");
296 MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
297 MODULE_DESCRIPTION("GBit switch driver for Mediatek MT7621 SoC");