diff options
Diffstat (limited to 'drivers/net/fec_mxc.c')
-rw-r--r-- | drivers/net/fec_mxc.c | 121 |
1 files changed, 105 insertions, 16 deletions
diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c index dac07b6e34..99c5c649a0 100644 --- a/drivers/net/fec_mxc.c +++ b/drivers/net/fec_mxc.c @@ -15,6 +15,7 @@ #include <miiphy.h> #include <net.h> #include <netdev.h> +#include <power/regulator.h> #include <asm/io.h> #include <linux/errno.h> @@ -122,6 +123,32 @@ static int fec_mdio_read(struct ethernet_regs *eth, uint8_t phyaddr, return val; } +static int fec_get_clk_rate(void *udev, int idx) +{ +#if IS_ENABLED(CONFIG_IMX8) + struct fec_priv *fec; + struct udevice *dev; + int ret; + + dev = udev; + if (!dev) { + ret = uclass_get_device(UCLASS_ETH, idx, &dev); + if (ret < 0) { + debug("Can't get FEC udev: %d\n", ret); + return ret; + } + } + + fec = dev_get_priv(dev); + if (fec) + return fec->clk_rate; + + return -EINVAL; +#else + return imx_get_fecclk(); +#endif +} + static void fec_mii_setspeed(struct ethernet_regs *eth) { /* @@ -139,9 +166,20 @@ static void fec_mii_setspeed(struct ethernet_regs *eth) * Given that ceil(clkrate / 5000000) <= 64, the calculation for * holdtime cannot result in a value greater than 3. */ - u32 pclk = imx_get_fecclk(); - u32 speed = DIV_ROUND_UP(pclk, 5000000); - u32 hold = DIV_ROUND_UP(pclk, 100000000) - 1; + u32 pclk; + u32 speed; + u32 hold; + int ret; + + ret = fec_get_clk_rate(NULL, 0); + if (ret < 0) { + printf("Can't find FEC0 clk rate: %d\n", ret); + return; + } + pclk = ret; + speed = DIV_ROUND_UP(pclk, 5000000); + hold = DIV_ROUND_UP(pclk, 100000000) - 1; + #ifdef FEC_QUIRK_ENET_MAC speed--; #endif @@ -1254,7 +1292,7 @@ static void fec_gpio_reset(struct fec_priv *priv) debug("fec_gpio_reset: fec_gpio_reset(dev)\n"); if (dm_gpio_is_valid(&priv->phy_reset_gpio)) { dm_gpio_set_value(&priv->phy_reset_gpio, 1); - udelay(priv->reset_delay); + mdelay(priv->reset_delay); dm_gpio_set_value(&priv->phy_reset_gpio, 0); } } @@ -1268,10 +1306,35 @@ static int fecmxc_probe(struct udevice *dev) uint32_t start; int ret; + if (IS_ENABLED(CONFIG_IMX8)) { + ret = clk_get_by_name(dev, "ipg", &priv->ipg_clk); + if (ret < 0) { + debug("Can't get FEC ipg clk: %d\n", ret); + return ret; + } + ret = clk_enable(&priv->ipg_clk); + if (ret < 0) { + debug("Can't enable FEC ipg clk: %d\n", ret); + return ret; + } + + priv->clk_rate = clk_get_rate(&priv->ipg_clk); + } + ret = fec_alloc_descs(priv); if (ret) return ret; +#ifdef CONFIG_DM_REGULATOR + if (priv->phy_supply) { + ret = regulator_autoset(priv->phy_supply); + if (ret) { + printf("%s: Error enabling phy supply\n", dev->name); + return ret; + } + } +#endif + #ifdef CONFIG_DM_GPIO fec_gpio_reset(priv); #endif @@ -1301,8 +1364,27 @@ static int fecmxc_probe(struct udevice *dev) } priv->bus = bus; - priv->xcv_type = CONFIG_FEC_XCV_TYPE; priv->interface = pdata->phy_interface; + switch (priv->interface) { + case PHY_INTERFACE_MODE_MII: + priv->xcv_type = MII100; + break; + case PHY_INTERFACE_MODE_RMII: + priv->xcv_type = RMII; + break; + case PHY_INTERFACE_MODE_RGMII: + case PHY_INTERFACE_MODE_RGMII_ID: + case PHY_INTERFACE_MODE_RGMII_RXID: + case PHY_INTERFACE_MODE_RGMII_TXID: + priv->xcv_type = RGMII; + break; + default: + priv->xcv_type = CONFIG_FEC_XCV_TYPE; + printf("Unsupported interface type %d defaulting to %d\n", + priv->interface, priv->xcv_type); + break; + } + ret = fec_phy_init(priv, dev); if (ret) goto err_phy; @@ -1327,6 +1409,11 @@ static int fecmxc_remove(struct udevice *dev) mdio_unregister(priv->bus); mdio_free(priv->bus); +#ifdef CONFIG_DM_REGULATOR + if (priv->phy_supply) + regulator_set_enable(priv->phy_supply, false); +#endif + return 0; } @@ -1350,24 +1437,25 @@ static int fecmxc_ofdata_to_platdata(struct udevice *dev) return -EINVAL; } +#ifdef CONFIG_DM_REGULATOR + device_get_supply_regulator(dev, "phy-supply", &priv->phy_supply); +#endif + #ifdef CONFIG_DM_GPIO ret = gpio_request_by_name(dev, "phy-reset-gpios", 0, - &priv->phy_reset_gpio, GPIOD_IS_OUT); - if (ret == 0) { - ret = dev_read_u32_array(dev, "phy-reset-duration", - &priv->reset_delay, 1); - } else if (ret == -ENOENT) { - priv->reset_delay = 1000; - ret = 0; - } + &priv->phy_reset_gpio, GPIOD_IS_OUT); + if (ret < 0) + return 0; /* property is optional, don't return error! */ + priv->reset_delay = dev_read_u32_default(dev, "phy-reset-duration", 1); if (priv->reset_delay > 1000) { - printf("FEX MXC: gpio reset timeout should be less the 1000\n"); - priv->reset_delay = 1000; + printf("FEC MXC: phy reset duration should be <= 1000ms\n"); + /* property value wrong, use default value */ + priv->reset_delay = 1; } #endif - return ret; + return 0; } static const struct udevice_id fecmxc_ids[] = { @@ -1376,6 +1464,7 @@ static const struct udevice_id fecmxc_ids[] = { { .compatible = "fsl,imx6sx-fec" }, { .compatible = "fsl,imx6ul-fec" }, { .compatible = "fsl,imx53-fec" }, + { .compatible = "fsl,imx7d-fec" }, { } }; |