Skip to content

Commit

Permalink
net: stmmac: dwmac-meson: extend phy mode setting
Browse files Browse the repository at this point in the history
In the Meson-AXG SoC, the phy mode setting of PRG_ETH0 in the glue layer
is extended from bit[0] to bit[2:0].
  There is no problem if we configure it to the RGMII 1000M PHY mode,
since the register setting is coincidentally compatible with previous one,
but for the RMII 100M PHY mode, the configuration need to be changed to
value - b100.
  This patch was verified with a RTL8201F 100M ethernet PHY.

Signed-off-by: Yixun Lan <yixun.lan@amlogic.com>
Acked-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Yixun Lan authored and David S. Miller committed May 1, 2018
1 parent 7e5d05e commit efacb56
Showing 1 changed file with 104 additions and 16 deletions.
120 changes: 104 additions & 16 deletions drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/of_net.h>
#include <linux/mfd/syscon.h>
#include <linux/platform_device.h>
Expand All @@ -29,6 +30,10 @@

#define PRG_ETH0_RGMII_MODE BIT(0)

#define PRG_ETH0_EXT_PHY_MODE_MASK GENMASK(2, 0)
#define PRG_ETH0_EXT_RGMII_MODE 1
#define PRG_ETH0_EXT_RMII_MODE 4

/* mux to choose between fclk_div2 (bit unset) and mpll2 (bit set) */
#define PRG_ETH0_CLK_M250_SEL_SHIFT 4
#define PRG_ETH0_CLK_M250_SEL_MASK GENMASK(4, 4)
Expand All @@ -47,12 +52,20 @@

#define MUX_CLK_NUM_PARENTS 2

struct meson8b_dwmac;

struct meson8b_dwmac_data {
int (*set_phy_mode)(struct meson8b_dwmac *dwmac);
};

struct meson8b_dwmac {
struct device *dev;
void __iomem *regs;
phy_interface_t phy_mode;
struct clk *rgmii_tx_clk;
u32 tx_delay_ns;
struct device *dev;
void __iomem *regs;

const struct meson8b_dwmac_data *data;
phy_interface_t phy_mode;
struct clk *rgmii_tx_clk;
u32 tx_delay_ns;
};

struct meson8b_dwmac_clk_configs {
Expand Down Expand Up @@ -171,6 +184,59 @@ static int meson8b_init_rgmii_tx_clk(struct meson8b_dwmac *dwmac)
return 0;
}

static int meson8b_set_phy_mode(struct meson8b_dwmac *dwmac)
{
switch (dwmac->phy_mode) {
case PHY_INTERFACE_MODE_RGMII:
case PHY_INTERFACE_MODE_RGMII_RXID:
case PHY_INTERFACE_MODE_RGMII_ID:
case PHY_INTERFACE_MODE_RGMII_TXID:
/* enable RGMII mode */
meson8b_dwmac_mask_bits(dwmac, PRG_ETH0,
PRG_ETH0_RGMII_MODE,
PRG_ETH0_RGMII_MODE);
break;
case PHY_INTERFACE_MODE_RMII:
/* disable RGMII mode -> enables RMII mode */
meson8b_dwmac_mask_bits(dwmac, PRG_ETH0,
PRG_ETH0_RGMII_MODE, 0);
break;
default:
dev_err(dwmac->dev, "fail to set phy-mode %s\n",
phy_modes(dwmac->phy_mode));
return -EINVAL;
}

return 0;
}

static int meson_axg_set_phy_mode(struct meson8b_dwmac *dwmac)
{
switch (dwmac->phy_mode) {
case PHY_INTERFACE_MODE_RGMII:
case PHY_INTERFACE_MODE_RGMII_RXID:
case PHY_INTERFACE_MODE_RGMII_ID:
case PHY_INTERFACE_MODE_RGMII_TXID:
/* enable RGMII mode */
meson8b_dwmac_mask_bits(dwmac, PRG_ETH0,
PRG_ETH0_EXT_PHY_MODE_MASK,
PRG_ETH0_EXT_RGMII_MODE);
break;
case PHY_INTERFACE_MODE_RMII:
/* disable RGMII mode -> enables RMII mode */
meson8b_dwmac_mask_bits(dwmac, PRG_ETH0,
PRG_ETH0_EXT_PHY_MODE_MASK,
PRG_ETH0_EXT_RMII_MODE);
break;
default:
dev_err(dwmac->dev, "fail to set phy-mode %s\n",
phy_modes(dwmac->phy_mode));
return -EINVAL;
}

return 0;
}

