Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
cdcaeceb
Commit
cdcaeceb
authored
Dec 04, 2012
by
Guenter Roeck
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
hwmon: (nct6775) Add support for automatic fan control
Signed-off-by:
Guenter Roeck
<
linux@roeck-us.net
>
parent
77eb5b37
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
1161 additions
and
7 deletions
+1161
-7
Documentation/hwmon/nct6775
Documentation/hwmon/nct6775
+69
-0
drivers/hwmon/nct6775.c
drivers/hwmon/nct6775.c
+1092
-7
No files found.
Documentation/hwmon/nct6775
View file @
cdcaeceb
...
...
@@ -87,6 +87,75 @@ pwm[1-5]_mode - controls if output is PWM or DC level
* 0 DC output
* 1 PWM output
Common fan control attributes
-----------------------------
pwm[1-5]_temp_sel Temperature source. Value is temperature sensor index.
For example, select '1' for temp1_input.
Thermal Cruise mode (2)
-----------------------
If the temperature is in the range defined by:
pwm[1-5]_target_temp Target temperature, unit millidegree Celsius
(range 0 - 127000)
pwm[1-5]_temp_tolerance
Target temperature tolerance, unit millidegree Celsius
there are no changes to fan speed. Once the temperature leaves the interval, fan
speed increases (if temperature is higher that desired) or decreases (if
temperature is lower than desired), using the following limits and time
intervals.
pwm[1-5]_start fan pwm start value (range 1 - 255), to start fan
when the temperature is above defined range.
pwm[1-5]_floor lowest fan pwm (range 0 - 255) if temperature is below
the defined range. If set to 0, the fan is expected to
stop if the temperature is below the defined range.
pwm[1-5]_step_up_time milliseconds before fan speed is increased
pwm[1-5]_step_down_time milliseconds before fan speed is decreased
pwm[1-5]_stop_time how many milliseconds must elapse to switch
corresponding fan off (when the temperature was below
defined range).
Speed Cruise mode (3)
---------------------
This modes tries to keep the fan speed constant.
fan[1-5]_target Target fan speed
fan[1-5]_tolerance
Target speed tolerance
Untested; use at your own risk.
Smart Fan IV mode (5)
---------------------
This mode offers multiple slopes to control the fan speed. The slopes can be
controlled by setting the pwm and temperature attributes. When the temperature
rises, the chip will calculate the DC/PWM output based on the current slope.
There are up to seven data points depending on the chip type. Subsequent data
points should be set to higher temperatures and higher pwm values to achieve
higher fan speeds with increasing temperature. The last data point reflects
critical temperature mode, in which the fans should run at full speed.
pwm[1-5]_auto_point[1-7]_pwm
pwm value to be set if temperature reaches matching
temperature range.
pwm[1-5]_auto_point[1-7]_temp
Temperature over which the matching pwm is enabled.
pwm[1-5]_temp_tolerance
Temperature tolerance, unit millidegree Celsius
pwm[1-5]_crit_temp_tolerance
Temperature tolerance for critical temperature,
unit millidegree Celsius
pwm[1-5]_step_up_time milliseconds before fan speed is increased
pwm[1-5]_step_down_time milliseconds before fan speed is decreased
Usage Notes
-----------
...
...
drivers/hwmon/nct6775.c
View file @
cdcaeceb
...
...
@@ -215,8 +215,23 @@ static const u8 NCT6775_CR_CASEOPEN_CLR_MASK[] = { 0x20, 0x01 };
static
const
u8
NCT6775_REG_PWM_MODE
[]
=
{
0x04
,
0x04
,
0x12
};
static
const
u8
NCT6775_PWM_MODE_MASK
[]
=
{
0x01
,
0x02
,
0x01
};
static
const
u16
NCT6775_REG_FAN_MODE
[]
=
{
0x102
,
0x202
,
0x302
,
0x802
,
0x902
};
/* Advanced Fan control, some values are common for all fans */
static
const
u16
NCT6775_REG_TARGET
[]
=
{
0x101
,
0x201
,
0x301
,
0x801
,
0x901
};
static
const
u16
NCT6775_REG_FAN_MODE
[]
=
{
0x102
,
0x202
,
0x302
,
0x802
,
0x902
};
static
const
u16
NCT6775_REG_FAN_STEP_DOWN_TIME
[]
=
{
0x103
,
0x203
,
0x303
,
0x803
,
0x903
};
static
const
u16
NCT6775_REG_FAN_STEP_UP_TIME
[]
=
{
0x104
,
0x204
,
0x304
,
0x804
,
0x904
};
static
const
u16
NCT6775_REG_FAN_STOP_OUTPUT
[]
=
{
0x105
,
0x205
,
0x305
,
0x805
,
0x905
};
static
const
u16
NCT6775_REG_FAN_START_OUTPUT
[]
=
{
0x106
,
0x206
,
0x306
,
0x806
,
0x906
};
static
const
u16
NCT6775_REG_FAN_MAX_OUTPUT
[]
=
{
0x10a
,
0x20a
,
0x30a
};
static
const
u16
NCT6775_REG_FAN_STEP_OUTPUT
[]
=
{
0x10b
,
0x20b
,
0x30b
};
static
const
u16
NCT6775_REG_FAN_STOP_TIME
[]
=
{
0x107
,
0x207
,
0x307
,
0x807
,
0x907
};
static
const
u16
NCT6775_REG_PWM
[]
=
{
0x109
,
0x209
,
0x309
,
0x809
,
0x909
};
static
const
u16
NCT6775_REG_PWM_READ
[]
=
{
0x01
,
0x03
,
0x11
,
0x13
,
0x15
};
...
...
@@ -237,8 +252,26 @@ static const u16 NCT6775_REG_TEMP_OVER[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
static
const
u16
NCT6775_REG_TEMP_SOURCE
[
ARRAY_SIZE
(
NCT6775_REG_TEMP
)]
=
{
0x621
,
0x622
,
0x623
,
0x624
,
0x625
,
0x626
};
static
const
u16
NCT6775_REG_TEMP_SEL
[]
=
{
0x100
,
0x200
,
0x300
,
0x800
,
0x900
};
static
const
u16
NCT6775_REG_TEMP_OFFSET
[]
=
{
0x454
,
0x455
,
0x456
};
static
const
u16
NCT6775_REG_AUTO_TEMP
[]
=
{
0x121
,
0x221
,
0x321
,
0x821
,
0x921
};
static
const
u16
NCT6775_REG_AUTO_PWM
[]
=
{
0x127
,
0x227
,
0x327
,
0x827
,
0x927
};
#define NCT6775_AUTO_TEMP(data, nr, p) ((data)->REG_AUTO_TEMP[nr] + (p))
#define NCT6775_AUTO_PWM(data, nr, p) ((data)->REG_AUTO_PWM[nr] + (p))
static
const
u16
NCT6775_REG_CRITICAL_ENAB
[]
=
{
0x134
,
0x234
,
0x334
};
static
const
u16
NCT6775_REG_CRITICAL_TEMP
[]
=
{
0x135
,
0x235
,
0x335
,
0x835
,
0x935
};
static
const
u16
NCT6775_REG_CRITICAL_TEMP_TOLERANCE
[]
=
{
0x138
,
0x238
,
0x338
,
0x838
,
0x938
};
static
const
char
*
const
nct6775_temp_label
[]
=
{
""
,
"SYSTIN"
,
...
...
@@ -281,6 +314,9 @@ static const s8 NCT6776_ALARM_BITS[] = {
4
,
5
,
13
,
-
1
,
-
1
,
-
1
,
/* temp1..temp6 */
12
,
9
};
/* intrusion0, intrusion1 */
static
const
u16
NCT6776_REG_TOLERANCE_H
[]
=
{
0x10c
,
0x20c
,
0x30c
,
0x80c
,
0x90c
};
static
const
u8
NCT6776_REG_PWM_MODE
[]
=
{
0x04
,
0
,
0
};
static
const
u8
NCT6776_PWM_MODE_MASK
[]
=
{
0x01
,
0
,
0
};
...
...
@@ -344,6 +380,11 @@ static const u16 NCT6779_REG_FAN[] = { 0x4b0, 0x4b2, 0x4b4, 0x4b6, 0x4b8 };
static
const
u16
NCT6779_REG_FAN_PULSES
[]
=
{
0x644
,
0x645
,
0x646
,
0x647
,
0x648
};
static
const
u16
NCT6779_REG_CRITICAL_PWM_ENABLE
[]
=
{
0x136
,
0x236
,
0x336
,
0x836
,
0x936
};
static
const
u16
NCT6779_REG_CRITICAL_PWM
[]
=
{
0x137
,
0x237
,
0x337
,
0x837
,
0x937
};
static
const
u16
NCT6779_REG_TEMP
[]
=
{
0x27
,
0x150
};
static
const
u16
NCT6779_REG_TEMP_CONFIG
[
ARRAY_SIZE
(
NCT6779_REG_TEMP
)]
=
{
0x18
,
0x152
};
...
...
@@ -412,6 +453,18 @@ static int pwm_enable_to_reg(enum pwm_enable mode)
* Conversions
*/
/* 1 is DC mode, output in ms */
static
unsigned
int
step_time_from_reg
(
u8
reg
,
u8
mode
)
{
return
mode
?
400
*
reg
:
100
*
reg
;
}
static
u8
step_time_to_reg
(
unsigned
int
msec
,
u8
mode
)
{
return
clamp_val
((
mode
?
(
msec
+
200
)
/
400
:
(
msec
+
50
)
/
100
),
1
,
255
);
}
static
unsigned
int
fan_from_reg8
(
u16
reg
,
unsigned
int
divreg
)
{
if
(
reg
==
0
||
reg
==
255
)
...
...
@@ -444,6 +497,14 @@ static unsigned int fan_from_reg16(u16 reg, unsigned int divreg)
return
1350000U
/
(
reg
<<
divreg
);
}
static
u16
fan_to_reg
(
u32
fan
,
unsigned
int
divreg
)
{
if
(
!
fan
)
return
0
;
return
(
1350000U
/
fan
)
>>
divreg
;
}
static
inline
unsigned
int
div_from_reg
(
u8
reg
)
{
...
...
@@ -498,18 +559,31 @@ struct nct6775_data {
const
u16
*
REG_VIN
;
const
u16
*
REG_IN_MINMAX
[
2
];
const
u16
*
REG_TARGET
;
const
u16
*
REG_FAN
;
const
u16
*
REG_FAN_MODE
;
const
u16
*
REG_FAN_MIN
;
const
u16
*
REG_FAN_PULSES
;
const
u16
*
REG_FAN_TIME
[
3
];
const
u16
*
REG_TOLERANCE_H
;
const
u8
*
REG_PWM_MODE
;
const
u8
*
PWM_MODE_MASK
;
const
u16
*
REG_PWM
[
1
];
/* [0]=pwm */
const
u16
*
REG_PWM
[
5
];
/* [0]=pwm, [1]=pwm_start, [2]=pwm_floor,
* [3]=pwm_max, [4]=pwm_step
*/
const
u16
*
REG_PWM_READ
;
const
u16
*
REG_AUTO_TEMP
;
const
u16
*
REG_AUTO_PWM
;
const
u16
*
REG_CRITICAL_TEMP
;
const
u16
*
REG_CRITICAL_TEMP_TOLERANCE
;
const
u16
*
REG_TEMP_SOURCE
;
/* temp register sources */
const
u16
*
REG_TEMP_SEL
;
const
u16
*
REG_TEMP_OFFSET
;
const
u16
*
REG_ALARM
;
...
...
@@ -551,7 +625,26 @@ struct nct6775_data {
* 4->SmartFan III
* 5->enhanced variable thermal cruise (SmartFan IV)
*/
u8
pwm
[
1
][
5
];
/* [0]=pwm */
u8
pwm
[
5
][
5
];
/* [0]=pwm, [1]=pwm_start, [2]=pwm_floor,
* [3]=pwm_max, [4]=pwm_step
*/
u8
target_temp
[
5
];
u8
target_temp_mask
;
u32
target_speed
[
5
];
u32
target_speed_tolerance
[
5
];
u8
speed_tolerance_limit
;
u8
temp_tolerance
[
2
][
5
];
u8
tolerance_mask
;
u8
fan_time
[
3
][
5
];
/* 0 = stop_time, 1 = step_up, 2 = step_down */
/* Automatic fan speed control registers */
int
auto_pwm_num
;
u8
auto_pwm
[
5
][
7
];
u8
auto_temp
[
5
][
7
];
u8
pwm_temp_sel
[
5
];
u8
vid
;
u8
vrm
;
...
...
@@ -833,7 +926,7 @@ static void nct6775_update_pwm(struct device *dev)
{
struct
nct6775_data
*
data
=
dev_get_drvdata
(
dev
);
int
i
,
j
;
int
fanmodecfg
;
int
fanmodecfg
,
reg
;
bool
duty_is_dc
;
for
(
i
=
0
;
i
<
data
->
pwm_num
;
i
++
)
{
...
...
@@ -856,6 +949,96 @@ static void nct6775_update_pwm(struct device *dev)
data
->
pwm_enable
[
i
]
=
reg_to_pwm_enable
(
data
->
pwm
[
0
][
i
],
(
fanmodecfg
>>
4
)
&
7
);
if
(
!
data
->
temp_tolerance
[
0
][
i
]
||
data
->
pwm_enable
[
i
]
!=
speed_cruise
)
data
->
temp_tolerance
[
0
][
i
]
=
fanmodecfg
&
0x0f
;
if
(
!
data
->
target_speed_tolerance
[
i
]
||
data
->
pwm_enable
[
i
]
==
speed_cruise
)
{
u8
t
=
fanmodecfg
&
0x0f
;
if
(
data
->
REG_TOLERANCE_H
)
{
t
|=
(
nct6775_read_value
(
data
,
data
->
REG_TOLERANCE_H
[
i
])
&
0x70
)
>>
1
;
}
data
->
target_speed_tolerance
[
i
]
=
t
;
}
data
->
temp_tolerance
[
1
][
i
]
=
nct6775_read_value
(
data
,
data
->
REG_CRITICAL_TEMP_TOLERANCE
[
i
]);
reg
=
nct6775_read_value
(
data
,
data
->
REG_TEMP_SEL
[
i
]);
data
->
pwm_temp_sel
[
i
]
=
reg
&
0x1f
;
/* If fan can stop, report floor as 0 */
if
(
reg
&
0x80
)
data
->
pwm
[
2
][
i
]
=
0
;
}
}
static
void
nct6775_update_pwm_limits
(
struct
device
*
dev
)
{
struct
nct6775_data
*
data
=
dev_get_drvdata
(
dev
);
int
i
,
j
;
u8
reg
;
u16
reg_t
;
for
(
i
=
0
;
i
<
data
->
pwm_num
;
i
++
)
{
if
(
!
(
data
->
has_pwm
&
(
1
<<
i
)))
continue
;
for
(
j
=
0
;
j
<
3
;
j
++
)
{
data
->
fan_time
[
j
][
i
]
=
nct6775_read_value
(
data
,
data
->
REG_FAN_TIME
[
j
][
i
]);
}
reg_t
=
nct6775_read_value
(
data
,
data
->
REG_TARGET
[
i
]);
/* Update only in matching mode or if never updated */
if
(
!
data
->
target_temp
[
i
]
||
data
->
pwm_enable
[
i
]
==
thermal_cruise
)
data
->
target_temp
[
i
]
=
reg_t
&
data
->
target_temp_mask
;
if
(
!
data
->
target_speed
[
i
]
||
data
->
pwm_enable
[
i
]
==
speed_cruise
)
{
if
(
data
->
REG_TOLERANCE_H
)
{
reg_t
|=
(
nct6775_read_value
(
data
,
data
->
REG_TOLERANCE_H
[
i
])
&
0x0f
)
<<
8
;
}
data
->
target_speed
[
i
]
=
reg_t
;
}
for
(
j
=
0
;
j
<
data
->
auto_pwm_num
;
j
++
)
{
data
->
auto_pwm
[
i
][
j
]
=
nct6775_read_value
(
data
,
NCT6775_AUTO_PWM
(
data
,
i
,
j
));
data
->
auto_temp
[
i
][
j
]
=
nct6775_read_value
(
data
,
NCT6775_AUTO_TEMP
(
data
,
i
,
j
));
}
/* critical auto_pwm temperature data */
data
->
auto_temp
[
i
][
data
->
auto_pwm_num
]
=
nct6775_read_value
(
data
,
data
->
REG_CRITICAL_TEMP
[
i
]);
switch
(
data
->
kind
)
{
case
nct6775
:
reg
=
nct6775_read_value
(
data
,
NCT6775_REG_CRITICAL_ENAB
[
i
]);
data
->
auto_pwm
[
i
][
data
->
auto_pwm_num
]
=
(
reg
&
0x02
)
?
0xff
:
0x00
;
break
;
case
nct6776
:
data
->
auto_pwm
[
i
][
data
->
auto_pwm_num
]
=
0xff
;
break
;
case
nct6779
:
reg
=
nct6775_read_value
(
data
,
NCT6779_REG_CRITICAL_PWM_ENABLE
[
i
]);
if
(
reg
&
1
)
data
->
auto_pwm
[
i
][
data
->
auto_pwm_num
]
=
nct6775_read_value
(
data
,
NCT6779_REG_CRITICAL_PWM
[
i
]);
else
data
->
auto_pwm
[
i
][
data
->
auto_pwm_num
]
=
0xff
;
break
;
}
}
}
...
...
@@ -905,6 +1088,7 @@ static struct nct6775_data *nct6775_update_device(struct device *dev)
}
nct6775_update_pwm
(
dev
);
nct6775_update_pwm_limits
(
dev
);
/* Measured temperatures and limits */
for
(
i
=
0
;
i
<
NUM_TEMP
;
i
++
)
{
...
...
@@ -1754,20 +1938,91 @@ store_pwm(struct device *dev, struct device_attribute *attr, const char *buf,
int
nr
=
sattr
->
nr
;
int
index
=
sattr
->
index
;
unsigned
long
val
;
int
minval
[
5
]
=
{
0
,
1
,
1
,
data
->
pwm
[
2
][
nr
],
0
};
int
maxval
[
5
]
=
{
255
,
255
,
data
->
pwm
[
3
][
nr
]
?
:
255
,
255
,
255
};
int
err
;
u8
reg
;
err
=
kstrtoul
(
buf
,
10
,
&
val
);
if
(
err
<
0
)
return
err
;
val
=
clamp_val
(
val
,
0
,
255
);
val
=
clamp_val
(
val
,
minval
[
index
],
maxval
[
index
]
);
mutex_lock
(
&
data
->
update_lock
);
data
->
pwm
[
index
][
nr
]
=
val
;
nct6775_write_value
(
data
,
data
->
REG_PWM
[
index
][
nr
],
val
);
if
(
index
==
2
)
{
/* floor: disable if val == 0 */
reg
=
nct6775_read_value
(
data
,
data
->
REG_TEMP_SEL
[
nr
]);
reg
&=
0x7f
;
if
(
val
)
reg
|=
0x80
;
nct6775_write_value
(
data
,
data
->
REG_TEMP_SEL
[
nr
],
reg
);
}
mutex_unlock
(
&
data
->
update_lock
);
return
count
;
}
/* Returns 0 if OK, -EINVAL otherwise */
static
int
check_trip_points
(
struct
nct6775_data
*
data
,
int
nr
)
{
int
i
;
for
(
i
=
0
;
i
<
data
->
auto_pwm_num
-
1
;
i
++
)
{
if
(
data
->
auto_temp
[
nr
][
i
]
>
data
->
auto_temp
[
nr
][
i
+
1
])
return
-
EINVAL
;
}
for
(
i
=
0
;
i
<
data
->
auto_pwm_num
-
1
;
i
++
)
{
if
(
data
->
auto_pwm
[
nr
][
i
]
>
data
->
auto_pwm
[
nr
][
i
+
1
])
return
-
EINVAL
;
}
/* validate critical temperature and pwm if enabled (pwm > 0) */
if
(
data
->
auto_pwm
[
nr
][
data
->
auto_pwm_num
])
{
if
(
data
->
auto_temp
[
nr
][
data
->
auto_pwm_num
-
1
]
>
data
->
auto_temp
[
nr
][
data
->
auto_pwm_num
]
||
data
->
auto_pwm
[
nr
][
data
->
auto_pwm_num
-
1
]
>
data
->
auto_pwm
[
nr
][
data
->
auto_pwm_num
])
return
-
EINVAL
;
}
return
0
;
}
static
void
pwm_update_registers
(
struct
nct6775_data
*
data
,
int
nr
)
{
u8
reg
;
switch
(
data
->
pwm_enable
[
nr
])
{
case
off
:
case
manual
:
break
;
case
speed_cruise
:
reg
=
nct6775_read_value
(
data
,
data
->
REG_FAN_MODE
[
nr
]);
reg
=
(
reg
&
~
data
->
tolerance_mask
)
|
(
data
->
target_speed_tolerance
[
nr
]
&
data
->
tolerance_mask
);
nct6775_write_value
(
data
,
data
->
REG_FAN_MODE
[
nr
],
reg
);
nct6775_write_value
(
data
,
data
->
REG_TARGET
[
nr
],
data
->
target_speed
[
nr
]
&
0xff
);
if
(
data
->
REG_TOLERANCE_H
)
{
reg
=
(
data
->
target_speed
[
nr
]
>>
8
)
&
0x0f
;
reg
|=
(
data
->
target_speed_tolerance
[
nr
]
&
0x38
)
<<
1
;
nct6775_write_value
(
data
,
data
->
REG_TOLERANCE_H
[
nr
],
reg
);
}
break
;
case
thermal_cruise
:
nct6775_write_value
(
data
,
data
->
REG_TARGET
[
nr
],
data
->
target_temp
[
nr
]);
/* intentional */
default:
reg
=
nct6775_read_value
(
data
,
data
->
REG_FAN_MODE
[
nr
]);
reg
=
(
reg
&
~
data
->
tolerance_mask
)
|
data
->
temp_tolerance
[
0
][
nr
];
nct6775_write_value
(
data
,
data
->
REG_FAN_MODE
[
nr
],
reg
);
break
;
}
}
static
ssize_t
show_pwm_enable
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
...
...
@@ -1798,6 +2053,12 @@ store_pwm_enable(struct device *dev, struct device_attribute *attr,
if
(
val
==
sf3
&&
data
->
kind
!=
nct6775
)
return
-
EINVAL
;
if
(
val
==
sf4
&&
check_trip_points
(
data
,
nr
))
{
dev_err
(
dev
,
"Inconsistent trip points, not switching to SmartFan IV mode
\n
"
);
dev_err
(
dev
,
"Adjust trip points and try again
\n
"
);
return
-
EINVAL
;
}
mutex_lock
(
&
data
->
update_lock
);
data
->
pwm_enable
[
nr
]
=
val
;
if
(
val
==
off
)
{
...
...
@@ -1807,6 +2068,7 @@ store_pwm_enable(struct device *dev, struct device_attribute *attr,
data
->
pwm
[
0
][
nr
]
=
255
;
nct6775_write_value
(
data
,
data
->
REG_PWM
[
0
][
nr
],
255
);
}
pwm_update_registers
(
data
,
nr
);
reg
=
nct6775_read_value
(
data
,
data
->
REG_FAN_MODE
[
nr
]);
reg
&=
0x0f
;
reg
|=
pwm_enable_to_reg
(
val
)
<<
4
;
...
...
@@ -1815,6 +2077,235 @@ store_pwm_enable(struct device *dev, struct device_attribute *attr,
return
count
;
}
static
ssize_t
show_pwm_temp_sel
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
struct
nct6775_data
*
data
=
nct6775_update_device
(
dev
);
struct
sensor_device_attribute
*
sattr
=
to_sensor_dev_attr
(
attr
);
int
i
,
src
,
sel
=
0
;
src
=
data
->
pwm_temp_sel
[
sattr
->
index
];
for
(
i
=
0
;
i
<
NUM_TEMP
;
i
++
)
{
if
(
!
(
data
->
have_temp
&
(
1
<<
i
)))
continue
;
if
(
src
==
data
->
temp_src
[
i
])
{
sel
=
i
+
1
;
break
;
}
}
return
sprintf
(
buf
,
"%d
\n
"
,
sel
);
}
static
ssize_t
store_pwm_temp_sel
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
const
char
*
buf
,
size_t
count
)
{
struct
nct6775_data
*
data
=
nct6775_update_device
(
dev
);
struct
sensor_device_attribute
*
sattr
=
to_sensor_dev_attr
(
attr
);
int
nr
=
sattr
->
index
;
unsigned
long
val
;
int
err
,
reg
,
src
;
err
=
kstrtoul
(
buf
,
10
,
&
val
);
if
(
err
<
0
)
return
err
;
if
(
val
==
0
||
val
>
NUM_TEMP
)
return
-
EINVAL
;
if
(
!
(
data
->
have_temp
&
(
1
<<
(
val
-
1
)))
||
!
data
->
temp_src
[
val
-
1
])
return
-
EINVAL
;
mutex_lock
(
&
data
->
update_lock
);
src
=
data
->
temp_src
[
val
-
1
];
data
->
pwm_temp_sel
[
nr
]
=
src
;
reg
=
nct6775_read_value
(
data
,
data
->
REG_TEMP_SEL
[
nr
]);
reg
&=
0xe0
;
reg
|=
src
;
nct6775_write_value
(
data
,
data
->
REG_TEMP_SEL
[
nr
],
reg
);
mutex_unlock
(
&
data
->
update_lock
);
return
count
;
}
static
ssize_t
show_target_temp
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
struct
nct6775_data
*
data
=
nct6775_update_device
(
dev
);
struct
sensor_device_attribute
*
sattr
=
to_sensor_dev_attr
(
attr
);
return
sprintf
(
buf
,
"%d
\n
"
,
data
->
target_temp
[
sattr
->
index
]
*
1000
);
}
static
ssize_t
store_target_temp
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
const
char
*
buf
,
size_t
count
)
{
struct
nct6775_data
*
data
=
dev_get_drvdata
(
dev
);
struct
sensor_device_attribute
*
sattr
=
to_sensor_dev_attr
(
attr
);
int
nr
=
sattr
->
index
;
unsigned
long
val
;
int
err
;
err
=
kstrtoul
(
buf
,
10
,
&
val
);
if
(
err
<
0
)
return
err
;
val
=
clamp_val
(
DIV_ROUND_CLOSEST
(
val
,
1000
),
0
,
data
->
target_temp_mask
);
mutex_lock
(
&
data
->
update_lock
);
data
->
target_temp
[
nr
]
=
val
;
pwm_update_registers
(
data
,
nr
);
mutex_unlock
(
&
data
->
update_lock
);
return
count
;
}
static
ssize_t
show_target_speed
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
struct
nct6775_data
*
data
=
nct6775_update_device
(
dev
);
struct
sensor_device_attribute
*
sattr
=
to_sensor_dev_attr
(
attr
);
int
nr
=
sattr
->
index
;
return
sprintf
(
buf
,
"%d
\n
"
,
fan_from_reg16
(
data
->
target_speed
[
nr
],
data
->
fan_div
[
nr
]));
}
static
ssize_t
store_target_speed
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
const
char
*
buf
,
size_t
count
)
{
struct
nct6775_data
*
data
=
dev_get_drvdata
(
dev
);
struct
sensor_device_attribute
*
sattr
=
to_sensor_dev_attr
(
attr
);
int
nr
=
sattr
->
index
;
unsigned
long
val
;
int
err
;
u16
speed
;
err
=
kstrtoul
(
buf
,
10
,
&
val
);
if
(
err
<
0
)
return
err
;
val
=
clamp_val
(
val
,
0
,
1350000U
);
speed
=
fan_to_reg
(
val
,
data
->
fan_div
[
nr
]);
mutex_lock
(
&
data
->
update_lock
);
data
->
target_speed
[
nr
]
=
speed
;
pwm_update_registers
(
data
,
nr
);
mutex_unlock
(
&
data
->
update_lock
);
return
count
;
}
static
ssize_t
show_temp_tolerance
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
struct
nct6775_data
*
data
=
nct6775_update_device
(
dev
);
struct
sensor_device_attribute_2
*
sattr
=
to_sensor_dev_attr_2
(
attr
);
int
nr
=
sattr
->
nr
;
int
index
=
sattr
->
index
;
return
sprintf
(
buf
,
"%d
\n
"
,
data
->
temp_tolerance
[
index
][
nr
]
*
1000
);
}
static
ssize_t
store_temp_tolerance
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
const
char
*
buf
,
size_t
count
)
{
struct
nct6775_data
*
data
=
dev_get_drvdata
(
dev
);
struct
sensor_device_attribute_2
*
sattr
=
to_sensor_dev_attr_2
(
attr
);
int
nr
=
sattr
->
nr
;
int
index
=
sattr
->
index
;
unsigned
long
val
;
int
err
;
err
=
kstrtoul
(
buf
,
10
,
&
val
);
if
(
err
<
0
)
return
err
;
/* Limit tolerance as needed */
val
=
clamp_val
(
DIV_ROUND_CLOSEST
(
val
,
1000
),
0
,
data
->
tolerance_mask
);
mutex_lock
(
&
data
->
update_lock
);
data
->
temp_tolerance
[
index
][
nr
]
=
val
;
if
(
index
)
pwm_update_registers
(
data
,
nr
);
else
nct6775_write_value
(
data
,
data
->
REG_CRITICAL_TEMP_TOLERANCE
[
nr
],
val
);
mutex_unlock
(
&
data
->
update_lock
);
return
count
;
}
/*
* Fan speed tolerance is a tricky beast, since the associated register is
* a tick counter, but the value is reported and configured as rpm.
* Compute resulting low and high rpm values and report the difference.
*/
static
ssize_t
show_speed_tolerance
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
struct
nct6775_data
*
data
=
nct6775_update_device
(
dev
);
struct
sensor_device_attribute
*
sattr
=
to_sensor_dev_attr
(
attr
);
int
nr
=
sattr
->
index
;
int
low
=
data
->
target_speed
[
nr
]
-
data
->
target_speed_tolerance
[
nr
];
int
high
=
data
->
target_speed
[
nr
]
+
data
->
target_speed_tolerance
[
nr
];
int
tolerance
;
if
(
low
<=
0
)
low
=
1
;
if
(
high
>
0xffff
)
high
=
0xffff
;
if
(
high
<
low
)
high
=
low
;
tolerance
=
(
fan_from_reg16
(
low
,
data
->
fan_div
[
nr
])
-
fan_from_reg16
(
high
,
data
->
fan_div
[
nr
]))
/
2
;
return
sprintf
(
buf
,
"%d
\n
"
,
tolerance
);
}
static
ssize_t
store_speed_tolerance
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
const
char
*
buf
,
size_t
count
)
{
struct
nct6775_data
*
data
=
dev_get_drvdata
(
dev
);
struct
sensor_device_attribute
*
sattr
=
to_sensor_dev_attr
(
attr
);
int
nr
=
sattr
->
index
;
unsigned
long
val
;
int
err
;
int
low
,
high
;
err
=
kstrtoul
(
buf
,
10
,
&
val
);
if
(
err
<
0
)
return
err
;
high
=
fan_from_reg16
(
data
->
target_speed
[
nr
],
data
->
fan_div
[
nr
])
+
val
;
low
=
fan_from_reg16
(
data
->
target_speed
[
nr
],
data
->
fan_div
[
nr
])
-
val
;
if
(
low
<=
0
)
low
=
1
;
if
(
high
<
low
)
high
=
low
;
val
=
(
fan_to_reg
(
low
,
data
->
fan_div
[
nr
])
-
fan_to_reg
(
high
,
data
->
fan_div
[
nr
]))
/
2
;
/* Limit tolerance as needed */
val
=
clamp_val
(
val
,
0
,
data
->
speed_tolerance_limit
);
mutex_lock
(
&
data
->
update_lock
);
data
->
target_speed_tolerance
[
nr
]
=
val
;
pwm_update_registers
(
data
,
nr
);
mutex_unlock
(
&
data
->
update_lock
);
return
count
;
}
static
SENSOR_DEVICE_ATTR_2
(
pwm1
,
S_IWUSR
|
S_IRUGO
,
show_pwm
,
store_pwm
,
0
,
0
);
static
SENSOR_DEVICE_ATTR_2
(
pwm2
,
S_IWUSR
|
S_IRUGO
,
show_pwm
,
store_pwm
,
1
,
0
);
static
SENSOR_DEVICE_ATTR_2
(
pwm3
,
S_IWUSR
|
S_IRUGO
,
show_pwm
,
store_pwm
,
2
,
0
);
...
...
@@ -1843,6 +2334,88 @@ static SENSOR_DEVICE_ATTR(pwm4_enable, S_IWUSR | S_IRUGO, show_pwm_enable,
static
SENSOR_DEVICE_ATTR
(
pwm5_enable
,
S_IWUSR
|
S_IRUGO
,
show_pwm_enable
,
store_pwm_enable
,
4
);
static
SENSOR_DEVICE_ATTR
(
pwm1_temp_sel
,
S_IWUSR
|
S_IRUGO
,
show_pwm_temp_sel
,
store_pwm_temp_sel
,
0
);
static
SENSOR_DEVICE_ATTR
(
pwm2_temp_sel
,
S_IWUSR
|
S_IRUGO
,
show_pwm_temp_sel
,
store_pwm_temp_sel
,
1
);
static
SENSOR_DEVICE_ATTR
(
pwm3_temp_sel
,
S_IWUSR
|
S_IRUGO
,
show_pwm_temp_sel
,
store_pwm_temp_sel
,
2
);
static
SENSOR_DEVICE_ATTR
(
pwm4_temp_sel
,
S_IWUSR
|
S_IRUGO
,
show_pwm_temp_sel
,
store_pwm_temp_sel
,
3
);
static
SENSOR_DEVICE_ATTR
(
pwm5_temp_sel
,
S_IWUSR
|
S_IRUGO
,
show_pwm_temp_sel
,
store_pwm_temp_sel
,
4
);
static
SENSOR_DEVICE_ATTR
(
pwm1_target_temp
,
S_IWUSR
|
S_IRUGO
,
show_target_temp
,
store_target_temp
,
0
);
static
SENSOR_DEVICE_ATTR
(
pwm2_target_temp
,
S_IWUSR
|
S_IRUGO
,
show_target_temp
,
store_target_temp
,
1
);
static
SENSOR_DEVICE_ATTR
(
pwm3_target_temp
,
S_IWUSR
|
S_IRUGO
,
show_target_temp
,
store_target_temp
,
2
);
static
SENSOR_DEVICE_ATTR
(
pwm4_target_temp
,
S_IWUSR
|
S_IRUGO
,
show_target_temp
,
store_target_temp
,
3
);
static
SENSOR_DEVICE_ATTR
(
pwm5_target_temp
,
S_IWUSR
|
S_IRUGO
,
show_target_temp
,
store_target_temp
,
4
);
static
SENSOR_DEVICE_ATTR
(
fan1_target
,
S_IWUSR
|
S_IRUGO
,
show_target_speed
,
store_target_speed
,
0
);
static
SENSOR_DEVICE_ATTR
(
fan2_target
,
S_IWUSR
|
S_IRUGO
,
show_target_speed
,
store_target_speed
,
1
);
static
SENSOR_DEVICE_ATTR
(
fan3_target
,
S_IWUSR
|
S_IRUGO
,
show_target_speed
,
store_target_speed
,
2
);
static
SENSOR_DEVICE_ATTR
(
fan4_target
,
S_IWUSR
|
S_IRUGO
,
show_target_speed
,
store_target_speed
,
3
);
static
SENSOR_DEVICE_ATTR
(
fan5_target
,
S_IWUSR
|
S_IRUGO
,
show_target_speed
,
store_target_speed
,
4
);
static
SENSOR_DEVICE_ATTR
(
fan1_tolerance
,
S_IWUSR
|
S_IRUGO
,
show_speed_tolerance
,
store_speed_tolerance
,
0
);
static
SENSOR_DEVICE_ATTR
(
fan2_tolerance
,
S_IWUSR
|
S_IRUGO
,
show_speed_tolerance
,
store_speed_tolerance
,
1
);
static
SENSOR_DEVICE_ATTR
(
fan3_tolerance
,
S_IWUSR
|
S_IRUGO
,
show_speed_tolerance
,
store_speed_tolerance
,
2
);
static
SENSOR_DEVICE_ATTR
(
fan4_tolerance
,
S_IWUSR
|
S_IRUGO
,
show_speed_tolerance
,
store_speed_tolerance
,
3
);
static
SENSOR_DEVICE_ATTR
(
fan5_tolerance
,
S_IWUSR
|
S_IRUGO
,
show_speed_tolerance
,
store_speed_tolerance
,
4
);
/* Smart Fan registers */
static
ssize_t
show_fan_time
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
struct
nct6775_data
*
data
=
nct6775_update_device
(
dev
);
struct
sensor_device_attribute_2
*
sattr
=
to_sensor_dev_attr_2
(
attr
);
int
nr
=
sattr
->
nr
;
int
index
=
sattr
->
index
;
return
sprintf
(
buf
,
"%d
\n
"
,
step_time_from_reg
(
data
->
fan_time
[
index
][
nr
],
data
->
pwm_mode
[
nr
]));
}
static
ssize_t
store_fan_time
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
const
char
*
buf
,
size_t
count
)
{
struct
nct6775_data
*
data
=
dev_get_drvdata
(
dev
);
struct
sensor_device_attribute_2
*
sattr
=
to_sensor_dev_attr_2
(
attr
);
int
nr
=
sattr
->
nr
;
int
index
=
sattr
->
index
;
unsigned
long
val
;
int
err
;
err
=
kstrtoul
(
buf
,
10
,
&
val
);
if
(
err
<
0
)
return
err
;
val
=
step_time_to_reg
(
val
,
data
->
pwm_mode
[
nr
]);
mutex_lock
(
&
data
->
update_lock
);
data
->
fan_time
[
index
][
nr
]
=
val
;
nct6775_write_value
(
data
,
data
->
REG_FAN_TIME
[
index
][
nr
],
val
);
mutex_unlock
(
&
data
->
update_lock
);
return
count
;
}
static
ssize_t
show_name
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
...
...
@@ -1853,35 +2426,190 @@ show_name(struct device *dev, struct device_attribute *attr, char *buf)
static
DEVICE_ATTR
(
name
,
S_IRUGO
,
show_name
,
NULL
);
static
struct
attribute
*
nct6775_attributes_pwm
[
5
][
4
]
=
{
static
SENSOR_DEVICE_ATTR_2
(
pwm1_stop_time
,
S_IWUSR
|
S_IRUGO
,
show_fan_time
,
store_fan_time
,
0
,
0
);
static
SENSOR_DEVICE_ATTR_2
(
pwm2_stop_time
,
S_IWUSR
|
S_IRUGO
,
show_fan_time
,
store_fan_time
,
1
,
0
);
static
SENSOR_DEVICE_ATTR_2
(
pwm3_stop_time
,
S_IWUSR
|
S_IRUGO
,
show_fan_time
,
store_fan_time
,
2
,
0
);
static
SENSOR_DEVICE_ATTR_2
(
pwm4_stop_time
,
S_IWUSR
|
S_IRUGO
,
show_fan_time
,
store_fan_time
,
3
,
0
);
static
SENSOR_DEVICE_ATTR_2
(
pwm5_stop_time
,
S_IWUSR
|
S_IRUGO
,
show_fan_time
,
store_fan_time
,
4
,
0
);
static
SENSOR_DEVICE_ATTR_2
(
pwm1_step_up_time
,
S_IWUSR
|
S_IRUGO
,
show_fan_time
,
store_fan_time
,
0
,
1
);
static
SENSOR_DEVICE_ATTR_2
(
pwm2_step_up_time
,
S_IWUSR
|
S_IRUGO
,
show_fan_time
,
store_fan_time
,
1
,
1
);
static
SENSOR_DEVICE_ATTR_2
(
pwm3_step_up_time
,
S_IWUSR
|
S_IRUGO
,
show_fan_time
,
store_fan_time
,
2
,
1
);
static
SENSOR_DEVICE_ATTR_2
(
pwm4_step_up_time
,
S_IWUSR
|
S_IRUGO
,
show_fan_time
,
store_fan_time
,
3
,
1
);
static
SENSOR_DEVICE_ATTR_2
(
pwm5_step_up_time
,
S_IWUSR
|
S_IRUGO
,
show_fan_time
,
store_fan_time
,
4
,
1
);
static
SENSOR_DEVICE_ATTR_2
(
pwm1_step_down_time
,
S_IWUSR
|
S_IRUGO
,
show_fan_time
,
store_fan_time
,
0
,
2
);
static
SENSOR_DEVICE_ATTR_2
(
pwm2_step_down_time
,
S_IWUSR
|
S_IRUGO
,
show_fan_time
,
store_fan_time
,
1
,
2
);
static
SENSOR_DEVICE_ATTR_2
(
pwm3_step_down_time
,
S_IWUSR
|
S_IRUGO
,
show_fan_time
,
store_fan_time
,
2
,
2
);
static
SENSOR_DEVICE_ATTR_2
(
pwm4_step_down_time
,
S_IWUSR
|
S_IRUGO
,
show_fan_time
,
store_fan_time
,
3
,
2
);
static
SENSOR_DEVICE_ATTR_2
(
pwm5_step_down_time
,
S_IWUSR
|
S_IRUGO
,
show_fan_time
,
store_fan_time
,
4
,
2
);
static
SENSOR_DEVICE_ATTR_2
(
pwm1_start
,
S_IWUSR
|
S_IRUGO
,
show_pwm
,
store_pwm
,
0
,
1
);
static
SENSOR_DEVICE_ATTR_2
(
pwm2_start
,
S_IWUSR
|
S_IRUGO
,
show_pwm
,
store_pwm
,
1
,
1
);
static
SENSOR_DEVICE_ATTR_2
(
pwm3_start
,
S_IWUSR
|
S_IRUGO
,
show_pwm
,
store_pwm
,
2
,
1
);
static
SENSOR_DEVICE_ATTR_2
(
pwm4_start
,
S_IWUSR
|
S_IRUGO
,
show_pwm
,
store_pwm
,
3
,
1
);
static
SENSOR_DEVICE_ATTR_2
(
pwm5_start
,
S_IWUSR
|
S_IRUGO
,
show_pwm
,
store_pwm
,
4
,
1
);
static
SENSOR_DEVICE_ATTR_2
(
pwm1_floor
,
S_IWUSR
|
S_IRUGO
,
show_pwm
,
store_pwm
,
0
,
2
);
static
SENSOR_DEVICE_ATTR_2
(
pwm2_floor
,
S_IWUSR
|
S_IRUGO
,
show_pwm
,
store_pwm
,
1
,
2
);
static
SENSOR_DEVICE_ATTR_2
(
pwm3_floor
,
S_IWUSR
|
S_IRUGO
,
show_pwm
,
store_pwm
,
2
,
2
);
static
SENSOR_DEVICE_ATTR_2
(
pwm4_floor
,
S_IWUSR
|
S_IRUGO
,
show_pwm
,
store_pwm
,
3
,
2
);
static
SENSOR_DEVICE_ATTR_2
(
pwm5_floor
,
S_IWUSR
|
S_IRUGO
,
show_pwm
,
store_pwm
,
4
,
2
);
static
SENSOR_DEVICE_ATTR_2
(
pwm1_temp_tolerance
,
S_IWUSR
|
S_IRUGO
,
show_temp_tolerance
,
store_temp_tolerance
,
0
,
0
);
static
SENSOR_DEVICE_ATTR_2
(
pwm2_temp_tolerance
,
S_IWUSR
|
S_IRUGO
,
show_temp_tolerance
,
store_temp_tolerance
,
1
,
0
);
static
SENSOR_DEVICE_ATTR_2
(
pwm3_temp_tolerance
,
S_IWUSR
|
S_IRUGO
,
show_temp_tolerance
,
store_temp_tolerance
,
2
,
0
);
static
SENSOR_DEVICE_ATTR_2
(
pwm4_temp_tolerance
,
S_IWUSR
|
S_IRUGO
,
show_temp_tolerance
,
store_temp_tolerance
,
3
,
0
);
static
SENSOR_DEVICE_ATTR_2
(
pwm5_temp_tolerance
,
S_IWUSR
|
S_IRUGO
,
show_temp_tolerance
,
store_temp_tolerance
,
4
,
0
);
static
SENSOR_DEVICE_ATTR_2
(
pwm1_crit_temp_tolerance
,
S_IWUSR
|
S_IRUGO
,
show_temp_tolerance
,
store_temp_tolerance
,
0
,
1
);
static
SENSOR_DEVICE_ATTR_2
(
pwm2_crit_temp_tolerance
,
S_IWUSR
|
S_IRUGO
,
show_temp_tolerance
,
store_temp_tolerance
,
1
,
1
);
static
SENSOR_DEVICE_ATTR_2
(
pwm3_crit_temp_tolerance
,
S_IWUSR
|
S_IRUGO
,
show_temp_tolerance
,
store_temp_tolerance
,
2
,
1
);
static
SENSOR_DEVICE_ATTR_2
(
pwm4_crit_temp_tolerance
,
S_IWUSR
|
S_IRUGO
,
show_temp_tolerance
,
store_temp_tolerance
,
3
,
1
);
static
SENSOR_DEVICE_ATTR_2
(
pwm5_crit_temp_tolerance
,
S_IWUSR
|
S_IRUGO
,
show_temp_tolerance
,
store_temp_tolerance
,
4
,
1
);
/* pwm_max is not supported on all chips */
static
struct
sensor_device_attribute_2
sda_pwm_max
[]
=
{
SENSOR_ATTR_2
(
pwm1_max
,
S_IWUSR
|
S_IRUGO
,
show_pwm
,
store_pwm
,
0
,
3
),
SENSOR_ATTR_2
(
pwm2_max
,
S_IWUSR
|
S_IRUGO
,
show_pwm
,
store_pwm
,
1
,
3
),
SENSOR_ATTR_2
(
pwm3_max
,
S_IWUSR
|
S_IRUGO
,
show_pwm
,
store_pwm
,
2
,
3
),
SENSOR_ATTR_2
(
pwm4_max
,
S_IWUSR
|
S_IRUGO
,
show_pwm
,
store_pwm
,
3
,
3
),
SENSOR_ATTR_2
(
pwm5_max
,
S_IWUSR
|
S_IRUGO
,
show_pwm
,
store_pwm
,
4
,
3
),
};
/* pwm_step is not supported on all chips */
static
struct
sensor_device_attribute_2
sda_pwm_step
[]
=
{
SENSOR_ATTR_2
(
pwm1_step
,
S_IWUSR
|
S_IRUGO
,
show_pwm
,
store_pwm
,
0
,
4
),
SENSOR_ATTR_2
(
pwm2_step
,
S_IWUSR
|
S_IRUGO
,
show_pwm
,
store_pwm
,
1
,
4
),
SENSOR_ATTR_2
(
pwm3_step
,
S_IWUSR
|
S_IRUGO
,
show_pwm
,
store_pwm
,
2
,
4
),
SENSOR_ATTR_2
(
pwm4_step
,
S_IWUSR
|
S_IRUGO
,
show_pwm
,
store_pwm
,
3
,
4
),
SENSOR_ATTR_2
(
pwm5_step
,
S_IWUSR
|
S_IRUGO
,
show_pwm
,
store_pwm
,
4
,
4
),
};
static
struct
attribute
*
nct6775_attributes_pwm
[
5
][
15
]
=
{
{
&
sensor_dev_attr_pwm1
.
dev_attr
.
attr
,
&
sensor_dev_attr_pwm1_mode
.
dev_attr
.
attr
,
&
sensor_dev_attr_pwm1_enable
.
dev_attr
.
attr
,
&
sensor_dev_attr_pwm1_temp_sel
.
dev_attr
.
attr
,
&
sensor_dev_attr_pwm1_temp_tolerance
.
dev_attr
.
attr
,
&
sensor_dev_attr_pwm1_crit_temp_tolerance
.
dev_attr
.
attr
,
&
sensor_dev_attr_pwm1_target_temp
.
dev_attr
.
attr
,
&
sensor_dev_attr_fan1_target
.
dev_attr
.
attr
,
&
sensor_dev_attr_fan1_tolerance
.
dev_attr
.
attr
,
&
sensor_dev_attr_pwm1_stop_time
.
dev_attr
.
attr
,
&
sensor_dev_attr_pwm1_step_up_time
.
dev_attr
.
attr
,
&
sensor_dev_attr_pwm1_step_down_time
.
dev_attr
.
attr
,
&
sensor_dev_attr_pwm1_start
.
dev_attr
.
attr
,
&
sensor_dev_attr_pwm1_floor
.
dev_attr
.
attr
,
NULL
},
{
&
sensor_dev_attr_pwm2
.
dev_attr
.
attr
,
&
sensor_dev_attr_pwm2_mode
.
dev_attr
.
attr
,
&
sensor_dev_attr_pwm2_enable
.
dev_attr
.
attr
,
&
sensor_dev_attr_pwm2_temp_sel
.
dev_attr
.
attr
,
&
sensor_dev_attr_pwm2_temp_tolerance
.
dev_attr
.
attr
,
&
sensor_dev_attr_pwm2_crit_temp_tolerance
.
dev_attr
.
attr
,
&
sensor_dev_attr_pwm2_target_temp
.
dev_attr
.
attr
,
&
sensor_dev_attr_fan2_target
.
dev_attr
.
attr
,
&
sensor_dev_attr_fan2_tolerance
.
dev_attr
.
attr
,
&
sensor_dev_attr_pwm2_stop_time
.
dev_attr
.
attr
,
&
sensor_dev_attr_pwm2_step_up_time
.
dev_attr
.
attr
,
&
sensor_dev_attr_pwm2_step_down_time
.
dev_attr
.
attr
,
&
sensor_dev_attr_pwm2_start
.
dev_attr
.
attr
,
&
sensor_dev_attr_pwm2_floor
.
dev_attr
.
attr
,
NULL
},
{
&
sensor_dev_attr_pwm3
.
dev_attr
.
attr
,
&
sensor_dev_attr_pwm3_mode
.
dev_attr
.
attr
,
&
sensor_dev_attr_pwm3_enable
.
dev_attr
.
attr
,
&
sensor_dev_attr_pwm3_temp_sel
.
dev_attr
.
attr
,
&
sensor_dev_attr_pwm3_temp_tolerance
.
dev_attr
.
attr
,
&
sensor_dev_attr_pwm3_crit_temp_tolerance
.
dev_attr
.
attr
,
&
sensor_dev_attr_pwm3_target_temp
.
dev_attr
.
attr
,
&
sensor_dev_attr_fan3_target
.
dev_attr
.
attr
,
&
sensor_dev_attr_fan3_tolerance
.
dev_attr
.
attr
,
&
sensor_dev_attr_pwm3_stop_time
.
dev_attr
.
attr
,
&
sensor_dev_attr_pwm3_step_up_time
.
dev_attr
.
attr
,
&
sensor_dev_attr_pwm3_step_down_time
.
dev_attr
.
attr
,
&
sensor_dev_attr_pwm3_start
.
dev_attr
.
attr
,
&
sensor_dev_attr_pwm3_floor
.
dev_attr
.
attr
,
NULL
},
{
&
sensor_dev_attr_pwm4
.
dev_attr
.
attr
,
&
sensor_dev_attr_pwm4_mode
.
dev_attr
.
attr
,
&
sensor_dev_attr_pwm4_enable
.
dev_attr
.
attr
,
&
sensor_dev_attr_pwm4_temp_sel
.
dev_attr
.
attr
,
&
sensor_dev_attr_pwm4_temp_tolerance
.
dev_attr
.
attr
,
&
sensor_dev_attr_pwm4_crit_temp_tolerance
.
dev_attr
.
attr
,
&
sensor_dev_attr_pwm4_target_temp
.
dev_attr
.
attr
,
&
sensor_dev_attr_fan4_target
.
dev_attr
.
attr
,
&
sensor_dev_attr_fan4_tolerance
.
dev_attr
.
attr
,
&
sensor_dev_attr_pwm4_stop_time
.
dev_attr
.
attr
,
&
sensor_dev_attr_pwm4_step_up_time
.
dev_attr
.
attr
,
&
sensor_dev_attr_pwm4_step_down_time
.
dev_attr
.
attr
,
&
sensor_dev_attr_pwm4_start
.
dev_attr
.
attr
,
&
sensor_dev_attr_pwm4_floor
.
dev_attr
.
attr
,
NULL
},
{
&
sensor_dev_attr_pwm5
.
dev_attr
.
attr
,
&
sensor_dev_attr_pwm5_mode
.
dev_attr
.
attr
,
&
sensor_dev_attr_pwm5_enable
.
dev_attr
.
attr
,
&
sensor_dev_attr_pwm5_temp_sel
.
dev_attr
.
attr
,
&
sensor_dev_attr_pwm5_temp_tolerance
.
dev_attr
.
attr
,
&
sensor_dev_attr_pwm5_crit_temp_tolerance
.
dev_attr
.
attr
,
&
sensor_dev_attr_pwm5_target_temp
.
dev_attr
.
attr
,
&
sensor_dev_attr_fan5_target
.
dev_attr
.
attr
,
&
sensor_dev_attr_fan5_tolerance
.
dev_attr
.
attr
,
&
sensor_dev_attr_pwm5_stop_time
.
dev_attr
.
attr
,
&
sensor_dev_attr_pwm5_step_up_time
.
dev_attr
.
attr
,
&
sensor_dev_attr_pwm5_step_down_time
.
dev_attr
.
attr
,
&
sensor_dev_attr_pwm5_start
.
dev_attr
.
attr
,
&
sensor_dev_attr_pwm5_floor
.
dev_attr
.
attr
,
NULL
},
};
...
...
@@ -1894,6 +2622,277 @@ static const struct attribute_group nct6775_group_pwm[5] = {
{
.
attrs
=
nct6775_attributes_pwm
[
4
]
},
};
static
ssize_t
show_auto_pwm
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
struct
nct6775_data
*
data
=
nct6775_update_device
(
dev
);
struct
sensor_device_attribute_2
*
sattr
=
to_sensor_dev_attr_2
(
attr
);
return
sprintf
(
buf
,
"%d
\n
"
,
data
->
auto_pwm
[
sattr
->
nr
][
sattr
->
index
]);
}
static
ssize_t
store_auto_pwm
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
const
char
*
buf
,
size_t
count
)
{
struct
nct6775_data
*
data
=
dev_get_drvdata
(
dev
);
struct
sensor_device_attribute_2
*
sattr
=
to_sensor_dev_attr_2
(
attr
);
int
nr
=
sattr
->
nr
;
int
point
=
sattr
->
index
;
unsigned
long
val
;
int
err
;
u8
reg
;
err
=
kstrtoul
(
buf
,
10
,
&
val
);
if
(
err
<
0
)
return
err
;
if
(
val
>
255
)
return
-
EINVAL
;
if
(
point
==
data
->
auto_pwm_num
)
{
if
(
data
->
kind
!=
nct6775
&&
!
val
)
return
-
EINVAL
;
if
(
data
->
kind
!=
nct6779
&&
val
)
val
=
0xff
;
}
mutex_lock
(
&
data
->
update_lock
);
data
->
auto_pwm
[
nr
][
point
]
=
val
;
if
(
point
<
data
->
auto_pwm_num
)
{
nct6775_write_value
(
data
,
NCT6775_AUTO_PWM
(
data
,
nr
,
point
),
data
->
auto_pwm
[
nr
][
point
]);
}
else
{
switch
(
data
->
kind
)
{
case
nct6775
:
/* disable if needed (pwm == 0) */
reg
=
nct6775_read_value
(
data
,
NCT6775_REG_CRITICAL_ENAB
[
nr
]);
if
(
val
)
reg
|=
0x02
;
else
reg
&=
~
0x02
;
nct6775_write_value
(
data
,
NCT6775_REG_CRITICAL_ENAB
[
nr
],
reg
);
break
;
case
nct6776
:
break
;
/* always enabled, nothing to do */
case
nct6779
:
nct6775_write_value
(
data
,
NCT6779_REG_CRITICAL_PWM
[
nr
],
val
);
reg
=
nct6775_read_value
(
data
,
NCT6779_REG_CRITICAL_PWM_ENABLE
[
nr
]);
if
(
val
==
255
)
reg
&=
~
0x01
;
else
reg
|=
0x01
;
nct6775_write_value
(
data
,
NCT6779_REG_CRITICAL_PWM_ENABLE
[
nr
],
reg
);
break
;
}
}
mutex_unlock
(
&
data
->
update_lock
);
return
count
;
}
static
ssize_t
show_auto_temp
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
struct
nct6775_data
*
data
=
nct6775_update_device
(
dev
);
struct
sensor_device_attribute_2
*
sattr
=
to_sensor_dev_attr_2
(
attr
);
int
nr
=
sattr
->
nr
;
int
point
=
sattr
->
index
;
/*
* We don't know for sure if the temperature is signed or unsigned.
* Assume it is unsigned.
*/
return
sprintf
(
buf
,
"%d
\n
"
,
data
->
auto_temp
[
nr
][
point
]
*
1000
);
}
static
ssize_t
store_auto_temp
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
const
char
*
buf
,
size_t
count
)
{
struct
nct6775_data
*
data
=
dev_get_drvdata
(
dev
);
struct
sensor_device_attribute_2
*
sattr
=
to_sensor_dev_attr_2
(
attr
);
int
nr
=
sattr
->
nr
;
int
point
=
sattr
->
index
;
unsigned
long
val
;
int
err
;
err
=
kstrtoul
(
buf
,
10
,
&
val
);
if
(
err
)
return
err
;
if
(
val
>
255000
)
return
-
EINVAL
;
mutex_lock
(
&
data
->
update_lock
);
data
->
auto_temp
[
nr
][
point
]
=
DIV_ROUND_CLOSEST
(
val
,
1000
);
if
(
point
<
data
->
auto_pwm_num
)
{
nct6775_write_value
(
data
,
NCT6775_AUTO_TEMP
(
data
,
nr
,
point
),
data
->
auto_temp
[
nr
][
point
]);
}
else
{
nct6775_write_value
(
data
,
data
->
REG_CRITICAL_TEMP
[
nr
],
data
->
auto_temp
[
nr
][
point
]);
}
mutex_unlock
(
&
data
->
update_lock
);
return
count
;
}
/*
* The number of auto-point trip points is chip dependent.
* Need to check support while generating/removing attribute files.
*/
static
struct
sensor_device_attribute_2
sda_auto_pwm_arrays
[]
=
{
SENSOR_ATTR_2
(
pwm1_auto_point1_pwm
,
S_IWUSR
|
S_IRUGO
,
show_auto_pwm
,
store_auto_pwm
,
0
,
0
),
SENSOR_ATTR_2
(
pwm1_auto_point1_temp
,
S_IWUSR
|
S_IRUGO
,
show_auto_temp
,
store_auto_temp
,
0
,
0
),
SENSOR_ATTR_2
(
pwm1_auto_point2_pwm
,
S_IWUSR
|
S_IRUGO
,
show_auto_pwm
,
store_auto_pwm
,
0
,
1
),
SENSOR_ATTR_2
(
pwm1_auto_point2_temp
,
S_IWUSR
|
S_IRUGO
,
show_auto_temp
,
store_auto_temp
,
0
,
1
),
SENSOR_ATTR_2
(
pwm1_auto_point3_pwm
,
S_IWUSR
|
S_IRUGO
,
show_auto_pwm
,
store_auto_pwm
,
0
,
2
),
SENSOR_ATTR_2
(
pwm1_auto_point3_temp
,
S_IWUSR
|
S_IRUGO
,
show_auto_temp
,
store_auto_temp
,
0
,
2
),
SENSOR_ATTR_2
(
pwm1_auto_point4_pwm
,
S_IWUSR
|
S_IRUGO
,
show_auto_pwm
,
store_auto_pwm
,
0
,
3
),
SENSOR_ATTR_2
(
pwm1_auto_point4_temp
,
S_IWUSR
|
S_IRUGO
,
show_auto_temp
,
store_auto_temp
,
0
,
3
),
SENSOR_ATTR_2
(
pwm1_auto_point5_pwm
,
S_IWUSR
|
S_IRUGO
,
show_auto_pwm
,
store_auto_pwm
,
0
,
4
),
SENSOR_ATTR_2
(
pwm1_auto_point5_temp
,
S_IWUSR
|
S_IRUGO
,
show_auto_temp
,
store_auto_temp
,
0
,
4
),
SENSOR_ATTR_2
(
pwm1_auto_point6_pwm
,
S_IWUSR
|
S_IRUGO
,
show_auto_pwm
,
store_auto_pwm
,
0
,
5
),
SENSOR_ATTR_2
(
pwm1_auto_point6_temp
,
S_IWUSR
|
S_IRUGO
,
show_auto_temp
,
store_auto_temp
,
0
,
5
),
SENSOR_ATTR_2
(
pwm1_auto_point7_pwm
,
S_IWUSR
|
S_IRUGO
,
show_auto_pwm
,
store_auto_pwm
,
0
,
6
),
SENSOR_ATTR_2
(
pwm1_auto_point7_temp
,
S_IWUSR
|
S_IRUGO
,
show_auto_temp
,
store_auto_temp
,
0
,
6
),
SENSOR_ATTR_2
(
pwm2_auto_point1_pwm
,
S_IWUSR
|
S_IRUGO
,
show_auto_pwm
,
store_auto_pwm
,
1
,
0
),
SENSOR_ATTR_2
(
pwm2_auto_point1_temp
,
S_IWUSR
|
S_IRUGO
,
show_auto_temp
,
store_auto_temp
,
1
,
0
),
SENSOR_ATTR_2
(
pwm2_auto_point2_pwm
,
S_IWUSR
|
S_IRUGO
,
show_auto_pwm
,
store_auto_pwm
,
1
,
1
),
SENSOR_ATTR_2
(
pwm2_auto_point2_temp
,
S_IWUSR
|
S_IRUGO
,
show_auto_temp
,
store_auto_temp
,
1
,
1
),
SENSOR_ATTR_2
(
pwm2_auto_point3_pwm
,
S_IWUSR
|
S_IRUGO
,
show_auto_pwm
,
store_auto_pwm
,
1
,
2
),
SENSOR_ATTR_2
(
pwm2_auto_point3_temp
,
S_IWUSR
|
S_IRUGO
,
show_auto_temp
,
store_auto_temp
,
1
,
2
),
SENSOR_ATTR_2
(
pwm2_auto_point4_pwm
,
S_IWUSR
|
S_IRUGO
,
show_auto_pwm
,
store_auto_pwm
,
1
,
3
),
SENSOR_ATTR_2
(
pwm2_auto_point4_temp
,
S_IWUSR
|
S_IRUGO
,
show_auto_temp
,
store_auto_temp
,
1
,
3
),
SENSOR_ATTR_2
(
pwm2_auto_point5_pwm
,
S_IWUSR
|
S_IRUGO
,
show_auto_pwm
,
store_auto_pwm
,
1
,
4
),
SENSOR_ATTR_2
(
pwm2_auto_point5_temp
,
S_IWUSR
|
S_IRUGO
,
show_auto_temp
,
store_auto_temp
,
1
,
4
),
SENSOR_ATTR_2
(
pwm2_auto_point6_pwm
,
S_IWUSR
|
S_IRUGO
,
show_auto_pwm
,
store_auto_pwm
,
1
,
5
),
SENSOR_ATTR_2
(
pwm2_auto_point6_temp
,
S_IWUSR
|
S_IRUGO
,
show_auto_temp
,
store_auto_temp
,
1
,
5
),
SENSOR_ATTR_2
(
pwm2_auto_point7_pwm
,
S_IWUSR
|
S_IRUGO
,
show_auto_pwm
,
store_auto_pwm
,
1
,
6
),
SENSOR_ATTR_2
(
pwm2_auto_point7_temp
,
S_IWUSR
|
S_IRUGO
,
show_auto_temp
,
store_auto_temp
,
1
,
6
),
SENSOR_ATTR_2
(
pwm3_auto_point1_pwm
,
S_IWUSR
|
S_IRUGO
,
show_auto_pwm
,
store_auto_pwm
,
2
,
0
),
SENSOR_ATTR_2
(
pwm3_auto_point1_temp
,
S_IWUSR
|
S_IRUGO
,
show_auto_temp
,
store_auto_temp
,
2
,
0
),
SENSOR_ATTR_2
(
pwm3_auto_point2_pwm
,
S_IWUSR
|
S_IRUGO
,
show_auto_pwm
,
store_auto_pwm
,
2
,
1
),
SENSOR_ATTR_2
(
pwm3_auto_point2_temp
,
S_IWUSR
|
S_IRUGO
,
show_auto_temp
,
store_auto_temp
,
2
,
1
),
SENSOR_ATTR_2
(
pwm3_auto_point3_pwm
,
S_IWUSR
|
S_IRUGO
,
show_auto_pwm
,
store_auto_pwm
,
2
,
2
),
SENSOR_ATTR_2
(
pwm3_auto_point3_temp
,
S_IWUSR
|
S_IRUGO
,
show_auto_temp
,
store_auto_temp
,
2
,
2
),
SENSOR_ATTR_2
(
pwm3_auto_point4_pwm
,
S_IWUSR
|
S_IRUGO
,
show_auto_pwm
,
store_auto_pwm
,
2
,
3
),
SENSOR_ATTR_2
(
pwm3_auto_point4_temp
,
S_IWUSR
|
S_IRUGO
,
show_auto_temp
,
store_auto_temp
,
2
,
3
),
SENSOR_ATTR_2
(
pwm3_auto_point5_pwm
,
S_IWUSR
|
S_IRUGO
,
show_auto_pwm
,
store_auto_pwm
,
2
,
4
),
SENSOR_ATTR_2
(
pwm3_auto_point5_temp
,
S_IWUSR
|
S_IRUGO
,
show_auto_temp
,
store_auto_temp
,
2
,
4
),
SENSOR_ATTR_2
(
pwm3_auto_point6_pwm
,
S_IWUSR
|
S_IRUGO
,
show_auto_pwm
,
store_auto_pwm
,
2
,
5
),
SENSOR_ATTR_2
(
pwm3_auto_point6_temp
,
S_IWUSR
|
S_IRUGO
,
show_auto_temp
,
store_auto_temp
,
2
,
5
),
SENSOR_ATTR_2
(
pwm3_auto_point7_pwm
,
S_IWUSR
|
S_IRUGO
,
show_auto_pwm
,
store_auto_pwm
,
2
,
6
),
SENSOR_ATTR_2
(
pwm3_auto_point7_temp
,
S_IWUSR
|
S_IRUGO
,
show_auto_temp
,
store_auto_temp
,
2
,
6
),
SENSOR_ATTR_2
(
pwm4_auto_point1_pwm
,
S_IWUSR
|
S_IRUGO
,
show_auto_pwm
,
store_auto_pwm
,
3
,
0
),
SENSOR_ATTR_2
(
pwm4_auto_point1_temp
,
S_IWUSR
|
S_IRUGO
,
show_auto_temp
,
store_auto_temp
,
3
,
0
),
SENSOR_ATTR_2
(
pwm4_auto_point2_pwm
,
S_IWUSR
|
S_IRUGO
,
show_auto_pwm
,
store_auto_pwm
,
3
,
1
),
SENSOR_ATTR_2
(
pwm4_auto_point2_temp
,
S_IWUSR
|
S_IRUGO
,
show_auto_temp
,
store_auto_temp
,
3
,
1
),
SENSOR_ATTR_2
(
pwm4_auto_point3_pwm
,
S_IWUSR
|
S_IRUGO
,
show_auto_pwm
,
store_auto_pwm
,
3
,
2
),
SENSOR_ATTR_2
(
pwm4_auto_point3_temp
,
S_IWUSR
|
S_IRUGO
,
show_auto_temp
,
store_auto_temp
,
3
,
2
),
SENSOR_ATTR_2
(
pwm4_auto_point4_pwm
,
S_IWUSR
|
S_IRUGO
,
show_auto_pwm
,
store_auto_pwm
,
3
,
3
),
SENSOR_ATTR_2
(
pwm4_auto_point4_temp
,
S_IWUSR
|
S_IRUGO
,
show_auto_temp
,
store_auto_temp
,
3
,
3
),
SENSOR_ATTR_2
(
pwm4_auto_point5_pwm
,
S_IWUSR
|
S_IRUGO
,
show_auto_pwm
,
store_auto_pwm
,
3
,
4
),
SENSOR_ATTR_2
(
pwm4_auto_point5_temp
,
S_IWUSR
|
S_IRUGO
,
show_auto_temp
,
store_auto_temp
,
3
,
4
),
SENSOR_ATTR_2
(
pwm4_auto_point6_pwm
,
S_IWUSR
|
S_IRUGO
,
show_auto_pwm
,
store_auto_pwm
,
3
,
5
),
SENSOR_ATTR_2
(
pwm4_auto_point6_temp
,
S_IWUSR
|
S_IRUGO
,
show_auto_temp
,
store_auto_temp
,
3
,
5
),
SENSOR_ATTR_2
(
pwm4_auto_point7_pwm
,
S_IWUSR
|
S_IRUGO
,
show_auto_pwm
,
store_auto_pwm
,
3
,
6
),
SENSOR_ATTR_2
(
pwm4_auto_point7_temp
,
S_IWUSR
|
S_IRUGO
,
show_auto_temp
,
store_auto_temp
,
3
,
6
),
SENSOR_ATTR_2
(
pwm5_auto_point1_pwm
,
S_IWUSR
|
S_IRUGO
,
show_auto_pwm
,
store_auto_pwm
,
4
,
0
),
SENSOR_ATTR_2
(
pwm5_auto_point1_temp
,
S_IWUSR
|
S_IRUGO
,
show_auto_temp
,
store_auto_temp
,
4
,
0
),
SENSOR_ATTR_2
(
pwm5_auto_point2_pwm
,
S_IWUSR
|
S_IRUGO
,
show_auto_pwm
,
store_auto_pwm
,
4
,
1
),
SENSOR_ATTR_2
(
pwm5_auto_point2_temp
,
S_IWUSR
|
S_IRUGO
,
show_auto_temp
,
store_auto_temp
,
4
,
1
),
SENSOR_ATTR_2
(
pwm5_auto_point3_pwm
,
S_IWUSR
|
S_IRUGO
,
show_auto_pwm
,
store_auto_pwm
,
4
,
2
),
SENSOR_ATTR_2
(
pwm5_auto_point3_temp
,
S_IWUSR
|
S_IRUGO
,
show_auto_temp
,
store_auto_temp
,
4
,
2
),
SENSOR_ATTR_2
(
pwm5_auto_point4_pwm
,
S_IWUSR
|
S_IRUGO
,
show_auto_pwm
,
store_auto_pwm
,
4
,
3
),
SENSOR_ATTR_2
(
pwm5_auto_point4_temp
,
S_IWUSR
|
S_IRUGO
,
show_auto_temp
,
store_auto_temp
,
4
,
3
),
SENSOR_ATTR_2
(
pwm5_auto_point5_pwm
,
S_IWUSR
|
S_IRUGO
,
show_auto_pwm
,
store_auto_pwm
,
4
,
4
),
SENSOR_ATTR_2
(
pwm5_auto_point5_temp
,
S_IWUSR
|
S_IRUGO
,
show_auto_temp
,
store_auto_temp
,
4
,
4
),
SENSOR_ATTR_2
(
pwm5_auto_point6_pwm
,
S_IWUSR
|
S_IRUGO
,
show_auto_pwm
,
store_auto_pwm
,
4
,
5
),
SENSOR_ATTR_2
(
pwm5_auto_point6_temp
,
S_IWUSR
|
S_IRUGO
,
show_auto_temp
,
store_auto_temp
,
4
,
5
),
SENSOR_ATTR_2
(
pwm5_auto_point7_pwm
,
S_IWUSR
|
S_IRUGO
,
show_auto_pwm
,
store_auto_pwm
,
4
,
6
),
SENSOR_ATTR_2
(
pwm5_auto_point7_temp
,
S_IWUSR
|
S_IRUGO
,
show_auto_temp
,
store_auto_temp
,
4
,
6
),
};
static
ssize_t
show_vid
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
...
...
@@ -1969,6 +2968,15 @@ static void nct6775_device_remove_files(struct device *dev)
for
(
i
=
0
;
i
<
data
->
pwm_num
;
i
++
)
sysfs_remove_group
(
&
dev
->
kobj
,
&
nct6775_group_pwm
[
i
]);
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
sda_pwm_max
);
i
++
)
device_remove_file
(
dev
,
&
sda_pwm_max
[
i
].
dev_attr
);
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
sda_pwm_step
);
i
++
)
device_remove_file
(
dev
,
&
sda_pwm_step
[
i
].
dev_attr
);
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
sda_auto_pwm_arrays
);
i
++
)
device_remove_file
(
dev
,
&
sda_auto_pwm_arrays
[
i
].
dev_attr
);
for
(
i
=
0
;
i
<
data
->
in_num
;
i
++
)
sysfs_remove_group
(
&
dev
->
kobj
,
&
nct6775_group_in
[
i
]);
...
...
@@ -2161,6 +3169,7 @@ static int nct6775_probe(struct platform_device *pdev)
case
nct6775
:
data
->
in_num
=
9
;
data
->
pwm_num
=
3
;
data
->
auto_pwm_num
=
6
;
data
->
has_fan_div
=
true
;
data
->
temp_fixed_num
=
3
;
...
...
@@ -2168,6 +3177,9 @@ static int nct6775_probe(struct platform_device *pdev)
data
->
fan_from_reg
=
fan_from_reg16
;
data
->
fan_from_reg_min
=
fan_from_reg8
;
data
->
target_temp_mask
=
0x7f
;
data
->
tolerance_mask
=
0x0f
;
data
->
speed_tolerance_limit
=
15
;
data
->
temp_label
=
nct6775_temp_label
;
data
->
temp_label_num
=
ARRAY_SIZE
(
nct6775_temp_label
);
...
...
@@ -2178,16 +3190,30 @@ static int nct6775_probe(struct platform_device *pdev)
data
->
REG_VIN
=
NCT6775_REG_IN
;
data
->
REG_IN_MINMAX
[
0
]
=
NCT6775_REG_IN_MIN
;
data
->
REG_IN_MINMAX
[
1
]
=
NCT6775_REG_IN_MAX
;
data
->
REG_TARGET
=
NCT6775_REG_TARGET
;
data
->
REG_FAN
=
NCT6775_REG_FAN
;
data
->
REG_FAN_MODE
=
NCT6775_REG_FAN_MODE
;
data
->
REG_FAN_MIN
=
NCT6775_REG_FAN_MIN
;
data
->
REG_FAN_PULSES
=
NCT6775_REG_FAN_PULSES
;
data
->
REG_FAN_TIME
[
0
]
=
NCT6775_REG_FAN_STOP_TIME
;
data
->
REG_FAN_TIME
[
1
]
=
NCT6775_REG_FAN_STEP_UP_TIME
;
data
->
REG_FAN_TIME
[
2
]
=
NCT6775_REG_FAN_STEP_DOWN_TIME
;
data
->
REG_PWM
[
0
]
=
NCT6775_REG_PWM
;
data
->
REG_PWM
[
1
]
=
NCT6775_REG_FAN_START_OUTPUT
;
data
->
REG_PWM
[
2
]
=
NCT6775_REG_FAN_STOP_OUTPUT
;
data
->
REG_PWM
[
3
]
=
NCT6775_REG_FAN_MAX_OUTPUT
;
data
->
REG_PWM
[
4
]
=
NCT6775_REG_FAN_STEP_OUTPUT
;
data
->
REG_PWM_READ
=
NCT6775_REG_PWM_READ
;
data
->
REG_PWM_MODE
=
NCT6775_REG_PWM_MODE
;
data
->
PWM_MODE_MASK
=
NCT6775_PWM_MODE_MASK
;
data
->
REG_AUTO_TEMP
=
NCT6775_REG_AUTO_TEMP
;
data
->
REG_AUTO_PWM
=
NCT6775_REG_AUTO_PWM
;
data
->
REG_CRITICAL_TEMP
=
NCT6775_REG_CRITICAL_TEMP
;
data
->
REG_CRITICAL_TEMP_TOLERANCE
=
NCT6775_REG_CRITICAL_TEMP_TOLERANCE
;
data
->
REG_TEMP_OFFSET
=
NCT6775_REG_TEMP_OFFSET
;
data
->
REG_TEMP_SOURCE
=
NCT6775_REG_TEMP_SOURCE
;
data
->
REG_TEMP_SEL
=
NCT6775_REG_TEMP_SEL
;
data
->
REG_ALARM
=
NCT6775_REG_ALARM
;
reg_temp
=
NCT6775_REG_TEMP
;
...
...
@@ -2202,6 +3228,7 @@ static int nct6775_probe(struct platform_device *pdev)
case
nct6776
:
data
->
in_num
=
9
;
data
->
pwm_num
=
3
;
data
->
auto_pwm_num
=
4
;
data
->
has_fan_div
=
false
;
data
->
temp_fixed_num
=
3
;
...
...
@@ -2209,6 +3236,9 @@ static int nct6775_probe(struct platform_device *pdev)
data
->
fan_from_reg
=
fan_from_reg13
;
data
->
fan_from_reg_min
=
fan_from_reg13
;
data
->
target_temp_mask
=
0xff
;
data
->
tolerance_mask
=
0x07
;
data
->
speed_tolerance_limit
=
63
;
data
->
temp_label
=
nct6776_temp_label
;
data
->
temp_label_num
=
ARRAY_SIZE
(
nct6776_temp_label
);
...
...
@@ -2219,16 +3249,29 @@ static int nct6775_probe(struct platform_device *pdev)
data
->
REG_VIN
=
NCT6775_REG_IN
;
data
->
REG_IN_MINMAX
[
0
]
=
NCT6775_REG_IN_MIN
;
data
->
REG_IN_MINMAX
[
1
]
=
NCT6775_REG_IN_MAX
;
data
->
REG_TARGET
=
NCT6775_REG_TARGET
;
data
->
REG_FAN
=
NCT6775_REG_FAN
;
data
->
REG_FAN_MODE
=
NCT6775_REG_FAN_MODE
;
data
->
REG_FAN_MIN
=
NCT6776_REG_FAN_MIN
;
data
->
REG_FAN_PULSES
=
NCT6776_REG_FAN_PULSES
;
data
->
REG_FAN_TIME
[
0
]
=
NCT6775_REG_FAN_STOP_TIME
;
data
->
REG_FAN_TIME
[
1
]
=
NCT6775_REG_FAN_STEP_UP_TIME
;
data
->
REG_FAN_TIME
[
2
]
=
NCT6775_REG_FAN_STEP_DOWN_TIME
;
data
->
REG_TOLERANCE_H
=
NCT6776_REG_TOLERANCE_H
;
data
->
REG_PWM
[
0
]
=
NCT6775_REG_PWM
;
data
->
REG_PWM
[
1
]
=
NCT6775_REG_FAN_START_OUTPUT
;
data
->
REG_PWM
[
2
]
=
NCT6775_REG_FAN_STOP_OUTPUT
;
data
->
REG_PWM_READ
=
NCT6775_REG_PWM_READ
;
data
->
REG_PWM_MODE
=
NCT6776_REG_PWM_MODE
;
data
->
PWM_MODE_MASK
=
NCT6776_PWM_MODE_MASK
;
data
->
REG_AUTO_TEMP
=
NCT6775_REG_AUTO_TEMP
;
data
->
REG_AUTO_PWM
=
NCT6775_REG_AUTO_PWM
;
data
->
REG_CRITICAL_TEMP
=
NCT6775_REG_CRITICAL_TEMP
;
data
->
REG_CRITICAL_TEMP_TOLERANCE
=
NCT6775_REG_CRITICAL_TEMP_TOLERANCE
;
data
->
REG_TEMP_OFFSET
=
NCT6775_REG_TEMP_OFFSET
;
data
->
REG_TEMP_SOURCE
=
NCT6775_REG_TEMP_SOURCE
;
data
->
REG_TEMP_SEL
=
NCT6775_REG_TEMP_SEL
;
data
->
REG_ALARM
=
NCT6775_REG_ALARM
;
reg_temp
=
NCT6775_REG_TEMP
;
...
...
@@ -2243,6 +3286,7 @@ static int nct6775_probe(struct platform_device *pdev)
case
nct6779
:
data
->
in_num
=
15
;
data
->
pwm_num
=
5
;
data
->
auto_pwm_num
=
4
;
data
->
has_fan_div
=
false
;
data
->
temp_fixed_num
=
6
;
...
...
@@ -2250,6 +3294,9 @@ static int nct6775_probe(struct platform_device *pdev)
data
->
fan_from_reg
=
fan_from_reg13
;
data
->
fan_from_reg_min
=
fan_from_reg13
;
data
->
target_temp_mask
=
0xff
;
data
->
tolerance_mask
=
0x07
;
data
->
speed_tolerance_limit
=
63
;
data
->
temp_label
=
nct6779_temp_label
;
data
->
temp_label_num
=
ARRAY_SIZE
(
nct6779_temp_label
);
...
...
@@ -2260,16 +3307,29 @@ static int nct6775_probe(struct platform_device *pdev)
data
->
REG_VIN
=
NCT6779_REG_IN
;
data
->
REG_IN_MINMAX
[
0
]
=
NCT6775_REG_IN_MIN
;
data
->
REG_IN_MINMAX
[
1
]
=
NCT6775_REG_IN_MAX
;
data
->
REG_TARGET
=
NCT6775_REG_TARGET
;
data
->
REG_FAN
=
NCT6779_REG_FAN
;
data
->
REG_FAN_MODE
=
NCT6775_REG_FAN_MODE
;
data
->
REG_FAN_MIN
=
NCT6776_REG_FAN_MIN
;
data
->
REG_FAN_PULSES
=
NCT6779_REG_FAN_PULSES
;
data
->
REG_FAN_TIME
[
0
]
=
NCT6775_REG_FAN_STOP_TIME
;
data
->
REG_FAN_TIME
[
1
]
=
NCT6775_REG_FAN_STEP_UP_TIME
;
data
->
REG_FAN_TIME
[
2
]
=
NCT6775_REG_FAN_STEP_DOWN_TIME
;
data
->
REG_TOLERANCE_H
=
NCT6776_REG_TOLERANCE_H
;
data
->
REG_PWM
[
0
]
=
NCT6775_REG_PWM
;
data
->
REG_PWM
[
1
]
=
NCT6775_REG_FAN_START_OUTPUT
;
data
->
REG_PWM
[
2
]
=
NCT6775_REG_FAN_STOP_OUTPUT
;
data
->
REG_PWM_READ
=
NCT6775_REG_PWM_READ
;
data
->
REG_PWM_MODE
=
NCT6776_REG_PWM_MODE
;
data
->
PWM_MODE_MASK
=
NCT6776_PWM_MODE_MASK
;
data
->
REG_AUTO_TEMP
=
NCT6775_REG_AUTO_TEMP
;
data
->
REG_AUTO_PWM
=
NCT6775_REG_AUTO_PWM
;
data
->
REG_CRITICAL_TEMP
=
NCT6775_REG_CRITICAL_TEMP
;
data
->
REG_CRITICAL_TEMP_TOLERANCE
=
NCT6775_REG_CRITICAL_TEMP_TOLERANCE
;
data
->
REG_TEMP_OFFSET
=
NCT6779_REG_TEMP_OFFSET
;
data
->
REG_TEMP_SOURCE
=
NCT6775_REG_TEMP_SOURCE
;
data
->
REG_TEMP_SEL
=
NCT6775_REG_TEMP_SEL
;
data
->
REG_ALARM
=
NCT6779_REG_ALARM
;
reg_temp
=
NCT6779_REG_TEMP
;
...
...
@@ -2484,6 +3544,31 @@ static int nct6775_probe(struct platform_device *pdev)
err
=
sysfs_create_group
(
&
dev
->
kobj
,
&
nct6775_group_pwm
[
i
]);
if
(
err
)
goto
exit_remove
;
if
(
data
->
REG_PWM
[
3
])
{
err
=
device_create_file
(
dev
,
&
sda_pwm_max
[
i
].
dev_attr
);
if
(
err
)
goto
exit_remove
;
}
if
(
data
->
REG_PWM
[
4
])
{
err
=
device_create_file
(
dev
,
&
sda_pwm_step
[
i
].
dev_attr
);
if
(
err
)
goto
exit_remove
;
}
}
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
sda_auto_pwm_arrays
);
i
++
)
{
struct
sensor_device_attribute_2
*
attr
=
&
sda_auto_pwm_arrays
[
i
];
if
(
!
(
data
->
has_pwm
&
(
1
<<
attr
->
nr
)))
continue
;
if
(
attr
->
index
>
data
->
auto_pwm_num
)
continue
;
err
=
device_create_file
(
dev
,
&
attr
->
dev_attr
);
if
(
err
)
goto
exit_remove
;
}
for
(
i
=
0
;
i
<
data
->
in_num
;
i
++
)
{
...
...
@@ -2518,7 +3603,7 @@ static int nct6775_probe(struct platform_device *pdev)
goto
exit_remove
;
}
err
=
device_create_file
(
dev
,
&
sda_fan_pulses
[
i
].
dev_attr
);
&
sda_fan_pulses
[
i
].
dev_attr
);
if
(
err
)
goto
exit_remove
;
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment