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

Reply via email to