All of lore.kernel.org
 help / color / mirror / Atom feed
From: Andrew Lunn <andrew@lunn.ch>
To: Egil Hjelmeland <privat@egil-hjelmeland.no>
Cc: corbet@lwn.net, vivien.didelot@savoirfairelinux.com,
	f.fainelli@gmail.com, davem@davemloft.net, kernel@pengutronix.de,
	linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org,
	netdev@vger.kernel.org
Subject: Re: [PATCH net-next v2 01/10] net: dsa: lan9303: Fixed MDIO interface
Date: Wed, 26 Jul 2017 18:55:50 +0200	[thread overview]
Message-ID: <20170726165550.GN12049@lunn.ch> (raw)
In-Reply-To: <20170725161553.30147-2-privat@egil-hjelmeland.no>

On Tue, Jul 25, 2017 at 06:15:44PM +0200, Egil Hjelmeland wrote:
> Fixes after testing on actual HW:
> 
> - lan9303_mdio_write()/_read() must multiply register number
>   by 4 to get offset
> 
> - Indirect access (PMI) to phy register only work in I2C mode. In
>   MDIO mode phy registers must be accessed directly. Introduced
>   struct lan9303_phy_ops to handle the two modes. Renamed functions
>   to clarify.
> 
> - lan9303_detect_phy_setup() : Failed MDIO read return 0xffff.
>   Handle that.
> 
> Signed-off-by: Egil Hjelmeland <privat@egil-hjelmeland.no>
> ---
>  drivers/net/dsa/lan9303-core.c | 42 +++++++++++++++++++++++++++---------------
>  drivers/net/dsa/lan9303.h      | 11 +++++++++++
>  drivers/net/dsa/lan9303_i2c.c  |  2 ++
>  drivers/net/dsa/lan9303_mdio.c | 34 ++++++++++++++++++++++++++++++++++
>  4 files changed, 74 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/net/dsa/lan9303-core.c b/drivers/net/dsa/lan9303-core.c
> index cd76e61f1fca..e622db586c3d 100644
> --- a/drivers/net/dsa/lan9303-core.c
> +++ b/drivers/net/dsa/lan9303-core.c
> @@ -20,6 +20,9 @@
>  
>  #include "lan9303.h"
>  
> +/* 13.2 System Control and Status Registers
> + * Multiply register number by 4 to get address offset.
> + */
>  #define LAN9303_CHIP_REV 0x14
>  # define LAN9303_CHIP_ID 0x9303
>  #define LAN9303_IRQ_CFG 0x15
> @@ -53,6 +56,9 @@
>  #define LAN9303_VIRT_PHY_BASE 0x70
>  #define LAN9303_VIRT_SPECIAL_CTRL 0x77
>  
> +/*13.4 Switch Fabric Control and Status Registers
> + * Accessed indirectly via SWITCH_CSR_CMD, SWITCH_CSR_DATA.
> + */
>  #define LAN9303_SW_DEV_ID 0x0000
>  #define LAN9303_SW_RESET 0x0001
>  #define LAN9303_SW_RESET_RESET BIT(0)
> @@ -242,7 +248,7 @@ static int lan9303_virt_phy_reg_write(struct lan9303 *chip, int regnum, u16 val)
>  	return regmap_write(chip->regmap, LAN9303_VIRT_PHY_BASE + regnum, val);
>  }
>  
> -static int lan9303_port_phy_reg_wait_for_completion(struct lan9303 *chip)
> +static int lan9303_indirect_phy_wait_for_completion(struct lan9303 *chip)
>  {
>  	int ret, i;
>  	u32 reg;
> @@ -262,7 +268,7 @@ static int lan9303_port_phy_reg_wait_for_completion(struct lan9303 *chip)
>  	return -EIO;
>  }
>  
> -static int lan9303_port_phy_reg_read(struct lan9303 *chip, int addr, int regnum)
> +static int lan9303_indirect_phy_read(struct lan9303 *chip, int addr, int regnum)
>  {
>  	int ret;
>  	u32 val;
> @@ -272,7 +278,7 @@ static int lan9303_port_phy_reg_read(struct lan9303 *chip, int addr, int regnum)
>  
>  	mutex_lock(&chip->indirect_mutex);
>  
> -	ret = lan9303_port_phy_reg_wait_for_completion(chip);
> +	ret = lan9303_indirect_phy_wait_for_completion(chip);
>  	if (ret)
>  		goto on_error;
>  
> @@ -281,7 +287,7 @@ static int lan9303_port_phy_reg_read(struct lan9303 *chip, int addr, int regnum)
>  	if (ret)
>  		goto on_error;
>  
> -	ret = lan9303_port_phy_reg_wait_for_completion(chip);
> +	ret = lan9303_indirect_phy_wait_for_completion(chip);
>  	if (ret)
>  		goto on_error;
>  
> @@ -299,8 +305,8 @@ static int lan9303_port_phy_reg_read(struct lan9303 *chip, int addr, int regnum)
>  	return ret;
>  }
>  
> -static int lan9303_phy_reg_write(struct lan9303 *chip, int addr, int regnum,
> -				 unsigned int val)
> +static int lan9303_indirect_phy_write(struct lan9303 *chip, int addr,
> +				      int regnum, u16 val)
>  {
>  	int ret;
>  	u32 reg;
> @@ -311,7 +317,7 @@ static int lan9303_phy_reg_write(struct lan9303 *chip, int addr, int regnum,
>  
>  	mutex_lock(&chip->indirect_mutex);
>  
> -	ret = lan9303_port_phy_reg_wait_for_completion(chip);
> +	ret = lan9303_indirect_phy_wait_for_completion(chip);
>  	if (ret)
>  		goto on_error;
>  
> @@ -328,6 +334,11 @@ static int lan9303_phy_reg_write(struct lan9303 *chip, int addr, int regnum,
>  	return ret;
>  }
>  
> +const struct lan9303_phy_ops lan9303_indirect_phy_ops = {
> +	.phy_read = lan9303_indirect_phy_read,
> +	.phy_write = lan9303_indirect_phy_write,
> +};
> +
>  static int lan9303_switch_wait_for_completion(struct lan9303 *chip)
>  {
>  	int ret, i;
> @@ -427,14 +438,15 @@ static int lan9303_detect_phy_setup(struct lan9303 *chip)
>  	 * Special reg 18 of phy 3 reads as 0x0000, if 'phy_addr_sel_strap' is 0
>  	 * and the IDs are 0-1-2, else it contains something different from
>  	 * 0x0000, which means 'phy_addr_sel_strap' is 1 and the IDs are 1-2-3.
> +	 * 0xffff is returned for failed MDIO access.

Hi Egil

0xffff is not really a failure. It just means there is nothing on the
bus at that address. The bus has a weak pull-up, so defaults to one.

>  	 */
> -	reg = lan9303_port_phy_reg_read(chip, 3, MII_LAN911X_SPECIAL_MODES);
> +	reg = chip->ops->phy_read(chip, 3, MII_LAN911X_SPECIAL_MODES);
>  	if (reg < 0) {
>  		dev_err(chip->dev, "Failed to detect phy config: %d\n", reg);
>  		return reg;
>  	}
>  
> -	if (reg != 0)
> +	if ((reg != 0) && (reg != 0xffff))
>  		chip->phy_addr_sel_strap = 1;
>  	else
>  		chip->phy_addr_sel_strap = 0;
> @@ -719,7 +731,7 @@ static int lan9303_phy_read(struct dsa_switch *ds, int phy, int regnum)
>  	if (phy > phy_base + 2)
>  		return -ENODEV;
>  
> -	return lan9303_port_phy_reg_read(chip, phy, regnum);
> +	return chip->ops->phy_read(chip, phy, regnum);
>  }
>  
>  static int lan9303_phy_write(struct dsa_switch *ds, int phy, int regnum,
> @@ -733,7 +745,7 @@ static int lan9303_phy_write(struct dsa_switch *ds, int phy, int regnum,
>  	if (phy > phy_base + 2)
>  		return -ENODEV;
>  
> -	return lan9303_phy_reg_write(chip, phy, regnum, val);
> +	return chip->ops->phy_write(chip, phy, regnum, val);
>  }
>  
>  static int lan9303_port_enable(struct dsa_switch *ds, int port,
> @@ -766,13 +778,13 @@ static void lan9303_port_disable(struct dsa_switch *ds, int port,
>  	switch (port) {
>  	case 1:
>  		lan9303_disable_packet_processing(chip, LAN9303_PORT_1_OFFSET);
> -		lan9303_phy_reg_write(chip, chip->phy_addr_sel_strap + 1,
> -				      MII_BMCR, BMCR_PDOWN);
> +		lan9303_phy_write(ds, chip->phy_addr_sel_strap + 1,
> +				  MII_BMCR, BMCR_PDOWN);
>  		break;
>  	case 2:
>  		lan9303_disable_packet_processing(chip, LAN9303_PORT_2_OFFSET);
> -		lan9303_phy_reg_write(chip, chip->phy_addr_sel_strap + 2,
> -				      MII_BMCR, BMCR_PDOWN);
> +		lan9303_phy_write(ds, chip->phy_addr_sel_strap + 2,
> +				  MII_BMCR, BMCR_PDOWN);
>  		break;
>  	default:
>  		dev_dbg(chip->dev,
> diff --git a/drivers/net/dsa/lan9303.h b/drivers/net/dsa/lan9303.h
> index d1512dad2d90..444d00b460e1 100644
> --- a/drivers/net/dsa/lan9303.h
> +++ b/drivers/net/dsa/lan9303.h
> @@ -2,6 +2,15 @@
>  #include <linux/device.h>
>  #include <net/dsa.h>
>  
> +struct lan9303;
> +
> +struct lan9303_phy_ops {
> +	/* PHY 1 &2 access*/

A space would be nice here after the &.

> +	int	(*phy_read)(struct lan9303 *chip, int port, int regnum);
> +	int	(*phy_write)(struct lan9303 *chip, int port,
> +			     int regnum, u16 val);
> +};
> +
>  struct lan9303 {
>  	struct device *dev;
>  	struct regmap *regmap;
> @@ -11,9 +20,11 @@ struct lan9303 {
>  	bool phy_addr_sel_strap;
>  	struct dsa_switch *ds;
>  	struct mutex indirect_mutex; /* protect indexed register access */
> +	const struct lan9303_phy_ops *ops;
>  };
>  
>  extern const struct regmap_access_table lan9303_register_set;
> +extern const struct lan9303_phy_ops lan9303_indirect_phy_ops;
>  
>  int lan9303_probe(struct lan9303 *chip, struct device_node *np);
>  int lan9303_remove(struct lan9303 *chip);
> diff --git a/drivers/net/dsa/lan9303_i2c.c b/drivers/net/dsa/lan9303_i2c.c
> index ab3ce0da5071..24ec20f7f444 100644
> --- a/drivers/net/dsa/lan9303_i2c.c
> +++ b/drivers/net/dsa/lan9303_i2c.c
> @@ -63,6 +63,8 @@ static int lan9303_i2c_probe(struct i2c_client *client,
>  	i2c_set_clientdata(client, sw_dev);
>  	sw_dev->chip.dev = &client->dev;
>  
> +	sw_dev->chip.ops = &lan9303_indirect_phy_ops;
> +
>  	ret = lan9303_probe(&sw_dev->chip, client->dev.of_node);
>  	if (ret != 0)
>  		return ret;
> diff --git a/drivers/net/dsa/lan9303_mdio.c b/drivers/net/dsa/lan9303_mdio.c
> index 93c36c0541cf..94df12c5362f 100644
> --- a/drivers/net/dsa/lan9303_mdio.c
> +++ b/drivers/net/dsa/lan9303_mdio.c
> @@ -39,6 +39,7 @@ static void lan9303_mdio_real_write(struct mdio_device *mdio, int reg, u16 val)
>  static int lan9303_mdio_write(void *ctx, uint32_t reg, uint32_t val)
>  {
>  	struct lan9303_mdio *sw_dev = (struct lan9303_mdio *)ctx;
> +	reg <<= 2; /* reg num to offset */
>  
>  	mutex_lock(&sw_dev->device->bus->mdio_lock);
>  	lan9303_mdio_real_write(sw_dev->device, reg, val & 0xffff);
> @@ -56,6 +57,7 @@ static u16 lan9303_mdio_real_read(struct mdio_device *mdio, int reg)
>  static int lan9303_mdio_read(void *ctx, uint32_t reg, uint32_t *val)
>  {
>  	struct lan9303_mdio *sw_dev = (struct lan9303_mdio *)ctx;
> +	reg <<= 2; /* reg num to offset */
>  
>  	mutex_lock(&sw_dev->device->bus->mdio_lock);
>  	*val = lan9303_mdio_real_read(sw_dev->device, reg);
> @@ -65,6 +67,36 @@ static int lan9303_mdio_read(void *ctx, uint32_t reg, uint32_t *val)
>  	return 0;
>  }
>  
> +int lan9303_mdio_phy_write(struct lan9303 *chip, int phy, int regnum, u16 val)
> +{
> +	struct lan9303_mdio *sw_dev = dev_get_drvdata(chip->dev);
> +	struct mdio_device *mdio = sw_dev->device;
> +
> +	mutex_lock(&mdio->bus->mdio_lock);
> +	mdio->bus->write(mdio->bus, phy, regnum, val);
> +	mutex_unlock(&mdio->bus->mdio_lock);

It is better to use mdiobus_read/write or if you are nesting mdio
busses, mdiobus_read_nested/mdiobus_write_nested. Please test this
code with lockdep enabled.

And as others have pointed out, there are too many changes in this one
patch.

Thanks
	Andrew

  parent reply	other threads:[~2017-07-26 16:56 UTC|newest]

Thread overview: 38+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-07-25 16:15 [PATCH net-next v2 00/10] net: dsa: lan9303: unicast offload, fdb,mdb,STP Egil Hjelmeland
2017-07-25 16:15 ` [PATCH net-next v2 01/10] net: dsa: lan9303: Fixed MDIO interface Egil Hjelmeland
2017-07-25 19:15   ` Vivien Didelot
2017-07-26 12:18     ` Egil Hjelmeland
2017-07-26 14:30       ` Vivien Didelot
2017-07-26 14:50         ` Egil Hjelmeland
2017-07-26 17:52         ` Andrew Lunn
2017-07-26 20:07           ` David Miller
2017-07-26 20:47             ` Egil Hjelmeland
2017-07-26 21:39               ` Andrew Lunn
2017-07-26 16:55   ` Andrew Lunn [this message]
2017-07-28 11:08     ` Egil Hjelmeland
2017-07-28 13:36       ` Andrew Lunn
2017-07-27  7:07   ` kbuild test robot
2017-07-25 16:15 ` [PATCH net-next v2 02/10] net: dsa: lan9303: Do not disable/enable switch fabric port 0 at startup Egil Hjelmeland
2017-07-26 16:58   ` Andrew Lunn
2017-07-27 10:39     ` Egil Hjelmeland
2017-07-25 16:15 ` [PATCH net-next v2 03/10] net: dsa: lan9303: Refactor lan9303_enable_packet_processing() Egil Hjelmeland
2017-07-25 16:15 ` [PATCH net-next v2 04/10] net: dsa: lan9303: Added adjust_link() method Egil Hjelmeland
2017-07-26 17:09   ` Andrew Lunn
2017-07-27 10:45     ` Egil Hjelmeland
2017-07-25 16:15 ` [PATCH net-next v2 05/10] net: dsa: added dsa_net_device_to_dsa_port() Egil Hjelmeland
2017-07-25 16:15 ` [PATCH net-next v2 06/10] net: dsa: lan9303: added sysfs node swe_bcst_throt Egil Hjelmeland
2017-07-26 17:14   ` Andrew Lunn
2017-07-27 10:59     ` Egil Hjelmeland
2017-07-27 13:26       ` Andrew Lunn
2017-07-27 13:32         ` Jiri Pirko
2017-07-25 16:15 ` [PATCH net-next v2 07/10] net: dsa: lan9303: Added basic offloading of unicast traffic Egil Hjelmeland
2017-07-26 17:24   ` Andrew Lunn
2017-07-27 11:21     ` Egil Hjelmeland
2017-07-27 13:31       ` Andrew Lunn
2017-07-27 14:07         ` Egil Hjelmeland
2017-07-27  0:17   ` kbuild test robot
2017-07-25 16:15 ` [PATCH net-next v2 08/10] net: dsa: lan9303: Added ALR/fdb/mdb handling Egil Hjelmeland
2017-07-26 17:41   ` Andrew Lunn
2017-07-27 11:04     ` Egil Hjelmeland
2017-07-25 16:15 ` [PATCH net-next v2 09/10] net: dsa: lan9303: Added Documentation/networking/dsa/lan9303.txt Egil Hjelmeland
2017-07-25 16:15 ` [PATCH net-next v2 10/10] net: dsa: lan9303: Only allocate 3 ports Egil Hjelmeland

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170726165550.GN12049@lunn.ch \
    --to=andrew@lunn.ch \
    --cc=corbet@lwn.net \
    --cc=davem@davemloft.net \
    --cc=f.fainelli@gmail.com \
    --cc=kernel@pengutronix.de \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=privat@egil-hjelmeland.no \
    --cc=vivien.didelot@savoirfairelinux.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.