Merge branch 'GEHC-Bx50-Switch-Support'
Sebastian Reichel says: ==================== GEHC Bx50 Switch Support This adds support for the internal switch found in GE Healthcare B450v3, B650v3 and B850v3. All devices use a GPIO bitbanged MDIO bus to communicate with the switch and a PCIe based network card for exchanging network data. The cpu network data link requires, that the switch's internal phy interface is enabled, so support for that is added by the first patch in this series. The patch series is based on v4.15-rc8. Changes since PATCHv4: * Introduce dsa_port_link_(un)register_of and mark the fixed variant static. * Update patch description to describe the phy<->phy connection from i210 to the Marvell switch Changes since PATCHv3: * Enable the phy in dsa_port_setup() instead of abusing the fixed link setup function Changes since PATCHv2: * Add phy nodes to switch in bx50.dtsi and reference them from switch ports * Enable cpu-port's phy based on 'phy-handle' instead of 'phy-mode' Changes since PATCHv1: * Use 'marvell,mv88e6085' instead of introducing compatible string for mv88e6240. * Fix indention of DT nodes * Only enable 'cpu' phy, if explicitly set to "internal". ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
c89b517da1
@ -112,3 +112,55 @@
|
||||
line-name = "PCA9539-P07";
|
||||
};
|
||||
};
|
||||
|
||||
&pci_root {
|
||||
/* Intel Corporation I210 Gigabit Network Connection */
|
||||
switch_nic: ethernet@3,0 {
|
||||
compatible = "pci8086,1533";
|
||||
reg = <0x00010000 0 0 0 0>;
|
||||
};
|
||||
};
|
||||
|
||||
&switch_ports {
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
label = "enacq";
|
||||
phy-handle = <&switchphy0>;
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
label = "eneport1";
|
||||
phy-handle = <&switchphy1>;
|
||||
};
|
||||
|
||||
port@2 {
|
||||
reg = <2>;
|
||||
label = "enix";
|
||||
phy-handle = <&switchphy2>;
|
||||
};
|
||||
|
||||
port@3 {
|
||||
reg = <3>;
|
||||
label = "enid";
|
||||
phy-handle = <&switchphy3>;
|
||||
};
|
||||
|
||||
port@4 {
|
||||
reg = <4>;
|
||||
label = "cpu";
|
||||
ethernet = <&switch_nic>;
|
||||
phy-handle = <&switchphy4>;
|
||||
};
|
||||
|
||||
port@5 {
|
||||
reg = <5>;
|
||||
label = "enembc";
|
||||
|
||||
/* connected to Ethernet MAC of AT91RM9200 in MII mode */
|
||||
fixed-link {
|
||||
speed = <100>;
|
||||
full-duplex;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -111,3 +111,55 @@
|
||||
fsl,tx-cal-45-dp-ohms = <55>;
|
||||
fsl,tx-d-cal = <100>;
|
||||
};
|
||||
|
||||
&pci_root {
|
||||
/* Intel Corporation I210 Gigabit Network Connection */
|
||||
switch_nic: ethernet@3,0 {
|
||||
compatible = "pci8086,1533";
|
||||
reg = <0x00010000 0 0 0 0>;
|
||||
};
|
||||
};
|
||||
|
||||
&switch_ports {
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
label = "enacq";
|
||||
phy-handle = <&switchphy0>;
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
label = "eneport1";
|
||||
phy-handle = <&switchphy1>;
|
||||
};
|
||||
|
||||
port@2 {
|
||||
reg = <2>;
|
||||
label = "enix";
|
||||
phy-handle = <&switchphy2>;
|
||||
};
|
||||
|
||||
port@3 {
|
||||
reg = <3>;
|
||||
label = "enid";
|
||||
phy-handle = <&switchphy3>;
|
||||
};
|
||||
|
||||
port@4 {
|
||||
reg = <4>;
|
||||
label = "cpu";
|
||||
ethernet = <&switch_nic>;
|
||||
phy-handle = <&switchphy4>;
|
||||
};
|
||||
|
||||
port@5 {
|
||||
reg = <5>;
|
||||
label = "enembc";
|
||||
|
||||
/* connected to Ethernet MAC of AT91RM9200 in MII mode */
|
||||
fixed-link {
|
||||
speed = <100>;
|
||||
full-duplex;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -212,3 +212,78 @@
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&pci_root {
|
||||
/* PLX Technology, Inc. PEX 8605 PCI Express 4-port Gen2 Switch */
|
||||
bridge@1,0 {
|
||||
compatible = "pci10b5,8605";
|
||||
reg = <0x00010000 0 0 0 0>;
|
||||
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
#interrupt-cells = <1>;
|
||||
|
||||
bridge@2,1 {
|
||||
compatible = "pci10b5,8605";
|
||||
reg = <0x00020800 0 0 0 0>;
|
||||
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
#interrupt-cells = <1>;
|
||||
|
||||
/* Intel Corporation I210 Gigabit Network Connection */
|
||||
ethernet@3,0 {
|
||||
compatible = "pci8086,1533";
|
||||
reg = <0x00030000 0 0 0 0>;
|
||||
};
|
||||
};
|
||||
|
||||
bridge@2,2 {
|
||||
compatible = "pci10b5,8605";
|
||||
reg = <0x00021000 0 0 0 0>;
|
||||
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
#interrupt-cells = <1>;
|
||||
|
||||
/* Intel Corporation I210 Gigabit Network Connection */
|
||||
switch_nic: ethernet@4,0 {
|
||||
compatible = "pci8086,1533";
|
||||
reg = <0x00040000 0 0 0 0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&switch_ports {
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
label = "eneport1";
|
||||
phy-handle = <&switchphy0>;
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
label = "eneport2";
|
||||
phy-handle = <&switchphy1>;
|
||||
};
|
||||
|
||||
port@2 {
|
||||
reg = <2>;
|
||||
label = "enix";
|
||||
phy-handle = <&switchphy2>;
|
||||
};
|
||||
|
||||
port@3 {
|
||||
reg = <3>;
|
||||
label = "enid";
|
||||
phy-handle = <&switchphy3>;
|
||||
};
|
||||
|
||||
port@4 {
|
||||
reg = <4>;
|
||||
label = "cpu";
|
||||
ethernet = <&switch_nic>;
|
||||
phy-handle = <&switchphy4>;
|
||||
};
|
||||
};
|
||||
|
@ -92,6 +92,56 @@
|
||||
mux-int-port = <1>;
|
||||
mux-ext-port = <4>;
|
||||
};
|
||||
|
||||
aliases {
|
||||
mdio-gpio0 = &mdio0;
|
||||
};
|
||||
|
||||
mdio0: mdio-gpio {
|
||||
compatible = "virtual,mdio-gpio";
|
||||
gpios = <&gpio2 5 GPIO_ACTIVE_HIGH>, /* mdc */
|
||||
<&gpio2 7 GPIO_ACTIVE_HIGH>; /* mdio */
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
switch@0 {
|
||||
compatible = "marvell,mv88e6085"; /* 88e6240*/
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <0>;
|
||||
|
||||
switch_ports: ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
mdio {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
switchphy0: switchphy@0 {
|
||||
reg = <0>;
|
||||
};
|
||||
|
||||
switchphy1: switchphy@1 {
|
||||
reg = <1>;
|
||||
};
|
||||
|
||||
switchphy2: switchphy@2 {
|
||||
reg = <2>;
|
||||
};
|
||||
|
||||
switchphy3: switchphy@3 {
|
||||
reg = <3>;
|
||||
};
|
||||
|
||||
switchphy4: switchphy@4 {
|
||||
reg = <4>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&ecspi5 {
|
||||
@ -326,3 +376,15 @@
|
||||
tcxo-clock-frequency = <26000000>;
|
||||
};
|
||||
};
|
||||
|
||||
&pcie {
|
||||
/* Synopsys, Inc. Device */
|
||||
pci_root: root@0,0 {
|
||||
compatible = "pci16c3,abcd";
|
||||
reg = <0x00000000 0 0 0 0>;
|
||||
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
#interrupt-cells = <1>;
|
||||
};
|
||||
};
|
||||
|
@ -271,13 +271,12 @@ static int dsa_port_setup(struct dsa_port *dp)
|
||||
break;
|
||||
case DSA_PORT_TYPE_CPU:
|
||||
case DSA_PORT_TYPE_DSA:
|
||||
err = dsa_port_fixed_link_register_of(dp);
|
||||
err = dsa_port_link_register_of(dp);
|
||||
if (err) {
|
||||
dev_err(ds->dev, "failed to register fixed link for port %d.%d\n",
|
||||
dev_err(ds->dev, "failed to setup link for port %d.%d\n",
|
||||
ds->index, dp->index);
|
||||
return err;
|
||||
}
|
||||
|
||||
break;
|
||||
case DSA_PORT_TYPE_USER:
|
||||
err = dsa_slave_create(dp);
|
||||
@ -301,7 +300,7 @@ static void dsa_port_teardown(struct dsa_port *dp)
|
||||
break;
|
||||
case DSA_PORT_TYPE_CPU:
|
||||
case DSA_PORT_TYPE_DSA:
|
||||
dsa_port_fixed_link_unregister_of(dp);
|
||||
dsa_port_link_unregister_of(dp);
|
||||
break;
|
||||
case DSA_PORT_TYPE_USER:
|
||||
if (dp->slave) {
|
||||
|
@ -166,8 +166,8 @@ int dsa_port_vlan_add(struct dsa_port *dp,
|
||||
struct switchdev_trans *trans);
|
||||
int dsa_port_vlan_del(struct dsa_port *dp,
|
||||
const struct switchdev_obj_port_vlan *vlan);
|
||||
int dsa_port_fixed_link_register_of(struct dsa_port *dp);
|
||||
void dsa_port_fixed_link_unregister_of(struct dsa_port *dp);
|
||||
int dsa_port_link_register_of(struct dsa_port *dp);
|
||||
void dsa_port_link_unregister_of(struct dsa_port *dp);
|
||||
|
||||
/* slave.c */
|
||||
extern const struct dsa_device_ops notag_netdev_ops;
|
||||
|
@ -86,7 +86,7 @@ static int dsa_cpu_dsa_setups(struct dsa_switch *ds)
|
||||
if (!(dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)))
|
||||
continue;
|
||||
|
||||
ret = dsa_port_fixed_link_register_of(&ds->ports[port]);
|
||||
ret = dsa_port_link_register_of(&ds->ports[port]);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
@ -275,7 +275,7 @@ static void dsa_switch_destroy(struct dsa_switch *ds)
|
||||
for (port = 0; port < ds->num_ports; port++) {
|
||||
if (!(dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)))
|
||||
continue;
|
||||
dsa_port_fixed_link_unregister_of(&ds->ports[port]);
|
||||
dsa_port_link_unregister_of(&ds->ports[port]);
|
||||
}
|
||||
|
||||
if (ds->slave_mii_bus && ds->ops->phy_read)
|
||||
|
113
net/dsa/port.c
113
net/dsa/port.c
@ -273,7 +273,56 @@ int dsa_port_vlan_del(struct dsa_port *dp,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dsa_port_fixed_link_register_of(struct dsa_port *dp)
|
||||
static int dsa_port_setup_phy_of(struct dsa_port *dp, bool enable)
|
||||
{
|
||||
struct device_node *port_dn = dp->dn;
|
||||
struct device_node *phy_dn;
|
||||
struct dsa_switch *ds = dp->ds;
|
||||
struct phy_device *phydev;
|
||||
int port = dp->index;
|
||||
int err = 0;
|
||||
|
||||
phy_dn = of_parse_phandle(port_dn, "phy-handle", 0);
|
||||
if (!phy_dn)
|
||||
return 0;
|
||||
|
||||
phydev = of_phy_find_device(phy_dn);
|
||||
if (!phydev) {
|
||||
err = -EPROBE_DEFER;
|
||||
goto err_put_of;
|
||||
}
|
||||
|
||||
if (enable) {
|
||||
err = genphy_config_init(phydev);
|
||||
if (err < 0)
|
||||
goto err_put_dev;
|
||||
|
||||
err = genphy_resume(phydev);
|
||||
if (err < 0)
|
||||
goto err_put_dev;
|
||||
|
||||
err = genphy_read_status(phydev);
|
||||
if (err < 0)
|
||||
goto err_put_dev;
|
||||
} else {
|
||||
err = genphy_suspend(phydev);
|
||||
if (err < 0)
|
||||
goto err_put_dev;
|
||||
}
|
||||
|
||||
if (ds->ops->adjust_link)
|
||||
ds->ops->adjust_link(ds, port, phydev);
|
||||
|
||||
dev_dbg(ds->dev, "enabled port's phy: %s", phydev_name(phydev));
|
||||
|
||||
err_put_dev:
|
||||
put_device(&phydev->mdio.dev);
|
||||
err_put_of:
|
||||
of_node_put(phy_dn);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int dsa_port_fixed_link_register_of(struct dsa_port *dp)
|
||||
{
|
||||
struct device_node *dn = dp->dn;
|
||||
struct dsa_switch *ds = dp->ds;
|
||||
@ -282,38 +331,44 @@ int dsa_port_fixed_link_register_of(struct dsa_port *dp)
|
||||
int mode;
|
||||
int err;
|
||||
|
||||
if (of_phy_is_fixed_link(dn)) {
|
||||
err = of_phy_register_fixed_link(dn);
|
||||
if (err) {
|
||||
dev_err(ds->dev,
|
||||
"failed to register the fixed PHY of port %d\n",
|
||||
port);
|
||||
return err;
|
||||
}
|
||||
|
||||
phydev = of_phy_find_device(dn);
|
||||
|
||||
mode = of_get_phy_mode(dn);
|
||||
if (mode < 0)
|
||||
mode = PHY_INTERFACE_MODE_NA;
|
||||
phydev->interface = mode;
|
||||
|
||||
genphy_config_init(phydev);
|
||||
genphy_read_status(phydev);
|
||||
|
||||
if (ds->ops->adjust_link)
|
||||
ds->ops->adjust_link(ds, port, phydev);
|
||||
|
||||
put_device(&phydev->mdio.dev);
|
||||
err = of_phy_register_fixed_link(dn);
|
||||
if (err) {
|
||||
dev_err(ds->dev,
|
||||
"failed to register the fixed PHY of port %d\n",
|
||||
port);
|
||||
return err;
|
||||
}
|
||||
|
||||
phydev = of_phy_find_device(dn);
|
||||
|
||||
mode = of_get_phy_mode(dn);
|
||||
if (mode < 0)
|
||||
mode = PHY_INTERFACE_MODE_NA;
|
||||
phydev->interface = mode;
|
||||
|
||||
genphy_config_init(phydev);
|
||||
genphy_read_status(phydev);
|
||||
|
||||
if (ds->ops->adjust_link)
|
||||
ds->ops->adjust_link(ds, port, phydev);
|
||||
|
||||
put_device(&phydev->mdio.dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dsa_port_fixed_link_unregister_of(struct dsa_port *dp)
|
||||
int dsa_port_link_register_of(struct dsa_port *dp)
|
||||
{
|
||||
struct device_node *dn = dp->dn;
|
||||
|
||||
if (of_phy_is_fixed_link(dn))
|
||||
of_phy_deregister_fixed_link(dn);
|
||||
if (of_phy_is_fixed_link(dp->dn))
|
||||
return dsa_port_fixed_link_register_of(dp);
|
||||
else
|
||||
return dsa_port_setup_phy_of(dp, true);
|
||||
}
|
||||
|
||||
void dsa_port_link_unregister_of(struct dsa_port *dp)
|
||||
{
|
||||
if (of_phy_is_fixed_link(dp->dn))
|
||||
of_phy_deregister_fixed_link(dp->dn);
|
||||
else
|
||||
dsa_port_setup_phy_of(dp, false);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user