[U-Boot] [PATCH 2/5] net: dwc_eth_qos: add Ethernet stm32mp1 support

Christophe ROULLIER christophe.roullier at st.com
Fri May 10 13:55:57 UTC 2019


Hi Joe,

On 09/05/2019 23:07, Joe Hershberger wrote:
> On Fri, Apr 26, 2019 at 6:16 AM Christophe Roullier
> <christophe.roullier at st.com>  wrote:
>> Synopsys GMAC 4.20 is used. And Phy mode for eval and disco is RMII
>> with PHY Realtek RTL8211 (RGMII)
>> We also support some other PHY config on stm32mp157c
>> PHY_MODE        (MII,GMII, RMII, RGMII) and in normal,
>> PHY wo crystal (25Mhz and 50Mhz), No 125Mhz from PHY config
> Can you split this into separate logical patches?

If it is possible, I would like to keep this in same patch.

Because the choice to select phy-mode and with or without crystal is 
only in eqos_probe_resources_stm32 and it is managed by DT properties.

Thanks in advance.

Christophe

> Thanks,
> -Joe
>
>> Signed-off-by: Christophe Roullier<christophe.roullier at st.com>
>> ---
>>
>>   drivers/net/dwc_eth_qos.c | 435 +++++++++++++++++++++++++++++++++-----
>>   1 file changed, 383 insertions(+), 52 deletions(-)
>>
>> diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c
>> index 9f1c5af46e9..a6546d5e5ce 100644
>> --- a/drivers/net/dwc_eth_qos.c
>> +++ b/drivers/net/dwc_eth_qos.c
>> @@ -26,7 +26,6 @@
>>    *    supports a single RGMII PHY. This configuration also has SW control over
>>    *    all clock and reset signals to the HW block.
>>    */
>> -
>>   #include <common.h>
>>   #include <clk.h>
>>   #include <dm.h>
>> @@ -95,6 +94,7 @@ struct eqos_mac_regs {
>>   #define EQOS_MAC_RXQ_CTRL0_RXQ0EN_MASK                 3
>>   #define EQOS_MAC_RXQ_CTRL0_RXQ0EN_NOT_ENABLED          0
>>   #define EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB          2
>> +#define EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_AV           1
>>
>>   #define EQOS_MAC_RXQ_CTRL2_PSRQ0_SHIFT                 0
>>   #define EQOS_MAC_RXQ_CTRL2_PSRQ0_MASK                  0xff
>> @@ -108,6 +108,7 @@ struct eqos_mac_regs {
>>   #define EQOS_MAC_MDIO_ADDRESS_RDA_SHIFT                        16
>>   #define EQOS_MAC_MDIO_ADDRESS_CR_SHIFT                 8
>>   #define EQOS_MAC_MDIO_ADDRESS_CR_20_35                 2
>> +#define EQOS_MAC_MDIO_ADDRESS_CR_250_300               5
>>   #define EQOS_MAC_MDIO_ADDRESS_SKAP                     BIT(4)
>>   #define EQOS_MAC_MDIO_ADDRESS_GOC_SHIFT                        2
>>   #define EQOS_MAC_MDIO_ADDRESS_GOC_READ                 3
>> @@ -260,6 +261,29 @@ struct eqos_desc {
>>
>>   struct eqos_config {
>>          bool reg_access_always_ok;
>> +       int mdio_wait;
>> +       int swr_wait;
>> +       int config_mac;
>> +       int config_mac_mdio;
>> +       int (*interface)(struct udevice *dev);
>> +       struct eqos_ops *ops;
>> +};
>> +
>> +struct eqos_ops {
>> +       void (*eqos_inval_desc)(void *desc);
>> +       void (*eqos_flush_desc)(void *desc);
>> +       void (*eqos_inval_buffer)(void *buf, size_t size);
>> +       void (*eqos_flush_buffer)(void *buf, size_t size);
>> +       int (*eqos_probe_resources)(struct udevice *dev);
>> +       int (*eqos_remove_resources)(struct udevice *dev);
>> +       int (*eqos_stop_resets)(struct udevice *dev);
>> +       int (*eqos_start_resets)(struct udevice *dev);
>> +       void (*eqos_stop_clks)(struct udevice *dev);
>> +       int (*eqos_start_clks)(struct udevice *dev);
>> +       int (*eqos_calibrate_pads)(struct udevice *dev);
>> +       int (*eqos_disable_calibration)(struct udevice *dev);
>> +       int (*eqos_set_tx_clk_speed)(struct udevice *dev);
>> +       ulong (*eqos_get_tick_clk_rate)(struct udevice *dev);
>>   };
>>
>>   struct eqos_priv {
>> @@ -276,6 +300,7 @@ struct eqos_priv {
>>          struct clk clk_rx;
>>          struct clk clk_ptp_ref;
>>          struct clk clk_tx;
>> +       struct clk clk_ck;
>>          struct clk clk_slave_bus;
>>          struct mii_dev *mii;
>>          struct phy_device *phy;
>> @@ -327,7 +352,7 @@ static void eqos_free_descs(void *descs)
>>   #endif
>>   }
>>
>> -static void eqos_inval_desc(void *desc)
>> +static void eqos_inval_desc_tegra186(void *desc)
>>   {
>>   #ifndef CONFIG_SYS_NONCACHED_MEMORY
>>          unsigned long start = (unsigned long)desc & ~(ARCH_DMA_MINALIGN - 1);
>> @@ -338,14 +363,36 @@ static void eqos_inval_desc(void *desc)
>>   #endif
>>   }
>>
>> -static void eqos_flush_desc(void *desc)
>> +static void eqos_inval_desc_stm32(void *desc)
>> +{
>> +#ifndef CONFIG_SYS_NONCACHED_MEMORY
>> +       unsigned long start = rounddown((unsigned long)desc, ARCH_DMA_MINALIGN);
>> +       unsigned long end = roundup((unsigned long)desc + EQOS_DESCRIPTOR_SIZE,
>> +                                   ARCH_DMA_MINALIGN);
>> +
>> +       invalidate_dcache_range(start, end);
>> +#endif
>> +}
>> +
>> +static void eqos_flush_desc_tegra186(void *desc)
>>   {
>>   #ifndef CONFIG_SYS_NONCACHED_MEMORY
>>          flush_cache((unsigned long)desc, EQOS_DESCRIPTOR_SIZE);
>>   #endif
>>   }
>>
>> -static void eqos_inval_buffer(void *buf, size_t size)
>> +static void eqos_flush_desc_stm32(void *desc)
>> +{
>> +#ifndef CONFIG_SYS_NONCACHED_MEMORY
>> +       unsigned long start = rounddown((unsigned long)desc, ARCH_DMA_MINALIGN);
>> +       unsigned long end = roundup((unsigned long)desc + EQOS_DESCRIPTOR_SIZE,
>> +                                   ARCH_DMA_MINALIGN);
>> +
>> +       flush_dcache_range(start, end);
>> +#endif
>> +}
>> +
>> +static void eqos_inval_buffer_tegra186(void *buf, size_t size)
>>   {
>>          unsigned long start = (unsigned long)buf & ~(ARCH_DMA_MINALIGN - 1);
>>          unsigned long end = ALIGN(start + size, ARCH_DMA_MINALIGN);
>> @@ -353,11 +400,29 @@ static void eqos_inval_buffer(void *buf, size_t size)
>>          invalidate_dcache_range(start, end);
>>   }
>>
>> -static void eqos_flush_buffer(void *buf, size_t size)
>> +static void eqos_inval_buffer_stm32(void *buf, size_t size)
>> +{
>> +       unsigned long start = rounddown((unsigned long)buf, ARCH_DMA_MINALIGN);
>> +       unsigned long end = roundup((unsigned long)buf + size,
>> +                                   ARCH_DMA_MINALIGN);
>> +
>> +       invalidate_dcache_range(start, end);
>> +}
>> +
>> +static void eqos_flush_buffer_tegra186(void *buf, size_t size)
>>   {
>>          flush_cache((unsigned long)buf, size);
>>   }
>>
>> +static void eqos_flush_buffer_stm32(void *buf, size_t size)
>> +{
>> +       unsigned long start = rounddown((unsigned long)buf, ARCH_DMA_MINALIGN);
>> +       unsigned long end = roundup((unsigned long)buf + size,
>> +                                   ARCH_DMA_MINALIGN);
>> +
>> +       flush_dcache_range(start, end);
>> +}
>> +
>>   static int eqos_mdio_wait_idle(struct eqos_priv *eqos)
>>   {
>>          return wait_for_bit_le32(&eqos->mac_regs->mdio_address,
>> @@ -386,14 +451,14 @@ static int eqos_mdio_read(struct mii_dev *bus, int mdio_addr, int mdio_devad,
>>                  EQOS_MAC_MDIO_ADDRESS_C45E;
>>          val |= (mdio_addr << EQOS_MAC_MDIO_ADDRESS_PA_SHIFT) |
>>                  (mdio_reg << EQOS_MAC_MDIO_ADDRESS_RDA_SHIFT) |
>> -               (EQOS_MAC_MDIO_ADDRESS_CR_20_35 <<
>> +               (eqos->config->config_mac_mdio <<
>>                   EQOS_MAC_MDIO_ADDRESS_CR_SHIFT) |
>>                  (EQOS_MAC_MDIO_ADDRESS_GOC_READ <<
>>                   EQOS_MAC_MDIO_ADDRESS_GOC_SHIFT) |
>>                  EQOS_MAC_MDIO_ADDRESS_GB;
>>          writel(val, &eqos->mac_regs->mdio_address);
>>
>> -       udelay(10);
>> +       udelay(eqos->config->mdio_wait);
>>
>>          ret = eqos_mdio_wait_idle(eqos);
>>          if (ret) {
>> @@ -432,14 +497,14 @@ static int eqos_mdio_write(struct mii_dev *bus, int mdio_addr, int mdio_devad,
>>                  EQOS_MAC_MDIO_ADDRESS_C45E;
>>          val |= (mdio_addr << EQOS_MAC_MDIO_ADDRESS_PA_SHIFT) |
>>                  (mdio_reg << EQOS_MAC_MDIO_ADDRESS_RDA_SHIFT) |
>> -               (EQOS_MAC_MDIO_ADDRESS_CR_20_35 <<
>> +               (eqos->config->config_mac_mdio <<
>>                   EQOS_MAC_MDIO_ADDRESS_CR_SHIFT) |
>>                  (EQOS_MAC_MDIO_ADDRESS_GOC_WRITE <<
>>                   EQOS_MAC_MDIO_ADDRESS_GOC_SHIFT) |
>>                  EQOS_MAC_MDIO_ADDRESS_GB;
>>          writel(val, &eqos->mac_regs->mdio_address);
>>
>> -       udelay(10);
>> +       udelay(eqos->config->mdio_wait);
>>
>>          ret = eqos_mdio_wait_idle(eqos);
>>          if (ret) {
>> @@ -509,6 +574,53 @@ err:
>>          return ret;
>>   }
>>
>> +static int eqos_start_clks_stm32(struct udevice *dev)
>> +{
>> +       struct eqos_priv *eqos = dev_get_priv(dev);
>> +       int ret;
>> +
>> +       debug("%s(dev=%p):\n", __func__, dev);
>> +
>> +       ret = clk_enable(&eqos->clk_master_bus);
>> +       if (ret < 0) {
>> +               pr_err("clk_enable(clk_master_bus) failed: %d", ret);
>> +               goto err;
>> +       }
>> +
>> +       ret = clk_enable(&eqos->clk_rx);
>> +       if (ret < 0) {
>> +               pr_err("clk_enable(clk_rx) failed: %d", ret);
>> +               goto err_disable_clk_master_bus;
>> +       }
>> +
>> +       ret = clk_enable(&eqos->clk_tx);
>> +       if (ret < 0) {
>> +               pr_err("clk_enable(clk_tx) failed: %d", ret);
>> +               goto err_disable_clk_rx;
>> +       }
>> +
>> +       if (clk_valid(&eqos->clk_ck)) {
>> +               ret = clk_enable(&eqos->clk_ck);
>> +               if (ret < 0) {
>> +                       pr_err("clk_enable(clk_ck) failed: %d", ret);
>> +                       goto err_disable_clk_tx;
>> +               }
>> +       }
>> +
>> +       debug("%s: OK\n", __func__);
>> +       return 0;
>> +
>> +err_disable_clk_tx:
>> +       clk_disable(&eqos->clk_tx);
>> +err_disable_clk_rx:
>> +       clk_disable(&eqos->clk_rx);
>> +err_disable_clk_master_bus:
>> +       clk_disable(&eqos->clk_master_bus);
>> +err:
>> +       debug("%s: FAILED: %d\n", __func__, ret);
>> +       return ret;
>> +}
>> +
>>   void eqos_stop_clks_tegra186(struct udevice *dev)
>>   {
>>          struct eqos_priv *eqos = dev_get_priv(dev);
>> @@ -524,6 +636,21 @@ void eqos_stop_clks_tegra186(struct udevice *dev)
>>          debug("%s: OK\n", __func__);
>>   }
>>
>> +void eqos_stop_clks_stm32(struct udevice *dev)
>> +{
>> +       struct eqos_priv *eqos = dev_get_priv(dev);
>> +
>> +       debug("%s(dev=%p):\n", __func__, dev);
>> +
>> +       clk_disable(&eqos->clk_tx);
>> +       clk_disable(&eqos->clk_rx);
>> +       clk_disable(&eqos->clk_master_bus);
>> +       if (clk_valid(&eqos->clk_ck))
>> +               clk_disable(&eqos->clk_ck);
>> +
>> +       debug("%s: OK\n", __func__);
>> +}
>> +
>>   static int eqos_start_resets_tegra186(struct udevice *dev)
>>   {
>>          struct eqos_priv *eqos = dev_get_priv(dev);
>> @@ -563,6 +690,11 @@ static int eqos_start_resets_tegra186(struct udevice *dev)
>>          return 0;
>>   }
>>
>> +static int eqos_start_resets_stm32(struct udevice *dev)
>> +{
>> +       return 0;
>> +}
>> +
>>   static int eqos_stop_resets_tegra186(struct udevice *dev)
>>   {
>>          struct eqos_priv *eqos = dev_get_priv(dev);
>> @@ -573,6 +705,11 @@ static int eqos_stop_resets_tegra186(struct udevice *dev)
>>          return 0;
>>   }
>>
>> +static int eqos_stop_resets_stm32(struct udevice *dev)
>> +{
>> +       return 0;
>> +}
>> +
>>   static int eqos_calibrate_pads_tegra186(struct udevice *dev)
>>   {
>>          struct eqos_priv *eqos = dev_get_priv(dev);
>> @@ -632,6 +769,23 @@ static ulong eqos_get_tick_clk_rate_tegra186(struct udevice *dev)
>>          return clk_get_rate(&eqos->clk_slave_bus);
>>   }
>>
>> +static ulong eqos_get_tick_clk_rate_stm32(struct udevice *dev)
>> +{
>> +       struct eqos_priv *eqos = dev_get_priv(dev);
>> +
>> +       return clk_get_rate(&eqos->clk_master_bus);
>> +}
>> +
>> +static int eqos_calibrate_pads_stm32(struct udevice *dev)
>> +{
>> +       return 0;
>> +}
>> +
>> +static int eqos_disable_calibration_stm32(struct udevice *dev)
>> +{
>> +       return 0;
>> +}
>> +
>>   static int eqos_set_full_duplex(struct udevice *dev)
>>   {
>>          struct eqos_priv *eqos = dev_get_priv(dev);
>> @@ -726,6 +880,11 @@ static int eqos_set_tx_clk_speed_tegra186(struct udevice *dev)
>>          return 0;
>>   }
>>
>> +static int eqos_set_tx_clk_speed_stm32(struct udevice *dev)
>> +{
>> +       return 0;
>> +}
>> +
>>   static int eqos_adjust_link(struct udevice *dev)
>>   {
>>          struct eqos_priv *eqos = dev_get_priv(dev);
>> @@ -766,23 +925,23 @@ static int eqos_adjust_link(struct udevice *dev)
>>          }
>>
>>          if (en_calibration) {
>> -               ret = eqos_calibrate_pads_tegra186(dev);
>> +               ret = eqos->config->ops->eqos_calibrate_pads(dev);
>>                  if (ret < 0) {
>> -                       pr_err("eqos_calibrate_pads_tegra186() failed: %d", ret);
>> +                       pr_err("eqos_calibrate_pads() failed: %d",
>> +                              ret);
>>                          return ret;
>>                  }
>>          } else {
>> -               ret = eqos_disable_calibration_tegra186(dev);
>> +               ret = eqos->config->ops->eqos_disable_calibration(dev);
>>                  if (ret < 0) {
>> -                       pr_err("eqos_disable_calibration_tegra186() failed: %d",
>> -                             ret);
>> +                       pr_err("eqos_disable_calibration() failed: %d",
>> +                              ret);
>>                          return ret;
>>                  }
>>          }
>> -
>> -       ret = eqos_set_tx_clk_speed_tegra186(dev);
>> +       ret = eqos->config->ops->eqos_set_tx_clk_speed(dev);
>>          if (ret < 0) {
>> -               pr_err("eqos_set_tx_clk_speed_tegra186() failed: %d", ret);
>> +               pr_err("eqos_set_tx_clk_speed() failed: %d", ret);
>>                  return ret;
>>          }
>>
>> @@ -846,15 +1005,15 @@ static int eqos_start(struct udevice *dev)
>>          eqos->tx_desc_idx = 0;
>>          eqos->rx_desc_idx = 0;
>>
>> -       ret = eqos_start_clks_tegra186(dev);
>> +       ret = eqos->config->ops->eqos_start_clks(dev);
>>          if (ret < 0) {
>> -               pr_err("eqos_start_clks_tegra186() failed: %d", ret);
>> +               pr_err("eqos_start_clks() failed: %d", ret);
>>                  goto err;
>>          }
>>
>> -       ret = eqos_start_resets_tegra186(dev);
>> +       ret = eqos->config->ops->eqos_start_resets(dev);
>>          if (ret < 0) {
>> -               pr_err("eqos_start_resets_tegra186() failed: %d", ret);
>> +               pr_err("eqos_start_resets() failed: %d", ret);
>>                  goto err_stop_clks;
>>          }
>>
>> @@ -863,32 +1022,41 @@ static int eqos_start(struct udevice *dev)
>>          eqos->reg_access_ok = true;
>>
>>          ret = wait_for_bit_le32(&eqos->dma_regs->mode,
>> -                               EQOS_DMA_MODE_SWR, false, 10, false);
>> +                               EQOS_DMA_MODE_SWR, false,
>> +                               eqos->config->swr_wait, false);
>>          if (ret) {
>>                  pr_err("EQOS_DMA_MODE_SWR stuck");
>>                  goto err_stop_resets;
>>          }
>>
>> -       ret = eqos_calibrate_pads_tegra186(dev);
>> +       ret = eqos->config->ops->eqos_calibrate_pads(dev);
>>          if (ret < 0) {
>> -               pr_err("eqos_calibrate_pads_tegra186() failed: %d", ret);
>> +               pr_err("eqos_calibrate_pads() failed: %d", ret);
>>                  goto err_stop_resets;
>>          }
>> +       rate = eqos->config->ops->eqos_get_tick_clk_rate(dev);
>>
>> -       rate = eqos_get_tick_clk_rate_tegra186(dev);
>>          val = (rate / 1000000) - 1;
>>          writel(val, &eqos->mac_regs->us_tic_counter);
>>
>> -       eqos->phy = phy_connect(eqos->mii, 0, dev, 0);
>> +       /*
>> +        * if PHY was already connected and configured,
>> +        * don't need to reconnect/reconfigure again
>> +        */
>>          if (!eqos->phy) {
>> -               pr_err("phy_connect() failed");
>> -               goto err_stop_resets;
>> -       }
>> -       ret = phy_config(eqos->phy);
>> -       if (ret < 0) {
>> -               pr_err("phy_config() failed: %d", ret);
>> -               goto err_shutdown_phy;
>> +               eqos->phy = phy_connect(eqos->mii, 0, dev,
>> +                                       eqos->config->interface(dev));
>> +               if (!eqos->phy) {
>> +                       pr_err("phy_connect() failed");
>> +                       goto err_stop_resets;
>> +               }
>> +               ret = phy_config(eqos->phy);
>> +               if (ret < 0) {
>> +                       pr_err("phy_config() failed: %d", ret);
>> +                       goto err_shutdown_phy;
>> +               }
>>          }
>> +
>>          ret = phy_startup(eqos->phy);
>>          if (ret < 0) {
>>                  pr_err("phy_startup() failed: %d", ret);
>> @@ -993,7 +1161,7 @@ static int eqos_start(struct udevice *dev)
>>          clrsetbits_le32(&eqos->mac_regs->rxq_ctrl0,
>>                          EQOS_MAC_RXQ_CTRL0_RXQ0EN_MASK <<
>>                          EQOS_MAC_RXQ_CTRL0_RXQ0EN_SHIFT,
>> -                       EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB <<
>> +                       eqos->config->config_mac <<
>>                          EQOS_MAC_RXQ_CTRL0_RXQ0EN_SHIFT);
>>
>>          /* Set TX flow control parameters */
>> @@ -1074,7 +1242,7 @@ static int eqos_start(struct udevice *dev)
>>                                               (i * EQOS_MAX_PACKET_SIZE));
>>                  rx_desc->des3 |= EQOS_DESC3_OWN | EQOS_DESC3_BUF1V;
>>          }
>> -       flush_cache((unsigned long)eqos->descs, EQOS_DESCRIPTORS_SIZE);
>> +       eqos->config->ops->eqos_flush_desc(eqos->descs);
>>
>>          writel(0, &eqos->dma_regs->ch0_txdesc_list_haddress);
>>          writel((ulong)eqos->tx_descs, &eqos->dma_regs->ch0_txdesc_list_address);
>> @@ -1113,11 +1281,10 @@ static int eqos_start(struct udevice *dev)
>>
>>   err_shutdown_phy:
>>          phy_shutdown(eqos->phy);
>> -       eqos->phy = NULL;
>>   err_stop_resets:
>> -       eqos_stop_resets_tegra186(dev);
>> +       eqos->config->ops->eqos_stop_resets(dev);
>>   err_stop_clks:
>> -       eqos_stop_clks_tegra186(dev);
>> +       eqos->config->ops->eqos_stop_clks(dev);
>>   err:
>>          pr_err("FAILED: %d", ret);
>>          return ret;
>> @@ -1170,10 +1337,9 @@ void eqos_stop(struct udevice *dev)
>>
>>          if (eqos->phy) {
>>                  phy_shutdown(eqos->phy);
>> -               eqos->phy = NULL;
>>          }
>> -       eqos_stop_resets_tegra186(dev);
>> -       eqos_stop_clks_tegra186(dev);
>> +       eqos->config->ops->eqos_stop_resets(dev);
>> +       eqos->config->ops->eqos_stop_clks(dev);
>>
>>          debug("%s: OK\n", __func__);
>>   }
>> @@ -1188,7 +1354,7 @@ int eqos_send(struct udevice *dev, void *packet, int length)
>>                length);
>>
>>          memcpy(eqos->tx_dma_buf, packet, length);
>> -       eqos_flush_buffer(eqos->tx_dma_buf, length);
>> +       eqos->config->ops->eqos_flush_buffer(eqos->tx_dma_buf, length);
>>
>>          tx_desc = &(eqos->tx_descs[eqos->tx_desc_idx]);
>>          eqos->tx_desc_idx++;
>> @@ -1203,12 +1369,12 @@ int eqos_send(struct udevice *dev, void *packet, int length)
>>           */
>>          mb();
>>          tx_desc->des3 = EQOS_DESC3_OWN | EQOS_DESC3_FD | EQOS_DESC3_LD | length;
>> -       eqos_flush_desc(tx_desc);
>> +       eqos->config->ops->eqos_flush_desc(tx_desc);
>>
>>          writel((ulong)(tx_desc + 1), &eqos->dma_regs->ch0_txdesc_tail_pointer);
>>
>>          for (i = 0; i < 1000000; i++) {
>> -               eqos_inval_desc(tx_desc);
>> +               eqos->config->ops->eqos_inval_desc(tx_desc);
>>                  if (!(readl(&tx_desc->des3) & EQOS_DESC3_OWN))
>>                          return 0;
>>                  udelay(1);
>> @@ -1238,7 +1404,7 @@ int eqos_recv(struct udevice *dev, int flags, uchar **packetp)
>>          length = rx_desc->des3 & 0x7fff;
>>          debug("%s: *packetp=%p, length=%d\n", __func__, *packetp, length);
>>
>> -       eqos_inval_buffer(*packetp, length);
>> +       eqos->config->ops->eqos_inval_buffer(*packetp, length);
>>
>>          return length;
>>   }
>> @@ -1269,7 +1435,7 @@ int eqos_free_pkt(struct udevice *dev, uchar *packet, int length)
>>           */
>>          mb();
>>          rx_desc->des3 |= EQOS_DESC3_OWN | EQOS_DESC3_BUF1V;
>> -       eqos_flush_desc(rx_desc);
>> +       eqos->config->ops->eqos_flush_desc(rx_desc);
>>
>>          writel((ulong)rx_desc, &eqos->dma_regs->ch0_rxdesc_tail_pointer);
>>
>> @@ -1304,7 +1470,7 @@ static int eqos_probe_resources_core(struct udevice *dev)
>>                  ret = -ENOMEM;
>>                  goto err_free_descs;
>>          }
>> -       debug("%s: rx_dma_buf=%p\n", __func__, eqos->rx_dma_buf);
>> +       debug("%s: tx_dma_buf=%p\n", __func__, eqos->tx_dma_buf);
>>
>>          eqos->rx_dma_buf = memalign(EQOS_BUFFER_ALIGN, EQOS_RX_BUFFER_SIZE);
>>          if (!eqos->rx_dma_buf) {
>> @@ -1312,7 +1478,7 @@ static int eqos_probe_resources_core(struct udevice *dev)
>>                  ret = -ENOMEM;
>>                  goto err_free_tx_dma_buf;
>>          }
>> -       debug("%s: tx_dma_buf=%p\n", __func__, eqos->tx_dma_buf);
>> +       debug("%s: rx_dma_buf=%p\n", __func__, eqos->rx_dma_buf);
>>
>>          eqos->rx_pkt = malloc(EQOS_MAX_PACKET_SIZE);
>>          if (!eqos->rx_pkt) {
>> @@ -1424,6 +1590,98 @@ err_free_reset_eqos:
>>          return ret;
>>   }
>>
>> +/* board-specific Ethernet Interface initializations. */
>> +__weak int board_interface_eth_init(int interface_type, bool eth_clk_sel_reg,
>> +                                   bool eth_ref_clk_sel_reg)
>> +{
>> +       return 0;
>> +}
>> +
>> +static int eqos_probe_resources_stm32(struct udevice *dev)
>> +{
>> +       struct eqos_priv *eqos = dev_get_priv(dev);
>> +       int ret;
>> +       int interface;
>> +       bool eth_clk_sel_reg = false;
>> +       bool eth_ref_clk_sel_reg = false;
>> +
>> +       debug("%s(dev=%p):\n", __func__, dev);
>> +
>> +       interface = eqos->config->interface(dev);
>> +
>> +       if (interface == -1) {
>> +               pr_err("Invalid PHY interface\n");
>> +               return -EINVAL;
>> +       }
>> +
>> +       /* Gigabit Ethernet 125MHz clock selection. */
>> +       eth_clk_sel_reg = dev_read_bool(dev, "st,eth_clk_sel");
>> +
>> +       /* Ethernet 50Mhz RMII clock selection */
>> +       eth_ref_clk_sel_reg =
>> +               dev_read_bool(dev, "st,eth_ref_clk_sel");
>> +
>> +       ret = board_interface_eth_init(interface, eth_clk_sel_reg,
>> +                                      eth_ref_clk_sel_reg);
>> +       if (ret)
>> +               return -EINVAL;
>> +
>> +       ret = clk_get_by_name(dev, "stmmaceth", &eqos->clk_master_bus);
>> +       if (ret) {
>> +               pr_err("clk_get_by_name(master_bus) failed: %d", ret);
>> +               goto err_probe;
>> +       }
>> +
>> +       ret = clk_get_by_name(dev, "mac-clk-rx", &eqos->clk_rx);
>> +       if (ret) {
>> +               pr_err("clk_get_by_name(rx) failed: %d", ret);
>> +               goto err_free_clk_master_bus;
>> +       }
>> +
>> +       ret = clk_get_by_name(dev, "mac-clk-tx", &eqos->clk_tx);
>> +       if (ret) {
>> +               pr_err("clk_get_by_name(tx) failed: %d", ret);
>> +               goto err_free_clk_rx;
>> +       }
>> +
>> +       /*  Get ETH_CLK clocks (optional) */
>> +       ret = clk_get_by_name(dev, "eth-ck", &eqos->clk_ck);
>> +       if (ret)
>> +               pr_warn("No phy clock provided %d", ret);
>> +
>> +       debug("%s: OK\n", __func__);
>> +       return 0;
>> +
>> +err_free_clk_rx:
>> +       clk_free(&eqos->clk_rx);
>> +err_free_clk_master_bus:
>> +       clk_free(&eqos->clk_master_bus);
>> +err_probe:
>> +
>> +       debug("%s: returns %d\n", __func__, ret);
>> +       return ret;
>> +}
>> +
>> +static int eqos_get_interface_stm32(struct udevice *dev)
>> +{
>> +       const char *phy_mode;
>> +       int interface = -1;
>> +
>> +       debug("%s(dev=%p):\n", __func__, dev);
>> +
>> +       phy_mode = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "phy-mode",
>> +                              NULL);
>> +       if (phy_mode)
>> +               interface = phy_get_interface_by_name(phy_mode);
>> +
>> +       return interface;
>> +}
>> +
>> +static int eqos_get_interface_tegra186(struct udevice *dev)
>> +{
>> +       return 0;
>> +}
>> +
>>   static int eqos_remove_resources_tegra186(struct udevice *dev)
>>   {
>>          struct eqos_priv *eqos = dev_get_priv(dev);
>> @@ -1442,6 +1700,22 @@ static int eqos_remove_resources_tegra186(struct udevice *dev)
>>          return 0;
>>   }
>>
>> +static int eqos_remove_resources_stm32(struct udevice *dev)
>> +{
>> +       struct eqos_priv *eqos = dev_get_priv(dev);
>> +
>> +       debug("%s(dev=%p):\n", __func__, dev);
>> +
>> +       clk_free(&eqos->clk_tx);
>> +       clk_free(&eqos->clk_rx);
>> +       clk_free(&eqos->clk_master_bus);
>> +       if (clk_valid(&eqos->clk_ck))
>> +               clk_free(&eqos->clk_ck);
>> +
>> +       debug("%s: OK\n", __func__);
>> +       return 0;
>> +}
>> +
>>   static int eqos_probe(struct udevice *dev)
>>   {
>>          struct eqos_priv *eqos = dev_get_priv(dev);
>> @@ -1468,15 +1742,16 @@ static int eqos_probe(struct udevice *dev)
>>                  return ret;
>>          }
>>
>> -       ret = eqos_probe_resources_tegra186(dev);
>> +       ret = eqos->config->ops->eqos_probe_resources(dev);
>>          if (ret < 0) {
>> -               pr_err("eqos_probe_resources_tegra186() failed: %d", ret);
>> +               pr_err("eqos_probe_resources() failed: %d", ret);
>>                  goto err_remove_resources_core;
>>          }
>>
>>          eqos->mii = mdio_alloc();
>>          if (!eqos->mii) {
>>                  pr_err("mdio_alloc() failed");
>> +               ret = -ENOMEM;
>>                  goto err_remove_resources_tegra;
>>          }
>>          eqos->mii->read = eqos_mdio_read;
>> @@ -1496,7 +1771,7 @@ static int eqos_probe(struct udevice *dev)
>>   err_free_mdio:
>>          mdio_free(eqos->mii);
>>   err_remove_resources_tegra:
>> -       eqos_remove_resources_tegra186(dev);
>> +       eqos->config->ops->eqos_remove_resources(dev);
>>   err_remove_resources_core:
>>          eqos_remove_resources_core(dev);
>>
>> @@ -1512,7 +1787,8 @@ static int eqos_remove(struct udevice *dev)
>>
>>          mdio_unregister(eqos->mii);
>>          mdio_free(eqos->mii);
>> -       eqos_remove_resources_tegra186(dev);
>> +       eqos->config->ops->eqos_remove_resources(dev);
>> +
>>          eqos_probe_resources_core(dev);
>>
>>          debug("%s: OK\n", __func__);
>> @@ -1528,8 +1804,58 @@ static const struct eth_ops eqos_ops = {
>>          .write_hwaddr = eqos_write_hwaddr,
>>   };
>>
>> +static struct eqos_ops eqos_tegra186_ops = {
>> +       .eqos_inval_desc = eqos_inval_desc_tegra186,
>> +       .eqos_flush_desc = eqos_flush_desc_tegra186,
>> +       .eqos_inval_buffer = eqos_inval_buffer_tegra186,
>> +       .eqos_flush_buffer = eqos_flush_buffer_tegra186,
>> +       .eqos_probe_resources = eqos_probe_resources_tegra186,
>> +       .eqos_remove_resources = eqos_remove_resources_tegra186,
>> +       .eqos_stop_resets = eqos_stop_resets_tegra186,
>> +       .eqos_start_resets = eqos_start_resets_tegra186,
>> +       .eqos_stop_clks = eqos_stop_clks_tegra186,
>> +       .eqos_start_clks = eqos_start_clks_tegra186,
>> +       .eqos_calibrate_pads = eqos_calibrate_pads_tegra186,
>> +       .eqos_disable_calibration = eqos_disable_calibration_tegra186,
>> +       .eqos_set_tx_clk_speed = eqos_set_tx_clk_speed_tegra186,
>> +       .eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_tegra186
>> +};
>> +
>>   static const struct eqos_config eqos_tegra186_config = {
>>          .reg_access_always_ok = false,
>> +       .mdio_wait = 10,
>> +       .swr_wait = 10,
>> +       .config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB,
>> +       .config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_20_35,
>> +       .interface = eqos_get_interface_tegra186,
>> +       .ops = &eqos_tegra186_ops
>> +};
>> +
>> +static struct eqos_ops eqos_stm32_ops = {
>> +       .eqos_inval_desc = eqos_inval_desc_stm32,
>> +       .eqos_flush_desc = eqos_flush_desc_stm32,
>> +       .eqos_inval_buffer = eqos_inval_buffer_stm32,
>> +       .eqos_flush_buffer = eqos_flush_buffer_stm32,
>> +       .eqos_probe_resources = eqos_probe_resources_stm32,
>> +       .eqos_remove_resources = eqos_remove_resources_stm32,
>> +       .eqos_stop_resets = eqos_stop_resets_stm32,
>> +       .eqos_start_resets = eqos_start_resets_stm32,
>> +       .eqos_stop_clks = eqos_stop_clks_stm32,
>> +       .eqos_start_clks = eqos_start_clks_stm32,
>> +       .eqos_calibrate_pads = eqos_calibrate_pads_stm32,
>> +       .eqos_disable_calibration = eqos_disable_calibration_stm32,
>> +       .eqos_set_tx_clk_speed = eqos_set_tx_clk_speed_stm32,
>> +       .eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_stm32
>> +};
>> +
>> +static const struct eqos_config eqos_stm32_config = {
>> +       .reg_access_always_ok = false,
>> +       .mdio_wait = 10000,
>> +       .swr_wait = 50,
>> +       .config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_AV,
>> +       .config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_250_300,
>> +       .interface = eqos_get_interface_stm32,
>> +       .ops = &eqos_stm32_ops
>>   };
>>
>>   static const struct udevice_id eqos_ids[] = {
>> @@ -1537,6 +1863,11 @@ static const struct udevice_id eqos_ids[] = {
>>                  .compatible = "nvidia,tegra186-eqos",
>>                  .data = (ulong)&eqos_tegra186_config
>>          },
>> +       {
>> +               .compatible = "snps,dwmac-4.20a",
>> +               .data = (ulong)&eqos_stm32_config
>> +       },
>> +
>>          { }
>>   };
>>
>> --
>> 2.17.1
>>
>> _______________________________________________
>> U-Boot mailing list
>> U-Boot at lists.denx.de
>> https://lists.denx.de/listinfo/u-boot


More information about the U-Boot mailing list