Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1344289 > unrolled thread
| Started by | John Crispin <blogic@openwrt.org> |
|---|---|
| First post | 2016-02-26 15:30 +0100 |
| Last post | 2016-02-26 18:40 +0100 |
| Articles | 11 — 5 participants |
Back to article view | Back to linux.kernel
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
[PATCH V2 03/12] net-next: mediatek: add embedded switch driver (ESW) John Crispin <blogic@openwrt.org> - 2016-02-26 15:30 +0100
Re: [PATCH V2 03/12] net-next: mediatek: add embedded switch driver (ESW) Andrew Lunn <andrew@lunn.ch> - 2016-02-26 16:20 +0100
Re: [PATCH V2 03/12] net-next: mediatek: add embedded switch driver (ESW) John Crispin <blogic@openwrt.org> - 2016-02-26 16:30 +0100
Re: [PATCH V2 03/12] net-next: mediatek: add embedded switch driver (ESW) Andrew Lunn <andrew@lunn.ch> - 2016-02-26 18:10 +0100
Re: [PATCH V2 03/12] net-next: mediatek: add embedded switch driver (ESW) David Miller <davem@davemloft.net> - 2016-02-26 18:50 +0100
Re: [PATCH V2 03/12] net-next: mediatek: add embedded switch driver (ESW) David Miller <davem@davemloft.net> - 2016-02-26 18:40 +0100
Re: [PATCH V2 03/12] net-next: mediatek: add embedded switch driver (ESW) Florian Fainelli <f.fainelli@gmail.com> - 2016-02-26 19:40 +0100
Re: [PATCH V2 03/12] net-next: mediatek: add embedded switch driver (ESW) Felix Fietkau <nbd@openwrt.org> - 2016-02-26 17:30 +0100
Re: [PATCH V2 03/12] net-next: mediatek: add embedded switch driver (ESW) Andrew Lunn <andrew@lunn.ch> - 2016-02-26 18:40 +0100
Re: [PATCH V2 03/12] net-next: mediatek: add embedded switch driver (ESW) David Miller <davem@davemloft.net> - 2016-02-26 18:50 +0100
Re: [PATCH V2 03/12] net-next: mediatek: add embedded switch driver (ESW) David Miller <davem@davemloft.net> - 2016-02-26 18:40 +0100
| From | John Crispin <blogic@openwrt.org> |
|---|---|
| Date | 2016-02-26 15:30 +0100 |
| Subject | [PATCH V2 03/12] net-next: mediatek: add embedded switch driver (ESW) |
| Message-ID | <r6rz3-4yI-7@gated-at.bofh.it> |
The ESW is found in many of the old 100mbit MIPS based SoCs. it has 5
external ports, 1 cpu port and 1 further port that the internal HW
offloading engine connects to.
This driver is very basic and only provides basic init and irq support.
The SoC and switch core both have support for a special tag making DSA
support possible.
I have managed to work out all the names of the registers of the ESW,
however the init for the phys uses lots of voodoo magic which is based
on the SDK driver code. It will be hard to find out the real names for
the phy registers and their bits.
Signed-off-by: John Crispin <blogic@openwrt.org>
---
drivers/net/ethernet/mediatek/esw_rt3050.c | 642 ++++++++++++++++++++++++++++
drivers/net/ethernet/mediatek/esw_rt3050.h | 21 +
2 files changed, 663 insertions(+)
create mode 100644 drivers/net/ethernet/mediatek/esw_rt3050.c
create mode 100644 drivers/net/ethernet/mediatek/esw_rt3050.h
diff --git a/drivers/net/ethernet/mediatek/esw_rt3050.c b/drivers/net/ethernet/mediatek/esw_rt3050.c
new file mode 100644
index 0000000..8da4bec
--- /dev/null
+++ b/drivers/net/ethernet/mediatek/esw_rt3050.c
@@ -0,0 +1,642 @@
+/* This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Copyright (C) 2009-2016 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2009-2016 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2013-2016 Michael Lee <igvtee@gmail.com>
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <asm/mach-ralink/ralink_regs.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+
+#include "mtk_eth_soc.h"
+
+/* HW limitations for this switch:
+ * - No large frame support (PKT_MAX_LEN at most 1536)
+ * - Can't have untagged vlan and tagged vlan on one port at the same time,
+ * though this might be possible using the undocumented PPE.
+ */
+
+#define RT305X_ESW_REG_ISR 0x00
+#define RT305X_ESW_REG_IMR 0x04
+#define RT305X_ESW_REG_FCT0 0x08
+#define RT305X_ESW_REG_PFC1 0x14
+#define RT305X_ESW_REG_ATS 0x24
+#define RT305X_ESW_REG_ATS0 0x28
+#define RT305X_ESW_REG_ATS1 0x2c
+#define RT305X_ESW_REG_ATS2 0x30
+#define RT305X_ESW_REG_PVIDC(_n) (0x40 + 4 * (_n))
+#define RT305X_ESW_REG_VLANI(_n) (0x50 + 4 * (_n))
+#define RT305X_ESW_REG_VMSC(_n) (0x70 + 4 * (_n))
+#define RT305X_ESW_REG_POA 0x80
+#define RT305X_ESW_REG_FPA 0x84
+#define RT305X_ESW_REG_SOCPC 0x8c
+#define RT305X_ESW_REG_POC0 0x90
+#define RT305X_ESW_REG_POC1 0x94
+#define RT305X_ESW_REG_POC2 0x98
+#define RT305X_ESW_REG_SGC 0x9c
+#define RT305X_ESW_REG_STRT 0xa0
+#define RT305X_ESW_REG_PCR0 0xc0
+#define RT305X_ESW_REG_PCR1 0xc4
+#define RT305X_ESW_REG_FPA2 0xc8
+#define RT305X_ESW_REG_FCT2 0xcc
+#define RT305X_ESW_REG_SGC2 0xe4
+#define RT305X_ESW_REG_P0LED 0xa4
+#define RT305X_ESW_REG_P1LED 0xa8
+#define RT305X_ESW_REG_P2LED 0xac
+#define RT305X_ESW_REG_P3LED 0xb0
+#define RT305X_ESW_REG_P4LED 0xb4
+#define RT305X_ESW_REG_PXPC(_x) (0xe8 + (4 * _x))
+#define RT305X_ESW_REG_P1PC 0xec
+#define RT305X_ESW_REG_P2PC 0xf0
+#define RT305X_ESW_REG_P3PC 0xf4
+#define RT305X_ESW_REG_P4PC 0xf8
+#define RT305X_ESW_REG_P5PC 0xfc
+
+#define RT305X_ESW_LED_LINK 0
+#define RT305X_ESW_LED_100M 1
+#define RT305X_ESW_LED_DUPLEX 2
+#define RT305X_ESW_LED_ACTIVITY 3
+#define RT305X_ESW_LED_COLLISION 4
+#define RT305X_ESW_LED_LINKACT 5
+#define RT305X_ESW_LED_DUPLCOLL 6
+#define RT305X_ESW_LED_10MACT 7
+#define RT305X_ESW_LED_100MACT 8
+/* Additional led states not in datasheet: */
+#define RT305X_ESW_LED_BLINK 10
+#define RT305X_ESW_LED_ON 12
+
+#define RT305X_ESW_LINK_S 25
+#define RT305X_ESW_DUPLEX_S 9
+#define RT305X_ESW_SPD_S 0
+
+#define RT305X_ESW_PCR0_WT_NWAY_DATA_S 16
+#define RT305X_ESW_PCR0_WT_PHY_CMD BIT(13)
+#define RT305X_ESW_PCR0_CPU_PHY_REG_S 8
+
+#define RT305X_ESW_PCR1_WT_DONE BIT(0)
+
+#define RT305X_ESW_ATS_TIMEOUT (5 * HZ)
+#define RT305X_ESW_PHY_TIMEOUT (5 * HZ)
+
+#define RT305X_ESW_PVIDC_PVID_M 0xfff
+#define RT305X_ESW_PVIDC_PVID_S 12
+
+#define RT305X_ESW_VLANI_VID_M 0xfff
+#define RT305X_ESW_VLANI_VID_S 12
+
+#define RT305X_ESW_VMSC_MSC_M 0xff
+#define RT305X_ESW_VMSC_MSC_S 8
+
+#define RT305X_ESW_SOCPC_DISUN2CPU_S 0
+#define RT305X_ESW_SOCPC_DISMC2CPU_S 8
+#define RT305X_ESW_SOCPC_DISBC2CPU_S 16
+#define RT305X_ESW_SOCPC_CRC_PADDING BIT(25)
+
+#define RT305X_ESW_POC0_EN_BP_S 0
+#define RT305X_ESW_POC0_EN_FC_S 8
+#define RT305X_ESW_POC0_DIS_RMC2CPU_S 16
+#define RT305X_ESW_POC0_DIS_PORT_M 0x7f
+#define RT305X_ESW_POC0_DIS_PORT_S 23
+
+#define RT305X_ESW_POC2_UNTAG_EN_M 0xff
+#define RT305X_ESW_POC2_UNTAG_EN_S 0
+#define RT305X_ESW_POC2_ENAGING_S 8
+#define RT305X_ESW_POC2_DIS_UC_PAUSE_S 16
+
+#define RT305X_ESW_SGC2_DOUBLE_TAG_M 0x7f
+#define RT305X_ESW_SGC2_DOUBLE_TAG_S 0
+#define RT305X_ESW_SGC2_LAN_PMAP_M 0x3f
+#define RT305X_ESW_SGC2_LAN_PMAP_S 24
+
+#define RT305X_ESW_PFC1_EN_VLAN_M 0xff
+#define RT305X_ESW_PFC1_EN_VLAN_S 16
+#define RT305X_ESW_PFC1_EN_TOS_S 24
+
+#define RT305X_ESW_VLAN_NONE 0xfff
+
+#define RT305X_ESW_GSC_BC_STROM_MASK 0x3
+#define RT305X_ESW_GSC_BC_STROM_SHIFT 4
+
+#define RT305X_ESW_GSC_LED_FREQ_MASK 0x3
+#define RT305X_ESW_GSC_LED_FREQ_SHIFT 23
+
+#define RT305X_ESW_POA_LINK_MASK 0x1f
+#define RT305X_ESW_POA_LINK_SHIFT 25
+
+#define RT305X_ESW_PORT_ST_CHG BIT(26)
+#define RT305X_ESW_PORT0 0
+#define RT305X_ESW_PORT1 1
+#define RT305X_ESW_PORT2 2
+#define RT305X_ESW_PORT3 3
+#define RT305X_ESW_PORT4 4
+#define RT305X_ESW_PORT5 5
+#define RT305X_ESW_PORT6 6
+
+#define RT305X_ESW_PMAP_LLLLLL 0x3f
+#define RT305X_ESW_PMAP_LLLLWL 0x2f
+#define RT305X_ESW_PMAP_WLLLLL 0x3e
+
+#define RT305X_ESW_PORTS_INTERNAL \
+ (BIT(RT305X_ESW_PORT0) | BIT(RT305X_ESW_PORT1) | \
+ BIT(RT305X_ESW_PORT2) | BIT(RT305X_ESW_PORT3) | \
+ BIT(RT305X_ESW_PORT4))
+
+#define RT305X_ESW_PORTS_NOCPU \
+ (RT305X_ESW_PORTS_INTERNAL | BIT(RT305X_ESW_PORT5))
+
+#define RT305X_ESW_PORTS_CPU BIT(RT305X_ESW_PORT6)
+
+#define RT305X_ESW_PORTS_ALL \
+ (RT305X_ESW_PORTS_NOCPU | RT305X_ESW_PORTS_CPU)
+
+#define RT305X_ESW_NUM_PORTS 7
+#define RT305X_ESW_NUM_LEDS 5
+
+#define RT5350_EWS_REG_LED_POLARITY 0x168
+#define RT5350_RESET_EPHY BIT(24)
+
+struct esw_port {
+ bool disable;
+ u8 led;
+};
+
+struct rt305x_esw {
+ struct device *dev;
+ void __iomem *base;
+ int irq;
+
+ /* Protects against concurrent register r/w operations. */
+ spinlock_t reg_rw_lock;
+
+ unsigned char port_map;
+ unsigned int reg_led_polarity;
+
+ struct esw_port ports[RT305X_ESW_NUM_PORTS];
+
+};
+
+static inline void esw_w32(struct rt305x_esw *esw, u32 val, unsigned reg)
+{
+ __raw_writel(val, esw->base + reg);
+}
+
+static inline u32 esw_r32(struct rt305x_esw *esw, unsigned reg)
+{
+ return __raw_readl(esw->base + reg);
+}
+
+static inline void esw_rmw_raw(struct rt305x_esw *esw, unsigned reg,
+ unsigned long mask, unsigned long val)
+{
+ unsigned long t;
+
+ t = __raw_readl(esw->base + reg) & ~mask;
+ __raw_writel(t | val, esw->base + reg);
+}
+
+static void esw_rmw(struct rt305x_esw *esw, unsigned reg,
+ unsigned long mask, unsigned long val)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&esw->reg_rw_lock, flags);
+ esw_rmw_raw(esw, reg, mask, val);
+ spin_unlock_irqrestore(&esw->reg_rw_lock, flags);
+}
+
+static u32 rt305x_mii_write(struct rt305x_esw *esw, u32 phy_addr,
+ u32 phy_register, u32 write_data)
+{
+ unsigned long t_start = jiffies;
+ int ret = 0;
+
+ while (1) {
+ if (!(esw_r32(esw, RT305X_ESW_REG_PCR1) &
+ RT305X_ESW_PCR1_WT_DONE))
+ break;
+ if (time_after(jiffies, t_start + RT305X_ESW_PHY_TIMEOUT)) {
+ ret = 1;
+ goto out;
+ }
+ }
+
+ write_data &= 0xffff;
+ esw_w32(esw, (write_data << RT305X_ESW_PCR0_WT_NWAY_DATA_S) |
+ (phy_register << RT305X_ESW_PCR0_CPU_PHY_REG_S) |
+ (phy_addr) | RT305X_ESW_PCR0_WT_PHY_CMD,
+ RT305X_ESW_REG_PCR0);
+
+ t_start = jiffies;
+ while (1) {
+ if (esw_r32(esw, RT305X_ESW_REG_PCR1) &
+ RT305X_ESW_PCR1_WT_DONE)
+ break;
+
+ if (time_after(jiffies, t_start + RT305X_ESW_PHY_TIMEOUT)) {
+ ret = 1;
+ break;
+ }
+ }
+out:
+ if (ret)
+ dev_err(esw->dev, "ramips_eth: MDIO timeout\n");
+ return ret;
+}
+
+static unsigned esw_get_port_disable(struct rt305x_esw *esw)
+{
+ unsigned reg;
+
+ reg = esw_r32(esw, RT305X_ESW_REG_POC0);
+ return (reg >> RT305X_ESW_POC0_DIS_PORT_S) &
+ RT305X_ESW_POC0_DIS_PORT_M;
+}
+
+static void esw_hw_init(struct mtk_eth *eth, struct rt305x_esw *esw)
+{
+ int i;
+ u8 port_disable = 0;
+ u8 port_map = RT305X_ESW_PMAP_LLLLLL;
+
+ /* vodoo from original driver */
+ esw_w32(esw, 0xC8A07850, RT305X_ESW_REG_FCT0);
+ esw_w32(esw, 0x00000000, RT305X_ESW_REG_SGC2);
+ /* Port priority 1 for all ports, vlan enabled. */
+ esw_w32(esw, 0x00005555 |
+ (RT305X_ESW_PORTS_ALL << RT305X_ESW_PFC1_EN_VLAN_S),
+ RT305X_ESW_REG_PFC1);
+
+ /* Enable Back Pressure, and Flow Control */
+ esw_w32(esw, ((RT305X_ESW_PORTS_ALL << RT305X_ESW_POC0_EN_BP_S) |
+ (RT305X_ESW_PORTS_ALL << RT305X_ESW_POC0_EN_FC_S)),
+ RT305X_ESW_REG_POC0);
+
+ /* Enable Aging, and VLAN TAG removal */
+ esw_w32(esw, ((RT305X_ESW_PORTS_ALL << RT305X_ESW_POC2_ENAGING_S) |
+ (RT305X_ESW_PORTS_NOCPU << RT305X_ESW_POC2_UNTAG_EN_S)),
+ RT305X_ESW_REG_POC2);
+
+ esw_w32(esw, 0x00d6500c, RT305X_ESW_REG_FCT2);
+
+ /* 300s aging timer, max packet len 1536, broadcast storm prevention
+ * disabled, disable collision abort, mac xor48 hash, 10 packet back
+ * pressure jam, GMII disable was_transmit, back pressure disabled,
+ * 30ms led flash, unmatched IGMP as broadcast, rmc tb fault to all
+ * ports.
+ */
+ esw_w32(esw, 0x0008a301, RT305X_ESW_REG_SGC);
+
+ /* Setup SoC Port control register */
+ esw_w32(esw,
+ (RT305X_ESW_SOCPC_CRC_PADDING |
+ (RT305X_ESW_PORTS_CPU << RT305X_ESW_SOCPC_DISUN2CPU_S) |
+ (RT305X_ESW_PORTS_CPU << RT305X_ESW_SOCPC_DISMC2CPU_S) |
+ (RT305X_ESW_PORTS_CPU << RT305X_ESW_SOCPC_DISBC2CPU_S)),
+ RT305X_ESW_REG_SOCPC);
+
+ /* ext phy base addr 31, enable port 5 polling, rx/tx clock skew 1,
+ * turbo mii off, rgmi 3.3v off
+ * port5: disabled
+ * port6: enabled, gige, full-duplex, rx/tx-flow-control
+ */
+ esw_w32(esw, 0x3f502b28, RT305X_ESW_REG_FPA2);
+ esw_w32(esw, 0x00000000, RT305X_ESW_REG_FPA);
+
+ /* Force Link/Activity on ports */
+ esw_w32(esw, 0x00000005, RT305X_ESW_REG_P0LED);
+ esw_w32(esw, 0x00000005, RT305X_ESW_REG_P1LED);
+ esw_w32(esw, 0x00000005, RT305X_ESW_REG_P2LED);
+ esw_w32(esw, 0x00000005, RT305X_ESW_REG_P3LED);
+ esw_w32(esw, 0x00000005, RT305X_ESW_REG_P4LED);
+
+ /* Copy disabled port configuration from bootloader setup */
+ port_disable = esw_get_port_disable(esw);
+ for (i = 0; i < 6; i++)
+ esw->ports[i].disable = (port_disable & (1 << i)) != 0;
+
+ if (ralink_soc == RT305X_SOC_RT3352) {
+ /* reset EPHY */
+ mtk_reset(eth, RT5350_RESET_EPHY);
+
+ rt305x_mii_write(esw, 0, 31, 0x8000);
+ for (i = 0; i < 5; i++) {
+ if (esw->ports[i].disable) {
+ rt305x_mii_write(esw, i, MII_BMCR, BMCR_PDOWN);
+ } else {
+ rt305x_mii_write(esw, i, MII_BMCR,
+ BMCR_FULLDPLX |
+ BMCR_ANENABLE |
+ BMCR_SPEED100);
+ }
+ /* TX10 waveform coefficient LSB=0 disable PHY */
+ rt305x_mii_write(esw, i, 26, 0x1601);
+ /* TX100/TX10 AD/DA current bias */
+ rt305x_mii_write(esw, i, 29, 0x7016);
+ /* TX100 slew rate control */
+ rt305x_mii_write(esw, i, 30, 0x0038);
+ }
+
+ /* select global register */
+ rt305x_mii_write(esw, 0, 31, 0x0);
+ /* enlarge agcsel threshold 3 and threshold 2 */
+ rt305x_mii_write(esw, 0, 1, 0x4a40);
+ /* enlarge agcsel threshold 5 and threshold 4 */
+ rt305x_mii_write(esw, 0, 2, 0x6254);
+ /* enlarge agcsel threshold */
+ rt305x_mii_write(esw, 0, 3, 0xa17f);
+ rt305x_mii_write(esw, 0, 12, 0x7eaa);
+ /* longer TP_IDL tail length */
+ rt305x_mii_write(esw, 0, 14, 0x65);
+ /* increased squelch pulse count threshold. */
+ rt305x_mii_write(esw, 0, 16, 0x0684);
+ /* set TX10 signal amplitude threshold to minimum */
+ rt305x_mii_write(esw, 0, 17, 0x0fe0);
+ /* set squelch amplitude to higher threshold */
+ rt305x_mii_write(esw, 0, 18, 0x40ba);
+ /* tune TP_IDL tail and head waveform, enable power
+ * down slew rate control
+ */
+ rt305x_mii_write(esw, 0, 22, 0x253f);
+ /* set PLL/Receive bias current are calibrated */
+ rt305x_mii_write(esw, 0, 27, 0x2fda);
+ /* change PLL/Receive bias current to internal(RT3350) */
+ rt305x_mii_write(esw, 0, 28, 0xc410);
+ /* change PLL bias current to internal(RT3052_MP3) */
+ rt305x_mii_write(esw, 0, 29, 0x598b);
+ /* select local register */
+ rt305x_mii_write(esw, 0, 31, 0x8000);
+ } else if (ralink_soc == RT305X_SOC_RT5350) {
+ /* reset EPHY */
+ mtk_reset(eth, RT5350_RESET_EPHY);
+
+ /* set the led polarity */
+ esw_w32(esw, esw->reg_led_polarity & 0x1F,
+ RT5350_EWS_REG_LED_POLARITY);
+
+ /* local registers */
+ rt305x_mii_write(esw, 0, 31, 0x8000);
+ for (i = 0; i < 5; i++) {
+ if (esw->ports[i].disable) {
+ rt305x_mii_write(esw, i, MII_BMCR, BMCR_PDOWN);
+ } else {
+ rt305x_mii_write(esw, i, MII_BMCR,
+ BMCR_FULLDPLX |
+ BMCR_ANENABLE |
+ BMCR_SPEED100);
+ }
+ /* TX10 waveform coefficient LSB=0 disable PHY */
+ rt305x_mii_write(esw, i, 26, 0x1601);
+ /* TX100/TX10 AD/DA current bias */
+ rt305x_mii_write(esw, i, 29, 0x7015);
+ /* TX100 slew rate control */
+ rt305x_mii_write(esw, i, 30, 0x0038);
+ }
+
+ /* global registers */
+ rt305x_mii_write(esw, 0, 31, 0x0);
+ /* enlarge agcsel threshold 3 and threshold 2 */
+ rt305x_mii_write(esw, 0, 1, 0x4a40);
+ /* enlarge agcsel threshold 5 and threshold 4 */
+ rt305x_mii_write(esw, 0, 2, 0x6254);
+ /* enlarge agcsel threshold 6 */
+ rt305x_mii_write(esw, 0, 3, 0xa17f);
+ rt305x_mii_write(esw, 0, 12, 0x7eaa);
+ /* longer TP_IDL tail length */
+ rt305x_mii_write(esw, 0, 14, 0x65);
+ /* increased squelch pulse count threshold. */
+ rt305x_mii_write(esw, 0, 16, 0x0684);
+ /* set TX10 signal amplitude threshold to minimum */
+ rt305x_mii_write(esw, 0, 17, 0x0fe0);
+ /* set squelch amplitude to higher threshold */
+ rt305x_mii_write(esw, 0, 18, 0x40ba);
+ /* tune TP_IDL tail and head waveform, enable power
+ * down slew rate control
+ */
+ rt305x_mii_write(esw, 0, 22, 0x253f);
+ /* set PLL/Receive bias current are calibrated */
+ rt305x_mii_write(esw, 0, 27, 0x2fda);
+ /* change PLL/Receive bias current to internal(RT3350) */
+ rt305x_mii_write(esw, 0, 28, 0xc410);
+ /* change PLL bias current to internal(RT3052_MP3) */
+ rt305x_mii_write(esw, 0, 29, 0x598b);
+ /* select local register */
+ rt305x_mii_write(esw, 0, 31, 0x8000);
+ } else if (ralink_soc == MT762X_SOC_MT7628AN ||
+ ralink_soc == MT762X_SOC_MT7688) {
+ int i;
+
+ /* reset EPHY */
+ mtk_reset(eth, RT5350_RESET_EPHY);
+
+ rt305x_mii_write(esw, 0, 31, 0x2000); /* change G2 page */
+ rt305x_mii_write(esw, 0, 26, 0x0020);
+
+ for (i = 0; i < 5; i++) {
+ rt305x_mii_write(esw, i, 31, 0x8000);
+ rt305x_mii_write(esw, i, 0, 0x3100);
+ rt305x_mii_write(esw, i, 30, 0xa000);
+ rt305x_mii_write(esw, i, 31, 0xa000);
+ rt305x_mii_write(esw, i, 16, 0x0606);
+ rt305x_mii_write(esw, i, 23, 0x0f0e);
+ rt305x_mii_write(esw, i, 24, 0x1610);
+ rt305x_mii_write(esw, i, 30, 0x1f15);
+ rt305x_mii_write(esw, i, 28, 0x6111);
+ rt305x_mii_write(esw, i, 31, 0x2000);
+ rt305x_mii_write(esw, i, 26, 0x0000);
+ }
+
+ /* 100Base AOI setting */
+ rt305x_mii_write(esw, 0, 31, 0x5000);
+ rt305x_mii_write(esw, 0, 19, 0x004a);
+ rt305x_mii_write(esw, 0, 20, 0x015a);
+ rt305x_mii_write(esw, 0, 21, 0x00ee);
+ rt305x_mii_write(esw, 0, 22, 0x0033);
+ rt305x_mii_write(esw, 0, 23, 0x020a);
+ rt305x_mii_write(esw, 0, 24, 0x0000);
+ rt305x_mii_write(esw, 0, 25, 0x024a);
+ rt305x_mii_write(esw, 0, 26, 0x035a);
+ rt305x_mii_write(esw, 0, 27, 0x02ee);
+ rt305x_mii_write(esw, 0, 28, 0x0233);
+ rt305x_mii_write(esw, 0, 29, 0x000a);
+ rt305x_mii_write(esw, 0, 30, 0x0000);
+ } else {
+ rt305x_mii_write(esw, 0, 31, 0x8000);
+ for (i = 0; i < 5; i++) {
+ if (esw->ports[i].disable) {
+ rt305x_mii_write(esw, i, MII_BMCR, BMCR_PDOWN);
+ } else {
+ rt305x_mii_write(esw, i, MII_BMCR,
+ BMCR_FULLDPLX |
+ BMCR_ANENABLE |
+ BMCR_SPEED100);
+ }
+ /* TX10 waveform coefficient */
+ rt305x_mii_write(esw, i, 26, 0x1601);
+ /* TX100/TX10 AD/DA current bias */
+ rt305x_mii_write(esw, i, 29, 0x7058);
+ /* TX100 slew rate control */
+ rt305x_mii_write(esw, i, 30, 0x0018);
+ }
+
+ /* PHY IOT */
+ /* select global register */
+ rt305x_mii_write(esw, 0, 31, 0x0);
+ /* tune TP_IDL tail and head waveform */
+ rt305x_mii_write(esw, 0, 22, 0x052f);
+ /* set TX10 signal amplitude threshold to minimum */
+ rt305x_mii_write(esw, 0, 17, 0x0fe0);
+ /* set squelch amplitude to higher threshold */
+ rt305x_mii_write(esw, 0, 18, 0x40ba);
+ /* longer TP_IDL tail length */
+ rt305x_mii_write(esw, 0, 14, 0x65);
+ /* select local register */
+ rt305x_mii_write(esw, 0, 31, 0x8000);
+ }
+
+ if (esw->port_map)
+ port_map = esw->port_map;
+ else
+ port_map = RT305X_ESW_PMAP_LLLLLL;
+
+ /* Unused HW feature, but still nice to be consistent here...
+ * This is also exported to userspace ('lan' attribute) so it's
+ * conveniently usable to decide which ports go into the wan vlan by
+ * default.
+ */
+ esw_rmw(esw, RT305X_ESW_REG_SGC2,
+ RT305X_ESW_SGC2_LAN_PMAP_M << RT305X_ESW_SGC2_LAN_PMAP_S,
+ port_map << RT305X_ESW_SGC2_LAN_PMAP_S);
+
+ /* make the switch leds blink */
+ for (i = 0; i < RT305X_ESW_NUM_LEDS; i++)
+ esw->ports[i].led = 0x05;
+
+ /* Only unmask the port change interrupt */
+ esw_w32(esw, ~RT305X_ESW_PORT_ST_CHG, RT305X_ESW_REG_IMR);
+}
+
+static irqreturn_t esw_interrupt(int irq, void *_esw)
+{
+ struct rt305x_esw *esw = (struct rt305x_esw *)_esw;
+ u32 status;
+
+ status = esw_r32(esw, RT305X_ESW_REG_ISR);
+ if (status & RT305X_ESW_PORT_ST_CHG) {
+ u32 link = esw_r32(esw, RT305X_ESW_REG_POA);
+
+ link >>= RT305X_ESW_POA_LINK_SHIFT;
+ link &= RT305X_ESW_POA_LINK_MASK;
+ dev_info(esw->dev, "link changed 0x%02X\n", link);
+ }
+ esw_w32(esw, status, RT305X_ESW_REG_ISR);
+
+ return IRQ_HANDLED;
+}
+
+static const struct of_device_id mediatek_esw_match[] = {
+ { .compatible = "ralink,rt3050-esw" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, mediatek_esw_match);
+
+int mtk_esw_init(struct mtk_eth *eth)
+{
+ struct device_node *np = eth->switch_np;
+ struct platform_device *pdev = of_find_device_by_node(np);
+ struct rt305x_esw *esw;
+ int ret;
+
+ if (!pdev)
+ return -ENODEV;
+
+ if (!of_device_is_compatible(np, mediatek_esw_match->compatible))
+ return -EINVAL;
+
+ esw = platform_get_drvdata(pdev);
+ if (!esw)
+ return -ENODEV;
+ eth->sw_priv = esw;
+
+ esw_hw_init(eth, esw);
+
+ ret = devm_request_irq(&pdev->dev, esw->irq, esw_interrupt, 0, "esw",
+ esw);
+ if (!ret) {
+ esw_w32(esw, RT305X_ESW_PORT_ST_CHG, RT305X_ESW_REG_ISR);
+ esw_w32(esw, ~RT305X_ESW_PORT_ST_CHG, RT305X_ESW_REG_IMR);
+ }
+
+ return 0;
+}
+
+static int esw_probe(struct platform_device *pdev)
+{
+ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ struct device_node *np = pdev->dev.of_node;
+ const __be32 *port_map, *reg_init;
+ struct rt305x_esw *esw;
+ int ret;
+
+ esw = devm_kzalloc(&pdev->dev, sizeof(*esw), GFP_KERNEL);
+ if (!esw)
+ return -ENOMEM;
+
+ esw->dev = &pdev->dev;
+ esw->irq = irq_of_parse_and_map(np, 0);
+ esw->base = devm_ioremap_resource(&pdev->dev, res);
+ if (!esw->base)
+ return -EADDRNOTAVAIL;
+
+ port_map = of_get_property(np, "mediatek,portmap", NULL);
+ if (port_map)
+ esw->port_map = be32_to_cpu(*port_map);
+
+ reg_init = of_get_property(np, "mediatek,led_polarity", NULL);
+ if (reg_init)
+ esw->reg_led_polarity = be32_to_cpu(*reg_init);
+
+ platform_set_drvdata(pdev, esw);
+
+ spin_lock_init(&esw->reg_rw_lock);
+
+ return ret;
+}
+
+static int esw_remove(struct platform_device *pdev)
+{
+ struct rt305x_esw *esw = platform_get_drvdata(pdev);
+
+ if (esw) {
+ esw_w32(esw, ~0, RT305X_ESW_REG_IMR);
+ platform_set_drvdata(pdev, NULL);
+ }
+
+ return 0;
+}
+
+static struct platform_driver esw_driver = {
+ .probe = esw_probe,
+ .remove = esw_remove,
+ .driver = {
+ .name = "rt3050-esw",
+ .owner = THIS_MODULE,
+ .of_match_table = mediatek_esw_match,
+ },
+};
+
+module_platform_driver(esw_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
+MODULE_DESCRIPTION("Switch driver for RT305X SoC");
diff --git a/drivers/net/ethernet/mediatek/esw_rt3050.h b/drivers/net/ethernet/mediatek/esw_rt3050.h
new file mode 100644
index 0000000..9b0837a
--- /dev/null
+++ b/drivers/net/ethernet/mediatek/esw_rt3050.h
@@ -0,0 +1,21 @@
+/* This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Copyright (C) 2009-2016 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2009-2016 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2013-2016 Michael Lee <igvtee@gmail.com>
+ */
+
+#ifndef _RALINK_ESW_RT3052_H__
+#define _RALINK_ESW_RT3052_H__
+
+int __init mtk_esw_init(struct mtk_eth *eth);
+void mtk_switch_exit(struct mtk_eth *eth);
+
+#endif
--
1.7.10.4
[toc] | [next] | [standalone]
| From | Andrew Lunn <andrew@lunn.ch> |
|---|---|
| Date | 2016-02-26 16:20 +0100 |
| Subject | Re: [PATCH V2 03/12] net-next: mediatek: add embedded switch driver (ESW) |
| Message-ID | <r6sls-5aU-5@gated-at.bofh.it> |
| In reply to | #1344289 |
On Fri, Feb 26, 2016 at 03:21:35PM +0100, John Crispin wrote: > The ESW is found in many of the old 100mbit MIPS based SoCs. it has 5 > external ports, 1 cpu port and 1 further port that the internal HW > offloading engine connects to. > > This driver is very basic and only provides basic init and irq support. > The SoC and switch core both have support for a special tag making DSA > support possible. Hi Crispin There was recently a discussion about adding switches without using DSA or switchdev. It was pretty much decided we would not accept such drivers. Sorry Andrew
[toc] | [prev] | [next] | [standalone]
| From | John Crispin <blogic@openwrt.org> |
|---|---|
| Date | 2016-02-26 16:30 +0100 |
| Subject | Re: [PATCH V2 03/12] net-next: mediatek: add embedded switch driver (ESW) |
| Message-ID | <r6sv8-5gy-9@gated-at.bofh.it> |
| In reply to | #1344327 |
On 26/02/2016 16:18, Andrew Lunn wrote: > On Fri, Feb 26, 2016 at 03:21:35PM +0100, John Crispin wrote: >> The ESW is found in many of the old 100mbit MIPS based SoCs. it has 5 >> external ports, 1 cpu port and 1 further port that the internal HW >> offloading engine connects to. >> >> This driver is very basic and only provides basic init and irq support. >> The SoC and switch core both have support for a special tag making DSA >> support possible. > > Hi Crispin > > There was recently a discussion about adding switches without using > DSA or switchdev. It was pretty much decided we would not accept such > drivers. > > Sorry > > Andrew > > _______________________________________________ > Linux-mediatek mailing list > Linux-mediatek@lists.infradead.org > http://lists.infradead.org/mailman/listinfo/linux-mediatek > Hi, would the series be ok if we just dropped those parts and then have a driver in the kernel that wont do much with the out of tree patches ? the problem here is that on one side people complain about vendors not sending code upstream. once they start being a good citizen and provide funding to send stuff upstream the feedback tends to be very bad as seen here. we are planning on doing a DSA driver but one step at a time. this kind of feedback will inevitably lead to vendors doing second thoughts of upstream contributions. John
[toc] | [prev] | [next] | [standalone]
| From | Andrew Lunn <andrew@lunn.ch> |
|---|---|
| Date | 2016-02-26 18:10 +0100 |
| Subject | Re: [PATCH V2 03/12] net-next: mediatek: add embedded switch driver (ESW) |
| Message-ID | <r6u3U-6vT-21@gated-at.bofh.it> |
| In reply to | #1344335 |
> the problem here is that on one side people complain about vendors not > sending code upstream. once they start being a good citizen and provide > funding to send stuff upstream the feedback tends to be very bad as seen > here. we are planning on doing a DSA driver but one step at a time. this > kind of feedback will inevitably lead to vendors doing second thoughts > of upstream contributions. I think it is great a vendor is providing funding to get code upstream. However, that code needs to conform with current kernel architecture and design philosophy. We as a community also need to be consistent. We have recently push back on Microchip with there LAN9352 who want to do something very similar, introduce the MAC and a very dumb switch driver. They are now looking at what it means to do a DSA driver. There is also talk of writing a DSA driver for the ks8995 family. As David said recently, a year ago this probably would of been accepted. But now, switches need to be DSA or switchdev. Andrew
[toc] | [prev] | [next] | [standalone]
| From | David Miller <davem@davemloft.net> |
|---|---|
| Date | 2016-02-26 18:50 +0100 |
| Subject | Re: [PATCH V2 03/12] net-next: mediatek: add embedded switch driver (ESW) |
| Message-ID | <r6uGB-6KV-3@gated-at.bofh.it> |
| In reply to | #1344470 |
From: Andrew Lunn <andrew@lunn.ch> Date: Fri, 26 Feb 2016 18:05:45 +0100 > I think it is great a vendor is providing funding to get code > upstream. However, that code needs to conform with current kernel > architecture and design philosophy. > > We as a community also need to be consistent. We have recently push > back on Microchip with there LAN9352 who want to do something very > similar, introduce the MAC and a very dumb switch driver. They are now > looking at what it means to do a DSA driver. There is also talk of > writing a DSA driver for the ks8995 family. > > As David said recently, a year ago this probably would of been > accepted. But now, switches need to be DSA or switchdev. +1
[toc] | [prev] | [next] | [standalone]
| From | David Miller <davem@davemloft.net> |
|---|---|
| Date | 2016-02-26 18:40 +0100 |
| Subject | Re: [PATCH V2 03/12] net-next: mediatek: add embedded switch driver (ESW) |
| Message-ID | <r6uwW-6GL-27@gated-at.bofh.it> |
| In reply to | #1344335 |
From: John Crispin <blogic@openwrt.org> Date: Fri, 26 Feb 2016 16:24:47 +0100 > the problem here is that on one side people complain about vendors not > sending code upstream. once they start being a good citizen and provide > funding to send stuff upstream the feedback tends to be very bad as seen > here. The feedback is not bad, on the contrary it is very positive and people like Andrew want to help people like you write proper switch drivers. If you were ignored, or rejected purely on the grounds of coding style issues, that would be "very bad" feedback.
[toc] | [prev] | [next] | [standalone]
| From | Florian Fainelli <f.fainelli@gmail.com> |
|---|---|
| Date | 2016-02-26 19:40 +0100 |
| Subject | Re: [PATCH V2 03/12] net-next: mediatek: add embedded switch driver (ESW) |
| Message-ID | <r6vt0-7nJ-19@gated-at.bofh.it> |
| In reply to | #1344335 |
On 26/02/16 07:24, John Crispin wrote: > > Hi, > > would the series be ok if we just dropped those parts and then have a > driver in the kernel that wont do much with the out of tree patches ? > > the problem here is that on one side people complain about vendors not > sending code upstream. once they start being a good citizen and provide > funding to send stuff upstream the feedback tends to be very bad as seen > here. I agree with David here, the feedback from Andrew is very constructive, you just don't like the feedback you are being given, which is a different thing. You can't always get a 12 series patches adding a new driver accepted after second try, look at all the recent submissions that occured, it took 5-6-7 maybe more submissions until things were in a shape where they could be merged. If for your next submission you get the feedback that switchdev/DSA is deprecated, and something new needs to be used, then I would agree that feedback is not acceptable, I doubt this will be the case unless we wait another 10 years to get these patches out. > we are planning on doing a DSA driver but one step at a time. this > kind of feedback will inevitably lead to vendors doing second thoughts > of upstream contributions. If you are planning on a DSA driver, which sounds like a good plan, then maybe drop the integrated switch parts for now, keep it as a local set of patches for your testing, and just get the basic CPU Ethernet MAC driver to work for data movement, so that part gets in, and later on, when your DSA driver is ready, that's one less thing to take care of. They ultimately are logically spearated drivers if you use DSA, a little less if you use switchdev. -- Florian
[toc] | [prev] | [next] | [standalone]
| From | Felix Fietkau <nbd@openwrt.org> |
|---|---|
| Date | 2016-02-26 17:30 +0100 |
| Subject | Re: [PATCH V2 03/12] net-next: mediatek: add embedded switch driver (ESW) |
| Message-ID | <r6trc-5Z1-43@gated-at.bofh.it> |
| In reply to | #1344327 |
On 2016-02-26 16:18, Andrew Lunn wrote: > On Fri, Feb 26, 2016 at 03:21:35PM +0100, John Crispin wrote: >> The ESW is found in many of the old 100mbit MIPS based SoCs. it has 5 >> external ports, 1 cpu port and 1 further port that the internal HW >> offloading engine connects to. >> >> This driver is very basic and only provides basic init and irq support. >> The SoC and switch core both have support for a special tag making DSA >> support possible. > > Hi Crispin > > There was recently a discussion about adding switches without using > DSA or switchdev. It was pretty much decided we would not accept such > drivers. For exactly this reason, the code does not provide any non-standard API for allowing the user to configure the switch. The hardware needs to be programmed with some defaults for the driver to be functional (since the switch logic is built into the SoC). In my opinion, leaving this part out does not make much sense and neither does deferring the entire patch series until we have a switchdev/DSA capable driver. This is just a starting point, which will be turned into a proper driver with the right APIs later. - Felix
[toc] | [prev] | [next] | [standalone]
| From | Andrew Lunn <andrew@lunn.ch> |
|---|---|
| Date | 2016-02-26 18:40 +0100 |
| Subject | Re: [PATCH V2 03/12] net-next: mediatek: add embedded switch driver (ESW) |
| Message-ID | <r6uwX-6GL-39@gated-at.bofh.it> |
| In reply to | #1344422 |
On Fri, Feb 26, 2016 at 05:25:38PM +0100, Felix Fietkau wrote:
> On 2016-02-26 16:18, Andrew Lunn wrote:
> > On Fri, Feb 26, 2016 at 03:21:35PM +0100, John Crispin wrote:
> >> The ESW is found in many of the old 100mbit MIPS based SoCs. it has 5
> >> external ports, 1 cpu port and 1 further port that the internal HW
> >> offloading engine connects to.
> >>
> >> This driver is very basic and only provides basic init and irq support.
> >> The SoC and switch core both have support for a special tag making DSA
> >> support possible.
> >
> > Hi Crispin
> >
> > There was recently a discussion about adding switches without using
> > DSA or switchdev. It was pretty much decided we would not accept such
> > drivers.
> For exactly this reason, the code does not provide any non-standard API
> for allowing the user to configure the switch. The hardware needs to be
> programmed with some defaults for the driver to be functional (since the
> switch logic is built into the SoC).
>
>
> In my opinion, leaving this part out does not make much sense and
> neither does deferring the entire patch series until we have a
> switchdev/DSA capable driver. This is just a starting point, which will
> be turned into a proper driver with the right APIs later.
You are however introducing APIs which become things you need to
support. Your device tree binding for example. The device tree
maintainers consider this a stable API you need to maintain forever.
Can you guarantee that you can maintain this binding, and also support
the DSA binding? How messy is it going to make your code supporting
two bindings?
You currently have one netdev interface for five switch ports. When
you have a DSA driver, you have 5 additional netdev interfaces, one
per port, and your original interface is now unusable. Isn't that an
API change.
You need to find incremental steps towards a switchdev/DSA driver
which are not going to hinder you in the long run.
Andrew
[toc] | [prev] | [next] | [standalone]
| From | David Miller <davem@davemloft.net> |
|---|---|
| Date | 2016-02-26 18:50 +0100 |
| Subject | Re: [PATCH V2 03/12] net-next: mediatek: add embedded switch driver (ESW) |
| Message-ID | <r6uGB-6KV-11@gated-at.bofh.it> |
| In reply to | #1344422 |
From: Felix Fietkau <nbd@openwrt.org> Date: Fri, 26 Feb 2016 17:25:38 +0100 > In my opinion, leaving this part out does not make much sense and > neither does deferring the entire patch series until we have a > switchdev/DSA capable driver. This is just a starting point, which will > be turned into a proper driver with the right APIs later. I disagree, and we want people to concentrate on writing proper switchdev/DSA drivers. People like Andrew have offered to help in any way possible to make this as easy as possible, so please take this seriously. I would have accepted your arguments a year ago when we didn't have the right infrastructure, but now we do and there is no real excuse to submit partial or bastardized drivers for these kinds of hardware anymore Thanks in advance for your understanding, and I'm plan to stand very firm on this.
[toc] | [prev] | [next] | [standalone]
| From | David Miller <davem@davemloft.net> |
|---|---|
| Date | 2016-02-26 18:40 +0100 |
| Subject | Re: [PATCH V2 03/12] net-next: mediatek: add embedded switch driver (ESW) |
| Message-ID | <r6uwW-6GL-15@gated-at.bofh.it> |
| In reply to | #1344327 |
From: Andrew Lunn <andrew@lunn.ch> Date: Fri, 26 Feb 2016 16:18:13 +0100 > On Fri, Feb 26, 2016 at 03:21:35PM +0100, John Crispin wrote: >> The ESW is found in many of the old 100mbit MIPS based SoCs. it has 5 >> external ports, 1 cpu port and 1 further port that the internal HW >> offloading engine connects to. >> >> This driver is very basic and only provides basic init and irq support. >> The SoC and switch core both have support for a special tag making DSA >> support possible. > > Hi Crispin > > There was recently a discussion about adding switches without using > DSA or switchdev. It was pretty much decided we would not accept such > drivers. > > Sorry +1
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web