Skip to content

Commit 4007040

Browse files
fancerjonmason
authored andcommitted
ntb: idt: Alter temperature read method
In order to create a hwmon interface for the IDT PCIe-switch temperature sensor the already available reader method should be improved. Particularly we need to redesign it so one would be able to read temperature/offset values from registers of the passed types. Since IDT sensor interface provides temperature in unsigned format 0:7:1 (7 bits for real value and one for fraction) we also need to have helpers for the typical sysfs temperature data type conversion to and from this format. Even though the IDT PCIe-switch provided temperature offset got the same but signed type it can be translated by these methods too. Signed-off-by: Serge Semin <fancer.lancer@gmail.com> Signed-off-by: Jon Mason <jdmason@kudzu.us>
1 parent 906e86b commit 4007040

File tree

2 files changed

+152
-17
lines changed

2 files changed

+152
-17
lines changed

drivers/ntb/hw/idt/ntb_hw_idt.c

Lines changed: 96 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1828,23 +1828,100 @@ static int idt_ntb_peer_msg_write(struct ntb_dev *ntb, int pidx, int midx,
18281828
*=============================================================================
18291829
*/
18301830

1831+
/*
1832+
* idt_get_deg() - convert millidegree Celsius value to just degree
1833+
* @mdegC: IN - millidegree Celsius value
1834+
*
1835+
* Return: Degree corresponding to the passed millidegree value
1836+
*/
1837+
static inline s8 idt_get_deg(long mdegC)
1838+
{
1839+
return mdegC / 1000;
1840+
}
1841+
1842+
/*
1843+
* idt_get_frac() - retrieve 0/0.5 fraction of the millidegree Celsius value
1844+
* @mdegC: IN - millidegree Celsius value
1845+
*
1846+
* Return: 0/0.5 degree fraction of the passed millidegree value
1847+
*/
1848+
static inline u8 idt_get_deg_frac(long mdegC)
1849+
{
1850+
return (mdegC % 1000) >= 500 ? 5 : 0;
1851+
}
1852+
1853+
/*
1854+
* idt_get_temp_fmt() - convert millidegree Celsius value to 0:7:1 format
1855+
* @mdegC: IN - millidegree Celsius value
1856+
*
1857+
* Return: 0:7:1 format acceptable by the IDT temperature sensor
1858+
*/
1859+
static inline u8 idt_temp_get_fmt(long mdegC)
1860+
{
1861+
return (idt_get_deg(mdegC) << 1) | (idt_get_deg_frac(mdegC) ? 1 : 0);
1862+
}
1863+
1864+
/*
1865+
* idt_get_temp_sval() - convert temp sample to signed millidegree Celsius
1866+
* @data: IN - shifted to LSB 8-bits temperature sample
1867+
*
1868+
* Return: signed millidegree Celsius
1869+
*/
1870+
static inline long idt_get_temp_sval(u32 data)
1871+
{
1872+
return ((s8)data / 2) * 1000 + (data & 0x1 ? 500 : 0);
1873+
}
1874+
1875+
/*
1876+
* idt_get_temp_sval() - convert temp sample to unsigned millidegree Celsius
1877+
* @data: IN - shifted to LSB 8-bits temperature sample
1878+
*
1879+
* Return: unsigned millidegree Celsius
1880+
*/
1881+
static inline long idt_get_temp_uval(u32 data)
1882+
{
1883+
return (data / 2) * 1000 + (data & 0x1 ? 500 : 0);
1884+
}
1885+
18311886
/*
18321887
* idt_read_temp() - read temperature from chip sensor
18331888
* @ntb: NTB device context.
1834-
* @val: OUT - integer value of temperature
1835-
* @frac: OUT - fraction
1889+
* @type: IN - type of the temperature value to read
1890+
* @val: OUT - integer value of temperature in millidegree Celsius
18361891
*/
1837-
static void idt_read_temp(struct idt_ntb_dev *ndev, unsigned char *val,
1838-
unsigned char *frac)
1892+
static void idt_read_temp(struct idt_ntb_dev *ndev,
1893+
const enum idt_temp_val type, long *val)
18391894
{
18401895
u32 data;
18411896

1842-
/* Read the data from TEMP field of the TMPSTS register */
1843-
data = idt_sw_read(ndev, IDT_SW_TMPSTS);
1844-
data = GET_FIELD(TMPSTS_TEMP, data);
1845-
/* TEMP field has one fractional bit and seven integer bits */
1846-
*val = data >> 1;
1847-
*frac = ((data & 0x1) ? 5 : 0);
1897+
/* Alter the temperature field in accordance with the passed type */
1898+
switch (type) {
1899+
case IDT_TEMP_CUR:
1900+
data = GET_FIELD(TMPSTS_TEMP,
1901+
idt_sw_read(ndev, IDT_SW_TMPSTS));
1902+
break;
1903+
case IDT_TEMP_LOW:
1904+
data = GET_FIELD(TMPSTS_LTEMP,
1905+
idt_sw_read(ndev, IDT_SW_TMPSTS));
1906+
break;
1907+
case IDT_TEMP_HIGH:
1908+
data = GET_FIELD(TMPSTS_HTEMP,
1909+
idt_sw_read(ndev, IDT_SW_TMPSTS));
1910+
break;
1911+
case IDT_TEMP_OFFSET:
1912+
/* This is the only field with signed 0:7:1 format */
1913+
data = GET_FIELD(TMPADJ_OFFSET,
1914+
idt_sw_read(ndev, IDT_SW_TMPADJ));
1915+
*val = idt_get_temp_sval(data);
1916+
return;
1917+
default:
1918+
data = GET_FIELD(TMPSTS_TEMP,
1919+
idt_sw_read(ndev, IDT_SW_TMPSTS));
1920+
break;
1921+
}
1922+
1923+
/* The rest of the fields accept unsigned 0:7:1 format */
1924+
*val = idt_get_temp_uval(data);
18481925
}
18491926

18501927
/*
@@ -1860,10 +1937,10 @@ static void idt_read_temp(struct idt_ntb_dev *ndev, unsigned char *val,
18601937
*/
18611938
static void idt_temp_isr(struct idt_ntb_dev *ndev, u32 ntint_sts)
18621939
{
1863-
unsigned char val, frac;
1940+
unsigned long mdeg;
18641941

18651942
/* Read the current temperature value */
1866-
idt_read_temp(ndev, &val, &frac);
1943+
idt_read_temp(ndev, IDT_TEMP_CUR, &mdeg);
18671944

18681945
/* Read the temperature alarm to clean the alarm status out */
18691946
/*(void)idt_sw_read(ndev, IDT_SW_TMPALARM);*/
@@ -1875,7 +1952,8 @@ static void idt_temp_isr(struct idt_ntb_dev *ndev, u32 ntint_sts)
18751952
"Temp sensor IRQ detected %#08x", ntint_sts);
18761953

18771954
/* Print temperature value to log */
1878-
dev_warn(&ndev->ntb.pdev->dev, "Temperature %hhu.%hhu", val, frac);
1955+
dev_warn(&ndev->ntb.pdev->dev, "Temperature %hhd.%hhuC",
1956+
idt_get_deg(mdeg), idt_get_deg_frac(mdeg));
18791957
}
18801958

18811959
/*=============================================================================
@@ -2123,9 +2201,9 @@ static ssize_t idt_dbgfs_info_read(struct file *filp, char __user *ubuf,
21232201
size_t count, loff_t *offp)
21242202
{
21252203
struct idt_ntb_dev *ndev = filp->private_data;
2126-
unsigned char temp, frac, idx, pidx, cnt;
2204+
unsigned char idx, pidx, cnt;
2205+
unsigned long irqflags, mdeg;
21272206
ssize_t ret = 0, off = 0;
2128-
unsigned long irqflags;
21292207
enum ntb_speed speed;
21302208
enum ntb_width width;
21312209
char *strbuf;
@@ -2274,9 +2352,10 @@ static ssize_t idt_dbgfs_info_read(struct file *filp, char __user *ubuf,
22742352
off += scnprintf(strbuf + off, size - off, "\n");
22752353

22762354
/* Current temperature */
2277-
idt_read_temp(ndev, &temp, &frac);
2355+
idt_read_temp(ndev, IDT_TEMP_CUR, &mdeg);
22782356
off += scnprintf(strbuf + off, size - off,
2279-
"Switch temperature\t\t- %hhu.%hhuC\n", temp, frac);
2357+
"Switch temperature\t\t- %hhd.%hhuC\n",
2358+
idt_get_deg(mdeg), idt_get_deg_frac(mdeg));
22802359

22812360
/* Copy the buffer to the User Space */
22822361
ret = simple_read_from_buffer(ubuf, count, offp, strbuf, off);

