kernel: b53: add initial support for switches in BCM5301X
[openwrt/svn-archive/archive.git] / target / linux / generic / files / drivers / net / phy / b53 / b53_common.c
index 97968dbf0b0a2f9a907208d900d5a9bc73db1d95..39027c1771066e6eb9cdba0f088e84de7eec9885 100644 (file)
@@ -188,8 +188,13 @@ static void b53_set_vlan_entry(struct b53_device *dev, u16 vid, u16 members,
        if (is5325(dev)) {
                u32 entry = 0;
 
-               if (members)
-                       entry = (untag << VA_UNTAG_S) | members | VA_VALID_25;
+               if (members) {
+                       entry = (untag << VA_UNTAG_S) | members;
+                       if (dev->core_rev >= 3)
+                               entry |= VA_VALID_25_R4 | vid << VA_VID_HIGH_S;
+                       else
+                               entry |= VA_VALID_25;
+               }
 
                b53_write32(dev, B53_VLAN_PAGE, B53_VLAN_WRITE_25, entry);
                b53_write16(dev, B53_VLAN_PAGE, B53_VLAN_TABLE_ACCESS_25, vid |
@@ -367,7 +372,7 @@ static void b53_enable_ports(struct b53_device *dev)
                 */
                if (dev->enable_vlan || is_cpu_port(dev, i))
                        pvlan_mask = 0x1ff;
-               else if (is531x5(dev))
+               else if (is531x5(dev) || is5301x(dev))
                        /* BCM53115 may use a different port as cpu port */
                        pvlan_mask = BIT(dev->sw_dev.cpu_port);
                else
@@ -391,7 +396,7 @@ static void b53_enable_ports(struct b53_device *dev)
                            pvlan_mask);
 
                /* port state is handled by bcm63xx_enet driver */
-               if (!is63xx(dev))
+               if (!is63xx(dev) && !(is5301x(dev) && i == 6))
                        b53_write8(dev, B53_CTRL_PAGE, B53_PORT_CTRL(i),
                                   port_ctrl);
        }
@@ -459,8 +464,9 @@ void b53_switch_reset_gpio(struct b53_device *dev)
        if (gpio < 0)
                return;
 
-       gpio_set_value(gpio, 0);
-       gpio_direction_output(gpio, 1);
+       /*
+        * Reset sequence: RESET low(50ms)->high(20ms)
+        */
        gpio_set_value(gpio, 0);
        mdelay(50);
 
@@ -476,6 +482,11 @@ static int b53_switch_reset(struct b53_device *dev)
 
        b53_switch_reset_gpio(dev);
 
+       if (is539x(dev)) {
+               b53_write8(dev, B53_CTRL_PAGE, B53_SOFTRESET, 0x83);
+               b53_write8(dev, B53_CTRL_PAGE, B53_SOFTRESET, 0x00);
+       }
+
        b53_read8(dev, B53_CTRL_PAGE, B53_SWITCH_MODE, &mgmt);
 
        if (!(mgmt & SM_SW_FWD_EN)) {
@@ -512,7 +523,7 @@ static int b53_switch_reset(struct b53_device *dev)
                                return -EINVAL;
                        }
                }
