Skip to content

Commit 2627139

Browse files
committed
Merge branch 'ocelot-external-ports'
Colin Foster says: ==================== add support for ocelot external ports This is the start of part 3 of what is hopefully a 3-part series to add Ethernet switching support to Ocelot chips. Part 1 of the series (A New Chip) added general support for Ocelot chips that were controlled externally via SPI. https://lore.kernel.org/all/[email protected]/ Part 2 of the series (The Ethernet Strikes Back) added DSA Ethernet support for ports 0-3, which are the four copper ports that are internal to the chip. https://lore.kernel.org/all/[email protected]/ Part 3 will, at a minimum, add support for ports 4-7, which are configured to use QSGMII to an external phy (Return Of The QSGMII). With any luck, and some guidance, support for SGMII, SFPs, etc. will also be part of this series. V1 was submitted as an RFC - and that was rightly so. I suspected I wasn't doing something right, and that was certainly the case. V2 is much cleaner, so hopefully upgrading it to PATCH status is welcomed. Thanks to Russell and Vladimir for correcting my course from V1. In V1 I included a device tree snippet. I won't repeat that here, but I will include a boot log snippet, in case it is of use: ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents d4671cb + 4c05e5c commit 2627139

File tree

9 files changed

+169
-81
lines changed

9 files changed

+169
-81
lines changed

drivers/mfd/ocelot-core.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@
4545
#define VSC7512_SIO_CTRL_RES_START 0x710700f8
4646
#define VSC7512_SIO_CTRL_RES_SIZE 0x00000100
4747

48+
#define VSC7512_HSIO_RES_START 0x710d0000
49+
#define VSC7512_HSIO_RES_SIZE 0x00000128
50+
4851
#define VSC7512_ANA_RES_START 0x71880000
4952
#define VSC7512_ANA_RES_SIZE 0x00010000
5053

@@ -129,8 +132,13 @@ static const struct resource vsc7512_sgpio_resources[] = {
129132
DEFINE_RES_REG_NAMED(VSC7512_SIO_CTRL_RES_START, VSC7512_SIO_CTRL_RES_SIZE, "gcb_sio"),
130133
};
131134