drivers/ntb/hw/idt/ntb_hw_idt.h

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -885,13 +885,43 @@
885885
#define IDT_SWPxMSGCTL_PART_MASK 0x00000070U
886886
#define IDT_SWPxMSGCTL_PART_FLD 4
887887

888+
/*
889+
* TMPCTL register fields related constants
890+
* @IDT_TMPCTL_LTH_MASK: Low temperature threshold field mask
891+
* @IDT_TMPCTL_LTH_FLD: Low temperature threshold field offset
892+
* @IDT_TMPCTL_MTH_MASK: Middle temperature threshold field mask
893+
* @IDT_TMPCTL_MTH_FLD: Middle temperature threshold field offset
894+
* @IDT_TMPCTL_HTH_MASK: High temperature threshold field mask
895+
* @IDT_TMPCTL_HTH_FLD: High temperature threshold field offset
896+
* @IDT_TMPCTL_PDOWN: Temperature sensor power down
897+
*/
898+
#define IDT_TMPCTL_LTH_MASK 0x000000FFU
899+
#define IDT_TMPCTL_LTH_FLD 0
900+
#define IDT_TMPCTL_MTH_MASK 0x0000FF00U
901+
#define IDT_TMPCTL_MTH_FLD 8
902+
#define IDT_TMPCTL_HTH_MASK 0x00FF0000U
903+
#define IDT_TMPCTL_HTH_FLD 16
904+
#define IDT_TMPCTL_PDOWN 0x80000000U
905+
888906
/*
889907
* TMPSTS register fields related constants
890908
* @IDT_TMPSTS_TEMP_MASK: Current temperature field mask
891909
* @IDT_TMPSTS_TEMP_FLD: Current temperature field offset
892910
*/
893911
#define IDT_TMPSTS_TEMP_MASK 0x000000FFU
894912
#define IDT_TMPSTS_TEMP_FLD 0
913+
#define IDT_TMPSTS_LTEMP_MASK 0x0000FF00U
914+
#define IDT_TMPSTS_LTEMP_FLD 8
915+
#define IDT_TMPSTS_HTEMP_MASK 0x00FF0000U
916+
#define IDT_TMPSTS_HTEMP_FLD 16
917+
918+
/*
919+
* TMPADJ register fields related constants
920+
* @IDT_TMPADJ_OFFSET_MASK: Temperature value offset field mask
921+
* @IDT_TMPADJ_OFFSET_FLD: Temperature value offset field offset
922+
*/
923+
#define IDT_TMPADJ_OFFSET_MASK 0x000000FFU
924+
#define IDT_TMPADJ_OFFSET_FLD 0
895925

896926
/*
897927
* Helper macro to get/set the corresponding field value
@@ -950,6 +980,32 @@
950980
#define IDT_TRANS_ALIGN 4
951981
#define IDT_DIR_SIZE_ALIGN 1
952982

983+
/*
984+
* IDT PCIe-switch temperature sensor value limits
985+
* @IDT_TEMP_MIN_MDEG: Minimal integer value of temperature
986+
* @IDT_TEMP_MAX_MDEG: Maximal integer value of temperature
987+
* @IDT_TEMP_MIN_OFFSET:Minimal integer value of temperature offset
988+
* @IDT_TEMP_MAX_OFFSET:Maximal integer value of temperature offset
989+
*/
990+
#define IDT_TEMP_MIN_MDEG 0
991+
#define IDT_TEMP_MAX_MDEG 127500
992+
#define IDT_TEMP_MIN_OFFSET -64000
993+
#define IDT_TEMP_MAX_OFFSET 63500
994+
995+
/*
996+
* Temperature sensor values enumeration
997+
* @IDT_TEMP_CUR: Current temperature
998+
* @IDT_TEMP_LOW: Lowest historical temperature
999+
* @IDT_TEMP_HIGH: Highest historical temperature
1000+
* @IDT_TEMP_OFFSET: Current temperature offset
1001+
*/
1002+
enum idt_temp_val {
1003+
IDT_TEMP_CUR,
1004+
IDT_TEMP_LOW,
1005+
IDT_TEMP_HIGH,
1006+
IDT_TEMP_OFFSET
1007+
};
1008+
9531009
/*
9541010
* IDT Memory Windows type. Depending on the device settings, IDT supports
9551011
* Direct Address Translation MW registers and Lookup Table registers

0 commit comments

Comments
 (0)