diff options
-rw-r--r-- | drivers/ntb/hw/idt/Kconfig | 1 | ||||
-rw-r--r-- | drivers/ntb/hw/idt/ntb_hw_idt.c | 182 | ||||
-rw-r--r-- | drivers/ntb/hw/idt/ntb_hw_idt.h | 24 |
3 files changed, 206 insertions, 1 deletions
diff --git a/drivers/ntb/hw/idt/Kconfig b/drivers/ntb/hw/idt/Kconfig index b360e5613b9f..2ed147368fa8 100644 --- a/drivers/ntb/hw/idt/Kconfig +++ b/drivers/ntb/hw/idt/Kconfig | |||
@@ -1,6 +1,7 @@ | |||
1 | config NTB_IDT | 1 | config NTB_IDT |
2 | tristate "IDT PCIe-switch Non-Transparent Bridge support" | 2 | tristate "IDT PCIe-switch Non-Transparent Bridge support" |
3 | depends on PCI | 3 | depends on PCI |
4 | select HWMON | ||
4 | help | 5 | help |
5 | This driver supports NTB of cappable IDT PCIe-switches. | 6 | This driver supports NTB of cappable IDT PCIe-switches. |
6 | 7 | ||
diff --git a/drivers/ntb/hw/idt/ntb_hw_idt.c b/drivers/ntb/hw/idt/ntb_hw_idt.c index adb71f7c1043..19425a2c60cd 100644 --- a/drivers/ntb/hw/idt/ntb_hw_idt.c +++ b/drivers/ntb/hw/idt/ntb_hw_idt.c | |||
@@ -49,11 +49,14 @@ | |||
49 | #include <linux/init.h> | 49 | #include <linux/init.h> |
50 | #include <linux/interrupt.h> | 50 | #include <linux/interrupt.h> |
51 | #include <linux/spinlock.h> | 51 | #include <linux/spinlock.h> |
52 | #include <linux/mutex.h> | ||
52 | #include <linux/pci.h> | 53 | #include <linux/pci.h> |
53 | #include <linux/aer.h> | 54 | #include <linux/aer.h> |
54 | #include <linux/slab.h> | 55 | #include <linux/slab.h> |
55 | #include <linux/list.h> | 56 | #include <linux/list.h> |
56 | #include <linux/debugfs.h> | 57 | #include <linux/debugfs.h> |
58 | #include <linux/hwmon.h> | ||
59 | #include <linux/hwmon-sysfs.h> | ||
57 | #include <linux/ntb.h> | 60 | #include <linux/ntb.h> |
58 | 61 | ||
59 | #include "ntb_hw_idt.h" | 62 | #include "ntb_hw_idt.h" |
@@ -1925,6 +1928,153 @@ static void idt_read_temp(struct idt_ntb_dev *ndev, | |||
1925 | } | 1928 | } |
1926 | 1929 | ||
1927 | /* | 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 | |||
2077 | /* | ||
1928 | * idt_temp_isr() - temperature sensor alarm events ISR | 2078 | * idt_temp_isr() - temperature sensor alarm events ISR |
1929 | * @ndev: IDT NTB hardware driver descriptor | 2079 | * @ndev: IDT NTB hardware driver descriptor |
1930 | * @ntint_sts: NT-function interrupt status | 2080 | * @ntint_sts: NT-function interrupt status |
@@ -1956,6 +2106,35 @@ static void idt_temp_isr(struct idt_ntb_dev *ndev, u32 ntint_sts) | |||
1956 | idt_get_deg(mdeg), idt_get_deg_frac(mdeg)); | 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 | * 8. ISRs related operations | 2139 | * 8. ISRs related operations |
1961 | * | 2140 | * |
@@ -2650,6 +2829,9 @@ static int idt_pci_probe(struct pci_dev *pdev, | |||
2650 | /* Initialize Messaging subsystem */ | 2829 | /* Initialize Messaging subsystem */ |
2651 | idt_init_msg(ndev); | 2830 | idt_init_msg(ndev); |
2652 | 2831 | ||
2832 | /* Initialize hwmon interface */ | ||
2833 | idt_init_temp(ndev); | ||
2834 | |||
2653 | /* Initialize IDT interrupts handler */ | 2835 | /* Initialize IDT interrupts handler */ |
2654 | ret = idt_init_isr(ndev); | 2836 | ret = idt_init_isr(ndev); |
2655 | if (ret != 0) | 2837 | if (ret != 0) |
diff --git a/drivers/ntb/hw/idt/ntb_hw_idt.h b/drivers/ntb/hw/idt/ntb_hw_idt.h index 9dfd6b11a621..032f81cb4d44 100644 --- a/drivers/ntb/hw/idt/ntb_hw_idt.h +++ b/drivers/ntb/hw/idt/ntb_hw_idt.h | |||
@@ -47,9 +47,9 @@ | |||
47 | #include <linux/pci_ids.h> | 47 | #include <linux/pci_ids.h> |
48 | #include <linux/interrupt.h> | 48 | #include <linux/interrupt.h> |
49 | #include <linux/spinlock.h> | 49 | #include <linux/spinlock.h> |
50 | #include <linux/mutex.h> | ||
50 | #include <linux/ntb.h> | 51 | #include <linux/ntb.h> |
51 | 52 | ||
52 | |||
53 | /* | 53 | /* |
54 | * Macro is used to create the struct pci_device_id that matches | 54 | * Macro is used to create the struct pci_device_id that matches |
55 | * the supported IDT PCIe-switches | 55 | * the supported IDT PCIe-switches |
@@ -907,6 +907,10 @@ | |||
907 | * TMPSTS register fields related constants | 907 | * TMPSTS register fields related constants |
908 | * @IDT_TMPSTS_TEMP_MASK: Current temperature field mask | 908 | * @IDT_TMPSTS_TEMP_MASK: Current temperature field mask |
909 | * @IDT_TMPSTS_TEMP_FLD: Current temperature field offset | 909 | * @IDT_TMPSTS_TEMP_FLD: Current temperature field offset |
910 | * @IDT_TMPSTS_LTEMP_MASK: Lowest temperature field mask | ||
911 | * @IDT_TMPSTS_LTEMP_FLD: Lowest temperature field offset | ||
912 | * @IDT_TMPSTS_HTEMP_MASK: Highest temperature field mask | ||
913 | * @IDT_TMPSTS_HTEMP_FLD: Highest temperature field offset | ||
910 | */ | 914 | */ |
911 | #define IDT_TMPSTS_TEMP_MASK 0x000000FFU | 915 | #define IDT_TMPSTS_TEMP_MASK 0x000000FFU |
912 | #define IDT_TMPSTS_TEMP_FLD 0 | 916 | #define IDT_TMPSTS_TEMP_FLD 0 |
@@ -916,6 +920,20 @@ | |||
916 | #define IDT_TMPSTS_HTEMP_FLD 16 | 920 | #define IDT_TMPSTS_HTEMP_FLD 16 |
917 | 921 | ||
918 | /* | 922 | /* |
923 | * TMPALARM register fields related constants | ||
924 | * @IDT_TMPALARM_LTEMP_MASK: Lowest temperature field mask | ||
925 | * @IDT_TMPALARM_LTEMP_FLD: Lowest temperature field offset | ||
926 | * @IDT_TMPALARM_HTEMP_MASK: Highest temperature field mask | ||
927 | * @IDT_TMPALARM_HTEMP_FLD: Highest temperature field offset | ||
928 | * @IDT_TMPALARM_IRQ_MASK: Alarm IRQ status mask | ||
929 | */ | ||
930 | #define IDT_TMPALARM_LTEMP_MASK 0x0000FF00U | ||
931 | #define IDT_TMPALARM_LTEMP_FLD 8 | ||
932 | #define IDT_TMPALARM_HTEMP_MASK 0x00FF0000U | ||
933 | #define IDT_TMPALARM_HTEMP_FLD 16 | ||
934 | #define IDT_TMPALARM_IRQ_MASK 0x3F000000U | ||
935 | |||
936 | /* | ||
919 | * TMPADJ register fields related constants | 937 | * TMPADJ register fields related constants |
920 | * @IDT_TMPADJ_OFFSET_MASK: Temperature value offset field mask | 938 | * @IDT_TMPADJ_OFFSET_MASK: Temperature value offset field mask |
921 | * @IDT_TMPADJ_OFFSET_FLD: Temperature value offset field offset | 939 | * @IDT_TMPADJ_OFFSET_FLD: Temperature value offset field offset |
@@ -1100,6 +1118,8 @@ struct idt_ntb_peer { | |||
1100 | * @msg_mask_lock: Message mask register lock | 1118 | * @msg_mask_lock: Message mask register lock |
1101 | * @gasa_lock: GASA registers access lock | 1119 | * @gasa_lock: GASA registers access lock |
1102 | * | 1120 | * |
1121 | * @hwmon_mtx: Temperature sensor interface update mutex | ||
1122 | * | ||
1103 | * @dbgfs_info: DebugFS info node | 1123 | * @dbgfs_info: DebugFS info node |
1104 | */ | 1124 | */ |
1105 | struct idt_ntb_dev { | 1125 | struct idt_ntb_dev { |
@@ -1127,6 +1147,8 @@ struct idt_ntb_dev { | |||
1127 | spinlock_t msg_mask_lock; | 1147 | spinlock_t msg_mask_lock; |
1128 | spinlock_t gasa_lock; | 1148 | spinlock_t gasa_lock; |
1129 | 1149 | ||
1150 | struct mutex hwmon_mtx; | ||
1151 | |||
1130 | struct dentry *dbgfs_info; | 1152 | struct dentry *dbgfs_info; |
1131 | }; | 1153 | }; |
1132 | #define to_ndev_ntb(__ntb) container_of(__ntb, struct idt_ntb_dev, ntb) | 1154 | #define to_ndev_ntb(__ntb) container_of(__ntb, struct idt_ntb_dev, ntb) |