135+
static const struct resource vsc7512_serdes_resources[] = {
136+
DEFINE_RES_REG_NAMED(VSC7512_HSIO_RES_START, VSC7512_HSIO_RES_SIZE, "hsio"),
137+
};
138+
132139
static const struct resource vsc7512_switch_resources[] = {
133140
DEFINE_RES_REG_NAMED(VSC7512_ANA_RES_START, VSC7512_ANA_RES_SIZE, "ana"),
141+
DEFINE_RES_REG_NAMED(VSC7512_HSIO_RES_START, VSC7512_HSIO_RES_SIZE, "hsio"),
134142
DEFINE_RES_REG_NAMED(VSC7512_QS_RES_START, VSC7512_QS_RES_SIZE, "qs"),
135143
DEFINE_RES_REG_NAMED(VSC7512_QSYS_RES_START, VSC7512_QSYS_RES_SIZE, "qsys"),
136144
DEFINE_RES_REG_NAMED(VSC7512_REW_RES_START, VSC7512_REW_RES_SIZE, "rew"),
@@ -176,6 +184,11 @@ static const struct mfd_cell vsc7512_devs[] = {
176184
.use_of_reg = true,
177185
.num_resources = ARRAY_SIZE(vsc7512_miim1_resources),
178186
.resources = vsc7512_miim1_resources,
187+
}, {
188+
.name = "ocelot-serdes",
189+
.of_compatible = "mscc,vsc7514-serdes",
190+
.num_resources = ARRAY_SIZE(vsc7512_serdes_resources),
191+
.resources = vsc7512_serdes_resources,
179192
}, {
180193
.name = "ocelot-ext-switch",
181194
.of_compatible = "mscc,vsc7512-switch",

drivers/net/dsa/ocelot/felix.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1056,6 +1056,17 @@ static void felix_phylink_get_caps(struct dsa_switch *ds, int port,
10561056
config->supported_interfaces);
10571057
}
10581058

1059+
static void felix_phylink_mac_config(struct dsa_switch *ds, int port,
1060+
unsigned int mode,
1061+
const struct phylink_link_state *state)
1062+
{
1063+
struct ocelot *ocelot = ds->priv;
1064+
struct felix *felix = ocelot_to_felix(ocelot);
1065+
1066+
if (felix->info->phylink_mac_config)
1067+
felix->info->phylink_mac_config(ocelot, port, mode, state);
1068+
}
1069+
10591070
static struct phylink_pcs *felix_phylink_mac_select_pcs(struct dsa_switch *ds,
10601071
int port,
10611072
phy_interface_t iface)
@@ -1555,6 +1566,9 @@ static int felix_setup(struct dsa_switch *ds)
15551566
if (err)
15561567
return err;
15571568

1569+
if (ocelot->targets[HSIO])
1570+
ocelot_pll5_init(ocelot);
1571+
15581572
err = ocelot_init(ocelot);
15591573
if (err)
15601574
goto out_mdiobus_free;
@@ -1571,6 +1585,10 @@ static int felix_setup(struct dsa_switch *ds)
15711585
dsa_switch_for_each_available_port(dp, ds) {
15721586
ocelot_init_port(ocelot, dp->index);
15731587

1588+
if (felix->info->configure_serdes)
1589+
felix->info->configure_serdes(ocelot, dp->index,
1590+
dp->dn);
1591+
15741592
/* Set the default QoS Classification based on PCP and DEI
15751593
* bits of vlan tag.
15761594
*/
@@ -2085,6 +2103,7 @@ const struct dsa_switch_ops felix_switch_ops = {
20852103
.get_sset_count = felix_get_sset_count,
20862104
.get_ts_info = felix_get_ts_info,
20872105
.phylink_get_caps = felix_phylink_get_caps,
2106+
.phylink_mac_config = felix_phylink_mac_config,
20882107
.phylink_mac_select_pcs = felix_phylink_mac_select_pcs,
20892108
.phylink_mac_link_down = felix_phylink_mac_link_down,
20902109
.phylink_mac_link_up = felix_phylink_mac_link_up,

drivers/net/dsa/ocelot/felix.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
#define OCELOT_PORT_MODE_USXGMII BIT(4)
1616
#define OCELOT_PORT_MODE_1000BASEX BIT(5)
1717

18+
struct device_node;
19+
1820
/* Platform-specific information */
1921
struct felix_info {
2022
/* Hardcoded resources provided by the hardware instantiation. */
@@ -58,6 +60,11 @@ struct felix_info {
5860
void (*tas_guard_bands_update)(struct ocelot *ocelot, int port);
5961
void (*port_sched_speed_set)(struct ocelot *ocelot, int port,
6062
u32 speed);
63+
void (*phylink_mac_config)(struct ocelot *ocelot, int port,
64+
unsigned int mode,
65+
const struct phylink_link_state *state);
66+
int (*configure_serdes)(struct ocelot *ocelot, int port,
67+
struct device_node *portnp);
6168
};
6269

6370
/* Methods for initializing the hardware resources specific to a tagging

drivers/net/dsa/ocelot/ocelot_ext.c

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,13 @@ static const u32 vsc7512_port_modes[VSC7514_NUM_PORTS] = {
2020
OCELOT_PORT_MODE_INTERNAL,
2121
OCELOT_PORT_MODE_INTERNAL,
2222
OCELOT_PORT_MODE_INTERNAL,
23-
OCELOT_PORT_MODE_NONE,
24-
OCELOT_PORT_MODE_NONE,
25-
OCELOT_PORT_MODE_NONE,
26-
OCELOT_PORT_MODE_NONE,
27-
OCELOT_PORT_MODE_NONE,
28-
OCELOT_PORT_MODE_NONE,
29-
OCELOT_PORT_MODE_NONE,
23+
OCELOT_PORT_MODE_SERDES,
24+
OCELOT_PORT_MODE_SERDES,
25+
OCELOT_PORT_MODE_SERDES,
26+
OCELOT_PORT_MODE_SERDES,
27+
OCELOT_PORT_MODE_SERDES,
28+
OCELOT_PORT_MODE_SGMII,
29+
OCELOT_PORT_MODE_SERDES,
3030
};
3131

3232
static const struct ocelot_ops ocelot_ext_ops = {
@@ -59,6 +59,8 @@ static const struct felix_info vsc7512_info = {
5959
.num_ports = VSC7514_NUM_PORTS,
6060
.num_tx_queues = OCELOT_NUM_TC,
6161
.port_modes = vsc7512_port_modes,
62+
.phylink_mac_config = ocelot_phylink_mac_config,
63+
.configure_serdes = ocelot_port_configure_serdes,
6264
};
6365

6466
static int ocelot_ext_probe(struct platform_device *pdev)

drivers/net/ethernet/mscc/ocelot.c

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
#include <linux/dsa/ocelot.h>
88
#include <linux/if_bridge.h>
99
#include <linux/iopoll.h>
10+
#include <linux/phy/phy.h>
11+
#include <soc/mscc/ocelot_hsio.h>
1012
#include <soc/mscc/ocelot_vcap.h>
1113
#include "ocelot.h"
1214
#include "ocelot_vcap.h"
@@ -211,6 +213,36 @@ static void ocelot_mact_init(struct ocelot *ocelot)
211213
ocelot_write(ocelot, MACACCESS_CMD_INIT, ANA_TABLES_MACACCESS);
212214
}
213215

216+
void ocelot_pll5_init(struct ocelot *ocelot)
217+
{
218+
/* Configure PLL5. This will need a proper CCF driver
219+
* The values are coming from the VTSS API for Ocelot
220+
*/
221+
regmap_write(ocelot->targets[HSIO], HSIO_PLL5G_CFG4,
222+
HSIO_PLL5G_CFG4_IB_CTRL(0x7600) |
223+
HSIO_PLL5G_CFG4_IB_BIAS_CTRL(0x8));
224+
regmap_write(ocelot->targets[HSIO], HSIO_PLL5G_CFG0,
225+
HSIO_PLL5G_CFG0_CORE_CLK_DIV(0x11) |
226+
HSIO_PLL5G_CFG0_CPU_CLK_DIV(2) |
227+
HSIO_PLL5G_CFG0_ENA_BIAS |
228+
HSIO_PLL5G_CFG0_ENA_VCO_BUF |
229+
HSIO_PLL5G_CFG0_ENA_CP1 |
230+
HSIO_PLL5G_CFG0_SELCPI(2) |
231+
HSIO_PLL5G_CFG0_LOOP_BW_RES(0xe) |
232+
HSIO_PLL5G_CFG0_SELBGV820(4) |
233+
HSIO_PLL5G_CFG0_DIV4 |
234+
HSIO_PLL5G_CFG0_ENA_CLKTREE |
235+
HSIO_PLL5G_CFG0_ENA_LANE);
236+
regmap_write(ocelot->targets[HSIO], HSIO_PLL5G_CFG2,
237+
HSIO_PLL5G_CFG2_EN_RESET_FRQ_DET |
238+
HSIO_PLL5G_CFG2_EN_RESET_OVERRUN |
239+
HSIO_PLL5G_CFG2_GAIN_TEST(0x8) |
240+
HSIO_PLL5G_CFG2_ENA_AMPCTRL |
241+
HSIO_PLL5G_CFG2_PWD_AMPCTRL_N |
242+
HSIO_PLL5G_CFG2_AMPC_SEL(0x10));
243+
}
244+
EXPORT_SYMBOL(ocelot_pll5_init);
245+
214246
static void ocelot_vcap_enable(struct ocelot *ocelot, int port)
215247
{
216248
ocelot_write_gix(ocelot, ANA_PORT_VCAP_S2_CFG_S2_ENA |
@@ -778,6 +810,71 @@ static int ocelot_port_flush(struct ocelot *ocelot, int port)
778810
return err;
779811
}
780812

813+
int ocelot_port_configure_serdes(struct ocelot *ocelot, int port,
814+
struct device_node *portnp)
815+
{
816+
struct ocelot_port *ocelot_port = ocelot->ports[port];
817+
struct device *dev = ocelot->dev;
818+
int err;
819+
820+
/* Ensure clock signals and speed are set on all QSGMII links */
821+
if (ocelot_port->phy_mode == PHY_INTERFACE_MODE_QSGMII)
822+
ocelot_port_rmwl(ocelot_port, 0,
823+
DEV_CLOCK_CFG_MAC_TX_RST |
824+
DEV_CLOCK_CFG_MAC_RX_RST,
825+
DEV_CLOCK_CFG);
826+
827+
if (ocelot_port->phy_mode != PHY_INTERFACE_MODE_INTERNAL) {
828+
struct phy *serdes = of_phy_get(portnp, NULL);
829+
830+
if (IS_ERR(serdes)) {
831+
err = PTR_ERR(serdes);
832+
dev_err_probe(dev, err,
833+
"missing SerDes phys for port %d\n",
834+
port);
835+
return err;
836+
}
837+
838+
err = phy_set_mode_ext(serdes, PHY_MODE_ETHERNET,
839+
ocelot_port->phy_mode);
840+
of_phy_put(serdes);
841+
if (err) {
842+
dev_err(dev, "Could not SerDes mode on port %d: %pe\n",
843+
port, ERR_PTR(err));
844+
return err;
845+
}
846+
}
847+
848+
return 0;
849+
}
850+
EXPORT_SYMBOL_GPL(ocelot_port_configure_serdes);
851+
852+
void ocelot_phylink_mac_config(struct ocelot *ocelot, int port,
853+
unsigned int link_an_mode,
854+
const struct phylink_link_state *state)
855+
{
856+
struct ocelot_port *ocelot_port = ocelot->ports[port];
857+
858+
/* Disable HDX fast control */
859+
ocelot_port_writel(ocelot_port, DEV_PORT_MISC_HDX_FAST_DIS,
860+
DEV_PORT_MISC);
861+
862+
/* SGMII only for now */
863+
ocelot_port_writel(ocelot_port, PCS1G_MODE_CFG_SGMII_MODE_ENA,
864+
PCS1G_MODE_CFG);
865+
ocelot_port_writel(ocelot_port, PCS1G_SD_CFG_SD_SEL, PCS1G_SD_CFG);
866+
867+
/* Enable PCS */
868+
ocelot_port_writel(ocelot_port, PCS1G_CFG_PCS_ENA, PCS1G_CFG);
869+
870+
/* No aneg on SGMII */
871+
ocelot_port_writel(ocelot_port, 0, PCS1G_ANEG_CFG);
872+
873+
/* No loopback */
874+
ocelot_port_writel(ocelot_port, 0, PCS1G_LB_CFG);
875+
}
876+
EXPORT_SYMBOL_GPL(ocelot_phylink_mac_config);
877+
781878
void ocelot_phylink_mac_link_down(struct ocelot *ocelot, int port,
782879
unsigned int link_an_mode,
783880
phy_interface_t interface,

drivers/net/ethernet/mscc/ocelot_net.c

Lines changed: 6 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1675,25 +1675,10 @@ static void vsc7514_phylink_mac_config(struct phylink_config *config,
16751675
{
16761676
struct net_device *ndev = to_net_dev(config->dev);
16771677
struct ocelot_port_private *priv = netdev_priv(ndev);
1678-
struct ocelot_port *ocelot_port = &priv->port;
1679-
1680-
/* Disable HDX fast control */
1681-
ocelot_port_writel(ocelot_port, DEV_PORT_MISC_HDX_FAST_DIS,
1682-
DEV_PORT_MISC);
1683-
1684-
/* SGMII only for now */
1685-
ocelot_port_writel(ocelot_port, PCS1G_MODE_CFG_SGMII_MODE_ENA,
1686-
PCS1G_MODE_CFG);
1687-
ocelot_port_writel(ocelot_port, PCS1G_SD_CFG_SD_SEL, PCS1G_SD_CFG);
1688-
1689-
/* Enable PCS */
1690-
ocelot_port_writel(ocelot_port, PCS1G_CFG_PCS_ENA, PCS1G_CFG);
1691-
1692-
/* No aneg on SGMII */
1693-
ocelot_port_writel(ocelot_port, 0, PCS1G_ANEG_CFG);
1678+
struct ocelot *ocelot = priv->port.ocelot;
1679+
int port = priv->port.index;
16941680

1695-
/* No loopback */
1696-
ocelot_port_writel(ocelot_port, 0, PCS1G_LB_CFG);
1681+
ocelot_phylink_mac_config(ocelot, port, link_an_mode, state);
16971682
}
16981683

16991684
static void vsc7514_phylink_mac_link_down(struct phylink_config *config,
@@ -1757,34 +1742,11 @@ static int ocelot_port_phylink_create(struct ocelot *ocelot, int port,
17571742
return -EINVAL;
17581743
}
17591744

1760-
/* Ensure clock signals and speed are set on all QSGMII links */
1761-
if (phy_mode == PHY_INTERFACE_MODE_QSGMII)
1762-
ocelot_port_rmwl(ocelot_port, 0,
1763-
DEV_CLOCK_CFG_MAC_TX_RST |
1764-
DEV_CLOCK_CFG_MAC_RX_RST,
1765-
DEV_CLOCK_CFG);
1766-
17671745
ocelot_port->phy_mode = phy_mode;
17681746

1769-
if (phy_mode != PHY_INTERFACE_MODE_INTERNAL) {
1770-
struct phy *serdes = of_phy_get(portnp, NULL);
1771-
1772-
if (IS_ERR(serdes)) {
1773-
err = PTR_ERR(serdes);
1774-
dev_err_probe(dev, err,
1775-
"missing SerDes phys for port %d\n",
1776-
port);
1777-
return err;
1778-
}
1779-
1780-
err = phy_set_mode_ext(serdes, PHY_MODE_ETHERNET, phy_mode);
1781-
of_phy_put(serdes);
1782-
if (err) {
1783-
dev_err(dev, "Could not SerDes mode on port %d: %pe\n",
1784-
port, ERR_PTR(err));
1785-
return err;
1786-
}
1787-
}
1747+
err = ocelot_port_configure_serdes(ocelot, port, portnp);
1748+
if (err)
1749+
return err;
17881750

17891751
priv = container_of(ocelot_port, struct ocelot_port_private, port);
17901752

drivers/net/ethernet/mscc/ocelot_vsc7514.c

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -18,43 +18,13 @@
1818

1919
#include <soc/mscc/ocelot.h>
2020
#include <soc/mscc/ocelot_vcap.h>
21-
#include <soc/mscc/ocelot_hsio.h>
2221
#include <soc/mscc/vsc7514_regs.h>
2322
#include "ocelot_fdma.h"
2423
#include "ocelot.h"
2524

2625
#define VSC7514_VCAP_POLICER_BASE 128
2726
#define VSC7514_VCAP_POLICER_MAX 191
2827

29-
static void ocelot_pll5_init(struct ocelot *ocelot)
30-
{
31-
/* Configure PLL5. This will need a proper CCF driver
32-
* The values are coming from the VTSS API for Ocelot
33-
*/
34-
regmap_write(ocelot->targets[HSIO], HSIO_PLL5G_CFG4,
35-
HSIO_PLL5G_CFG4_IB_CTRL(0x7600) |
36-
HSIO_PLL5G_CFG4_IB_BIAS_CTRL(0x8));
37-
regmap_write(ocelot->targets[HSIO], HSIO_PLL5G_CFG0,
38-
HSIO_PLL5G_CFG0_CORE_CLK_DIV(0x11) |
39-
HSIO_PLL5G_CFG0_CPU_CLK_DIV(2) |
40-
HSIO_PLL5G_CFG0_ENA_BIAS |
41-
HSIO_PLL5G_CFG0_ENA_VCO_BUF |
42-
HSIO_PLL5G_CFG0_ENA_CP1 |
43-
HSIO_PLL5G_CFG0_SELCPI(2) |
44-
HSIO_PLL5G_CFG0_LOOP_BW_RES(0xe) |
45-
HSIO_PLL5G_CFG0_SELBGV820(4) |
46-
HSIO_PLL5G_CFG0_DIV4 |
47-
HSIO_PLL5G_CFG0_ENA_CLKTREE |
48-
HSIO_PLL5G_CFG0_ENA_LANE);
49-
regmap_write(ocelot->targets[HSIO], HSIO_PLL5G_CFG2,
50-
HSIO_PLL5G_CFG2_EN_RESET_FRQ_DET |
51-
HSIO_PLL5G_CFG2_EN_RESET_OVERRUN |
52-
HSIO_PLL5G_CFG2_GAIN_TEST(0x8) |
53-
HSIO_PLL5G_CFG2_ENA_AMPCTRL |
54-
HSIO_PLL5G_CFG2_PWD_AMPCTRL_N |
55-
HSIO_PLL5G_CFG2_AMPC_SEL(0x10));
56-
}
57-
5828
static int ocelot_chip_init(struct ocelot *ocelot, const struct ocelot_ops *ops)
5929
{
6030
int ret;

drivers/phy/mscc/phy-ocelot-serdes.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,7 @@ static int serdes_probe(struct platform_device *pdev)
494494
{
495495
struct phy_provider *provider;
496496
struct serdes_ctrl *ctrl;
497+
struct resource *res;
497498
unsigned int i;
498499
int ret;
499500

@@ -503,6 +504,14 @@ static int serdes_probe(struct platform_device *pdev)
503504

504505
ctrl->dev = &pdev->dev;
505506
ctrl->regs = syscon_node_to_regmap(pdev->dev.parent->of_node);
507+
if (IS_ERR(ctrl->regs)) {
508+
/* Fall back to using IORESOURCE_REG, if possible */
509+
res = platform_get_resource(pdev, IORESOURCE_REG, 0);
510+
if (res)
511+
ctrl->regs = dev_get_regmap(ctrl->dev->parent,
512+
res->name);
513+
}
514+
506515
if (IS_ERR(ctrl->regs))
507516
return PTR_ERR(ctrl->regs);
508517

0 commit comments

Comments
 (0)