Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  aquantia_hwmon.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0
/* HWMON driver for Aquantia PHY
 *
 * Author: Nikita Yushchenko <nikita.yoush@cogentembedded.com>
 * Author: Andrew Lunn <andrew@lunn.ch>
 * Author: Heiner Kallweit <hkallweit1@gmail.com>
 */


#include <linux/phy.h>
#include <linux/device.h>
#include <linux/ctype.h>
#include <linux/hwmon.h>

#include "aquantia.h"

#if IS_REACHABLE(CONFIG_HWMON)

static umode_t aqr_hwmon_is_visible(const void *data,
        enum hwmon_sensor_types type,
        u32 attr, int channel)
{
 if (type != hwmon_temp)
  return 0;

 switch (attr) {
 case hwmon_temp_input:
 case hwmon_temp_min_alarm:
 case hwmon_temp_max_alarm:
 case hwmon_temp_lcrit_alarm:
 case hwmon_temp_crit_alarm:
  return 0444;
 case hwmon_temp_min:
 case hwmon_temp_max:
 case hwmon_temp_lcrit:
 case hwmon_temp_crit:
  return 0644;
 default:
  return 0;
 }
}

static int aqr_hwmon_get(struct phy_device *phydev, int reg, long *value)
{
 int temp = phy_read_mmd(phydev, MDIO_MMD_VEND1, reg);

 if (temp < 0)
  return temp;

 /* 16 bit value is 2's complement with LSB = 1/256th degree Celsius */
 *value = (s16)temp * 1000 / 256;

 return 0;
}

static int aqr_hwmon_set(struct phy_device *phydev, int reg, long value)
{
 int temp;

 if (value >= 128000 || value < -128000)
  return -ERANGE;

 temp = value * 256 / 1000;

 /* temp is in s16 range and we're interested in lower 16 bits only */
 return phy_write_mmd(phydev, MDIO_MMD_VEND1, reg, (u16)temp);
}

static int aqr_hwmon_test_bit(struct phy_device *phydev, int reg, int bit)
{
 int val = phy_read_mmd(phydev, MDIO_MMD_VEND1, reg);

 if (val < 0)
  return val;

 return !!(val & bit);
}

static int aqr_hwmon_status1(struct phy_device *phydev, int bit, long *value)
{
 int val = aqr_hwmon_test_bit(phydev, VEND1_GENERAL_STAT1, bit);

 if (val < 0)
  return val;

 *value = val;

 return 0;
}

static int aqr_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 reg;

 if (type != hwmon_temp)
  return -EOPNOTSUPP;

 switch (attr) {
 case hwmon_temp_input:
  reg = aqr_hwmon_test_bit(phydev, VEND1_THERMAL_STAT2,
      VEND1_THERMAL_STAT2_VALID);
  if (reg < 0)
   return reg;
  if (!reg)
   return -EBUSY;

  return aqr_hwmon_get(phydev, VEND1_THERMAL_STAT1, value);

 case hwmon_temp_lcrit:
  return aqr_hwmon_get(phydev, VEND1_THERMAL_PROV_LOW_TEMP_FAIL,
         value);
 case hwmon_temp_min:
  return aqr_hwmon_get(phydev, VEND1_THERMAL_PROV_LOW_TEMP_WARN,
         value);
 case hwmon_temp_max:
  return aqr_hwmon_get(phydev, VEND1_THERMAL_PROV_HIGH_TEMP_WARN,
         value);
 case hwmon_temp_crit:
  return aqr_hwmon_get(phydev, VEND1_THERMAL_PROV_HIGH_TEMP_FAIL,
         value);
 case hwmon_temp_lcrit_alarm:
  return aqr_hwmon_status1(phydev,
      VEND1_GENERAL_STAT1_LOW_TEMP_FAIL,
      value);
 case hwmon_temp_min_alarm:
  return aqr_hwmon_status1(phydev,
      VEND1_GENERAL_STAT1_LOW_TEMP_WARN,
      value);
 case hwmon_temp_max_alarm:
  return aqr_hwmon_status1(phydev,
      VEND1_GENERAL_STAT1_HIGH_TEMP_WARN,
      value);
 case hwmon_temp_crit_alarm:
  return aqr_hwmon_status1(phydev,
      VEND1_GENERAL_STAT1_HIGH_TEMP_FAIL,
      value);
 default:
  return -EOPNOTSUPP;
 }
}

static int aqr_hwmon_write(struct device *dev, enum hwmon_sensor_types type,
      u32 attr, int channel, long value)
{
 struct phy_device *phydev = dev_get_drvdata(dev);

 if (type != hwmon_temp)
  return -EOPNOTSUPP;

 switch (attr) {
 case hwmon_temp_lcrit:
  return aqr_hwmon_set(phydev, VEND1_THERMAL_PROV_LOW_TEMP_FAIL,
         value);
 case hwmon_temp_min:
  return aqr_hwmon_set(phydev, VEND1_THERMAL_PROV_LOW_TEMP_WARN,
         value);
 case hwmon_temp_max:
  return aqr_hwmon_set(phydev, VEND1_THERMAL_PROV_HIGH_TEMP_WARN,
         value);
 case hwmon_temp_crit:
  return aqr_hwmon_set(phydev, VEND1_THERMAL_PROV_HIGH_TEMP_FAIL,
         value);
 default:
  return -EOPNOTSUPP;
 }
}

static const struct hwmon_ops aqr_hwmon_ops = {
 .is_visible = aqr_hwmon_is_visible,
 .read = aqr_hwmon_read,
 .write = aqr_hwmon_write,
};

static const struct hwmon_channel_info * const aqr_hwmon_info[] = {
 HWMON_CHANNEL_INFO(chip, HWMON_C_REGISTER_TZ),
 HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT |
      HWMON_T_MAX | HWMON_T_MIN |
      HWMON_T_MAX_ALARM | HWMON_T_MIN_ALARM |
      HWMON_T_CRIT | HWMON_T_LCRIT |
      HWMON_T_CRIT_ALARM | HWMON_T_LCRIT_ALARM),
 NULL,
};

static const struct hwmon_chip_info aqr_hwmon_chip_info = {
 .ops = &aqr_hwmon_ops,
 .info = aqr_hwmon_info,
};

int aqr_hwmon_probe(struct phy_device *phydev)
{
 struct device *dev = &phydev->mdio.dev;
 struct device *hwmon_dev;
 char *hwmon_name;
 int i, j;

 hwmon_name = devm_kstrdup(dev, dev_name(dev), GFP_KERNEL);
 if (!hwmon_name)
  return -ENOMEM;

 for (i = j = 0; hwmon_name[i]; i++) {
  if (isalnum(hwmon_name[i])) {
   if (i != j)
    hwmon_name[j] = hwmon_name[i];
   j++;
  }
 }
 hwmon_name[j] = '\0';

 hwmon_dev = devm_hwmon_device_register_with_info(dev, hwmon_name,
     phydev, &aqr_hwmon_chip_info, NULL);

 return PTR_ERR_OR_ZERO(hwmon_dev);
}

#endif

Messung V0.5
C=99 H=99 G=98

¤ Dauer der Verarbeitung: 0.1 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge