All of lore.kernel.org
 help / color / mirror / Atom feed
From: Andrew Lunn <andrew@lunn.ch>
To: Russell King <rmk+kernel@armlinux.org.uk>,
	Guenter Roeck <linux@roeck-us.net>
Cc: Florian Fainelli <f.fainelli@gmail.com>, netdev@vger.kernel.org
Subject: Re: [PATCH] net: phy: marvell10g: add thermal hwmon device
Date: Thu, 29 Mar 2018 00:09:15 +0200	[thread overview]
Message-ID: <20180328220915.GB23595@lunn.ch> (raw)
In-Reply-To: <E1f18Bu-0005CL-O4@rmk-PC.armlinux.org.uk>

Hi Russell

Guenter Roeck, the HWMON maintainer should also be involved in
reviewing this patch.

	  Andrew


On Wed, Mar 28, 2018 at 11:20:26AM +0100, Russell King wrote:
> Add a thermal monitoring device for the Marvell 88x3310, which updates
> once a second.  We also need to hook into the suspend/resume mechanism
> to ensure that the thermal monitoring is reconfigured when we resume.
> 
> Suggested-by: Andrew Lunn <andrew@lunn.ch>
> Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
> ---
>  drivers/net/phy/marvell10g.c | 184 ++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 182 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c
> index 8a0bd98fdec7..db9d66781da6 100644
> --- a/drivers/net/phy/marvell10g.c
> +++ b/drivers/net/phy/marvell10g.c
> @@ -21,8 +21,10 @@
>   * If both the fiber and copper ports are connected, the first to gain
>   * link takes priority and the other port is completely locked out.
>   */
> -#include <linux/phy.h>
> +#include <linux/ctype.h>
> +#include <linux/hwmon.h>
>  #include <linux/marvell_phy.h>
> +#include <linux/phy.h>
>  
>  enum {
>  	MV_PCS_BASE_T		= 0x0000,
> @@ -40,6 +42,19 @@ enum {
>  	 */
>  	MV_AN_CTRL1000		= 0x8000, /* 1000base-T control register */
>  	MV_AN_STAT1000		= 0x8001, /* 1000base-T status register */
> +
> +	/* Vendor2 MMD registers */
> +	MV_V2_TEMP_CTRL		= 0xf08a,
> +	MV_V2_TEMP_CTRL_MASK	= 0xc000,
> +	MV_V2_TEMP_CTRL_SAMPLE	= 0x0000,
> +	MV_V2_TEMP_CTRL_DISABLE	= 0xc000,
> +	MV_V2_TEMP		= 0xf08c,
> +	MV_V2_TEMP_UNKNOWN	= 0x9600, /* unknown function */
> +};
> +
> +struct mv3310_priv {
> +	struct device *hwmon_dev;
> +	char *hwmon_name;
>  };
>  
>  static int mv3310_modify(struct phy_device *phydev, int devad, u16 reg,
> @@ -60,17 +75,180 @@ static int mv3310_modify(struct phy_device *phydev, int devad, u16 reg,
>  	return ret < 0 ? ret : 1;
>  }
>  
> +#ifdef CONFIG_HWMON
> +static umode_t mv3310_hwmon_is_visible(const void *data,
> +				       enum hwmon_sensor_types type,
> +				       u32 attr, int channel)
> +{
> +	if (type == hwmon_chip && attr == hwmon_chip_update_interval)
> +		return 0444;
> +	if (type == hwmon_temp && attr == hwmon_temp_input)
> +		return 0444;
> +	return 0;
> +}
> +
> +static int mv3310_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
> +			     u32 attr, int channel, long *value)
> +{
> +	struct phy_device *phydev = dev_get_drvdata(dev);
> +	int temp;
> +
> +	if (type == hwmon_chip && attr == hwmon_chip_update_interval) {
> +		*value = MSEC_PER_SEC;
> +		return 0;
> +	}
> +
> +	if (type == hwmon_temp && attr == hwmon_temp_input) {
> +		temp = phy_read_mmd(phydev, MDIO_MMD_VEND2, MV_V2_TEMP);
> +		if (temp < 0)
> +			return temp;
> +
> +		*value = ((temp & 0xff) - 75) * 1000;
> +
> +		return 0;
> +	}
> +
> +	return -EOPNOTSUPP;
> +}
> +
> +static const struct hwmon_ops mv3310_hwmon_ops = {
> +	.is_visible = mv3310_hwmon_is_visible,
> +	.read = mv3310_hwmon_read,
> +};
> +
> +static u32 mv3310_hwmon_chip_config[] = {
> +	HWMON_C_REGISTER_TZ | HWMON_C_UPDATE_INTERVAL,
> +	0,
> +};
> +
> +static const struct hwmon_channel_info mv3310_hwmon_chip = {
> +	.type = hwmon_chip,
> +	.config = mv3310_hwmon_chip_config,
> +};
> +
> +static u32 mv3310_hwmon_temp_config[] = {
> +	HWMON_T_INPUT,
> +	0,
> +};
> +
> +static const struct hwmon_channel_info mv3310_hwmon_temp = {
> +	.type = hwmon_temp,
> +	.config = mv3310_hwmon_temp_config,
> +};
> +
> +static const struct hwmon_channel_info *mv3310_hwmon_info[] = {
> +	&mv3310_hwmon_chip,
> +	&mv3310_hwmon_temp,
> +	NULL,
> +};
> +
> +static const struct hwmon_chip_info mv3310_hwmon_chip_info = {
> +	.ops = &mv3310_hwmon_ops,
> +	.info = mv3310_hwmon_info,
> +};
> +
> +static int mv3310_hwmon_config(struct phy_device *phydev, bool enable)
> +{
> +	u16 val;
> +	int ret;
> +
> +	ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, MV_V2_TEMP,
> +			    MV_V2_TEMP_UNKNOWN);
> +	if (ret < 0)
> +		return ret;
> +
> +	val = enable ? MV_V2_TEMP_CTRL_SAMPLE : MV_V2_TEMP_CTRL_DISABLE;
> +	ret = mv3310_modify(phydev, MDIO_MMD_VEND2, MV_V2_TEMP_CTRL,
> +			    MV_V2_TEMP_CTRL_MASK, val);
> +
> +	return ret < 0 ? ret : 0;
> +}
> +
> +static void mv3310_hwmon_disable(void *data)
> +{
> +	struct phy_device *phydev = data;
> +
> +	mv3310_hwmon_config(phydev, false);
> +}
> +
> +static int mv3310_hwmon_probe(struct phy_device *phydev)
> +{
> +	struct device *dev = &phydev->mdio.dev;
> +	struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
> +	int i, j, ret;
> +
> +	priv->hwmon_name = devm_kstrdup(dev, dev_name(dev), GFP_KERNEL);
> +	if (!priv->hwmon_name)
> +		return -ENODEV;
> +
> +	for (i = j = 0; priv->hwmon_name[i]; i++) {
> +		if (isalnum(priv->hwmon_name[i])) {
> +			if (i != j)
> +				priv->hwmon_name[j] = priv->hwmon_name[i];
> +			j++;
> +		}
> +	}
> +	priv->hwmon_name[j] = '\0';
> +
> +	ret = mv3310_hwmon_config(phydev, true);
> +	if (ret)
> +		return ret;
> +
> +	ret = devm_add_action_or_reset(dev, mv3310_hwmon_disable, phydev);
> +	if (ret)
> +		return ret;
> +
> +	priv->hwmon_dev = devm_hwmon_device_register_with_info(dev,
> +				priv->hwmon_name, phydev,
> +				&mv3310_hwmon_chip_info, NULL);
> +
> +	return PTR_ERR_OR_ZERO(priv->hwmon_dev);
> +}
> +#else
> +static inline int mv3310_hwmon_config(struct phy_device *phydev, bool enable)
> +{
> +	return 0;
> +}
> +
> +static int mv3310_hwmon_probe(struct phy_device *phydev)
> +{
> +	return 0;
> +}
> +#endif
> +
>  static int mv3310_probe(struct phy_device *phydev)
>  {
> +	struct mv3310_priv *priv;
>  	u32 mmd_mask = MDIO_DEVS_PMAPMD | MDIO_DEVS_AN;
> +	int ret;
>  
>  	if (!phydev->is_c45 ||
>  	    (phydev->c45_ids.devices_in_package & mmd_mask) != mmd_mask)
>  		return -ENODEV;
>  
> +	priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL);
> +	if (!priv)
> +		return -ENOMEM;
> +
> +	dev_set_drvdata(&phydev->mdio.dev, priv);
> +
> +	ret = mv3310_hwmon_probe(phydev);
> +	if (ret)
> +		return ret;
> +
> +	return 0;
> +}
> +
> +static int mv3310_suspend(struct phy_device *phydev)
> +{
>  	return 0;
>  }
>  
> +static int mv3310_resume(struct phy_device *phydev)
> +{
> +	return mv3310_hwmon_config(phydev, true);
> +}
> +
>  /*
>   * Resetting the MV88X3310 causes it to become non-responsive.  Avoid
>   * setting the reset bit(s).
> @@ -376,9 +554,11 @@ static struct phy_driver mv3310_drivers[] = {
>  				  SUPPORTED_FIBRE |
>  				  SUPPORTED_10000baseT_Full |
>  				  SUPPORTED_Backplane,
> -		.probe		= mv3310_probe,
>  		.soft_reset	= mv3310_soft_reset,
>  		.config_init	= mv3310_config_init,
> +		.probe		= mv3310_probe,
> +		.suspend	= mv3310_suspend,
> +		.resume		= mv3310_resume,
>  		.config_aneg	= mv3310_config_aneg,
>  		.aneg_done	= mv3310_aneg_done,
>  		.read_status	= mv3310_read_status,
> -- 
> 2.7.4
> 

  reply	other threads:[~2018-03-28 22:09 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-03-28 10:20 [PATCH] net: phy: marvell10g: add thermal hwmon device Russell King
2018-03-28 22:09 ` Andrew Lunn [this message]
2018-04-01  1:50 ` David Miller

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=20180328220915.GB23595@lunn.ch \
    --to=andrew@lunn.ch \
    --cc=f.fainelli@gmail.com \
    --cc=linux@roeck-us.net \
    --cc=netdev@vger.kernel.org \
    --cc=rmk+kernel@armlinux.org.uk \
    /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.