Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* HWMON driver for Aquantia PHY
0003  *
0004  * Author: Nikita Yushchenko <nikita.yoush@cogentembedded.com>
0005  * Author: Andrew Lunn <andrew@lunn.ch>
0006  * Author: Heiner Kallweit <hkallweit1@gmail.com>
0007  */
0008 
0009 #include <linux/phy.h>
0010 #include <linux/device.h>
0011 #include <linux/ctype.h>
0012 #include <linux/hwmon.h>
0013 
0014 #include "aquantia.h"
0015 
0016 /* Vendor specific 1, MDIO_MMD_VEND2 */
0017 #define VEND1_THERMAL_PROV_HIGH_TEMP_FAIL   0xc421
0018 #define VEND1_THERMAL_PROV_LOW_TEMP_FAIL    0xc422
0019 #define VEND1_THERMAL_PROV_HIGH_TEMP_WARN   0xc423
0020 #define VEND1_THERMAL_PROV_LOW_TEMP_WARN    0xc424
0021 #define VEND1_THERMAL_STAT1         0xc820
0022 #define VEND1_THERMAL_STAT2         0xc821
0023 #define VEND1_THERMAL_STAT2_VALID       BIT(0)
0024 #define VEND1_GENERAL_STAT1         0xc830
0025 #define VEND1_GENERAL_STAT1_HIGH_TEMP_FAIL  BIT(14)
0026 #define VEND1_GENERAL_STAT1_LOW_TEMP_FAIL   BIT(13)
0027 #define VEND1_GENERAL_STAT1_HIGH_TEMP_WARN  BIT(12)
0028 #define VEND1_GENERAL_STAT1_LOW_TEMP_WARN   BIT(11)
0029 
0030 #if IS_REACHABLE(CONFIG_HWMON)
0031 
0032 static umode_t aqr_hwmon_is_visible(const void *data,
0033                     enum hwmon_sensor_types type,
0034                     u32 attr, int channel)
0035 {
0036     if (type != hwmon_temp)
0037         return 0;
0038 
0039     switch (attr) {
0040     case hwmon_temp_input:
0041     case hwmon_temp_min_alarm:
0042     case hwmon_temp_max_alarm:
0043     case hwmon_temp_lcrit_alarm:
0044     case hwmon_temp_crit_alarm:
0045         return 0444;
0046     case hwmon_temp_min:
0047     case hwmon_temp_max:
0048     case hwmon_temp_lcrit:
0049     case hwmon_temp_crit:
0050         return 0644;
0051     default:
0052         return 0;
0053     }
0054 }
0055 
0056 static int aqr_hwmon_get(struct phy_device *phydev, int reg, long *value)
0057 {
0058     int temp = phy_read_mmd(phydev, MDIO_MMD_VEND1, reg);
0059 
0060     if (temp < 0)
0061         return temp;
0062 
0063     /* 16 bit value is 2's complement with LSB = 1/256th degree Celsius */
0064     *value = (s16)temp * 1000 / 256;
0065 
0066     return 0;
0067 }
0068 
0069 static int aqr_hwmon_set(struct phy_device *phydev, int reg, long value)
0070 {
0071     int temp;
0072 
0073     if (value >= 128000 || value < -128000)
0074         return -ERANGE;
0075 
0076     temp = value * 256 / 1000;
0077 
0078     /* temp is in s16 range and we're interested in lower 16 bits only */
0079     return phy_write_mmd(phydev, MDIO_MMD_VEND1, reg, (u16)temp);
0080 }
0081 
0082 static int aqr_hwmon_test_bit(struct phy_device *phydev, int reg, int bit)
0083 {
0084     int val = phy_read_mmd(phydev, MDIO_MMD_VEND1, reg);
0085 
0086     if (val < 0)
0087         return val;
0088 
0089     return !!(val & bit);
0090 }
0091 
0092 static int aqr_hwmon_status1(struct phy_device *phydev, int bit, long *value)
0093 {
0094     int val = aqr_hwmon_test_bit(phydev, VEND1_GENERAL_STAT1, bit);
0095 
0096     if (val < 0)
0097         return val;
0098 
0099     *value = val;
0100 
0101     return 0;
0102 }
0103 
0104 static int aqr_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
0105               u32 attr, int channel, long *value)
0106 {
0107     struct phy_device *phydev = dev_get_drvdata(dev);
0108     int reg;
0109 
0110     if (type != hwmon_temp)
0111         return -EOPNOTSUPP;
0112 
0113     switch (attr) {
0114     case hwmon_temp_input:
0115         reg = aqr_hwmon_test_bit(phydev, VEND1_THERMAL_STAT2,
0116                      VEND1_THERMAL_STAT2_VALID);
0117         if (reg < 0)
0118             return reg;
0119         if (!reg)
0120             return -EBUSY;
0121 
0122         return aqr_hwmon_get(phydev, VEND1_THERMAL_STAT1, value);
0123 
0124     case hwmon_temp_lcrit:
0125         return aqr_hwmon_get(phydev, VEND1_THERMAL_PROV_LOW_TEMP_FAIL,
0126                      value);
0127     case hwmon_temp_min:
0128         return aqr_hwmon_get(phydev, VEND1_THERMAL_PROV_LOW_TEMP_WARN,
0129                      value);
0130     case hwmon_temp_max:
0131         return aqr_hwmon_get(phydev, VEND1_THERMAL_PROV_HIGH_TEMP_WARN,
0132                      value);
0133     case hwmon_temp_crit:
0134         return aqr_hwmon_get(phydev, VEND1_THERMAL_PROV_HIGH_TEMP_FAIL,
0135                      value);
0136     case hwmon_temp_lcrit_alarm:
0137         return aqr_hwmon_status1(phydev,
0138                      VEND1_GENERAL_STAT1_LOW_TEMP_FAIL,
0139                      value);
0140     case hwmon_temp_min_alarm:
0141         return aqr_hwmon_status1(phydev,
0142                      VEND1_GENERAL_STAT1_LOW_TEMP_WARN,
0143                      value);
0144     case hwmon_temp_max_alarm:
0145         return aqr_hwmon_status1(phydev,
0146                      VEND1_GENERAL_STAT1_HIGH_TEMP_WARN,
0147                      value);
0148     case hwmon_temp_crit_alarm:
0149         return aqr_hwmon_status1(phydev,
0150                      VEND1_GENERAL_STAT1_HIGH_TEMP_FAIL,
0151                      value);
0152     default:
0153         return -EOPNOTSUPP;
0154     }
0155 }
0156 
0157 static int aqr_hwmon_write(struct device *dev, enum hwmon_sensor_types type,
0158                u32 attr, int channel, long value)
0159 {
0160     struct phy_device *phydev = dev_get_drvdata(dev);
0161 
0162     if (type != hwmon_temp)
0163         return -EOPNOTSUPP;
0164 
0165     switch (attr) {
0166     case hwmon_temp_lcrit:
0167         return aqr_hwmon_set(phydev, VEND1_THERMAL_PROV_LOW_TEMP_FAIL,
0168                      value);
0169     case hwmon_temp_min:
0170         return aqr_hwmon_set(phydev, VEND1_THERMAL_PROV_LOW_TEMP_WARN,
0171                      value);
0172     case hwmon_temp_max:
0173         return aqr_hwmon_set(phydev, VEND1_THERMAL_PROV_HIGH_TEMP_WARN,
0174                      value);
0175     case hwmon_temp_crit:
0176         return aqr_hwmon_set(phydev, VEND1_THERMAL_PROV_HIGH_TEMP_FAIL,
0177                      value);
0178     default:
0179         return -EOPNOTSUPP;
0180     }
0181 }
0182 
0183 static const struct hwmon_ops aqr_hwmon_ops = {
0184     .is_visible = aqr_hwmon_is_visible,
0185     .read = aqr_hwmon_read,
0186     .write = aqr_hwmon_write,
0187 };
0188 
0189 static u32 aqr_hwmon_chip_config[] = {
0190     HWMON_C_REGISTER_TZ,
0191     0,
0192 };
0193 
0194 static const struct hwmon_channel_info aqr_hwmon_chip = {
0195     .type = hwmon_chip,
0196     .config = aqr_hwmon_chip_config,
0197 };
0198 
0199 static u32 aqr_hwmon_temp_config[] = {
0200     HWMON_T_INPUT |
0201     HWMON_T_MAX | HWMON_T_MIN |
0202     HWMON_T_MAX_ALARM | HWMON_T_MIN_ALARM |
0203     HWMON_T_CRIT | HWMON_T_LCRIT |
0204     HWMON_T_CRIT_ALARM | HWMON_T_LCRIT_ALARM,
0205     0,
0206 };
0207 
0208 static const struct hwmon_channel_info aqr_hwmon_temp = {
0209     .type = hwmon_temp,
0210     .config = aqr_hwmon_temp_config,
0211 };
0212 
0213 static const struct hwmon_channel_info *aqr_hwmon_info[] = {
0214     &aqr_hwmon_chip,
0215     &aqr_hwmon_temp,
0216     NULL,
0217 };
0218 
0219 static const struct hwmon_chip_info aqr_hwmon_chip_info = {
0220     .ops = &aqr_hwmon_ops,
0221     .info = aqr_hwmon_info,
0222 };
0223 
0224 int aqr_hwmon_probe(struct phy_device *phydev)
0225 {
0226     struct device *dev = &phydev->mdio.dev;
0227     struct device *hwmon_dev;
0228     char *hwmon_name;
0229     int i, j;
0230 
0231     hwmon_name = devm_kstrdup(dev, dev_name(dev), GFP_KERNEL);
0232     if (!hwmon_name)
0233         return -ENOMEM;
0234 
0235     for (i = j = 0; hwmon_name[i]; i++) {
0236         if (isalnum(hwmon_name[i])) {
0237             if (i != j)
0238                 hwmon_name[j] = hwmon_name[i];
0239             j++;
0240         }
0241     }
0242     hwmon_name[j] = '\0';
0243 
0244     hwmon_dev = devm_hwmon_device_register_with_info(dev, hwmon_name,
0245                     phydev, &aqr_hwmon_chip_info, NULL);
0246 
0247     return PTR_ERR_OR_ZERO(hwmon_dev);
0248 }
0249 
0250 #endif