diff options
Diffstat (limited to 'drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c')
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c | 82 |
1 files changed, 43 insertions, 39 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c index 6b65420e11b5..889e2bb6f7f5 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c @@ -36,6 +36,8 @@ #define MX93_GPR_ENET_QOS_INTF_SEL_RMII (0x4 << 1) #define MX93_GPR_ENET_QOS_INTF_SEL_RGMII (0x1 << 1) #define MX93_GPR_ENET_QOS_CLK_GEN_EN (0x1 << 0) +#define MX93_GPR_ENET_QOS_CLK_SEL_MASK BIT_MASK(0) +#define MX93_GPR_CLK_SEL_OFFSET (4) #define DMA_BUS_MODE 0x00001000 #define DMA_BUS_MODE_SFT_RESET (0x1 << 0) @@ -49,7 +51,7 @@ struct imx_dwmac_ops { int (*fix_soc_reset)(void *priv, void __iomem *ioaddr); int (*set_intf_mode)(struct plat_stmmacenet_data *plat_dat); - void (*fix_mac_speed)(void *priv, unsigned int speed, unsigned int mode); + void (*fix_mac_speed)(void *priv, int speed, unsigned int mode); }; struct imx_priv_data { @@ -108,13 +110,21 @@ imx8dxl_set_intf_mode(struct plat_stmmacenet_data *plat_dat) static int imx93_set_intf_mode(struct plat_stmmacenet_data *plat_dat) { struct imx_priv_data *dwmac = plat_dat->bsp_priv; - int val; + int val, ret; switch (plat_dat->mac_interface) { case PHY_INTERFACE_MODE_MII: val = MX93_GPR_ENET_QOS_INTF_SEL_MII; break; case PHY_INTERFACE_MODE_RMII: + if (dwmac->rmii_refclk_ext) { + ret = regmap_clear_bits(dwmac->intf_regmap, + dwmac->intf_reg_off + + MX93_GPR_CLK_SEL_OFFSET, + MX93_GPR_ENET_QOS_CLK_SEL_MASK); + if (ret) + return ret; + } val = MX93_GPR_ENET_QOS_INTF_SEL_RMII; break; case PHY_INTERFACE_MODE_RGMII: @@ -182,11 +192,24 @@ static void imx_dwmac_exit(struct platform_device *pdev, void *priv) /* nothing to do now */ } -static void imx_dwmac_fix_speed(void *priv, unsigned int speed, unsigned int mode) +static int imx_dwmac_set_clk_tx_rate(void *bsp_priv, struct clk *clk_tx_i, + phy_interface_t interface, int speed) +{ + struct imx_priv_data *dwmac = bsp_priv; + + interface = dwmac->plat_dat->mac_interface; + if (interface == PHY_INTERFACE_MODE_RMII || + interface == PHY_INTERFACE_MODE_MII) + return 0; + + return stmmac_set_clk_tx_rate(bsp_priv, clk_tx_i, interface, speed); +} + +static void imx_dwmac_fix_speed(void *priv, int speed, unsigned int mode) { struct plat_stmmacenet_data *plat_dat; struct imx_priv_data *dwmac = priv; - unsigned long rate; + long rate; int err; plat_dat = dwmac->plat_dat; @@ -196,18 +219,9 @@ static void imx_dwmac_fix_speed(void *priv, unsigned int speed, unsigned int mod (plat_dat->mac_interface == PHY_INTERFACE_MODE_MII)) return; - switch (speed) { - case SPEED_1000: - rate = 125000000; - break; - case SPEED_100: - rate = 25000000; - break; - case SPEED_10: - rate = 2500000; - break; - default: - dev_err(dwmac->dev, "invalid speed %u\n", speed); + rate = rgmii_clock(speed); + if (rate < 0) { + dev_err(dwmac->dev, "invalid speed %d\n", speed); return; } @@ -216,7 +230,7 @@ static void imx_dwmac_fix_speed(void *priv, unsigned int speed, unsigned int mod dev_err(dwmac->dev, "failed to set tx rate %lu\n", rate); } -static void imx93_dwmac_fix_speed(void *priv, unsigned int speed, unsigned int mode) +static void imx93_dwmac_fix_speed(void *priv, int speed, unsigned int mode) { struct imx_priv_data *dwmac = priv; unsigned int iface; @@ -301,15 +315,11 @@ imx_dwmac_parse_dt(struct imx_priv_data *dwmac, struct device *dev) * is required by i.MX8MP, i.MX93. * is optinoal for i.MX8DXL. */ - dwmac->intf_regmap = syscon_regmap_lookup_by_phandle(np, "intf_mode"); + dwmac->intf_regmap = + syscon_regmap_lookup_by_phandle_args(np, "intf_mode", 1, + &dwmac->intf_reg_off); if (IS_ERR(dwmac->intf_regmap)) return PTR_ERR(dwmac->intf_regmap); - - err = of_property_read_u32_index(np, "intf_mode", 1, &dwmac->intf_reg_off); - if (err) { - dev_err(dev, "Can't get intf mode reg offset (%d)\n", err); - return err; - } } return err; @@ -361,7 +371,6 @@ static int imx_dwmac_probe(struct platform_device *pdev) plat_dat->init = imx_dwmac_init; plat_dat->exit = imx_dwmac_exit; plat_dat->clks_config = imx_dwmac_clks_config; - plat_dat->fix_mac_speed = imx_dwmac_fix_speed; plat_dat->bsp_priv = dwmac; dwmac->plat_dat = plat_dat; dwmac->base_addr = stmmac_res.addr; @@ -370,24 +379,19 @@ static int imx_dwmac_probe(struct platform_device *pdev) if (ret) return ret; - ret = imx_dwmac_init(pdev, dwmac); - if (ret) - goto err_dwmac_init; - - if (dwmac->ops->fix_mac_speed) + if (dwmac->ops->fix_mac_speed) { plat_dat->fix_mac_speed = dwmac->ops->fix_mac_speed; + } else if (!dwmac->ops->mac_rgmii_txclk_auto_adj) { + plat_dat->clk_tx_i = dwmac->clk_tx; + plat_dat->set_clk_tx_rate = imx_dwmac_set_clk_tx_rate; + } + dwmac->plat_dat->fix_soc_reset = dwmac->ops->fix_soc_reset; - ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); + ret = stmmac_pltfr_probe(pdev, plat_dat, &stmmac_res); if (ret) - goto err_drv_probe; - - return 0; + imx_dwmac_clks_config(dwmac, false); -err_drv_probe: - imx_dwmac_exit(pdev, plat_dat->bsp_priv); -err_dwmac_init: - imx_dwmac_clks_config(dwmac, false); return ret; } @@ -422,7 +426,7 @@ MODULE_DEVICE_TABLE(of, imx_dwmac_match); static struct platform_driver imx_dwmac_driver = { .probe = imx_dwmac_probe, - .remove_new = stmmac_pltfr_remove, + .remove = stmmac_pltfr_remove, .driver = { .name = "imx-dwmac", .pm = &stmmac_pltfr_pm_ops, |