Le 2/22/19 à 12:12 PM, Parshuram Thombare a écrit :
> This patch add support for PCS (for SGMII interface) and 2.5Gbps MAC
> in Cadence ethernet controller driver.

At a high level you don't seem to be making use of PHYLINK so which
2.5Gbps interfaces do you actually support?

> 
> Signed-off-by: Parshuram Thombare <pthom...@cadence.com>
> ---

[snip]

> @@ -361,26 +361,50 @@ static int macb_mdio_write(struct mii_bus *bus, int 
> mii_id, int regnum,
>   * macb_set_tx_clk() - Set a clock to a new frequency
>   * @clk              Pointer to the clock to change
>   * @rate     New frequency in Hz
> + * @interafce        Phy interface

Typo: @interface and this is an unrelated change.

>   * @dev              Pointer to the struct net_device
>   */
> -static void macb_set_tx_clk(struct clk *clk, int speed, struct net_device 
> *dev)
> +static void macb_set_tx_clk(struct clk *clk, int speed,
> +                         phy_interface_t interface, struct net_device *dev)
>  {
>       long ferr, rate, rate_rounded;
>  
>       if (!clk)
>               return;
>  
> -     switch (speed) {
> -     case SPEED_10:
> +     if (interface == PHY_INTERFACE_MODE_GMII ||
> +         interface == PHY_INTERFACE_MODE_MII) {
> +             switch (speed) {
> +             case SPEED_10:>                 rate = 2500000;

You need to add one tab to align rate and break.

>               break;
> -     case SPEED_100:
> +             case SPEED_100:
>               rate = 25000000;
>               break;
> -     case SPEED_1000:
> +             case SPEED_1000:
>               rate = 125000000;
>               break;
> -     default:
> +             default:
> +             return;
> +             }
> +     } else if (interface == PHY_INTERFACE_MODE_SGMII) {
> +             switch (speed) {
> +             case SPEED_10:
> +             rate = 1250000;
> +             break;
> +             case SPEED_100:
> +             rate = 12500000;
> +             break;
> +             case SPEED_1000:
> +             rate = 125000000;
> +             break;
> +             case SPEED_2500:
> +             rate = 312500000;
> +             break;
> +             default:
> +             return;

The indentation is broken here and you can greatly simplify this with a
simple function that returns speed * 1250 and does an initial check for
unsupported speeds.

> +             }
> +     } else {
>               return;
>       }
>  
> @@ -410,30 +434,49 @@ static void macb_handle_link_change(struct net_device 
> *dev)
>  
>       spin_lock_irqsave(&bp->lock, flags);
>  
> -     if (phydev->link) {
> -             if ((bp->speed != phydev->speed) ||
> -                 (bp->duplex != phydev->duplex)) {
> -                     u32 reg;
> -
> -                     reg = macb_readl(bp, NCFGR);
> -                     reg &= ~(MACB_BIT(SPD) | MACB_BIT(FD));
> -                     if (macb_is_gem(bp))
> -                             reg &= ~GEM_BIT(GBE);
> +     if (phydev->link && (bp->speed != phydev->speed ||
> +                          bp->duplex != phydev->duplex)) {
> +             u32 reg;
>  
> -                     if (phydev->duplex)
> -                             reg |= MACB_BIT(FD);
> +             reg = macb_readl(bp, NCFGR);
> +             reg &= ~(MACB_BIT(SPD) | MACB_BIT(FD));
> +             if (macb_is_gem(bp))
> +                     reg &= ~GEM_BIT(GBE);
> +             if (phydev->duplex)
> +                     reg |= MACB_BIT(FD);
> +             macb_or_gem_writel(bp, NCFGR, reg);
> +
> +             if (bp->phy_interface == PHY_INTERFACE_MODE_SGMII &&
> +                 (phydev->speed == SPEED_1000 ||
> +                  phydev->speed == SPEED_2500)) {
> +                     if (bp->caps & MACB_CAPS_TWO_PT_FIVE_GIG_SPEED) {
> +                             reg = gem_readl(bp, NCR) &
> +                                     ~GEM_BIT(TWO_PT_FIVE_GIG);
> +                             gem_writel(bp, NCR, reg);
> +                     }

If you are making correct use of the capabilities then there is no point
in re-checking them here. If you allowed the MAC to advertise 2.5Gbps
then it is de-facto SGMII capable.

> +                     gem_writel(bp, NCFGR, GEM_BIT(GBE) |
> +                                     gem_readl(bp, NCFGR));
> +                     if (bp->caps & MACB_CAPS_TWO_PT_FIVE_GIG_SPEED &&
> +                         phydev->speed == SPEED_2500)
> +                             gem_writel(bp, NCR, gem_readl(bp, NCR) |
> +                                             GEM_BIT(TWO_PT_FIVE_GIG));
> +             } else if (phydev->speed == SPEED_1000) {
> +                     gem_writel(bp, NCFGR, GEM_BIT(GBE) |
> +                                     gem_readl(bp, NCFGR));
> +             } else {
> +                     if (bp->phy_interface == PHY_INTERFACE_MODE_SGMII) {
> +                             reg = gem_readl(bp, NCFGR);
> +                             reg &= ~(GEM_BIT(SGMIIEN) | GEM_BIT(PCSSEL));
> +                             gem_writel(bp, NCFGR, reg);
> +                     }
>                       if (phydev->speed == SPEED_100)
> -                             reg |= MACB_BIT(SPD);
> -                     if (phydev->speed == SPEED_1000 &&
> -                         bp->caps & MACB_CAPS_GIGABIT_MODE_AVAILABLE)
> -                             reg |= GEM_BIT(GBE);
> -
> -                     macb_or_gem_writel(bp, NCFGR, reg);
> -
> -                     bp->speed = phydev->speed;
> -                     bp->duplex = phydev->duplex;
> -                     status_change = 1;
> +                             macb_writel(bp, NCFGR, MACB_BIT(SPD) |
> +                                     macb_readl(bp, NCFGR));
>               }

There is a lot of repetition while setting the GBE bit which always set
based on speed == 1000 irrespective of the mode, so take that part out
of the if () else if () else () clauses.

> +
> +             bp->speed = phydev->speed;
> +             bp->duplex = phydev->duplex;
> +             status_change = 1;
>       }
>  
>       if (phydev->link != bp->link) {
> @@ -453,7 +496,8 @@ static void macb_handle_link_change(struct net_device 
> *dev)
>                       /* Update the TX clock rate if and only if the link is
>                        * up and there has been a link change.
>                        */
> -                     macb_set_tx_clk(bp->tx_clk, phydev->speed, dev);
> +                     macb_set_tx_clk(bp->tx_clk, phydev->speed,
> +                                     bp->phy_interface, dev);
>  
>                       netif_carrier_on(dev);
>                       netdev_info(dev, "link up (%d/%s)\n",
> @@ -543,10 +587,16 @@ static int macb_mii_probe(struct net_device *dev)
>       }
>  
>       /* mask with MAC supported features */
> -     if (macb_is_gem(bp) && bp->caps & MACB_CAPS_GIGABIT_MODE_AVAILABLE)
> -             phy_set_max_speed(phydev, SPEED_1000);
> -     else
> -             phy_set_max_speed(phydev, SPEED_100);
> +     if (macb_is_gem(bp)) {

You have changed the previous logic that also checked for
MACB_CAPS_GIGABIT_MODE_AVAILABLE, why?

> +             linkmode_copy(phydev->supported, PHY_GBIT_FEATURES);
> +             if (bp->caps & MACB_CAPS_TWO_PT_FIVE_GIG_SPEED)
> +                     linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
> +                                      phydev->supported);
> +     } else {
> +             linkmode_copy(phydev->supported, PHY_BASIC_FEATURES);
> +     }
> +
> +     linkmode_copy(phydev->advertising, phydev->supported);
>  
>       if (bp->caps & MACB_CAPS_NO_GIGABIT_HALF)
>               phy_remove_link_mode(phydev,
> @@ -2217,8 +2267,6 @@ static void macb_init_hw(struct macb *bp)
>       macb_set_hwaddr(bp);
>  
>       config = macb_mdc_clk_div(bp);
> -     if (bp->phy_interface == PHY_INTERFACE_MODE_SGMII)
> -             config |= GEM_BIT(SGMIIEN) | GEM_BIT(PCSSEL);
>       config |= MACB_BF(RBOF, NET_IP_ALIGN);  /* Make eth data aligned */
>       config |= MACB_BIT(PAE);                /* PAuse Enable */
>       config |= MACB_BIT(DRFCS);              /* Discard Rx FCS */
> @@ -3255,6 +3303,23 @@ static void macb_configure_caps(struct macb *bp,
>               dcfg = gem_readl(bp, DCFG1);
>               if (GEM_BFEXT(IRQCOR, dcfg) == 0)
>                       bp->caps |= MACB_CAPS_ISR_CLEAR_ON_WRITE;
> +             if (GEM_BFEXT(NO_PCS, dcfg) == 0)
> +                     bp->caps |= MACB_CAPS_PCS;
> +             switch (MACB_BFEXT(IDNUM, macb_readl(bp, MID))) {
> +             case MACB_GEM7016_IDNUM:
> +             case MACB_GEM7017_IDNUM:
> +             case MACB_GEM7017A_IDNUM:
> +             case MACB_GEM7020_IDNUM:
> +             case MACB_GEM7021_IDNUM:
> +             case MACB_GEM7021A_IDNUM:
> +             case MACB_GEM7022_IDNUM:
> +             if (bp->caps & MACB_CAPS_PCS)
> +                     bp->caps |= MACB_CAPS_TWO_PT_FIVE_GIG_SPEED;
> +             break;
> +
> +             default:
> +             break;
> +             }
>               dcfg = gem_readl(bp, DCFG2);
>               if ((dcfg & (GEM_BIT(RX_PKT_BUFF) | GEM_BIT(TX_PKT_BUFF))) == 0)
>                       bp->caps |= MACB_CAPS_FIFO_MODE;
> @@ -4110,7 +4175,28 @@ static int macb_probe(struct platform_device *pdev)
>               else
>                       bp->phy_interface = PHY_INTERFACE_MODE_MII;
>       } else {
> +             switch (err) {
> +             case PHY_INTERFACE_MODE_SGMII:
> +             if (bp->caps & MACB_CAPS_PCS) {
> +                     bp->phy_interface = PHY_INTERFACE_MODE_SGMII;
> +                     break;
> +             }

If SGMII was selected on a version of the IP that does not support it,
then falling back to GMII or MII does not sound correct, this is a hard
error that must be handled as such.
-- 
Florian

Reply via email to