This patch adds basic swconfig support for ramips_esw: root@OpenWrt:/# swconfig dev rt305x show Global attributes: Port 0: led: 5 pvid: 1 Port 1: led: 5 pvid: 1 Port 2: led: 5 pvid: 1 Port 3: led: 5 pvid: 1 Port 4: led: 5 pvid: 2 Port 5: led: ??? pvid: 1 Port 6: led: ??? pvid: 1 VLAN 1: ports: 0 1 2 3 6t VLAN 2: ports: 4 6t
Signed-off-by: Tobias Diedrich <ranma+open...@tdiedrich.de> Index: target/linux/ramips/files/drivers/net/ramips_esw.c =================================================================== --- target/linux/ramips/files/drivers/net/ramips_esw.c (revision 29943) +++ target/linux/ramips/files/drivers/net/ramips_esw.c (working copy) @@ -1,4 +1,5 @@ #include <linux/ioport.h> +#include <linux/switch.h> #include <rt305x_regs.h> #include <rt305x_esw_platform.h> @@ -25,6 +26,13 @@ #define RT305X_ESW_REG_P3LED 0xb0 #define RT305X_ESW_REG_P4LED 0xb4 +// The following led values might be not 100% correct +#define RT305X_ESW_LED_LINK 0 +#define RT305X_ESW_LED_ACT 3 +#define RT305X_ESW_LED_LINKACT 5 +#define RT305X_ESW_LED_BLINK 10 +#define RT305X_ESW_LED_ON 12 + #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 @@ -79,8 +87,10 @@ #define RT305X_ESW_NUM_VLANS 16 #define RT305X_ESW_NUM_PORTS 7 +#define RT305X_ESW_NUM_LEDS 5 struct rt305x_esw { + struct switch_dev swdev; void __iomem *base; struct rt305x_esw_platform_data *pdata; spinlock_t reg_rw_lock; @@ -160,6 +170,19 @@ return ret; } +static unsigned +rt305x_esw_get_vlan_id(struct rt305x_esw *esw, unsigned vlan) +{ + unsigned s; + unsigned val; + + s = RT305X_ESW_VLANI_VID_S * (vlan % 2); + val = rt305x_esw_rr(esw, RT305X_ESW_REG_VLANI(vlan / 2)); + val = (val >> s) & RT305X_ESW_VLANI_VID_M; + + return val; +} + static void rt305x_esw_set_vlan_id(struct rt305x_esw *esw, unsigned vlan, unsigned vid) { @@ -172,6 +195,17 @@ (vid & RT305X_ESW_VLANI_VID_M) << s); } +static unsigned +rt305x_esw_get_pvid(struct rt305x_esw *esw, unsigned port) +{ + unsigned s, val; + + s = RT305X_ESW_PVIDC_PVID_S * (port % 2); + val = rt305x_esw_rr(esw, + RT305X_ESW_REG_PVIDC(port / 2)); + return (val >> s) & RT305X_ESW_PVIDC_PVID_M; +} + static void rt305x_esw_set_pvid(struct rt305x_esw *esw, unsigned port, unsigned pvid) { @@ -184,6 +218,18 @@ (pvid & RT305X_ESW_PVIDC_PVID_M) << s); } +static unsigned +rt305x_esw_get_vmsc(struct rt305x_esw *esw, unsigned vlan) +{ + unsigned s, val; + + s = RT305X_ESW_VMSC_MSC_S * (vlan % 4); + val = rt305x_esw_rr(esw, RT305X_ESW_REG_VMSC(vlan / 4)); + val = (val >> s) & RT305X_ESW_VMSC_MSC_M; + + return val; +} + static void rt305x_esw_set_vmsc(struct rt305x_esw *esw, unsigned vlan, unsigned msc) { @@ -321,10 +367,208 @@ } static int +rt305x_esw_get_port_led(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); + int idx = val->port_vlan; + + if (idx < 0 || idx >= RT305X_ESW_NUM_LEDS) + return -EINVAL; + + val->value.i = rt305x_esw_rr(esw, RT305X_ESW_REG_P0LED + 4*idx); + + return 0; +} + +static int +rt305x_esw_set_port_led(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); + int idx = val->port_vlan; + + if (idx < 0 || idx >= RT305X_ESW_NUM_LEDS) + return -EINVAL; + + rt305x_esw_wr(esw, val->value.i, RT305X_ESW_REG_P0LED + 4*idx); + + return 0; +} + +static int +rt305x_esw_get_port_pvid(struct switch_dev *dev, int port, int *val) +{ + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); + + if (port >= RT305X_ESW_NUM_PORTS) + return -EINVAL; + + *val = rt305x_esw_get_pvid(esw, port); + + return 0; +} + +static int +rt305x_esw_set_port_pvid(struct switch_dev *dev, int port, int val) +{ + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); + + if (port >= RT305X_ESW_NUM_PORTS) + return -EINVAL; + + rt305x_esw_set_pvid(esw, port, val); + + return 0; +} + +static int +rt305x_esw_get_vlan_ports(struct switch_dev *dev, struct switch_val *val) +{ + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); + u32 vmsc, poc3; + int vlan_idx = -1; + int i; + + val->len = 0; + + if (val->port_vlan < 0 || val->port_vlan > RT305X_ESW_VLANI_VID_M) + return -EINVAL; + + for (i = 0; i < RT305X_ESW_NUM_VLANS; i++) { + if (rt305x_esw_get_vlan_id(esw, i) == val->port_vlan) { + vlan_idx = i; + break; + } + } + + if (vlan_idx == -1) + return -EINVAL; + + vmsc = rt305x_esw_get_vmsc(esw, vlan_idx); + poc3 = rt305x_esw_rr(esw, RT305X_ESW_REG_POC3); + + for (i = 0; i < RT305X_ESW_NUM_PORTS; i++) { + struct switch_port *p; + + if (!(vmsc & (1 << i))) + continue; + + p = &val->value.ports[val->len++]; + p->id = i; + if (poc3 & (1 << i)) + p->flags = 0; + else + p->flags = 1 << SWITCH_PORT_FLAG_TAGGED; + } + + return 0; +} + +static int +rt305x_esw_set_vlan_ports(struct switch_dev *dev, struct switch_val *val) +{ + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); + u32 vmsc, poc3; + int vlan_idx = -1; + int i; + + if (val->port_vlan < 0 || val->port_vlan > RT305X_ESW_VLANI_VID_M) + return -EINVAL; + + // one of the already defined vlans? + for (i = 0; i < RT305X_ESW_NUM_VLANS; i++) { + if (rt305x_esw_get_vlan_id(esw, i) == val->port_vlan) { + vlan_idx = i; + break; + } + } + + // select a free slot + for (i = 0; vlan_idx == -1 && i < RT305X_ESW_NUM_VLANS; i++) { + if (rt305x_esw_get_vmsc(esw, i) == 0) + vlan_idx = i; + } + + if (vlan_idx == -1 || val->len > RT305X_ESW_NUM_PORTS) + return -EINVAL; + + poc3 = rt305x_esw_rr(esw, RT305X_ESW_REG_POC3); + vmsc = 0; + + for (i = 0; i < val->len; i++) { + struct switch_port *p = &val->value.ports[i]; + int port_mask = 1 << p->id; + + if (p->id >= RT305X_ESW_NUM_PORTS) + return -EINVAL; + + vmsc |= port_mask; + if (p->flags & 1) + poc3 &= ~port_mask; + else + poc3 |= port_mask; + + if (poc3 & (1 << i)) + p->flags = 0; + else + p->flags = 1 << SWITCH_PORT_FLAG_TAGGED; + } + + if (vmsc) + rt305x_esw_set_vlan_id(esw, vlan_idx, val->port_vlan); + else + rt305x_esw_set_vlan_id(esw, vlan_idx, 0); + rt305x_esw_set_vmsc(esw, vlan_idx, vmsc); + rt305x_esw_wr(esw, RT305X_ESW_REG_POC3, poc3); + + return 0; +} + +static const struct switch_attr rt305x_esw_global[] = { +}; + +static const struct switch_attr rt305x_esw_port[] = { + { + .type = SWITCH_TYPE_INT, + .name = "led", + .description = "Get/Set port led mode (0 - 15)", + .max = 15, + .set = rt305x_esw_set_port_led, + .get = rt305x_esw_get_port_led, + }, +}; + +static const struct switch_attr rt305x_esw_vlan[] = { +}; + +static const struct switch_dev_ops rt305x_esw_ops = { + .attr_global = { + .attr = rt305x_esw_global, + .n_attr = ARRAY_SIZE(rt305x_esw_global), + }, + .attr_port = { + .attr = rt305x_esw_port, + .n_attr = ARRAY_SIZE(rt305x_esw_port), + }, + .attr_vlan = { + .attr = rt305x_esw_vlan, + .n_attr = ARRAY_SIZE(rt305x_esw_vlan), + }, + .get_vlan_ports = rt305x_esw_get_vlan_ports, + .set_vlan_ports = rt305x_esw_set_vlan_ports, + .get_port_pvid = rt305x_esw_get_port_pvid, + .set_port_pvid = rt305x_esw_set_port_pvid, +}; + +static int rt305x_esw_probe(struct platform_device *pdev) { struct rt305x_esw_platform_data *pdata; struct rt305x_esw *esw; + struct switch_dev *swdev; struct resource *res; int err; @@ -351,6 +595,22 @@ goto free_esw; } + dev_info(&pdev->dev, "about to fill out switch_dev struct\n"); + swdev = &esw->swdev; + swdev->name = "rt305x-esw"; + swdev->alias = "rt305x"; + swdev->cpu_port = RT305X_ESW_PORT6; + swdev->ports = RT305X_ESW_NUM_PORTS; + swdev->vlans = RT305X_ESW_NUM_VLANS; + swdev->ops = &rt305x_esw_ops; + + dev_info(&pdev->dev, "about to call register_switch\n"); + err = register_switch(swdev, NULL); + if (err < 0) { + dev_err(&pdev->dev, "register_switch failed\n"); + goto free_esw; + } + platform_set_drvdata(pdev, esw); esw->pdata = pdata; @@ -371,6 +631,7 @@ esw = platform_get_drvdata(pdev); if (esw) { + unregister_switch(&esw->swdev); platform_set_drvdata(pdev, NULL); iounmap(esw->base); kfree(esw); Index: target/linux/ramips/patches-2.6.39/103-ethernet.patch =================================================================== --- target/linux/ramips/patches-2.6.39/103-ethernet.patch (revision 29943) +++ target/linux/ramips/patches-2.6.39/103-ethernet.patch (working copy) @@ -1,12 +1,13 @@ --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig -@@ -494,6 +494,12 @@ config MIPS_AU1X00_ENET +@@ -494,6 +494,13 @@ config MIPS_AU1X00_ENET If you have an Alchemy Semi AU1X00 based system say Y. Otherwise, say N. +config MIPS_RAMIPS_NET + tristate "Ethernet driver for rt288x/rt305x" + depends on MIPS_RALINK ++ select SWCONFIG + help + This driver supports the etehrnet mac inside the ralink wisocs + Index: target/linux/ramips/base-files/etc/uci-defaults/network =================================================================== --- target/linux/ramips/base-files/etc/uci-defaults/network (revision 29943) +++ target/linux/ramips/base-files/etc/uci-defaults/network (working copy) @@ -55,6 +55,13 @@ RT3X5X=`cat /proc/cpuinfo | grep RT3.5` if [ -n "${RT3X5X}" ]; then ucidef_set_interfaces_lan_wan "eth0.1" "eth0.2" + if [ -x /sbin/swconfig ]; then + LANPORTS=`swconfig dev rt305x vlan 1 get ports` + WANPORTS=`swconfig dev rt305x vlan 2 get ports` + ucidef_add_switch "rt305x" "1" "1" + ucidef_add_switch_vlan "rt305x" "1" "$LANPORTS" + ucidef_add_switch_vlan "rt305x" "2" "$WANPORTS" + fi else ucidef_set_interfaces_lan_wan "eth0" "eth1" fi -- Tobias PGP: http://8ef7ddba.uguu.de _______________________________________________ openwrt-devel mailing list openwrt-devel@lists.openwrt.org https://lists.openwrt.org/mailman/listinfo/openwrt-devel