-       } else if (is531x5(dev) && dev->sw_dev.cpu_port == B53_CPU_PORT) {
+       } else if ((is531x5(dev) || is5301x(dev)) && dev->sw_dev.cpu_port == B53_CPU_PORT) {
                u8 mii_port_override;
 
                b53_read8(dev, B53_CTRL_PAGE, B53_PORT_OVERRIDE_CTRL,
@@ -969,7 +980,7 @@ static const struct switch_dev_ops b53_switch_ops_65 = {
                .n_attr = ARRAY_SIZE(b53_global_ops_65),
        },
        .attr_port = {
-               .attr = b53_no_ops,
+               .attr = b53_port_ops,
                .n_attr = ARRAY_SIZE(b53_port_ops),
        },
        .attr_vlan = {
@@ -1129,6 +1140,71 @@ static const struct b53_chip_data b53_switch_chips[] = {
                .jumbo_size_reg = B53_JUMBO_MAX_SIZE_63XX,
                .sw_ops = &b53_switch_ops,
        },
+       {
+               .chip_id = BCM53010_DEVICE_ID,
+               .dev_name = "BCM53010",
+               .alias = "bcm53011",
+               .vlans = 4096,
+               .enabled_ports = 0x1f,
+               .cpu_port = B53_CPU_PORT_25, // TODO: auto detect
+               .vta_regs = B53_VTA_REGS,
+               .duplex_reg = B53_DUPLEX_STAT_GE,
+               .jumbo_pm_reg = B53_JUMBO_PORT_MASK,
+               .jumbo_size_reg = B53_JUMBO_MAX_SIZE,
+               .sw_ops = &b53_switch_ops,
+       },
+       {
+               .chip_id = BCM53011_DEVICE_ID,
+               .dev_name = "BCM53011",
+               .alias = "bcm53011",
+               .vlans = 4096,
+               .enabled_ports = 0x1f,
+               .cpu_port = B53_CPU_PORT_25, // TODO: auto detect
+               .vta_regs = B53_VTA_REGS,
+               .duplex_reg = B53_DUPLEX_STAT_GE,
+               .jumbo_pm_reg = B53_JUMBO_PORT_MASK,
+               .jumbo_size_reg = B53_JUMBO_MAX_SIZE,
+               .sw_ops = &b53_switch_ops,
+       },
+       {
+               .chip_id = BCM53012_DEVICE_ID,
+               .dev_name = "BCM53012",
+               .alias = "bcm53011",
+               .vlans = 4096,
+               .enabled_ports = 0x1f,
+               .cpu_port = B53_CPU_PORT_25, // TODO: auto detect
+               .vta_regs = B53_VTA_REGS,
+               .duplex_reg = B53_DUPLEX_STAT_GE,
+               .jumbo_pm_reg = B53_JUMBO_PORT_MASK,
+               .jumbo_size_reg = B53_JUMBO_MAX_SIZE,
+               .sw_ops = &b53_switch_ops,
+       },
+       {
+               .chip_id = BCM53018_DEVICE_ID,
+               .dev_name = "BCM53018",
+               .alias = "bcm53018",
+               .vlans = 4096,
+               .enabled_ports = 0x1f,
+               .cpu_port = B53_CPU_PORT_25, // TODO: auto detect
+               .vta_regs = B53_VTA_REGS,
+               .duplex_reg = B53_DUPLEX_STAT_GE,
+               .jumbo_pm_reg = B53_JUMBO_PORT_MASK,
+               .jumbo_size_reg = B53_JUMBO_MAX_SIZE,
+               .sw_ops = &b53_switch_ops,
+       },
+       {
+               .chip_id = BCM53019_DEVICE_ID,
+               .dev_name = "BCM53019",
+               .alias = "bcm53019",
+               .vlans = 4096,
+               .enabled_ports = 0x1f,
+               .cpu_port = B53_CPU_PORT_25, // TODO: auto detect
+               .vta_regs = B53_VTA_REGS,
+               .duplex_reg = B53_DUPLEX_STAT_GE,
+               .jumbo_pm_reg = B53_JUMBO_PORT_MASK,
+               .jumbo_size_reg = B53_JUMBO_MAX_SIZE,
+               .sw_ops = &b53_switch_ops,
+       },
 };
 
 int b53_switch_init(struct b53_device *dev)
@@ -1216,7 +1292,7 @@ int b53_switch_init(struct b53_device *dev)
 
        dev->reset_gpio = b53_switch_get_reset_gpio(dev);
        if (dev->reset_gpio >= 0) {
-               ret = devm_gpio_request(dev->dev, dev->reset_gpio, "robo_reset");
+               ret = devm_gpio_request_one(dev->dev, dev->reset_gpio, GPIOF_OUT_INIT_HIGH, "robo_reset");
                if (ret)
                        return ret;
        }
@@ -1285,6 +1361,11 @@ int b53_switch_detect(struct b53_device *dev)
                switch (id32) {
                case BCM53115_DEVICE_ID:
                case BCM53125_DEVICE_ID:
+               case BCM53010_DEVICE_ID:
+               case BCM53011_DEVICE_ID:
+               case BCM53012_DEVICE_ID:
+               case BCM53018_DEVICE_ID:
+               case BCM53019_DEVICE_ID:
                        dev->chip_id = id32;
                        break;
                default:
@@ -1294,7 +1375,12 @@ int b53_switch_detect(struct b53_device *dev)
                }
        }
 
-       return b53_read8(dev, B53_MGMT_PAGE, B53_REV_ID, &dev->core_rev);
+       if (dev->chip_id == BCM5325_DEVICE_ID)
+               return b53_read8(dev, B53_STAT_PAGE, B53_REV_ID_25,
+                                &dev->core_rev);
+       else
+               return b53_read8(dev, B53_MGMT_PAGE, B53_REV_ID,
+                                &dev->core_rev);
 }
 EXPORT_SYMBOL(b53_switch_detect);