static int meson8b_init_prg_eth(struct meson8b_dwmac *dwmac)
{
int ret;
Expand All @@ -188,10 +254,6 @@ static int meson8b_init_prg_eth(struct meson8b_dwmac *dwmac)

case PHY_INTERFACE_MODE_RGMII_ID:
case PHY_INTERFACE_MODE_RGMII_TXID:
/* enable RGMII mode */
meson8b_dwmac_mask_bits(dwmac, PRG_ETH0, PRG_ETH0_RGMII_MODE,
PRG_ETH0_RGMII_MODE);

/* only relevant for RMII mode -> disable in RGMII mode */
meson8b_dwmac_mask_bits(dwmac, PRG_ETH0,
PRG_ETH0_INVERTED_RMII_CLK, 0);
Expand Down Expand Up @@ -224,10 +286,6 @@ static int meson8b_init_prg_eth(struct meson8b_dwmac *dwmac)
break;

case PHY_INTERFACE_MODE_RMII:
/* disable RGMII mode -> enables RMII mode */
meson8b_dwmac_mask_bits(dwmac, PRG_ETH0, PRG_ETH0_RGMII_MODE,
0);

/* invert internal clk_rmii_i to generate 25/2.5 tx_rx_clk */
meson8b_dwmac_mask_bits(dwmac, PRG_ETH0,
PRG_ETH0_INVERTED_RMII_CLK,
Expand Down Expand Up @@ -274,6 +332,11 @@ static int meson8b_dwmac_probe(struct platform_device *pdev)
goto err_remove_config_dt;
}

dwmac->data = (const struct meson8b_dwmac_data *)
of_device_get_match_data(&pdev->dev);
if (!dwmac->data)
return -EINVAL;

res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
dwmac->regs = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(dwmac->regs)) {
Expand All @@ -298,6 +361,10 @@ static int meson8b_dwmac_probe(struct platform_device *pdev)
if (ret)
goto err_remove_config_dt;

ret = dwmac->data->set_phy_mode(dwmac);
if (ret)
goto err_remove_config_dt;

ret = meson8b_init_prg_eth(dwmac);
if (ret)
goto err_remove_config_dt;
Expand All @@ -316,10 +383,31 @@ static int meson8b_dwmac_probe(struct platform_device *pdev)
return ret;
}

static const struct meson8b_dwmac_data meson8b_dwmac_data = {
.set_phy_mode = meson8b_set_phy_mode,
};

static const struct meson8b_dwmac_data meson_axg_dwmac_data = {
.set_phy_mode = meson_axg_set_phy_mode,
};

static const struct of_device_id meson8b_dwmac_match[] = {
{ .compatible = "amlogic,meson8b-dwmac" },
{ .compatible = "amlogic,meson8m2-dwmac" },
{ .compatible = "amlogic,meson-gxbb-dwmac" },
{
.compatible = "amlogic,meson8b-dwmac",
.data = &meson8b_dwmac_data,
},
{
.compatible = "amlogic,meson8m2-dwmac",
.data = &meson8b_dwmac_data,
},
{
.compatible = "amlogic,meson-gxbb-dwmac",
.data = &meson8b_dwmac_data,
},
{
.compatible = "amlogic,meson-axg-dwmac",
.data = &meson_axg_dwmac_data,
},
{ }
};
MODULE_DEVICE_TABLE(of, meson8b_dwmac_match);
Expand Down

0 comments on commit efacb56

Please sign in to comment.