|
49 | 49 | #include <linux/init.h>
|
50 | 50 | #include <linux/interrupt.h>
|
51 | 51 | #include <linux/spinlock.h>
|
| 52 | +#include <linux/mutex.h> |
52 | 53 | #include <linux/pci.h>
|
53 | 54 | #include <linux/aer.h>
|
54 | 55 | #include <linux/slab.h>
|
55 | 56 | #include <linux/list.h>
|
56 | 57 | #include <linux/debugfs.h>
|
| 58 | +#include <linux/hwmon.h> |
| 59 | +#include <linux/hwmon-sysfs.h> |
57 | 60 | #include <linux/ntb.h>
|
58 | 61 |
|
59 | 62 | #include "ntb_hw_idt.h"
|
@@ -1924,6 +1927,153 @@ static void idt_read_temp(struct idt_ntb_dev *ndev,
|
1924 | 1927 | *val = idt_get_temp_uval(data);
|
1925 | 1928 | }
|
1926 | 1929 |
|
| 1930 | +/* |
| 1931 | + * idt_write_temp() - write temperature to the chip sensor register |
| 1932 | + * @ntb: NTB device context. |
| 1933 | + * @type: IN - type of the temperature value to change |
| 1934 | + * @val: IN - integer value of temperature in millidegree Celsius |
| 1935 | + */ |
| 1936 | +static void idt_write_temp(struct idt_ntb_dev *ndev, |
| 1937 | + const enum idt_temp_val type, const long val) |
| 1938 | +{ |
| 1939 | + unsigned int reg; |
| 1940 | + u32 data; |
| 1941 | + u8 fmt; |
| 1942 | + |
| 1943 | + /* Retrieve the properly formatted temperature value */ |
| 1944 | + fmt = idt_temp_get_fmt(val); |
| 1945 | + |
| 1946 | + mutex_lock(&ndev->hwmon_mtx); |
| 1947 | + switch (type) { |
| 1948 | + case IDT_TEMP_LOW: |
| 1949 | + reg = IDT_SW_TMPALARM; |
| 1950 | + data = SET_FIELD(TMPALARM_LTEMP, idt_sw_read(ndev, reg), fmt) & |
| 1951 | + ~IDT_TMPALARM_IRQ_MASK; |
| 1952 | + break; |
| 1953 | + case IDT_TEMP_HIGH: |
| 1954 | + reg = IDT_SW_TMPALARM; |
| 1955 | + data = SET_FIELD(TMPALARM_HTEMP, idt_sw_read(ndev, reg), fmt) & |
| 1956 | + ~IDT_TMPALARM_IRQ_MASK; |
| 1957 | + break; |
| 1958 | + case IDT_TEMP_OFFSET: |
| 1959 | + reg = IDT_SW_TMPADJ; |
| 1960 | + data = SET_FIELD(TMPADJ_OFFSET, idt_sw_read(ndev, reg), fmt); |
| 1961 | + break; |
| 1962 | + default: |
| 1963 | + goto inval_spin_unlock; |
| 1964 | + } |
| 1965 | + |
| 1966 | + idt_sw_write(ndev, reg, data); |
| 1967 | + |
| 1968 | +inval_spin_unlock: |
| 1969 | + mutex_unlock(&ndev->hwmon_mtx); |
| 1970 | +} |
| 1971 | + |
| 1972 | +/* |
| 1973 | + * idt_sysfs_show_temp() - printout corresponding temperature value |
| 1974 | + * @dev: Pointer to the NTB device structure |
| 1975 | + * @da: Sensor device attribute structure |
| 1976 | + * @buf: Buffer to print temperature out |
| 1977 | + * |
| 1978 | + * Return: Number of written symbols or negative error |
| 1979 | + */ |
| 1980 | +static ssize_t idt_sysfs_show_temp(struct device *dev, |
| 1981 | + struct device_attribute *da, char *buf) |
| 1982 | +{ |
| 1983 | + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); |
| 1984 | + struct idt_ntb_dev *ndev = dev_get_drvdata(dev); |
| 1985 | + enum idt_temp_val type = attr->index; |
| 1986 | + long mdeg; |
| 1987 | + |
| 1988 | + idt_read_temp(ndev, type, &mdeg); |
| 1989 | + return sprintf(buf, "%ld\n", mdeg); |
| 1990 | +} |
| 1991 | + |
| 1992 | +/* |
| 1993 | + * idt_sysfs_set_temp() - set corresponding temperature value |
| 1994 | + * @dev: Pointer to the NTB device structure |
| 1995 | + * @da: Sensor device attribute structure |
| 1996 | + * @buf: Buffer to print temperature out |
| 1997 | + * @count: Size of the passed buffer |
| 1998 | + * |
| 1999 | + * Return: Number of written symbols or negative error |
| 2000 | + */ |
| 2001 | +static ssize_t idt_sysfs_set_temp(struct device *dev, |
| 2002 | + struct device_attribute *da, const char *buf, |
| 2003 | + size_t count) |
| 2004 | +{ |
| 2005 | + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); |
| 2006 | + struct idt_ntb_dev *ndev = dev_get_drvdata(dev); |
| 2007 | + enum idt_temp_val type = attr->index; |
| 2008 | + long mdeg; |
| 2009 | + int ret; |
| 2010 | + |
| 2011 | + ret = kstrtol(buf, 10, &mdeg); |
| 2012 | + if (ret) |
| 2013 | + return ret; |
| 2014 | + |
| 2015 | + /* Clamp the passed value in accordance with the type */ |
| 2016 | + if (type == IDT_TEMP_OFFSET) |
| 2017 | + mdeg = clamp_val(mdeg, IDT_TEMP_MIN_OFFSET, |
| 2018 | + IDT_TEMP_MAX_OFFSET); |
| 2019 | + else |
| 2020 | + mdeg = clamp_val(mdeg, IDT_TEMP_MIN_MDEG, IDT_TEMP_MAX_MDEG); |
| 2021 | + |
| 2022 | + idt_write_temp(ndev, type, mdeg); |
| 2023 | + |
| 2024 | + return count; |
| 2025 | +} |
| 2026 | + |
| 2027 | +/* |
| 2028 | + * idt_sysfs_reset_hist() - reset temperature history |
| 2029 | + * @dev: Pointer to the NTB device structure |
| 2030 | + * @da: Sensor device attribute structure |
| 2031 | + * @buf: Buffer to print temperature out |
| 2032 | + * @count: Size of the passed buffer |
| 2033 | + * |
| 2034 | + * Return: Number of written symbols or negative error |
| 2035 | + */ |
| 2036 | +static ssize_t idt_sysfs_reset_hist(struct device *dev, |
| 2037 | + struct device_attribute *da, |
| 2038 | + const char *buf, size_t count) |
| 2039 | +{ |
| 2040 | + struct idt_ntb_dev *ndev = dev_get_drvdata(dev); |
| 2041 | + |
| 2042 | + /* Just set the maximal value to the lowest temperature field and |
| 2043 | + * minimal value to the highest temperature field |
| 2044 | + */ |
| 2045 | + idt_write_temp(ndev, IDT_TEMP_LOW, IDT_TEMP_MAX_MDEG); |
| 2046 | + idt_write_temp(ndev, IDT_TEMP_HIGH, IDT_TEMP_MIN_MDEG); |
| 2047 | + |
| 2048 | + return count; |
| 2049 | +} |
| 2050 | + |
| 2051 | +/* |
| 2052 | + * Hwmon IDT sysfs attributes |
| 2053 | + */ |
| 2054 | +static SENSOR_DEVICE_ATTR(temp1_input, 0444, idt_sysfs_show_temp, NULL, |
| 2055 | + IDT_TEMP_CUR); |
| 2056 | +static SENSOR_DEVICE_ATTR(temp1_lowest, 0444, idt_sysfs_show_temp, NULL, |
| 2057 | + IDT_TEMP_LOW); |
| 2058 | +static SENSOR_DEVICE_ATTR(temp1_highest, 0444, idt_sysfs_show_temp, NULL, |
| 2059 | + IDT_TEMP_HIGH); |
| 2060 | +static SENSOR_DEVICE_ATTR(temp1_offset, 0644, idt_sysfs_show_temp, |
| 2061 | + idt_sysfs_set_temp, IDT_TEMP_OFFSET); |
| 2062 | +static DEVICE_ATTR(temp1_reset_history, 0200, NULL, idt_sysfs_reset_hist); |
| 2063 | + |
| 2064 | +/* |
| 2065 | + * Hwmon IDT sysfs attributes group |
| 2066 | + */ |
| 2067 | +static struct attribute *idt_temp_attrs[] = { |
| 2068 | + &sensor_dev_attr_temp1_input.dev_attr.attr, |
| 2069 | + &sensor_dev_attr_temp1_lowest.dev_attr.attr, |
| 2070 | + &sensor_dev_attr_temp1_highest.dev_attr.attr, |
| 2071 | + &sensor_dev_attr_temp1_offset.dev_attr.attr, |
| 2072 | + &dev_attr_temp1_reset_history.attr, |
| 2073 | + NULL |
| 2074 | +}; |
| 2075 | +ATTRIBUTE_GROUPS(idt_temp); |
| 2076 | + |
1927 | 2077 | /*
|
1928 | 2078 | * idt_temp_isr() - temperature sensor alarm events ISR
|
1929 | 2079 | * @ndev: IDT NTB hardware driver descriptor
|
@@ -1956,6 +2106,35 @@ static void idt_temp_isr(struct idt_ntb_dev *ndev, u32 ntint_sts)
|
1956 | 2106 | idt_get_deg(mdeg), idt_get_deg_frac(mdeg));
|
1957 | 2107 | }
|
1958 | 2108 |
|
| 2109 | +/* |
| 2110 | + * idt_init_temp() - initialize temperature sensor interface |
| 2111 | + * @ndev: IDT NTB hardware driver descriptor |
| 2112 | + * |
| 2113 | + * Simple sensor initializarion method is responsible for device switching |
| 2114 | + * on and resource management based hwmon interface registration. Note, that |
| 2115 | + * since the device is shared we won't disable it on remove, but leave it |
| 2116 | + * working until the system is powered off. |
| 2117 | + */ |
| 2118 | +static void idt_init_temp(struct idt_ntb_dev *ndev) |
| 2119 | +{ |
| 2120 | + struct device *hwmon; |
| 2121 | + |
| 2122 | + /* Enable sensor if it hasn't been already */ |
| 2123 | + idt_sw_write(ndev, IDT_SW_TMPCTL, 0x0); |
| 2124 | + |
| 2125 | + /* Initialize hwmon interface fields */ |
| 2126 | + mutex_init(&ndev->hwmon_mtx); |
| 2127 | + |
| 2128 | + hwmon = devm_hwmon_device_register_with_groups(&ndev->ntb.pdev->dev, |
| 2129 | + ndev->swcfg->name, ndev, idt_temp_groups); |
| 2130 | + if (IS_ERR(hwmon)) { |
| 2131 | + dev_err(&ndev->ntb.pdev->dev, "Couldn't create hwmon device"); |
| 2132 | + return; |
| 2133 | + } |
| 2134 | + |
| 2135 | + dev_dbg(&ndev->ntb.pdev->dev, "Temperature HWmon interface registered"); |
| 2136 | +} |
| 2137 | + |
1959 | 2138 | /*=============================================================================
|
1960 | 2139 | * 8. ISRs related operations
|
1961 | 2140 | *
|
@@ -2650,6 +2829,9 @@ static int idt_pci_probe(struct pci_dev *pdev,
|
2650 | 2829 | /* Initialize Messaging subsystem */
|
2651 | 2830 | idt_init_msg(ndev);
|
2652 | 2831 |
|
| 2832 | + /* Initialize hwmon interface */ |
| 2833 | + idt_init_temp(ndev); |
| 2834 | + |
2653 | 2835 | /* Initialize IDT interrupts handler */
|
2654 | 2836 | ret = idt_init_isr(ndev);
|
2655 | 2837 | if (ret != 0)
|
|
0 commit comments