Skip to content

Commit f84bf38

Browse files
atenartdavem330
authored andcommitted
net: mvpp2: initialize the GoP
The patch adds GoP (group of ports) initialization functions. The mvpp2 driver was relying on the firmware/bootloader initialization; this patch moves this setup to the mvpp2 driver. Signed-off-by: Antoine Tenart <[email protected]> Tested-by: Marcin Wojtas <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 76eb1b1 commit f84bf38

File tree

1 file changed

+170
-0
lines changed
  • drivers/net/ethernet/marvell

1 file changed

+170
-0
lines changed

drivers/net/ethernet/marvell/mvpp2.c

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <linux/inetdevice.h>
1919
#include <linux/mbus.h>
2020
#include <linux/module.h>
21+
#include <linux/mfd/syscon.h>
2122
#include <linux/interrupt.h>
2223
#include <linux/cpumask.h>
2324
#include <linux/of.h>
@@ -30,6 +31,7 @@
3031
#include <linux/clk.h>
3132
#include <linux/hrtimer.h>
3233
#include <linux/ktime.h>
34+
#include <linux/regmap.h>
3335
#include <uapi/linux/ppp_defs.h>
3436
#include <net/ip.h>
3537
#include <net/ipv6.h>
@@ -388,6 +390,38 @@
388390
#define MVPP2_QUEUE_NEXT_DESC(q, index) \
389391
(((index) < (q)->last_desc) ? ((index) + 1) : 0)
390392

393+
/* XPCS registers. PPv2.2 only */
394+
#define MVPP22_MPCS_BASE(port) (0x7000 + (port) * 0x1000)
395+
#define MVPP22_MPCS_CTRL 0x14
396+
#define MVPP22_MPCS_CTRL_FWD_ERR_CONN BIT(10)
397+
#define MVPP22_MPCS_CLK_RESET 0x14c
398+
#define MAC_CLK_RESET_SD_TX BIT(0)
399+
#define MAC_CLK_RESET_SD_RX BIT(1)
400+
#define MAC_CLK_RESET_MAC BIT(2)
401+
#define MVPP22_MPCS_CLK_RESET_DIV_RATIO(n) ((n) << 4)
402+
#define MVPP22_MPCS_CLK_RESET_DIV_SET BIT(11)
403+
404+
/* XPCS registers. PPv2.2 only */
405+
#define MVPP22_XPCS_BASE(port) (0x7400 + (port) * 0x1000)
406+
#define MVPP22_XPCS_CFG0 0x0
407+
#define MVPP22_XPCS_CFG0_PCS_MODE(n) ((n) << 3)
408+
#define MVPP22_XPCS_CFG0_ACTIVE_LANE(n) ((n) << 5)
409+
410+
/* System controller registers. Accessed through a regmap. */
411+
#define GENCONF_SOFT_RESET1 0x1108
412+
#define GENCONF_SOFT_RESET1_GOP BIT(6)
413+
#define GENCONF_PORT_CTRL0 0x1110
414+
#define GENCONF_PORT_CTRL0_BUS_WIDTH_SELECT BIT(1)
415+
#define GENCONF_PORT_CTRL0_RX_DATA_SAMPLE BIT(29)
416+
#define GENCONF_PORT_CTRL0_CLK_DIV_PHASE_CLR BIT(31)
417+
#define GENCONF_PORT_CTRL1 0x1114
418+
#define GENCONF_PORT_CTRL1_EN(p) BIT(p)
419+
#define GENCONF_PORT_CTRL1_RESET(p) (BIT(p) << 28)
420+
#define GENCONF_CTRL0 0x1120
421+
#define GENCONF_CTRL0_PORT0_RGMII BIT(0)
422+
#define GENCONF_CTRL0_PORT1_RGMII_MII BIT(1)
423+
#define GENCONF_CTRL0_PORT1_RGMII BIT(2)
424+
391425
/* Various constants */
392426

393427
/* Coalescing */
@@ -731,6 +765,11 @@ struct mvpp2 {
731765
*/
732766
void __iomem *swth_base[MVPP2_MAX_THREADS];
733767

768+
/* On PPv2.2, some port control registers are located into the system
769+
* controller space. These registers are accessible through a regmap.
770+
*/
771+
struct regmap *sysctrl_base;
772+
734773
/* Common clocks */
735774
struct clk *pp_clk;
736775
struct clk *gop_clk;
@@ -4259,6 +4298,123 @@ mvpp2_shared_interrupt_mask_unmask(struct mvpp2_port *port, bool mask)
42594298

42604299
/* Port configuration routines */
42614300

4301+
static void mvpp22_gop_init_rgmii(struct mvpp2_port *port)
4302+
{
4303+
struct mvpp2 *priv = port->priv;
4304+
u32 val;
4305+
4306+
regmap_read(priv->sysctrl_base, GENCONF_PORT_CTRL0, &val);
4307+
val |= GENCONF_PORT_CTRL0_BUS_WIDTH_SELECT;
4308+
regmap_write(priv->sysctrl_base, GENCONF_PORT_CTRL0, val);
4309+
4310+
regmap_read(priv->sysctrl_base, GENCONF_CTRL0, &val);
4311+
if (port->gop_id == 2)
4312+
val |= GENCONF_CTRL0_PORT0_RGMII | GENCONF_CTRL0_PORT1_RGMII;
4313+
else if (port->gop_id == 3)
4314+
val |= GENCONF_CTRL0_PORT1_RGMII_MII;
4315+
regmap_write(priv->sysctrl_base, GENCONF_CTRL0, val);
4316+
}
4317+
4318+
static void mvpp22_gop_init_sgmii(struct mvpp2_port *port)
4319+
{
4320+
struct mvpp2 *priv = port->priv;
4321+
u32 val;
4322+
4323+
regmap_read(priv->sysctrl_base, GENCONF_PORT_CTRL0, &val);
4324+
val |= GENCONF_PORT_CTRL0_BUS_WIDTH_SELECT |
4325+
GENCONF_PORT_CTRL0_RX_DATA_SAMPLE;
4326+
regmap_write(priv->sysctrl_base, GENCONF_PORT_CTRL0, val);
4327+
4328+
if (port->gop_id > 1) {
4329+
regmap_read(priv->sysctrl_base, GENCONF_CTRL0, &val);
4330+
if (port->gop_id == 2)
4331+
val &= ~GENCONF_CTRL0_PORT0_RGMII;
4332+
else if (port->gop_id == 3)
4333+
val &= ~GENCONF_CTRL0_PORT1_RGMII_MII;
4334+
regmap_write(priv->sysctrl_base, GENCONF_CTRL0, val);
4335+
}
4336+
}
4337+
4338+
static void mvpp22_gop_init_10gkr(struct mvpp2_port *port)
4339+
{
4340+
struct mvpp2 *priv = port->priv;
4341+
void __iomem *mpcs = priv->iface_base + MVPP22_MPCS_BASE(port->gop_id);
4342+
void __iomem *xpcs = priv->iface_base + MVPP22_XPCS_BASE(port->gop_id);
4343+
u32 val;
4344+
4345+
/* XPCS */
4346+
val = readl(xpcs + MVPP22_XPCS_CFG0);
4347+
val &= ~(MVPP22_XPCS_CFG0_PCS_MODE(0x3) |
4348+
MVPP22_XPCS_CFG0_ACTIVE_LANE(0x3));
4349+
val |= MVPP22_XPCS_CFG0_ACTIVE_LANE(2);
4350+
writel(val, xpcs + MVPP22_XPCS_CFG0);
4351+
4352+
/* MPCS */
4353+
val = readl(mpcs + MVPP22_MPCS_CTRL);
4354+
val &= ~MVPP22_MPCS_CTRL_FWD_ERR_CONN;
4355+
writel(val, mpcs + MVPP22_MPCS_CTRL);
4356+
4357+
val = readl(mpcs + MVPP22_MPCS_CLK_RESET);
4358+
val &= ~(MVPP22_MPCS_CLK_RESET_DIV_RATIO(0x7) | MAC_CLK_RESET_MAC |
4359+
MAC_CLK_RESET_SD_RX | MAC_CLK_RESET_SD_TX);
4360+
val |= MVPP22_MPCS_CLK_RESET_DIV_RATIO(1);
4361+
writel(val, mpcs + MVPP22_MPCS_CLK_RESET);
4362+
4363+
val &= ~MVPP22_MPCS_CLK_RESET_DIV_SET;
4364+
val |= MAC_CLK_RESET_MAC | MAC_CLK_RESET_SD_RX | MAC_CLK_RESET_SD_TX;
4365+
writel(val, mpcs + MVPP22_MPCS_CLK_RESET);
4366+
}
4367+
4368+
static int mvpp22_gop_init(struct mvpp2_port *port)
4369+
{
4370+
struct mvpp2 *priv = port->priv;
4371+
u32 val;
4372+
4373+
if (!priv->sysctrl_base)
4374+
return 0;
4375+
4376+
switch (port->phy_interface) {
4377+
case PHY_INTERFACE_MODE_RGMII:
4378+
case PHY_INTERFACE_MODE_RGMII_ID:
4379+
case PHY_INTERFACE_MODE_RGMII_RXID:
4380+
case PHY_INTERFACE_MODE_RGMII_TXID:
4381+
if (port->gop_id == 0)
4382+
goto invalid_conf;
4383+
mvpp22_gop_init_rgmii(port);
4384+
break;
4385+
case PHY_INTERFACE_MODE_SGMII:
4386+
mvpp22_gop_init_sgmii(port);
4387+
break;
4388+
case PHY_INTERFACE_MODE_10GKR:
4389+
if (port->gop_id != 0)
4390+
goto invalid_conf;
4391+
mvpp22_gop_init_10gkr(port);
4392+
break;
4393+
default:
4394+
goto unsupported_conf;
4395+
}
4396+
4397+
regmap_read(priv->sysctrl_base, GENCONF_PORT_CTRL1, &val);
4398+
val |= GENCONF_PORT_CTRL1_RESET(port->gop_id) |
4399+
GENCONF_PORT_CTRL1_EN(port->gop_id);
4400+
regmap_write(priv->sysctrl_base, GENCONF_PORT_CTRL1, val);
4401+
4402+
regmap_read(priv->sysctrl_base, GENCONF_PORT_CTRL0, &val);
4403+
val |= GENCONF_PORT_CTRL0_CLK_DIV_PHASE_CLR;
4404+
regmap_write(priv->sysctrl_base, GENCONF_PORT_CTRL0, val);
4405+
4406+
regmap_read(priv->sysctrl_base, GENCONF_SOFT_RESET1, &val);
4407+
val |= GENCONF_SOFT_RESET1_GOP;
4408+
regmap_write(priv->sysctrl_base, GENCONF_SOFT_RESET1, val);
4409+
4410+
unsupported_conf:
4411+
return 0;
4412+
4413+
invalid_conf:
4414+
netdev_err(port->dev, "Invalid port configuration\n");
4415+
return -EINVAL;
4416+
}
4417+
42624418
static void mvpp2_port_mii_gmac_configure_mode(struct mvpp2_port *port)
42634419
{
42644420
u32 val;
@@ -6105,6 +6261,9 @@ static void mvpp2_start_dev(struct mvpp2_port *port)
61056261
/* Enable interrupts on all CPUs */
61066262
mvpp2_interrupts_enable(port);
61076263

6264+
if (port->priv->hw_version == MVPP22)
6265+
mvpp22_gop_init(port);
6266+
61086267
mvpp2_port_mii_set(port);
61096268
mvpp2_port_enable(port);
61106269
phy_start(ndev->phydev);
@@ -7350,6 +7509,17 @@ static int mvpp2_probe(struct platform_device *pdev)
73507509
priv->iface_base = devm_ioremap_resource(&pdev->dev, res);
73517510
if (IS_ERR(priv->iface_base))
73527511
return PTR_ERR(priv->iface_base);
7512+
7513+
priv->sysctrl_base =
7514+
syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
7515+
"marvell,system-controller");
7516+
if (IS_ERR(priv->sysctrl_base))
7517+
/* The system controller regmap is optional for dt
7518+
* compatibility reasons. When not provided, the
7519+
* configuration of the GoP relies on the
7520+
* firmware/bootloader.
7521+
*/
7522+
priv->sysctrl_base = NULL;
73537523
}
73547524

73557525
for (i = 0; i < MVPP2_MAX_THREADS; i++) {

0 commit comments

Comments
 (0)