Re: [PATCH net-next 4/6] net: dsa: mt7530: Add the support of MT7531 switch

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, 2019-12-12 at 11:57 +0800, Florian Fainelli wrote:
> 
> On 12/10/2019 12:14 AM, Landen Chao wrote:
> > Add new support for MT7531:
> > 
> > MT7531 is the next generation of MT7530. It is also a 7-ports switch with
> > 5 giga embedded phys, 2 cpu ports, and the same MAC logic of MT7530. Cpu
> > port 6 only supports HSGMII interface. Cpu port 5 supports either RGMII
> > or HSGMII in different HW sku. Due to HSGMII interface support, pll, and
> > pad setting are different from MT7530. This patch adds different initial
> > setting of MT7531.
> > 
> > Signed-off-by: Landen Chao <landen.chao@xxxxxxxxxxxx>
> > Signed-off-by: Sean Wang <sean.wang@xxxxxxxxxxxx>
> > ---
> 
> [snip]
> 
> > +	/* Enable PHY power, since phy_device has not yet been created
> > +	 * provided for phy_[read,write]_mmd_indirect is called, we provide
> > +	 * our own mt7531_ind_mmd_phy_[read,write] to complete this
> > +	 * function.
> > +	 */
> > +	val = mt7531_ind_mmd_phy_read(priv, 0, PHY_DEV1F,
> > +				      MT7531_PHY_DEV1F_REG_403);
> > +	val |= MT7531_PHY_EN_BYPASS_MODE;
> > +	val &= ~MT7531_PHY_POWER_OFF;
> > +	mt7531_ind_mmd_phy_write(priv, 0, PHY_DEV1F,
> > +				 MT7531_PHY_DEV1F_REG_403, val);
> 
> You are doing this for port 0 only, is that because this broadcasts to
> all internal PHYs as well, or is it enough to somehow do it just for
> port 0? It sounds like you might want to make this operation a bit more
> scoped, if you have an external PHY that also responds to broadcast MDIO
> writes this could possibly cause some unattended effects, no?
All internal PHY addresses can be used to access the same PHY_DEV1F
group of registers.

I think the port "0" here must be changed to reference the "first
internal phy address" to prevent the situation you mentioned.
> 
> [snip]
> 
> > +static int mt7531_rgmii_setup(struct mt7530_priv *priv, u32 port)
> > +{
> > +	u32 val;
> > +
> > +	if (port != 5) {
> > +		dev_err(priv->dev, "RGMII mode is not available for port %d\n",
> > +			port);
> > +		return -EINVAL;
> > +	}
> > +
> > +	val = mt7530_read(priv, MT7531_CLKGEN_CTRL);
> > +	val |= GP_CLK_EN;
> > +	val &= ~GP_MODE_MASK;
> > +	val |= GP_MODE(MT7531_GP_MODE_RGMII);
> > +	val |= TXCLK_NO_REVERSE;
> > +	val |= RXCLK_NO_DELAY;
> 
> You actually need to look at the port's phy_interface_t value to
> determine whether the delays should be set/clear in either RX or TX
> directions.
Sure. Thanks for your advice.
> 
> [snip]
> 
> > -	if (phylink_autoneg_inband(mode)) {
> > +	if (phylink_autoneg_inband(mode) &&
> > +	    state->interface != PHY_INTERFACE_MODE_SGMII) {
> 
> So you don't support in-band auto-negotiation for 1000BaseX either?
According to the user manual I have, it only provides the configure 10M
+100M+1000M AN mode/1000M force mode/2500M force mode, so I mapping them
to SGMII/1000BaseX/2500BaseX. The user friendly part of this IP wraps
too much detail to map to the spec. I'll try to dig it out.
> 
> [snip]
> 
> > @@ -1590,9 +2197,20 @@ static void mt753x_phylink_validate(struct dsa_switch *ds, int port,
> >  	phylink_set_port_modes(mask);
> >  	phylink_set(mask, Autoneg);
> >  
> > -	if (state->interface == PHY_INTERFACE_MODE_TRGMII) {
> > +	switch (state->interface) {
> > +	case PHY_INTERFACE_MODE_TRGMII:
> >  		phylink_set(mask, 1000baseT_Full);
> > -	} else {
> > +		break;
> > +	case PHY_INTERFACE_MODE_1000BASEX:
> > +	case PHY_INTERFACE_MODE_2500BASEX:
> > +		phylink_set(mask, 1000baseX_Full);
> > +		phylink_set(mask, 2500baseX_Full);
> 
> Did you intend this to be:
> 
> 	case PHY_INTERFACE_MODE_2500BASEX:
> 		phylink_set(mask, 2500baseX_Full);
> 		/* fall through */
> 	case PHY_INTERFACE_MODE_1000BASEX:
> 		phylink_set(mask, 1000baseX_Full);
> 		break;
> 
> ?
As the user manual mentioned, it is more likely to be:
 	case PHY_INTERFACE_MODE_2500BASEX:
 		phylink_set(mask, 2500baseX_Full);
 		break;
 	case PHY_INTERFACE_MODE_1000BASEX:
 		phylink_set(mask, 1000baseX_Full);
 		break;
> [snip]
> 
> > +/* Register for PHY Indirect Access Control */
> > +#define MT7531_PHY_IAC			0x701C
> > +#define  PHY_ACS_ST			BIT(31)
> > +#define  MDIO_REG_ADDR_MASK		(0x1f << 25)
> > +#define  MDIO_PHY_ADDR_MASK		(0x1f << 20)
> > +#define  MDIO_CMD_MASK			(0x3 << 18)
> > +#define  MDIO_ST_MASK			(0x3 << 16)
> > +#define  MDIO_RW_DATA_MASK		(0xffff)
> > +#define  MDIO_REG_ADDR(x)		(((x) & 0x1f) << 25)
> > +#define  MDIO_DEV_ADDR(x)		(((x) & 0x1f) << 25)
> > +#define  MDIO_PHY_ADDR(x)		(((x) & 0x1f) << 20)
> > +#define  MDIO_CMD(x)			(((x) & 0x3) << 18)
> > +#define  MDIO_ST(x)			(((x) & 0x3) << 16)
> 
> I would suggest names that are more scoped because these could easily
> collide with existing of future definitions from include/linux/mdio.h.
Sure, I'll add "MT7531_" as the prefix.
> 
> > +
> > +enum mt7531_phy_iac_cmd {
> > +	MT7531_MDIO_ADDR = 0,
> > +	MT7531_MDIO_WRITE = 1,
> > +	MT7531_MDIO_READ = 2,
> > +	MT7531_MDIO_READ_CL45 = 3,
> > +};
> > +
> > +/* MDIO_ST: MDIO start field */
> > +enum mt7531_mdio_st {
> > +	MT7531_MDIO_ST_CL45 = 0,
> > +	MT7531_MDIO_ST_CL22 = 1,
> > +};
> > +
> > +#define  MDIO_CL22_READ			(MDIO_ST(MT7531_MDIO_ST_CL22) | \
> > +					 MDIO_CMD(MT7531_MDIO_READ))
> > +#define  MDIO_CL22_WRITE		(MDIO_ST(MT7531_MDIO_ST_CL22) | \
> > +					 MDIO_CMD(MT7531_MDIO_WRITE))
> > +#define  MDIO_CL45_ADDR			(MDIO_ST(MT7531_MDIO_ST_CL45) | \
> > +					 MDIO_CMD(MT7531_MDIO_ADDR))
> > +#define  MDIO_CL45_READ			(MDIO_ST(MT7531_MDIO_ST_CL45) | \
> > +					 MDIO_CMD(MT7531_MDIO_READ))
> > +#define  MDIO_CL45_WRITE		(MDIO_ST(MT7531_MDIO_ST_CL45) | \
> > +					 MDIO_CMD(MT7531_MDIO_WRITE))
> 
> Likewise.
I'll add "MT7531_" as the prefix.

Landen




[Index of Archives]     [Device Tree Compilter]     [Device Tree Spec]     [Linux Driver Backports]     [Video for Linux]     [Linux USB Devel]     [Linux PCI Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Yosemite Backpacking]


  Powered by Linux