From patchwork Tue Apr 3 09:31:45 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Russell King (Oracle)" X-Patchwork-Id: 894483 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=armlinux.org.uk Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=armlinux.org.uk header.i=@armlinux.org.uk header.b="UqmlpOeb"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 40FkPp0pLHz9s1P for ; Tue, 3 Apr 2018 19:31:58 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755290AbeDCJbz (ORCPT ); Tue, 3 Apr 2018 05:31:55 -0400 Received: from pandora.armlinux.org.uk ([78.32.30.218]:56120 "EHLO pandora.armlinux.org.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755134AbeDCJbx (ORCPT ); Tue, 3 Apr 2018 05:31:53 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=armlinux.org.uk; s=pandora-2014; h=Date:Sender:Message-Id:Content-Type: Content-Transfer-Encoding:MIME-Version:Subject:Cc:To:From:Reply-To:Content-ID :Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To: Resent-Cc:Resent-Message-ID:In-Reply-To:References:List-Id:List-Help: List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=0zoO1Y8H+cwdpeHd1nwX21uVYMACBUfHur3M+eEwoCc=; b=UqmlpOebFpvkxRIYd3kI23wKV5 fhm15nX35x124EpDb017Kuct3O5zPgGizj/nelZMc5dZDngkKTYDtWedIc255DOKRHo8ArlCSBfg8 yXiaZbrmgB7tEBiD8l3j7I/OziAYz/5ulSm9gHA/v2vBadZiBTW9BQGItOAIqCR2ShWQ=; Received: from e0022681537dd.dyn.armlinux.org.uk ([2002:4e20:1eda:1:222:68ff:fe15:37dd]:33280 helo=rmk-PC.armlinux.org.uk) by pandora.armlinux.org.uk with esmtpsa (TLSv1.2:ECDHE-RSA-AES128-GCM-SHA256:128) (Exim 4.90_1) (envelope-from ) id 1f3II6-0000wM-Eh; Tue, 03 Apr 2018 10:31:46 +0100 Received: from rmk by rmk-PC.armlinux.org.uk with local (Exim 4.82_1-5b7a7c0-XX) (envelope-from ) id 1f3II5-00077a-R3; Tue, 03 Apr 2018 10:31:45 +0100 From: Russell King To: Andrew Lunn , Florian Fainelli , Guenter Roeck Cc: netdev@vger.kernel.org Subject: [PATCH v2] net: phy: marvell10g: add thermal hwmon device MIME-Version: 1.0 Content-Disposition: inline Message-Id: Date: Tue, 03 Apr 2018 10:31:45 +0100 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org 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 Signed-off-by: Russell King --- v2: update to apply to net-next 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 +#include +#include #include +#include 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); +} + static int mv3310_config_init(struct phy_device *phydev) { __ETHTOOL_DECLARE_LINK_MODE_MASK(supported) = { 0, }; @@ -367,9 +545,11 @@ static struct phy_driver mv3310_drivers[] = { SUPPORTED_FIBRE | SUPPORTED_10000baseT_Full | SUPPORTED_Backplane, - .probe = mv3310_probe, .soft_reset = gen10g_no_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,