|
|
|
@ -24,6 +24,8 @@ |
|
|
|
|
#include <linux/kernel.h> |
|
|
|
|
#include <linux/module.h> |
|
|
|
|
#include <linux/switch.h> |
|
|
|
|
#include <linux/of.h> |
|
|
|
|
#include <linux/of_net.h> |
|
|
|
|
#include <linux/platform_data/b53.h> |
|
|
|
|
|
|
|
|
|
#include "b53_regs.h" |
|
|
|
@ -478,35 +480,88 @@ static void b53_switch_reset_gpio(struct b53_device *dev) |
|
|
|
|
dev->current_page = 0xff; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int b53_switch_reset(struct b53_device *dev) |
|
|
|
|
static int b53_configure_ports_of(struct b53_device *dev) |
|
|
|
|
{ |
|
|
|
|
u8 cpu_port = dev->sw_dev.cpu_port; |
|
|
|
|
u8 mgmt; |
|
|
|
|
struct device_node *dn, *pn; |
|
|
|
|
u32 port_num; |
|
|
|
|
|
|
|
|
|
b53_switch_reset_gpio(dev); |
|
|
|
|
dn = of_get_child_by_name(dev_of_node(dev->dev), "ports"); |
|
|
|
|
|
|
|
|
|
if (is539x(dev)) { |
|
|
|
|
b53_write8(dev, B53_CTRL_PAGE, B53_SOFTRESET, 0x83); |
|
|
|
|
b53_write8(dev, B53_CTRL_PAGE, B53_SOFTRESET, 0x00); |
|
|
|
|
} |
|
|
|
|
for_each_available_child_of_node(dn, pn) { |
|
|
|
|
struct device_node *fixed_link; |
|
|
|
|
|
|
|
|
|
b53_read8(dev, B53_CTRL_PAGE, B53_SWITCH_MODE, &mgmt); |
|
|
|
|
if (of_property_read_u32(pn, "reg", &port_num)) |
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
if (!(mgmt & SM_SW_FWD_EN)) { |
|
|
|
|
mgmt &= ~SM_SW_FWD_MODE; |
|
|
|
|
mgmt |= SM_SW_FWD_EN; |
|
|
|
|
if (port_num > B53_CPU_PORT) |
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
b53_write8(dev, B53_CTRL_PAGE, B53_SWITCH_MODE, mgmt); |
|
|
|
|
b53_read8(dev, B53_CTRL_PAGE, B53_SWITCH_MODE, &mgmt); |
|
|
|
|
fixed_link = of_get_child_by_name(pn, "fixed-link"); |
|
|
|
|
if (fixed_link) { |
|
|
|
|
u32 spd; |
|
|
|
|
u8 po = GMII_PO_LINK; |
|
|
|
|
int mode = of_get_phy_mode(pn); |
|
|
|
|
|
|
|
|
|
if (!of_property_read_u32(fixed_link, "speed", &spd)) { |
|
|
|
|
switch (spd) { |
|
|
|
|
case 10: |
|
|
|
|
po |= GMII_PO_SPEED_10M; |
|
|
|
|
break; |
|
|
|
|
case 100: |
|
|
|
|
po |= GMII_PO_SPEED_100M; |
|
|
|
|
break; |
|
|
|
|
case 2000: |
|
|
|
|
if (is_imp_port(dev, port_num)) |
|
|
|
|
po |= PORT_OVERRIDE_SPEED_2000M; |
|
|
|
|
else |
|
|
|
|
po |= GMII_PO_SPEED_2000M; |
|
|
|
|
/* fall through */ |
|
|
|
|
case 1000: |
|
|
|
|
po |= GMII_PO_SPEED_1000M; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!(mgmt & SM_SW_FWD_EN)) { |
|
|
|
|
pr_err("Failed to enable switch!\n"); |
|
|
|
|
return -EINVAL; |
|
|
|
|
if (of_property_read_bool(fixed_link, "full-duplex")) |
|
|
|
|
po |= PORT_OVERRIDE_FULL_DUPLEX; |
|
|
|
|
if (of_property_read_bool(fixed_link, "pause")) |
|
|
|
|
po |= GMII_PO_RX_FLOW; |
|
|
|
|
if (of_property_read_bool(fixed_link, "asym-pause")) |
|
|
|
|
po |= GMII_PO_TX_FLOW; |
|
|
|
|
|
|
|
|
|
if (is_imp_port(dev, port_num)) { |
|
|
|
|
po |= PORT_OVERRIDE_EN; |
|
|
|
|
|
|
|
|
|
if (is5325(dev) && |
|
|
|
|
mode == PHY_INTERFACE_MODE_REVMII) |
|
|
|
|
po |= PORT_OVERRIDE_RV_MII_25; |
|
|
|
|
|
|
|
|
|
b53_write8(dev, B53_CTRL_PAGE, |
|
|
|
|
B53_PORT_OVERRIDE_CTRL, po); |
|
|
|
|
|
|
|
|
|
if (is5325(dev) && |
|
|
|
|
mode == PHY_INTERFACE_MODE_REVMII) { |
|
|
|
|
b53_read8(dev, B53_CTRL_PAGE, |
|
|
|
|
B53_PORT_OVERRIDE_CTRL, &po); |
|
|
|
|
if (!(po & PORT_OVERRIDE_RV_MII_25)) |
|
|
|
|
pr_err("Failed to enable reverse MII mode\n"); |
|
|
|
|
return -EINVAL; |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
po |= GMII_PO_EN; |
|
|
|
|
b53_write8(dev, B53_CTRL_PAGE, |
|
|
|
|
B53_GMII_PORT_OVERRIDE_CTRL(port_num), |
|
|
|
|
po); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* enable all ports */ |
|
|
|
|
b53_enable_ports(dev); |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int b53_configure_ports(struct b53_device *dev) |
|
|
|
|
{ |
|
|
|
|
u8 cpu_port = dev->sw_dev.cpu_port; |
|
|
|
|
|
|
|
|
|
/* configure MII port if necessary */ |
|
|
|
|
if (is5325(dev)) { |
|
|
|
@ -576,6 +631,47 @@ static int b53_switch_reset(struct b53_device *dev) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int b53_switch_reset(struct b53_device *dev) |
|
|
|
|
{ |
|
|
|
|
int ret = 0; |
|
|
|
|
u8 mgmt; |
|
|
|
|
|
|
|
|
|
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)) { |
|
|
|
|
mgmt &= ~SM_SW_FWD_MODE; |
|
|
|
|
mgmt |= SM_SW_FWD_EN; |
|
|
|
|
|
|
|
|
|
b53_write8(dev, B53_CTRL_PAGE, B53_SWITCH_MODE, mgmt); |
|
|
|
|
b53_read8(dev, B53_CTRL_PAGE, B53_SWITCH_MODE, &mgmt); |
|
|
|
|
|
|
|
|
|
if (!(mgmt & SM_SW_FWD_EN)) { |
|
|
|
|
pr_err("Failed to enable switch!\n"); |
|
|
|
|
return -EINVAL; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* enable all ports */ |
|
|
|
|
b53_enable_ports(dev); |
|
|
|
|
|
|
|
|
|
if (dev->dev->of_node) |
|
|
|
|
ret = b53_configure_ports_of(dev); |
|
|
|
|
else |
|
|
|
|
ret = b53_configure_ports(dev); |
|
|
|
|
|
|
|
|
|
if (ret) |
|
|
|
|
return ret; |
|
|
|
|
|
|
|
|
|
b53_enable_mib(dev); |
|
|
|
|
|
|
|
|
|
return b53_flush_arl(dev); |
|
|
|
@ -1320,6 +1416,43 @@ static const struct b53_chip_data b53_switch_chips[] = { |
|
|
|
|
}, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
static int b53_switch_init_of(struct b53_device *dev) |
|
|
|
|
{ |
|
|
|
|
struct device_node *dn, *pn; |
|
|
|
|
const char *alias; |
|
|
|
|
u32 port_num; |
|
|
|
|
u16 ports = 0; |
|
|
|
|
|
|
|
|
|
dn = of_get_child_by_name(dev_of_node(dev->dev), "ports"); |
|
|
|
|
if (!dn) |
|
|
|
|
return -EINVAL; |
|
|
|
|
|
|
|
|
|
for_each_available_child_of_node(dn, pn) { |
|
|
|
|
const char *label; |
|
|
|
|
int len; |
|
|
|
|
|
|
|
|
|
if (of_property_read_u32(pn, "reg", &port_num)) |
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
if (port_num > B53_CPU_PORT) |
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
ports |= BIT(port_num); |
|
|
|
|
|
|
|
|
|
label = of_get_property(pn, "label", &len); |
|
|
|
|
if (label && !strcmp(label, "cpu")) |
|
|
|
|
dev->sw_dev.cpu_port = port_num; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
dev->enabled_ports = ports; |
|
|
|
|
|
|
|
|
|
if (!of_property_read_string(dev_of_node(dev->dev), "lede,alias", |
|
|
|
|
&alias)) |
|
|
|
|
dev->sw_dev.alias = devm_kstrdup(dev->dev, alias, GFP_KERNEL); |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int b53_switch_init(struct b53_device *dev) |
|
|
|
|
{ |
|
|
|
|
struct switch_dev *sw_dev = &dev->sw_dev; |
|
|
|
@ -1383,6 +1516,12 @@ static int b53_switch_init(struct b53_device *dev) |
|
|
|
|
sw_dev->cpu_port = 5; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (dev_of_node(dev->dev)) { |
|
|
|
|
ret = b53_switch_init_of(dev); |
|
|
|
|
if (ret) |
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
dev->enabled_ports |= BIT(sw_dev->cpu_port); |
|
|
|
|
sw_dev->ports = fls(dev->enabled_ports); |
|
|
|
|
|
|
|
|
|