diff options
34 files changed, 3229 insertions, 284 deletions
diff --git a/Documentation/hwmon/adm1275 b/Documentation/hwmon/adm1275 index 6a3a6476cf20..097b3ccc4be7 100644 --- a/Documentation/hwmon/adm1275 +++ b/Documentation/hwmon/adm1275 | |||
@@ -43,8 +43,8 @@ Documentation/hwmon/pmbus for details. | |||
43 | Sysfs entries | 43 | Sysfs entries |
44 | ------------- | 44 | ------------- |
45 | 45 | ||
46 | The following attributes are supported. Limits are read-write; all other | 46 | The following attributes are supported. Limits are read-write, history reset |
47 | attributes are read-only. | 47 | attributes are write-only, all other attributes are read-only. |
48 | 48 | ||
49 | in1_label "vin1" or "vout1" depending on chip variant and | 49 | in1_label "vin1" or "vout1" depending on chip variant and |
50 | configuration. | 50 | configuration. |
@@ -53,8 +53,12 @@ in1_min Minumum Voltage. From VOUT_UV_WARN_LIMIT register. | |||
53 | in1_max Maximum voltage. From VOUT_OV_WARN_LIMIT register. | 53 | in1_max Maximum voltage. From VOUT_OV_WARN_LIMIT register. |
54 | in1_min_alarm Voltage low alarm. From VOLTAGE_UV_WARNING status. | 54 | in1_min_alarm Voltage low alarm. From VOLTAGE_UV_WARNING status. |
55 | in1_max_alarm Voltage high alarm. From VOLTAGE_OV_WARNING status. | 55 | in1_max_alarm Voltage high alarm. From VOLTAGE_OV_WARNING status. |
56 | in1_highest Historical maximum voltage. | ||
57 | in1_reset_history Write any value to reset history. | ||
56 | 58 | ||
57 | curr1_label "iout1" | 59 | curr1_label "iout1" |
58 | curr1_input Measured current. From READ_IOUT register. | 60 | curr1_input Measured current. From READ_IOUT register. |
59 | curr1_max Maximum current. From IOUT_OC_WARN_LIMIT register. | 61 | curr1_max Maximum current. From IOUT_OC_WARN_LIMIT register. |
60 | curr1_max_alarm Current high alarm. From IOUT_OC_WARN_LIMIT register. | 62 | curr1_max_alarm Current high alarm. From IOUT_OC_WARN_LIMIT register. |
63 | curr1_highest Historical maximum current. | ||
64 | curr1_reset_history Write any value to reset history. | ||
diff --git a/Documentation/hwmon/coretemp b/Documentation/hwmon/coretemp index f85e913a3401..fa8776ab9b18 100644 --- a/Documentation/hwmon/coretemp +++ b/Documentation/hwmon/coretemp | |||
@@ -35,6 +35,13 @@ the Out-Of-Spec bit. Following table summarizes the exported sysfs files: | |||
35 | All Sysfs entries are named with their core_id (represented here by 'X'). | 35 | All Sysfs entries are named with their core_id (represented here by 'X'). |
36 | tempX_input - Core temperature (in millidegrees Celsius). | 36 | tempX_input - Core temperature (in millidegrees Celsius). |
37 | tempX_max - All cooling devices should be turned on (on Core2). | 37 | tempX_max - All cooling devices should be turned on (on Core2). |
38 | Initialized with IA32_THERM_INTERRUPT. When the CPU | ||
39 | temperature reaches this temperature, an interrupt is | ||
40 | generated and tempX_max_alarm is set. | ||
41 | tempX_max_hyst - If the CPU temperature falls below than temperature, | ||
42 | an interrupt is generated and tempX_max_alarm is reset. | ||
43 | tempX_max_alarm - Set if the temperature reaches or exceeds tempX_max. | ||
44 | Reset if the temperature drops to or below tempX_max_hyst. | ||
38 | tempX_crit - Maximum junction temperature (in millidegrees Celsius). | 45 | tempX_crit - Maximum junction temperature (in millidegrees Celsius). |
39 | tempX_crit_alarm - Set when Out-of-spec bit is set, never clears. | 46 | tempX_crit_alarm - Set when Out-of-spec bit is set, never clears. |
40 | Correct CPU operation is no longer guaranteed. | 47 | Correct CPU operation is no longer guaranteed. |
diff --git a/Documentation/hwmon/lm25066 b/Documentation/hwmon/lm25066 new file mode 100644 index 000000000000..a21db81c4591 --- /dev/null +++ b/Documentation/hwmon/lm25066 | |||
@@ -0,0 +1,90 @@ | |||
1 | Kernel driver max8688 | ||
2 | ===================== | ||
3 | |||
4 | Supported chips: | ||
5 | * National Semiconductor LM25066 | ||
6 | Prefix: 'lm25066' | ||
7 | Addresses scanned: - | ||
8 | Datasheets: | ||
9 | http://www.national.com/pf/LM/LM25066.html | ||
10 | http://www.national.com/pf/LM/LM25066A.html | ||
11 | * National Semiconductor LM5064 | ||
12 | Prefix: 'lm5064' | ||
13 | Addresses scanned: - | ||
14 | Datasheet: | ||
15 | http://www.national.com/pf/LM/LM5064.html | ||
16 | * National Semiconductor LM5066 | ||
17 | Prefix: 'lm5066' | ||
18 | Addresses scanned: - | ||
19 | Datasheet: | ||
20 | http://www.national.com/pf/LM/LM5066.html | ||
21 | |||
22 | Author: Guenter Roeck <guenter.roeck@ericsson.com> | ||
23 | |||
24 | |||
25 | Description | ||
26 | ----------- | ||
27 | |||
28 | This driver supports hardware montoring for National Semiconductor LM25066, | ||
29 | LM5064, and LM5064 Power Management, Monitoring, Control, and Protection ICs. | ||
30 | |||
31 | The driver is a client driver to the core PMBus driver. Please see | ||
32 | Documentation/hwmon/pmbus for details on PMBus client drivers. | ||
33 | |||
34 | |||
35 | Usage Notes | ||
36 | ----------- | ||
37 | |||
38 | This driver does not auto-detect devices. You will have to instantiate the | ||
39 | devices explicitly. Please see Documentation/i2c/instantiating-devices for | ||
40 | details. | ||
41 | |||
42 | |||
43 | Platform data support | ||
44 | --------------------- | ||
45 | |||
46 | The driver supports standard PMBus driver platform data. | ||
47 | |||
48 | |||
49 | Sysfs entries | ||
50 | ------------- | ||
51 | |||
52 | The following attributes are supported. Limits are read-write; all other | ||
53 | attributes are read-only. | ||
54 | |||
55 | in1_label "vin" | ||
56 | in1_input Measured input voltage. | ||
57 | in1_average Average measured input voltage. | ||
58 | in1_min Minimum input voltage. | ||
59 | in1_max Maximum input voltage. | ||
60 | in1_min_alarm Input voltage low alarm. | ||
61 | in1_max_alarm Input voltage high alarm. | ||
62 | |||
63 | in2_label "vout1" | ||
64 | in2_input Measured output voltage. | ||
65 | in2_average Average measured output voltage. | ||
66 | in2_min Minimum output voltage. | ||
67 | in2_min_alarm Output voltage low alarm. | ||
68 | |||
69 | in3_label "vout2" | ||
70 | in3_input Measured voltage on vaux pin | ||
71 | |||
72 | curr1_label "iin" | ||
73 | curr1_input Measured input current. | ||
74 | curr1_average Average measured input current. | ||
75 | curr1_max Maximum input current. | ||
76 | curr1_max_alarm Input current high alarm. | ||
77 | |||
78 | power1_label "pin" | ||
79 | power1_input Measured input power. | ||
80 | power1_average Average measured input power. | ||
81 | power1_max Maximum input power limit. | ||
82 | power1_alarm Input power alarm | ||
83 | power1_input_highest Historical maximum power. | ||
84 | power1_reset_history Write any value to reset maximum power history. | ||
85 | |||
86 | temp1_input Measured temperature. | ||
87 | temp1_max Maximum temperature. | ||
88 | temp1_crit Critical high temperature. | ||
89 | temp1_max_alarm Chip temperature high alarm. | ||
90 | temp1_crit_alarm Chip temperature critical high alarm. | ||
diff --git a/Documentation/hwmon/lm90 b/Documentation/hwmon/lm90 index f3efd18e87f4..9cd14cfe6515 100644 --- a/Documentation/hwmon/lm90 +++ b/Documentation/hwmon/lm90 | |||
@@ -113,7 +113,11 @@ Supported chips: | |||
113 | Prefix: 'w83l771' | 113 | Prefix: 'w83l771' |
114 | Addresses scanned: I2C 0x4c | 114 | Addresses scanned: I2C 0x4c |
115 | Datasheet: Not publicly available, can be requested from Nuvoton | 115 | Datasheet: Not publicly available, can be requested from Nuvoton |
116 | 116 | * Philips/NXP SA56004X | |
117 | Prefix: 'sa56004' | ||
118 | Addresses scanned: I2C 0x48 through 0x4F | ||
119 | Datasheet: Publicly available at NXP website | ||
120 | http://ics.nxp.com/products/interface/datasheet/sa56004x.pdf | ||
117 | 121 | ||
118 | Author: Jean Delvare <khali@linux-fr.org> | 122 | Author: Jean Delvare <khali@linux-fr.org> |
119 | 123 | ||
@@ -193,6 +197,9 @@ W83L771AWG/ASG | |||
193 | * The AWG and ASG variants only differ in package format. | 197 | * The AWG and ASG variants only differ in package format. |
194 | * Diode ideality factor configuration (remote sensor) at 0xE3 | 198 | * Diode ideality factor configuration (remote sensor) at 0xE3 |
195 | 199 | ||
200 | SA56004X: | ||
201 | * Better local resolution | ||
202 | |||
196 | All temperature values are given in degrees Celsius. Resolution | 203 | All temperature values are given in degrees Celsius. Resolution |
197 | is 1.0 degree for the local temperature, 0.125 degree for the remote | 204 | is 1.0 degree for the local temperature, 0.125 degree for the remote |
198 | temperature, except for the MAX6657, MAX6658 and MAX6659 which have a | 205 | temperature, except for the MAX6657, MAX6658 and MAX6659 which have a |
diff --git a/Documentation/hwmon/lm95245 b/Documentation/hwmon/lm95245 new file mode 100644 index 000000000000..cbd8aeab7124 --- /dev/null +++ b/Documentation/hwmon/lm95245 | |||
@@ -0,0 +1,33 @@ | |||
1 | Kernel driver lm95245 | ||
2 | ================== | ||
3 | |||
4 | Supported chips: | ||
5 | * National Semiconductor LM95245 | ||
6 | Addresses scanned: I2C 0x18, 0x19, 0x29, 0x4c, 0x4d | ||
7 | Datasheet: Publicly available at the National Semiconductor website | ||
8 | http://www.national.com/mpf/LM/LM95245.html | ||
9 | |||
10 | |||
11 | Author: Alexander Stein <alexander.stein@systec-electronic.com> | ||
12 | |||
13 | Description | ||
14 | ----------- | ||
15 | |||
16 | The LM95245 is an 11-bit digital temperature sensor with a 2-wire System | ||
17 | Management Bus (SMBus) interface and TruTherm technology that can monitor | ||
18 | the temperature of a remote diode as well as its own temperature. | ||
19 | The LM95245 can be used to very accurately monitor the temperature of | ||
20 | external devices such as microprocessors. | ||
21 | |||
22 | All temperature values are given in millidegrees Celsius. Local temperature | ||
23 | is given within a range of -127 to +127.875 degrees. Remote temperatures are | ||
24 | given within a range of -127 to +255 degrees. Resolution depends on | ||
25 | temperature input and range. | ||
26 | |||
27 | Each sensor has its own critical limit, but the hysteresis is common to all | ||
28 | two channels. | ||
29 | |||
30 | The lm95245 driver can change its update interval to a fixed set of values. | ||
31 | It will round up to the next selectable interval. See the datasheet for exact | ||
32 | values. Reading sensor values more often will do no harm, but will return | ||
33 | 'old' values. | ||
diff --git a/Documentation/hwmon/max16064 b/Documentation/hwmon/max16064 index 41728999e142..f6e8bcbfaccf 100644 --- a/Documentation/hwmon/max16064 +++ b/Documentation/hwmon/max16064 | |||
@@ -50,6 +50,8 @@ in[1-4]_min_alarm Voltage low alarm. From VOLTAGE_UV_WARNING status. | |||
50 | in[1-4]_max_alarm Voltage high alarm. From VOLTAGE_OV_WARNING status. | 50 | in[1-4]_max_alarm Voltage high alarm. From VOLTAGE_OV_WARNING status. |
51 | in[1-4]_lcrit_alarm Voltage critical low alarm. From VOLTAGE_UV_FAULT status. | 51 | in[1-4]_lcrit_alarm Voltage critical low alarm. From VOLTAGE_UV_FAULT status. |
52 | in[1-4]_crit_alarm Voltage critical high alarm. From VOLTAGE_OV_FAULT status. | 52 | in[1-4]_crit_alarm Voltage critical high alarm. From VOLTAGE_OV_FAULT status. |
53 | in[1-4]_highest Historical maximum voltage. | ||
54 | in[1-4]_reset_history Write any value to reset history. | ||
53 | 55 | ||
54 | temp1_input Measured temperature. From READ_TEMPERATURE_1 register. | 56 | temp1_input Measured temperature. From READ_TEMPERATURE_1 register. |
55 | temp1_max Maximum temperature. From OT_WARN_LIMIT register. | 57 | temp1_max Maximum temperature. From OT_WARN_LIMIT register. |
@@ -60,3 +62,5 @@ temp1_max_alarm Chip temperature high alarm. Set by comparing | |||
60 | temp1_crit_alarm Chip temperature critical high alarm. Set by comparing | 62 | temp1_crit_alarm Chip temperature critical high alarm. Set by comparing |
61 | READ_TEMPERATURE_1 with OT_FAULT_LIMIT if TEMP_OT_FAULT | 63 | READ_TEMPERATURE_1 with OT_FAULT_LIMIT if TEMP_OT_FAULT |
62 | status is set. | 64 | status is set. |
65 | temp1_highest Historical maximum temperature. | ||
66 | temp1_reset_history Write any value to reset history. | ||
diff --git a/Documentation/hwmon/max1668 b/Documentation/hwmon/max1668 new file mode 100644 index 000000000000..0616ed9758df --- /dev/null +++ b/Documentation/hwmon/max1668 | |||
@@ -0,0 +1,60 @@ | |||
1 | Kernel driver max1668 | ||
2 | ===================== | ||
3 | |||
4 | Supported chips: | ||
5 | * Maxim MAX1668, MAX1805 and MAX1989 | ||
6 | Prefix: 'max1668' | ||
7 | Addresses scanned: I2C 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, 0x4c, 0x4d, 0x4e | ||
8 | Datasheet: http://datasheets.maxim-ic.com/en/ds/MAX1668-MAX1989.pdf | ||
9 | |||
10 | Author: | ||
11 | David George <david.george@ska.ac.za> | ||
12 | |||
13 | Description | ||
14 | ----------- | ||
15 | |||
16 | This driver implements support for the Maxim MAX1668, MAX1805 and MAX1989 | ||
17 | chips. | ||
18 | |||
19 | The three devices are very similar, but the MAX1805 has a reduced feature | ||
20 | set; only two remote temperature inputs vs the four avaible on the other | ||
21 | two ICs. | ||
22 | |||
23 | The driver is able to distinguish between the devices and creates sysfs | ||
24 | entries as follows: | ||
25 | |||
26 | MAX1805, MAX1668 and MAX1989: | ||
27 | |||
28 | temp1_input ro local (ambient) temperature | ||
29 | temp1_max rw local temperature maximum threshold for alarm | ||
30 | temp1_max_alarm ro local temperature maximum threshold alarm | ||
31 | temp1_min rw local temperature minimum threshold for alarm | ||
32 | temp1_min_alarm ro local temperature minimum threshold alarm | ||
33 | temp2_input ro remote temperature 1 | ||
34 | temp2_max rw remote temperature 1 maximum threshold for alarm | ||
35 | temp2_max_alarm ro remote temperature 1 maximum threshold alarm | ||
36 | temp2_min rw remote temperature 1 minimum threshold for alarm | ||
37 | temp2_min_alarm ro remote temperature 1 minimum threshold alarm | ||
38 | temp3_input ro remote temperature 2 | ||
39 | temp3_max rw remote temperature 2 maximum threshold for alarm | ||
40 | temp3_max_alarm ro remote temperature 2 maximum threshold alarm | ||
41 | temp3_min rw remote temperature 2 minimum threshold for alarm | ||
42 | temp3_min_alarm ro remote temperature 2 minimum threshold alarm | ||
43 | |||
44 | MAX1668 and MAX1989 only: | ||
45 | temp4_input ro remote temperature 3 | ||
46 | temp4_max rw remote temperature 3 maximum threshold for alarm | ||
47 | temp4_max_alarm ro remote temperature 3 maximum threshold alarm | ||
48 | temp4_min rw remote temperature 3 minimum threshold for alarm | ||
49 | temp4_min_alarm ro remote temperature 3 minimum threshold alarm | ||
50 | temp5_input ro remote temperature 4 | ||
51 | temp5_max rw remote temperature 4 maximum threshold for alarm | ||
52 | temp5_max_alarm ro remote temperature 4 maximum threshold alarm | ||
53 | temp5_min rw remote temperature 4 minimum threshold for alarm | ||
54 | temp5_min_alarm ro remote temperature 4 minimum threshold alarm | ||
55 | |||
56 | Module Parameters | ||
57 | ----------------- | ||
58 | |||
59 | * read_only: int | ||
60 | Set to non-zero if you wish to prevent write access to alarm thresholds. | ||
diff --git a/Documentation/hwmon/max34440 b/Documentation/hwmon/max34440 index 6c525dd07d59..8ab51536a1eb 100644 --- a/Documentation/hwmon/max34440 +++ b/Documentation/hwmon/max34440 | |||
@@ -56,6 +56,8 @@ in[1-6]_min_alarm Voltage low alarm. From VOLTAGE_UV_WARNING status. | |||
56 | in[1-6]_max_alarm Voltage high alarm. From VOLTAGE_OV_WARNING status. | 56 | in[1-6]_max_alarm Voltage high alarm. From VOLTAGE_OV_WARNING status. |
57 | in[1-6]_lcrit_alarm Voltage critical low alarm. From VOLTAGE_UV_FAULT status. | 57 | in[1-6]_lcrit_alarm Voltage critical low alarm. From VOLTAGE_UV_FAULT status. |
58 | in[1-6]_crit_alarm Voltage critical high alarm. From VOLTAGE_OV_FAULT status. | 58 | in[1-6]_crit_alarm Voltage critical high alarm. From VOLTAGE_OV_FAULT status. |
59 | in[1-6]_highest Historical maximum voltage. | ||
60 | in[1-6]_reset_history Write any value to reset history. | ||
59 | 61 | ||
60 | curr[1-6]_label "iout[1-6]". | 62 | curr[1-6]_label "iout[1-6]". |
61 | curr[1-6]_input Measured current. From READ_IOUT register. | 63 | curr[1-6]_input Measured current. From READ_IOUT register. |
@@ -63,6 +65,8 @@ curr[1-6]_max Maximum current. From IOUT_OC_WARN_LIMIT register. | |||
63 | curr[1-6]_crit Critical maximum current. From IOUT_OC_FAULT_LIMIT register. | 65 | curr[1-6]_crit Critical maximum current. From IOUT_OC_FAULT_LIMIT register. |
64 | curr[1-6]_max_alarm Current high alarm. From IOUT_OC_WARNING status. | 66 | curr[1-6]_max_alarm Current high alarm. From IOUT_OC_WARNING status. |
65 | curr[1-6]_crit_alarm Current critical high alarm. From IOUT_OC_FAULT status. | 67 | curr[1-6]_crit_alarm Current critical high alarm. From IOUT_OC_FAULT status. |
68 | curr[1-6]_highest Historical maximum current. | ||
69 | curr[1-6]_reset_history Write any value to reset history. | ||
66 | 70 | ||
67 | in6 and curr6 attributes only exist for MAX34440. | 71 | in6 and curr6 attributes only exist for MAX34440. |
68 | 72 | ||
@@ -75,5 +79,7 @@ temp[1-8]_max Maximum temperature. From OT_WARN_LIMIT register. | |||
75 | temp[1-8]_crit Critical high temperature. From OT_FAULT_LIMIT register. | 79 | temp[1-8]_crit Critical high temperature. From OT_FAULT_LIMIT register. |
76 | temp[1-8]_max_alarm Temperature high alarm. | 80 | temp[1-8]_max_alarm Temperature high alarm. |
77 | temp[1-8]_crit_alarm Temperature critical high alarm. | 81 | temp[1-8]_crit_alarm Temperature critical high alarm. |
82 | temp[1-8]_highest Historical maximum temperature. | ||
83 | temp[1-8]_reset_history Write any value to reset history. | ||
78 | 84 | ||
79 | temp7 and temp8 attributes only exist for MAX34440. | 85 | temp7 and temp8 attributes only exist for MAX34440. |
diff --git a/Documentation/hwmon/max8688 b/Documentation/hwmon/max8688 index 0ddd3a412030..71ed10a3c94e 100644 --- a/Documentation/hwmon/max8688 +++ b/Documentation/hwmon/max8688 | |||
@@ -50,6 +50,8 @@ in1_min_alarm Voltage low alarm. From VOLTAGE_UV_WARNING status. | |||
50 | in1_max_alarm Voltage high alarm. From VOLTAGE_OV_WARNING status. | 50 | in1_max_alarm Voltage high alarm. From VOLTAGE_OV_WARNING status. |
51 | in1_lcrit_alarm Voltage critical low alarm. From VOLTAGE_UV_FAULT status. | 51 | in1_lcrit_alarm Voltage critical low alarm. From VOLTAGE_UV_FAULT status. |
52 | in1_crit_alarm Voltage critical high alarm. From VOLTAGE_OV_FAULT status. | 52 | in1_crit_alarm Voltage critical high alarm. From VOLTAGE_OV_FAULT status. |
53 | in1_highest Historical maximum voltage. | ||
54 | in1_reset_history Write any value to reset history. | ||
53 | 55 | ||
54 | curr1_label "iout1" | 56 | curr1_label "iout1" |
55 | curr1_input Measured current. From READ_IOUT register. | 57 | curr1_input Measured current. From READ_IOUT register. |
@@ -57,6 +59,8 @@ curr1_max Maximum current. From IOUT_OC_WARN_LIMIT register. | |||
57 | curr1_crit Critical maximum current. From IOUT_OC_FAULT_LIMIT register. | 59 | curr1_crit Critical maximum current. From IOUT_OC_FAULT_LIMIT register. |
58 | curr1_max_alarm Current high alarm. From IOUT_OC_WARN_LIMIT register. | 60 | curr1_max_alarm Current high alarm. From IOUT_OC_WARN_LIMIT register. |
59 | curr1_crit_alarm Current critical high alarm. From IOUT_OC_FAULT status. | 61 | curr1_crit_alarm Current critical high alarm. From IOUT_OC_FAULT status. |
62 | curr1_highest Historical maximum current. | ||
63 | curr1_reset_history Write any value to reset history. | ||
60 | 64 | ||
61 | temp1_input Measured temperature. From READ_TEMPERATURE_1 register. | 65 | temp1_input Measured temperature. From READ_TEMPERATURE_1 register. |
62 | temp1_max Maximum temperature. From OT_WARN_LIMIT register. | 66 | temp1_max Maximum temperature. From OT_WARN_LIMIT register. |
@@ -67,3 +71,5 @@ temp1_max_alarm Chip temperature high alarm. Set by comparing | |||
67 | temp1_crit_alarm Chip temperature critical high alarm. Set by comparing | 71 | temp1_crit_alarm Chip temperature critical high alarm. Set by comparing |
68 | READ_TEMPERATURE_1 with OT_FAULT_LIMIT if TEMP_OT_FAULT | 72 | READ_TEMPERATURE_1 with OT_FAULT_LIMIT if TEMP_OT_FAULT |
69 | status is set. | 73 | status is set. |
74 | temp1_highest Historical maximum temperature. | ||
75 | temp1_reset_history Write any value to reset history. | ||
diff --git a/Documentation/hwmon/ntc_thermistor b/Documentation/hwmon/ntc_thermistor new file mode 100644 index 000000000000..3bfda94096fd --- /dev/null +++ b/Documentation/hwmon/ntc_thermistor | |||
@@ -0,0 +1,93 @@ | |||
1 | Kernel driver ntc_thermistor | ||
2 | ================= | ||
3 | |||
4 | Supported thermistors: | ||
5 | * Murata NTC Thermistors NCP15WB473, NCP18WB473, NCP21WB473, NCP03WB473, NCP15WL333 | ||
6 | Prefixes: 'ncp15wb473', 'ncp18wb473', 'ncp21wb473', 'ncp03wb473', 'ncp15wl333' | ||
7 | Datasheet: Publicly available at Murata | ||
8 | |||
9 | Other NTC thermistors can be supported simply by adding compensation | ||
10 | tables; e.g., NCP15WL333 support is added by the table ncpXXwl333. | ||
11 | |||
12 | Authors: | ||
13 | MyungJoo Ham <myungjoo.ham@samsung.com> | ||
14 | |||
15 | Description | ||
16 | ----------- | ||
17 | |||
18 | The NTC thermistor is a simple thermistor that requires users to provide the | ||
19 | resistance and lookup the corresponding compensation table to get the | ||
20 | temperature input. | ||
21 | |||
22 | The NTC driver provides lookup tables with a linear approximation function | ||
23 | and four circuit models with an option not to use any of the four models. | ||
24 | |||
25 | The four circuit models provided are: | ||
26 | |||
27 | $: resister, [TH]: the thermistor | ||
28 | |||
29 | 1. connect = NTC_CONNECTED_POSITIVE, pullup_ohm > 0 | ||
30 | |||
31 | [pullup_uV] | ||
32 | | | | ||
33 | [TH] $ (pullup_ohm) | ||
34 | | | | ||
35 | +----+-----------------------[read_uV] | ||
36 | | | ||
37 | $ (pulldown_ohm) | ||
38 | | | ||
39 | --- (ground) | ||
40 | |||
41 | 2. connect = NTC_CONNECTED_POSITIVE, pullup_ohm = 0 (not-connected) | ||
42 | |||
43 | [pullup_uV] | ||
44 | | | ||
45 | [TH] | ||
46 | | | ||
47 | +----------------------------[read_uV] | ||
48 | | | ||
49 | $ (pulldown_ohm) | ||
50 | | | ||
51 | --- (ground) | ||
52 | |||
53 | 3. connect = NTC_CONNECTED_GROUND, pulldown_ohm > 0 | ||
54 | |||
55 | [pullup_uV] | ||
56 | | | ||
57 | $ (pullup_ohm) | ||
58 | | | ||
59 | +----+-----------------------[read_uV] | ||
60 | | | | ||
61 | [TH] $ (pulldown_ohm) | ||
62 | | | | ||
63 | -------- (ground) | ||
64 | |||
65 | 4. connect = NTC_CONNECTED_GROUND, pulldown_ohm = 0 (not-connected) | ||
66 | |||
67 | [pullup_uV] | ||
68 | | | ||
69 | $ (pullup_ohm) | ||
70 | | | ||
71 | +----------------------------[read_uV] | ||
72 | | | ||
73 | [TH] | ||
74 | | | ||
75 | --- (ground) | ||
76 | |||
77 | When one of the four circuit models is used, read_uV, pullup_uV, pullup_ohm, | ||
78 | pulldown_ohm, and connect should be provided. When none of the four models | ||
79 | are suitable or the user can get the resistance directly, the user should | ||
80 | provide read_ohm and _not_ provide the others. | ||
81 | |||
82 | Sysfs Interface | ||
83 | --------------- | ||
84 | name the mandatory global attribute, the thermistor name. | ||
85 | |||
86 | temp1_type always 4 (thermistor) | ||
87 | RO | ||
88 | |||
89 | temp1_input measure the temperature and provide the measured value. | ||
90 | (reading this file initiates the reading procedure.) | ||
91 | RO | ||
92 | |||
93 | Note that each NTC thermistor has only _one_ thermistor; thus, only temp1 exists. | ||
diff --git a/Documentation/hwmon/pmbus b/Documentation/hwmon/pmbus index 5e462fc7f99b..c36c1c1a62bb 100644 --- a/Documentation/hwmon/pmbus +++ b/Documentation/hwmon/pmbus | |||
@@ -13,6 +13,13 @@ Supported chips: | |||
13 | Prefix: 'ltc2978' | 13 | Prefix: 'ltc2978' |
14 | Addresses scanned: - | 14 | Addresses scanned: - |
15 | Datasheet: http://cds.linear.com/docs/Datasheet/2978fa.pdf | 15 | Datasheet: http://cds.linear.com/docs/Datasheet/2978fa.pdf |
16 | * ON Semiconductor ADP4000, NCP4200, NCP4208 | ||
17 | Prefixes: 'adp4000', 'ncp4200', 'ncp4208' | ||
18 | Addresses scanned: - | ||
19 | Datasheets: | ||
20 | http://www.onsemi.com/pub_link/Collateral/ADP4000-D.PDF | ||
21 | http://www.onsemi.com/pub_link/Collateral/NCP4200-D.PDF | ||
22 | http://www.onsemi.com/pub_link/Collateral/JUNE%202009-%20REV.%200.PDF | ||
16 | * Generic PMBus devices | 23 | * Generic PMBus devices |
17 | Prefix: 'pmbus' | 24 | Prefix: 'pmbus' |
18 | Addresses scanned: - | 25 | Addresses scanned: - |
diff --git a/Documentation/hwmon/sysfs-interface b/Documentation/hwmon/sysfs-interface index 8f63c244f1aa..a4aa8f600e09 100644 --- a/Documentation/hwmon/sysfs-interface +++ b/Documentation/hwmon/sysfs-interface | |||
@@ -139,6 +139,29 @@ in[0-*]_input Voltage input value. | |||
139 | thumb: drivers should report the voltage values at the | 139 | thumb: drivers should report the voltage values at the |
140 | "pins" of the chip. | 140 | "pins" of the chip. |
141 | 141 | ||
142 | in[0-*]_average | ||
143 | Average voltage | ||
144 | Unit: millivolt | ||
145 | RO | ||
146 | |||
147 | in[0-*]_lowest | ||
148 | Historical minimum voltage | ||
149 | Unit: millivolt | ||
150 | RO | ||
151 | |||
152 | in[0-*]_highest | ||
153 | Historical maximum voltage | ||
154 | Unit: millivolt | ||
155 | RO | ||
156 | |||
157 | in[0-*]_reset_history | ||
158 | Reset inX_lowest and inX_highest | ||
159 | WO | ||
160 | |||
161 | in_reset_history | ||
162 | Reset inX_lowest and inX_highest for all sensors | ||
163 | WO | ||
164 | |||
142 | in[0-*]_label Suggested voltage channel label. | 165 | in[0-*]_label Suggested voltage channel label. |
143 | Text string | 166 | Text string |
144 | Should only be created if the driver has hints about what | 167 | Should only be created if the driver has hints about what |
@@ -407,6 +430,29 @@ curr[1-*]_input Current input value | |||
407 | Unit: milliampere | 430 | Unit: milliampere |
408 | RO | 431 | RO |
409 | 432 | ||
433 | curr[1-*]_average | ||
434 | Average current use | ||
435 | Unit: milliampere | ||
436 | RO | ||
437 | |||
438 | curr[1-*]_lowest | ||
439 | Historical minimum current | ||
440 | Unit: milliampere | ||
441 | RO | ||
442 | |||
443 | curr[1-*]_highest | ||
444 | Historical maximum current | ||
445 | Unit: milliampere | ||
446 | RO | ||
447 | |||
448 | curr[1-*]_reset_history | ||
449 | Reset currX_lowest and currX_highest | ||
450 | WO | ||
451 | |||
452 | curr_reset_history | ||
453 | Reset currX_lowest and currX_highest for all sensors | ||
454 | WO | ||
455 | |||
410 | Also see the Alarms section for status flags associated with currents. | 456 | Also see the Alarms section for status flags associated with currents. |
411 | 457 | ||
412 | ********* | 458 | ********* |
diff --git a/MAINTAINERS b/MAINTAINERS index 1d2e79db0f58..cf5e8a79309b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -4150,6 +4150,13 @@ S: Orphan | |||
4150 | F: drivers/video/matrox/matroxfb_* | 4150 | F: drivers/video/matrox/matroxfb_* |
4151 | F: include/linux/matroxfb.h | 4151 | F: include/linux/matroxfb.h |
4152 | 4152 | ||
4153 | MAX1668 TEMPERATURE SENSOR DRIVER | ||
4154 | M: "David George" <david.george@ska.ac.za> | ||
4155 | L: lm-sensors@lm-sensors.org | ||
4156 | S: Maintained | ||
4157 | F: Documentation/hwmon/max1668 | ||
4158 | F: drivers/hwmon/max1668.c | ||
4159 | |||
4153 | MAX6650 HARDWARE MONITOR AND FAN CONTROLLER DRIVER | 4160 | MAX6650 HARDWARE MONITOR AND FAN CONTROLLER DRIVER |
4154 | M: "Hans J. Koch" <hjk@hansjkoch.de> | 4161 | M: "Hans J. Koch" <hjk@hansjkoch.de> |
4155 | L: lm-sensors@lm-sensors.org | 4162 | L: lm-sensors@lm-sensors.org |
@@ -4999,6 +5006,17 @@ F: drivers/i2c/busses/i2c-puv3.c | |||
4999 | F: drivers/video/fb-puv3.c | 5006 | F: drivers/video/fb-puv3.c |
5000 | F: drivers/rtc/rtc-puv3.c | 5007 | F: drivers/rtc/rtc-puv3.c |
5001 | 5008 | ||
5009 | PMBUS HARDWARE MONITORING DRIVERS | ||
5010 | M: Guenter Roeck <guenter.roeck@ericsson.com> | ||
5011 | L: lm-sensors@lm-sensors.org | ||
5012 | W: http://www.lm-sensors.org/ | ||
5013 | W: http://www.roeck-us.net/linux/drivers/ | ||
5014 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git | ||
5015 | S: Maintained | ||
5016 | F: Documentation/hwmon/pmbus | ||
5017 | F: drivers/hwmon/pmbus/ | ||
5018 | F: include/linux/i2c/pmbus.h | ||
5019 | |||
5002 | PMC SIERRA MaxRAID DRIVER | 5020 | PMC SIERRA MaxRAID DRIVER |
5003 | M: Anil Ravindranath <anil_ravindranath@pmc-sierra.com> | 5021 | M: Anil Ravindranath <anil_ravindranath@pmc-sierra.com> |
5004 | L: linux-scsi@vger.kernel.org | 5022 | L: linux-scsi@vger.kernel.org |
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 0598cd22edf2..0b62c3c6b7ce 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig | |||
@@ -623,7 +623,7 @@ config SENSORS_LM90 | |||
623 | LM86, LM89 and LM99, Analog Devices ADM1032, ADT7461, and ADT7461A, | 623 | LM86, LM89 and LM99, Analog Devices ADM1032, ADT7461, and ADT7461A, |
624 | Maxim MAX6646, MAX6647, MAX6648, MAX6649, MAX6657, MAX6658, MAX6659, | 624 | Maxim MAX6646, MAX6647, MAX6648, MAX6649, MAX6657, MAX6658, MAX6659, |
625 | MAX6680, MAX6681, MAX6692, MAX6695, MAX6696, ON Semiconductor NCT1008, | 625 | MAX6680, MAX6681, MAX6692, MAX6695, MAX6696, ON Semiconductor NCT1008, |
626 | and Winbond/Nuvoton W83L771W/G/AWG/ASG sensor chips. | 626 | Winbond/Nuvoton W83L771W/G/AWG/ASG and Philips SA56004 sensor chips. |
627 | 627 | ||
628 | This driver can also be built as a module. If so, the module | 628 | This driver can also be built as a module. If so, the module |
629 | will be called lm90. | 629 | will be called lm90. |
@@ -694,14 +694,24 @@ config SENSORS_LTC4261 | |||
694 | be called ltc4261. | 694 | be called ltc4261. |
695 | 695 | ||
696 | config SENSORS_LM95241 | 696 | config SENSORS_LM95241 |
697 | tristate "National Semiconductor LM95241 sensor chip" | 697 | tristate "National Semiconductor LM95241 and compatibles" |
698 | depends on I2C | 698 | depends on I2C |
699 | help | 699 | help |
700 | If you say yes here you get support for LM95241 sensor chip. | 700 | If you say yes here you get support for LM95231 and LM95241 sensor |
701 | chips. | ||
701 | 702 | ||
702 | This driver can also be built as a module. If so, the module | 703 | This driver can also be built as a module. If so, the module |
703 | will be called lm95241. | 704 | will be called lm95241. |
704 | 705 | ||
706 | config SENSORS_LM95245 | ||
707 | tristate "National Semiconductor LM95245 sensor chip" | ||
708 | depends on I2C && EXPERIMENTAL | ||
709 | help | ||
710 | If you say yes here you get support for LM95245 sensor chip. | ||
711 | |||
712 | This driver can also be built as a module. If so, the module | ||
713 | will be called lm95245. | ||
714 | |||
705 | config SENSORS_MAX1111 | 715 | config SENSORS_MAX1111 |
706 | tristate "Maxim MAX1111 Multichannel, Serial 8-bit ADC chip" | 716 | tristate "Maxim MAX1111 Multichannel, Serial 8-bit ADC chip" |
707 | depends on SPI_MASTER | 717 | depends on SPI_MASTER |
@@ -736,6 +746,16 @@ config SENSORS_MAX1619 | |||
736 | This driver can also be built as a module. If so, the module | 746 | This driver can also be built as a module. If so, the module |
737 | will be called max1619. | 747 | will be called max1619. |
738 | 748 | ||
749 | config SENSORS_MAX1668 | ||
750 | tristate "Maxim MAX1668 and compatibles" | ||
751 | depends on I2C && EXPERIMENTAL | ||
752 | help | ||
753 | If you say yes here you get support for MAX1668, MAX1989 and | ||
754 | MAX1805 chips. | ||
755 | |||
756 | This driver can also be built as a module. If so, the module | ||
757 | will be called max1668. | ||
758 | |||
739 | config SENSORS_MAX6639 | 759 | config SENSORS_MAX6639 |
740 | tristate "Maxim MAX6639 sensor chip" | 760 | tristate "Maxim MAX6639 sensor chip" |
741 | depends on I2C && EXPERIMENTAL | 761 | depends on I2C && EXPERIMENTAL |
@@ -767,6 +787,20 @@ config SENSORS_MAX6650 | |||
767 | This driver can also be built as a module. If so, the module | 787 | This driver can also be built as a module. If so, the module |
768 | will be called max6650. | 788 | will be called max6650. |
769 | 789 | ||
790 | config SENSORS_NTC_THERMISTOR | ||
791 | tristate "NTC thermistor support" | ||
792 | depends on EXPERIMENTAL | ||
793 | help | ||
794 | This driver supports NTC thermistors sensor reading and its | ||
795 | interpretation. The driver can also monitor the temperature and | ||
796 | send notifications about the temperature. | ||
797 | |||
798 | Currently, this driver supports | ||
799 | NCP15WB473, NCP18WB473, NCP21WB473, NCP03WB473, and NCP15WL333. | ||
800 | |||
801 | This driver can also be built as a module. If so, the module | ||
802 | will be called ntc-thermistor. | ||
803 | |||
770 | config SENSORS_PC87360 | 804 | config SENSORS_PC87360 |
771 | tristate "National Semiconductor PC87360 family" | 805 | tristate "National Semiconductor PC87360 family" |
772 | select HWMON_VID | 806 | select HWMON_VID |
@@ -807,92 +841,7 @@ config SENSORS_PCF8591 | |||
807 | These devices are hard to detect and rarely found on mainstream | 841 | These devices are hard to detect and rarely found on mainstream |
808 | hardware. If unsure, say N. | 842 | hardware. If unsure, say N. |
809 | 843 | ||
810 | config PMBUS | 844 | source drivers/hwmon/pmbus/Kconfig |
811 | tristate "PMBus support" | ||
812 | depends on I2C && EXPERIMENTAL | ||
813 | default n | ||
814 | help | ||
815 | Say yes here if you want to enable PMBus support. | ||
816 | |||
817 | This driver can also be built as a module. If so, the module will | ||
818 | be called pmbus_core. | ||
819 | |||
820 | if PMBUS | ||
821 | |||
822 | config SENSORS_PMBUS | ||
823 | tristate "Generic PMBus devices" | ||
824 | default n | ||
825 | help | ||
826 | If you say yes here you get hardware monitoring support for generic | ||
827 | PMBus devices, including but not limited to BMR450, BMR451, BMR453, | ||
828 | BMR454, and LTC2978. | ||
829 | |||
830 | This driver can also be built as a module. If so, the module will | ||
831 | be called pmbus. | ||
832 | |||
833 | config SENSORS_ADM1275 | ||
834 | tristate "Analog Devices ADM1275" | ||
835 | default n | ||
836 | help | ||
837 | If you say yes here you get hardware monitoring support for Analog | ||
838 | Devices ADM1275 Hot-Swap Controller and Digital Power Monitor. | ||
839 | |||
840 | This driver can also be built as a module. If so, the module will | ||
841 | be called adm1275. | ||
842 | |||
843 | config SENSORS_MAX16064 | ||
844 | tristate "Maxim MAX16064" | ||
845 | default n | ||
846 | help | ||
847 | If you say yes here you get hardware monitoring support for Maxim | ||
848 | MAX16064. | ||
849 | |||
850 | This driver can also be built as a module. If so, the module will | ||
851 | be called max16064. | ||
852 | |||
853 | config SENSORS_MAX34440 | ||
854 | tristate "Maxim MAX34440/MAX34441" | ||
855 | default n | ||
856 | help | ||
857 | If you say yes here you get hardware monitoring support for Maxim | ||
858 | MAX34440 and MAX34441. | ||
859 | |||
860 | This driver can also be built as a module. If so, the module will | ||
861 | be called max34440. | ||
862 | |||
863 | config SENSORS_MAX8688 | ||
864 | tristate "Maxim MAX8688" | ||
865 | default n | ||
866 | help | ||
867 | If you say yes here you get hardware monitoring support for Maxim | ||
868 | MAX8688. | ||
869 | |||
870 | This driver can also be built as a module. If so, the module will | ||
871 | be called max8688. | ||
872 | |||
873 | config SENSORS_UCD9000 | ||
874 | tristate "TI UCD90120, UCD90124, UCD9090, UCD90910" | ||
875 | default n | ||
876 | help | ||
877 | If you say yes here you get hardware monitoring support for TI | ||
878 | UCD90120, UCD90124, UCD9090, UCD90910 Sequencer and System Health | ||
879 | Controllers. | ||
880 | |||
881 | This driver can also be built as a module. If so, the module will | ||
882 | be called ucd9000. | ||
883 | |||
884 | config SENSORS_UCD9200 | ||
885 | tristate "TI UCD9220, UCD9222, UCD9224, UCD9240, UCD9244, UCD9246, UCD9248" | ||
886 | default n | ||
887 | help | ||
888 | If you say yes here you get hardware monitoring support for TI | ||
889 | UCD9220, UCD9222, UCD9224, UCD9240, UCD9244, UCD9246, and UCD9248 | ||
890 | Digital PWM System Controllers. | ||
891 | |||
892 | This driver can also be built as a module. If so, the module will | ||
893 | be called ucd9200. | ||
894 | |||
895 | endif # PMBUS | ||
896 | 845 | ||
897 | config SENSORS_SHT15 | 846 | config SENSORS_SHT15 |
898 | tristate "Sensiron humidity and temperature sensors. SHT15 and compat." | 847 | tristate "Sensiron humidity and temperature sensors. SHT15 and compat." |
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index d7995a1d0784..3c9ccefea791 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile | |||
@@ -80,6 +80,7 @@ obj-$(CONFIG_SENSORS_LM90) += lm90.o | |||
80 | obj-$(CONFIG_SENSORS_LM92) += lm92.o | 80 | obj-$(CONFIG_SENSORS_LM92) += lm92.o |
81 | obj-$(CONFIG_SENSORS_LM93) += lm93.o | 81 | obj-$(CONFIG_SENSORS_LM93) += lm93.o |
82 | obj-$(CONFIG_SENSORS_LM95241) += lm95241.o | 82 | obj-$(CONFIG_SENSORS_LM95241) += lm95241.o |
83 | obj-$(CONFIG_SENSORS_LM95245) += lm95245.o | ||
83 | obj-$(CONFIG_SENSORS_LTC4151) += ltc4151.o | 84 | obj-$(CONFIG_SENSORS_LTC4151) += ltc4151.o |
84 | obj-$(CONFIG_SENSORS_LTC4215) += ltc4215.o | 85 | obj-$(CONFIG_SENSORS_LTC4215) += ltc4215.o |
85 | obj-$(CONFIG_SENSORS_LTC4245) += ltc4245.o | 86 | obj-$(CONFIG_SENSORS_LTC4245) += ltc4245.o |
@@ -87,10 +88,12 @@ obj-$(CONFIG_SENSORS_LTC4261) += ltc4261.o | |||
87 | obj-$(CONFIG_SENSORS_MAX1111) += max1111.o | 88 | obj-$(CONFIG_SENSORS_MAX1111) += max1111.o |
88 | obj-$(CONFIG_SENSORS_MAX16065) += max16065.o | 89 | obj-$(CONFIG_SENSORS_MAX16065) += max16065.o |
89 | obj-$(CONFIG_SENSORS_MAX1619) += max1619.o | 90 | obj-$(CONFIG_SENSORS_MAX1619) += max1619.o |
91 | obj-$(CONFIG_SENSORS_MAX1668) += max1668.o | ||
90 | obj-$(CONFIG_SENSORS_MAX6639) += max6639.o | 92 | obj-$(CONFIG_SENSORS_MAX6639) += max6639.o |
91 | obj-$(CONFIG_SENSORS_MAX6642) += max6642.o | 93 | obj-$(CONFIG_SENSORS_MAX6642) += max6642.o |
92 | obj-$(CONFIG_SENSORS_MAX6650) += max6650.o | 94 | obj-$(CONFIG_SENSORS_MAX6650) += max6650.o |
93 | obj-$(CONFIG_SENSORS_MC13783_ADC)+= mc13783-adc.o | 95 | obj-$(CONFIG_SENSORS_MC13783_ADC)+= mc13783-adc.o |
96 | obj-$(CONFIG_SENSORS_NTC_THERMISTOR) += ntc_thermistor.o | ||
94 | obj-$(CONFIG_SENSORS_PC87360) += pc87360.o | 97 | obj-$(CONFIG_SENSORS_PC87360) += pc87360.o |
95 | obj-$(CONFIG_SENSORS_PC87427) += pc87427.o | 98 | obj-$(CONFIG_SENSORS_PC87427) += pc87427.o |
96 | obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o | 99 | obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o |
@@ -121,15 +124,7 @@ obj-$(CONFIG_SENSORS_W83L786NG) += w83l786ng.o | |||
121 | obj-$(CONFIG_SENSORS_WM831X) += wm831x-hwmon.o | 124 | obj-$(CONFIG_SENSORS_WM831X) += wm831x-hwmon.o |
122 | obj-$(CONFIG_SENSORS_WM8350) += wm8350-hwmon.o | 125 | obj-$(CONFIG_SENSORS_WM8350) += wm8350-hwmon.o |
123 | 126 | ||
124 | # PMBus drivers | 127 | obj-$(CONFIG_PMBUS) += pmbus/ |
125 | obj-$(CONFIG_PMBUS) += pmbus_core.o | ||
126 | obj-$(CONFIG_SENSORS_PMBUS) += pmbus.o | ||
127 | obj-$(CONFIG_SENSORS_ADM1275) += adm1275.o | ||
128 | obj-$(CONFIG_SENSORS_MAX16064) += max16064.o | ||
129 | obj-$(CONFIG_SENSORS_MAX34440) += max34440.o | ||
130 | obj-$(CONFIG_SENSORS_MAX8688) += max8688.o | ||
131 | obj-$(CONFIG_SENSORS_UCD9000) += ucd9000.o | ||
132 | obj-$(CONFIG_SENSORS_UCD9200) += ucd9200.o | ||
133 | 128 | ||
134 | ccflags-$(CONFIG_HWMON_DEBUG_CHIP) := -DDEBUG | 129 | ccflags-$(CONFIG_HWMON_DEBUG_CHIP) := -DDEBUG |
135 | 130 | ||
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c index 0070d5476dd0..59d83e83da7f 100644 --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c | |||
@@ -44,7 +44,9 @@ | |||
44 | #define BASE_SYSFS_ATTR_NO 2 /* Sysfs Base attr no for coretemp */ | 44 | #define BASE_SYSFS_ATTR_NO 2 /* Sysfs Base attr no for coretemp */ |
45 | #define NUM_REAL_CORES 16 /* Number of Real cores per cpu */ | 45 | #define NUM_REAL_CORES 16 /* Number of Real cores per cpu */ |
46 | #define CORETEMP_NAME_LENGTH 17 /* String Length of attrs */ | 46 | #define CORETEMP_NAME_LENGTH 17 /* String Length of attrs */ |
47 | #define MAX_ATTRS 5 /* Maximum no of per-core attrs */ | 47 | #define MAX_CORE_ATTRS 4 /* Maximum no of basic attrs */ |
48 | #define MAX_THRESH_ATTRS 3 /* Maximum no of Threshold attrs */ | ||
49 | #define TOTAL_ATTRS (MAX_CORE_ATTRS + MAX_THRESH_ATTRS) | ||
48 | #define MAX_CORE_DATA (NUM_REAL_CORES + BASE_SYSFS_ATTR_NO) | 50 | #define MAX_CORE_DATA (NUM_REAL_CORES + BASE_SYSFS_ATTR_NO) |
49 | 51 | ||
50 | #ifdef CONFIG_SMP | 52 | #ifdef CONFIG_SMP |
@@ -67,6 +69,9 @@ | |||
67 | * This value is passed as "id" field to rdmsr/wrmsr functions. | 69 | * This value is passed as "id" field to rdmsr/wrmsr functions. |
68 | * @status_reg: One of IA32_THERM_STATUS or IA32_PACKAGE_THERM_STATUS, | 70 | * @status_reg: One of IA32_THERM_STATUS or IA32_PACKAGE_THERM_STATUS, |
69 | * from where the temperature values should be read. | 71 | * from where the temperature values should be read. |
72 | * @intrpt_reg: One of IA32_THERM_INTERRUPT or IA32_PACKAGE_THERM_INTERRUPT, | ||
73 | * from where the thresholds are read. | ||
74 | * @attr_size: Total number of pre-core attrs displayed in the sysfs. | ||
70 | * @is_pkg_data: If this is 1, the temp_data holds pkgtemp data. | 75 | * @is_pkg_data: If this is 1, the temp_data holds pkgtemp data. |
71 | * Otherwise, temp_data holds coretemp data. | 76 | * Otherwise, temp_data holds coretemp data. |
72 | * @valid: If this is 1, the current temperature is valid. | 77 | * @valid: If this is 1, the current temperature is valid. |
@@ -74,15 +79,18 @@ | |||
74 | struct temp_data { | 79 | struct temp_data { |
75 | int temp; | 80 | int temp; |
76 | int ttarget; | 81 | int ttarget; |
82 | int tmin; | ||
77 | int tjmax; | 83 | int tjmax; |
78 | unsigned long last_updated; | 84 | unsigned long last_updated; |
79 | unsigned int cpu; | 85 | unsigned int cpu; |
80 | u32 cpu_core_id; | 86 | u32 cpu_core_id; |
81 | u32 status_reg; | 87 | u32 status_reg; |
88 | u32 intrpt_reg; | ||
89 | int attr_size; | ||
82 | bool is_pkg_data; | 90 | bool is_pkg_data; |
83 | bool valid; | 91 | bool valid; |
84 | struct sensor_device_attribute sd_attrs[MAX_ATTRS]; | 92 | struct sensor_device_attribute sd_attrs[TOTAL_ATTRS]; |
85 | char attr_name[MAX_ATTRS][CORETEMP_NAME_LENGTH]; | 93 | char attr_name[TOTAL_ATTRS][CORETEMP_NAME_LENGTH]; |
86 | struct mutex update_lock; | 94 | struct mutex update_lock; |
87 | }; | 95 | }; |
88 | 96 | ||
@@ -135,6 +143,19 @@ static ssize_t show_crit_alarm(struct device *dev, | |||
135 | return sprintf(buf, "%d\n", (eax >> 5) & 1); | 143 | return sprintf(buf, "%d\n", (eax >> 5) & 1); |
136 | } | 144 | } |
137 | 145 | ||
146 | static ssize_t show_max_alarm(struct device *dev, | ||
147 | struct device_attribute *devattr, char *buf) | ||
148 | { | ||
149 | u32 eax, edx; | ||
150 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
151 | struct platform_data *pdata = dev_get_drvdata(dev); | ||
152 | struct temp_data *tdata = pdata->core_data[attr->index]; | ||
153 | |||
154 | rdmsr_on_cpu(tdata->cpu, tdata->status_reg, &eax, &edx); | ||
155 | |||
156 | return sprintf(buf, "%d\n", !!(eax & THERM_STATUS_THRESHOLD1)); | ||
157 | } | ||
158 | |||
138 | static ssize_t show_tjmax(struct device *dev, | 159 | static ssize_t show_tjmax(struct device *dev, |
139 | struct device_attribute *devattr, char *buf) | 160 | struct device_attribute *devattr, char *buf) |
140 | { | 161 | { |
@@ -153,6 +174,83 @@ static ssize_t show_ttarget(struct device *dev, | |||
153 | return sprintf(buf, "%d\n", pdata->core_data[attr->index]->ttarget); | 174 | return sprintf(buf, "%d\n", pdata->core_data[attr->index]->ttarget); |
154 | } | 175 | } |
155 | 176 | ||
177 | static ssize_t store_ttarget(struct device *dev, | ||
178 | struct device_attribute *devattr, | ||
179 | const char *buf, size_t count) | ||
180 | { | ||
181 | struct platform_data *pdata = dev_get_drvdata(dev); | ||
182 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
183 | struct temp_data *tdata = pdata->core_data[attr->index]; | ||
184 | u32 eax, edx; | ||
185 | unsigned long val; | ||
186 | int diff; | ||
187 | |||
188 | if (strict_strtoul(buf, 10, &val)) | ||
189 | return -EINVAL; | ||
190 | |||
191 | /* | ||
192 | * THERM_MASK_THRESHOLD1 is 7 bits wide. Values are entered in terms | ||
193 | * of milli degree celsius. Hence don't accept val > (127 * 1000) | ||
194 | */ | ||
195 | if (val > tdata->tjmax || val > 127000) | ||
196 | return -EINVAL; | ||
197 | |||
198 | diff = (tdata->tjmax - val) / 1000; | ||
199 | |||
200 | mutex_lock(&tdata->update_lock); | ||
201 | rdmsr_on_cpu(tdata->cpu, tdata->intrpt_reg, &eax, &edx); | ||
202 | eax = (eax & ~THERM_MASK_THRESHOLD1) | | ||
203 | (diff << THERM_SHIFT_THRESHOLD1); | ||
204 | wrmsr_on_cpu(tdata->cpu, tdata->intrpt_reg, eax, edx); | ||
205 | tdata->ttarget = val; | ||
206 | mutex_unlock(&tdata->update_lock); | ||
207 | |||
208 | return count; | ||
209 | } | ||
210 | |||
211 | static ssize_t show_tmin(struct device *dev, | ||
212 | struct device_attribute *devattr, char *buf) | ||
213 | { | ||
214 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
215 | struct platform_data *pdata = dev_get_drvdata(dev); | ||
216 | |||
217 | return sprintf(buf, "%d\n", pdata->core_data[attr->index]->tmin); | ||
218 | } | ||
219 | |||
220 | static ssize_t store_tmin(struct device *dev, | ||
221 | struct device_attribute *devattr, | ||
222 | const char *buf, size_t count) | ||
223 | { | ||
224 | struct platform_data *pdata = dev_get_drvdata(dev); | ||
225 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
226 | struct temp_data *tdata = pdata->core_data[attr->index]; | ||
227 | u32 eax, edx; | ||
228 | unsigned long val; | ||
229 | int diff; | ||
230 | |||
231 | if (strict_strtoul(buf, 10, &val)) | ||
232 | return -EINVAL; | ||
233 | |||
234 | /* | ||
235 | * THERM_MASK_THRESHOLD0 is 7 bits wide. Values are entered in terms | ||
236 | * of milli degree celsius. Hence don't accept val > (127 * 1000) | ||
237 | */ | ||
238 | if (val > tdata->tjmax || val > 127000) | ||
239 | return -EINVAL; | ||
240 | |||
241 | diff = (tdata->tjmax - val) / 1000; | ||
242 | |||
243 | mutex_lock(&tdata->update_lock); | ||
244 | rdmsr_on_cpu(tdata->cpu, tdata->intrpt_reg, &eax, &edx); | ||
245 | eax = (eax & ~THERM_MASK_THRESHOLD0) | | ||
246 | (diff << THERM_SHIFT_THRESHOLD0); | ||
247 | wrmsr_on_cpu(tdata->cpu, tdata->intrpt_reg, eax, edx); | ||
248 | tdata->tmin = val; | ||
249 | mutex_unlock(&tdata->update_lock); | ||
250 | |||
251 | return count; | ||
252 | } | ||
253 | |||
156 | static ssize_t show_temp(struct device *dev, | 254 | static ssize_t show_temp(struct device *dev, |
157 | struct device_attribute *devattr, char *buf) | 255 | struct device_attribute *devattr, char *buf) |
158 | { | 256 | { |
@@ -344,23 +442,31 @@ static int create_core_attrs(struct temp_data *tdata, struct device *dev, | |||
344 | int attr_no) | 442 | int attr_no) |
345 | { | 443 | { |
346 | int err, i; | 444 | int err, i; |
347 | static ssize_t (*rd_ptr[MAX_ATTRS]) (struct device *dev, | 445 | static ssize_t (*rd_ptr[TOTAL_ATTRS]) (struct device *dev, |
348 | struct device_attribute *devattr, char *buf) = { | 446 | struct device_attribute *devattr, char *buf) = { |
349 | show_label, show_crit_alarm, show_ttarget, | 447 | show_label, show_crit_alarm, show_temp, show_tjmax, |
350 | show_temp, show_tjmax }; | 448 | show_max_alarm, show_ttarget, show_tmin }; |
351 | static const char *names[MAX_ATTRS] = { | 449 | static ssize_t (*rw_ptr[TOTAL_ATTRS]) (struct device *dev, |
450 | struct device_attribute *devattr, const char *buf, | ||
451 | size_t count) = { NULL, NULL, NULL, NULL, NULL, | ||
452 | store_ttarget, store_tmin }; | ||
453 | static const char *names[TOTAL_ATTRS] = { | ||
352 | "temp%d_label", "temp%d_crit_alarm", | 454 | "temp%d_label", "temp%d_crit_alarm", |
353 | "temp%d_max", "temp%d_input", | 455 | "temp%d_input", "temp%d_crit", |
354 | "temp%d_crit" }; | 456 | "temp%d_max_alarm", "temp%d_max", |
457 | "temp%d_max_hyst" }; | ||
355 | 458 | ||
356 | for (i = 0; i < MAX_ATTRS; i++) { | 459 | for (i = 0; i < tdata->attr_size; i++) { |
357 | snprintf(tdata->attr_name[i], CORETEMP_NAME_LENGTH, names[i], | 460 | snprintf(tdata->attr_name[i], CORETEMP_NAME_LENGTH, names[i], |
358 | attr_no); | 461 | attr_no); |
359 | sysfs_attr_init(&tdata->sd_attrs[i].dev_attr.attr); | 462 | sysfs_attr_init(&tdata->sd_attrs[i].dev_attr.attr); |
360 | tdata->sd_attrs[i].dev_attr.attr.name = tdata->attr_name[i]; | 463 | tdata->sd_attrs[i].dev_attr.attr.name = tdata->attr_name[i]; |
361 | tdata->sd_attrs[i].dev_attr.attr.mode = S_IRUGO; | 464 | tdata->sd_attrs[i].dev_attr.attr.mode = S_IRUGO; |
465 | if (rw_ptr[i]) { | ||
466 | tdata->sd_attrs[i].dev_attr.attr.mode |= S_IWUSR; | ||
467 | tdata->sd_attrs[i].dev_attr.store = rw_ptr[i]; | ||
468 | } | ||
362 | tdata->sd_attrs[i].dev_attr.show = rd_ptr[i]; | 469 | tdata->sd_attrs[i].dev_attr.show = rd_ptr[i]; |
363 | tdata->sd_attrs[i].dev_attr.store = NULL; | ||
364 | tdata->sd_attrs[i].index = attr_no; | 470 | tdata->sd_attrs[i].index = attr_no; |
365 | err = device_create_file(dev, &tdata->sd_attrs[i].dev_attr); | 471 | err = device_create_file(dev, &tdata->sd_attrs[i].dev_attr); |
366 | if (err) | 472 | if (err) |
@@ -374,38 +480,6 @@ exit_free: | |||
374 | return err; | 480 | return err; |
375 | } | 481 | } |
376 | 482 | ||
377 | static void update_ttarget(__u8 cpu_model, struct temp_data *tdata, | ||
378 | struct device *dev) | ||
379 | { | ||
380 | int err; | ||
381 | u32 eax, edx; | ||
382 | |||
383 | /* | ||
384 | * Initialize ttarget value. Eventually this will be | ||
385 | * initialized with the value from MSR_IA32_THERM_INTERRUPT | ||
386 | * register. If IA32_TEMPERATURE_TARGET is supported, this | ||
387 | * value will be over written below. | ||
388 | * To Do: Patch to initialize ttarget from MSR_IA32_THERM_INTERRUPT | ||
389 | */ | ||
390 | tdata->ttarget = tdata->tjmax - 20000; | ||
391 | |||
392 | /* | ||
393 | * Read the still undocumented IA32_TEMPERATURE_TARGET. It exists | ||
394 | * on older CPUs but not in this register, | ||
395 | * Atoms don't have it either. | ||
396 | */ | ||
397 | if (cpu_model > 0xe && cpu_model != 0x1c) { | ||
398 | err = rdmsr_safe_on_cpu(tdata->cpu, | ||
399 | MSR_IA32_TEMPERATURE_TARGET, &eax, &edx); | ||
400 | if (err) { | ||
401 | dev_warn(dev, | ||
402 | "Unable to read IA32_TEMPERATURE_TARGET MSR\n"); | ||
403 | } else { | ||
404 | tdata->ttarget = tdata->tjmax - | ||
405 | ((eax >> 8) & 0xff) * 1000; | ||
406 | } | ||
407 | } | ||
408 | } | ||
409 | 483 | ||
410 | static int __devinit chk_ucode_version(struct platform_device *pdev) | 484 | static int __devinit chk_ucode_version(struct platform_device *pdev) |
411 | { | 485 | { |
@@ -464,9 +538,12 @@ static struct temp_data *init_temp_data(unsigned int cpu, int pkg_flag) | |||
464 | 538 | ||
465 | tdata->status_reg = pkg_flag ? MSR_IA32_PACKAGE_THERM_STATUS : | 539 | tdata->status_reg = pkg_flag ? MSR_IA32_PACKAGE_THERM_STATUS : |
466 | MSR_IA32_THERM_STATUS; | 540 | MSR_IA32_THERM_STATUS; |
541 | tdata->intrpt_reg = pkg_flag ? MSR_IA32_PACKAGE_THERM_INTERRUPT : | ||
542 | MSR_IA32_THERM_INTERRUPT; | ||
467 | tdata->is_pkg_data = pkg_flag; | 543 | tdata->is_pkg_data = pkg_flag; |
468 | tdata->cpu = cpu; | 544 | tdata->cpu = cpu; |
469 | tdata->cpu_core_id = TO_CORE_ID(cpu); | 545 | tdata->cpu_core_id = TO_CORE_ID(cpu); |
546 | tdata->attr_size = MAX_CORE_ATTRS; | ||
470 | mutex_init(&tdata->update_lock); | 547 | mutex_init(&tdata->update_lock); |
471 | return tdata; | 548 | return tdata; |
472 | } | 549 | } |
@@ -516,7 +593,17 @@ static int create_core_data(struct platform_data *pdata, | |||
516 | else | 593 | else |
517 | tdata->tjmax = get_tjmax(c, cpu, &pdev->dev); | 594 | tdata->tjmax = get_tjmax(c, cpu, &pdev->dev); |
518 | 595 | ||
519 | update_ttarget(c->x86_model, tdata, &pdev->dev); | 596 | /* |
597 | * Test if we can access the intrpt register. If so, increase the | ||
598 | * 'size' enough to have ttarget/tmin/max_alarm interfaces. | ||
599 | * Initialize ttarget with bits 16:22 of MSR_IA32_THERM_INTERRUPT | ||
600 | */ | ||
601 | err = rdmsr_safe_on_cpu(cpu, tdata->intrpt_reg, &eax, &edx); | ||
602 | if (!err) { | ||
603 | tdata->attr_size += MAX_THRESH_ATTRS; | ||
604 | tdata->ttarget = tdata->tjmax - ((eax >> 16) & 0x7f) * 1000; | ||
605 | } | ||
606 | |||
520 | pdata->core_data[attr_no] = tdata; | 607 | pdata->core_data[attr_no] = tdata; |
521 | 608 | ||
522 | /* Create sysfs interfaces */ | 609 | /* Create sysfs interfaces */ |
@@ -553,7 +640,7 @@ static void coretemp_remove_core(struct platform_data *pdata, | |||
553 | struct temp_data *tdata = pdata->core_data[indx]; | 640 | struct temp_data *tdata = pdata->core_data[indx]; |
554 | 641 | ||
555 | /* Remove the sysfs attributes */ | 642 | /* Remove the sysfs attributes */ |
556 | for (i = 0; i < MAX_ATTRS; i++) | 643 | for (i = 0; i < tdata->attr_size; i++) |
557 | device_remove_file(dev, &tdata->sd_attrs[i].dev_attr); | 644 | device_remove_file(dev, &tdata->sd_attrs[i].dev_attr); |
558 | 645 | ||
559 | kfree(pdata->core_data[indx]); | 646 | kfree(pdata->core_data[indx]); |
diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c index 2f94f9504804..90ddb8774210 100644 --- a/drivers/hwmon/lm90.c +++ b/drivers/hwmon/lm90.c | |||
@@ -54,6 +54,9 @@ | |||
54 | * and extended mode. They are mostly compatible with LM90 except for a data | 54 | * and extended mode. They are mostly compatible with LM90 except for a data |
55 | * format difference for the temperature value registers. | 55 | * format difference for the temperature value registers. |
56 | * | 56 | * |
57 | * This driver also supports the SA56004 from Philips. This device is | ||
58 | * pin-compatible with the LM86, the ED/EDP parts are also address-compatible. | ||
59 | * | ||
57 | * Since the LM90 was the first chipset supported by this driver, most | 60 | * Since the LM90 was the first chipset supported by this driver, most |
58 | * comments will refer to this chipset, but are actually general and | 61 | * comments will refer to this chipset, but are actually general and |
59 | * concern all supported chipsets, unless mentioned otherwise. | 62 | * concern all supported chipsets, unless mentioned otherwise. |
@@ -96,13 +99,15 @@ | |||
96 | * MAX6659 can have address 0x4c, 0x4d or 0x4e. | 99 | * MAX6659 can have address 0x4c, 0x4d or 0x4e. |
97 | * MAX6680 and MAX6681 can have address 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, | 100 | * MAX6680 and MAX6681 can have address 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, |
98 | * 0x4c, 0x4d or 0x4e. | 101 | * 0x4c, 0x4d or 0x4e. |
102 | * SA56004 can have address 0x48 through 0x4F. | ||
99 | */ | 103 | */ |
100 | 104 | ||
101 | static const unsigned short normal_i2c[] = { | 105 | static const unsigned short normal_i2c[] = { |
102 | 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, 0x4c, 0x4d, 0x4e, I2C_CLIENT_END }; | 106 | 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, 0x48, 0x49, 0x4a, 0x4b, 0x4c, |
107 | 0x4d, 0x4e, 0x4f, I2C_CLIENT_END }; | ||
103 | 108 | ||
104 | enum chips { lm90, adm1032, lm99, lm86, max6657, max6659, adt7461, max6680, | 109 | enum chips { lm90, adm1032, lm99, lm86, max6657, max6659, adt7461, max6680, |
105 | max6646, w83l771, max6696 }; | 110 | max6646, w83l771, max6696, sa56004 }; |
106 | 111 | ||
107 | /* | 112 | /* |
108 | * The LM90 registers | 113 | * The LM90 registers |
@@ -152,6 +157,10 @@ enum chips { lm90, adm1032, lm99, lm86, max6657, max6659, adt7461, max6680, | |||
152 | #define MAX6659_REG_R_LOCAL_EMERG 0x17 | 157 | #define MAX6659_REG_R_LOCAL_EMERG 0x17 |
153 | #define MAX6659_REG_W_LOCAL_EMERG 0x17 | 158 | #define MAX6659_REG_W_LOCAL_EMERG 0x17 |
154 | 159 | ||
160 | /* SA56004 registers */ | ||
161 | |||
162 | #define SA56004_REG_R_LOCAL_TEMPL 0x22 | ||
163 | |||
155 | #define LM90_DEF_CONVRATE_RVAL 6 /* Def conversion rate register value */ | 164 | #define LM90_DEF_CONVRATE_RVAL 6 /* Def conversion rate register value */ |
156 | #define LM90_MAX_CONVRATE_MS 16000 /* Maximum conversion rate in ms */ | 165 | #define LM90_MAX_CONVRATE_MS 16000 /* Maximum conversion rate in ms */ |
157 | 166 | ||
@@ -161,7 +170,6 @@ enum chips { lm90, adm1032, lm99, lm86, max6657, max6659, adt7461, max6680, | |||
161 | #define LM90_FLAG_ADT7461_EXT (1 << 0) /* ADT7461 extended mode */ | 170 | #define LM90_FLAG_ADT7461_EXT (1 << 0) /* ADT7461 extended mode */ |
162 | /* Device features */ | 171 | /* Device features */ |
163 | #define LM90_HAVE_OFFSET (1 << 1) /* temperature offset register */ | 172 | #define LM90_HAVE_OFFSET (1 << 1) /* temperature offset register */ |
164 | #define LM90_HAVE_LOCAL_EXT (1 << 2) /* extended local temperature */ | ||
165 | #define LM90_HAVE_REM_LIMIT_EXT (1 << 3) /* extended remote limit */ | 173 | #define LM90_HAVE_REM_LIMIT_EXT (1 << 3) /* extended remote limit */ |
166 | #define LM90_HAVE_EMERGENCY (1 << 4) /* 3rd upper (emergency) limit */ | 174 | #define LM90_HAVE_EMERGENCY (1 << 4) /* 3rd upper (emergency) limit */ |
167 | #define LM90_HAVE_EMERGENCY_ALARM (1 << 5)/* emergency alarm */ | 175 | #define LM90_HAVE_EMERGENCY_ALARM (1 << 5)/* emergency alarm */ |
@@ -192,6 +200,7 @@ static const struct i2c_device_id lm90_id[] = { | |||
192 | { "max6696", max6696 }, | 200 | { "max6696", max6696 }, |
193 | { "nct1008", adt7461 }, | 201 | { "nct1008", adt7461 }, |
194 | { "w83l771", w83l771 }, | 202 | { "w83l771", w83l771 }, |
203 | { "sa56004", sa56004 }, | ||
195 | { } | 204 | { } |
196 | }; | 205 | }; |
197 | MODULE_DEVICE_TABLE(i2c, lm90_id); | 206 | MODULE_DEVICE_TABLE(i2c, lm90_id); |
@@ -204,6 +213,7 @@ struct lm90_params { | |||
204 | u16 alert_alarms; /* Which alarm bits trigger ALERT# */ | 213 | u16 alert_alarms; /* Which alarm bits trigger ALERT# */ |
205 | /* Upper 8 bits for max6695/96 */ | 214 | /* Upper 8 bits for max6695/96 */ |
206 | u8 max_convrate; /* Maximum conversion rate register value */ | 215 | u8 max_convrate; /* Maximum conversion rate register value */ |
216 | u8 reg_local_ext; /* Extended local temp register (optional) */ | ||
207 | }; | 217 | }; |
208 | 218 | ||
209 | static const struct lm90_params lm90_params[] = { | 219 | static const struct lm90_params lm90_params[] = { |
@@ -235,19 +245,20 @@ static const struct lm90_params lm90_params[] = { | |||
235 | .max_convrate = 9, | 245 | .max_convrate = 9, |
236 | }, | 246 | }, |
237 | [max6646] = { | 247 | [max6646] = { |
238 | .flags = LM90_HAVE_LOCAL_EXT, | ||
239 | .alert_alarms = 0x7c, | 248 | .alert_alarms = 0x7c, |
240 | .max_convrate = 6, | 249 | .max_convrate = 6, |
250 | .reg_local_ext = MAX6657_REG_R_LOCAL_TEMPL, | ||
241 | }, | 251 | }, |
242 | [max6657] = { | 252 | [max6657] = { |
243 | .flags = LM90_HAVE_LOCAL_EXT, | ||
244 | .alert_alarms = 0x7c, | 253 | .alert_alarms = 0x7c, |
245 | .max_convrate = 8, | 254 | .max_convrate = 8, |
255 | .reg_local_ext = MAX6657_REG_R_LOCAL_TEMPL, | ||
246 | }, | 256 | }, |
247 | [max6659] = { | 257 | [max6659] = { |
248 | .flags = LM90_HAVE_LOCAL_EXT | LM90_HAVE_EMERGENCY, | 258 | .flags = LM90_HAVE_EMERGENCY, |
249 | .alert_alarms = 0x7c, | 259 | .alert_alarms = 0x7c, |
250 | .max_convrate = 8, | 260 | .max_convrate = 8, |
261 | .reg_local_ext = MAX6657_REG_R_LOCAL_TEMPL, | ||
251 | }, | 262 | }, |
252 | [max6680] = { | 263 | [max6680] = { |
253 | .flags = LM90_HAVE_OFFSET, | 264 | .flags = LM90_HAVE_OFFSET, |
@@ -255,16 +266,23 @@ static const struct lm90_params lm90_params[] = { | |||
255 | .max_convrate = 7, | 266 | .max_convrate = 7, |
256 | }, | 267 | }, |
257 | [max6696] = { | 268 | [max6696] = { |
258 | .flags = LM90_HAVE_LOCAL_EXT | LM90_HAVE_EMERGENCY | 269 | .flags = LM90_HAVE_EMERGENCY |
259 | | LM90_HAVE_EMERGENCY_ALARM | LM90_HAVE_TEMP3, | 270 | | LM90_HAVE_EMERGENCY_ALARM | LM90_HAVE_TEMP3, |
260 | .alert_alarms = 0x187c, | 271 | .alert_alarms = 0x187c, |
261 | .max_convrate = 6, | 272 | .max_convrate = 6, |
273 | .reg_local_ext = MAX6657_REG_R_LOCAL_TEMPL, | ||
262 | }, | 274 | }, |
263 | [w83l771] = { | 275 | [w83l771] = { |
264 | .flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT, | 276 | .flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT, |
265 | .alert_alarms = 0x7c, | 277 | .alert_alarms = 0x7c, |
266 | .max_convrate = 8, | 278 | .max_convrate = 8, |
267 | }, | 279 | }, |
280 | [sa56004] = { | ||
281 | .flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT, | ||
282 | .alert_alarms = 0x7b, | ||
283 | .max_convrate = 9, | ||
284 | .reg_local_ext = SA56004_REG_R_LOCAL_TEMPL, | ||
285 | }, | ||
268 | }; | 286 | }; |
269 | 287 | ||
270 | /* | 288 | /* |
@@ -286,6 +304,7 @@ struct lm90_data { | |||
286 | u16 alert_alarms; /* Which alarm bits trigger ALERT# */ | 304 | u16 alert_alarms; /* Which alarm bits trigger ALERT# */ |
287 | /* Upper 8 bits for max6695/96 */ | 305 | /* Upper 8 bits for max6695/96 */ |
288 | u8 max_convrate; /* Maximum conversion rate */ | 306 | u8 max_convrate; /* Maximum conversion rate */ |
307 | u8 reg_local_ext; /* local extension register offset */ | ||
289 | 308 | ||
290 | /* registers values */ | 309 | /* registers values */ |
291 | s8 temp8[8]; /* 0: local low limit | 310 | s8 temp8[8]; /* 0: local low limit |
@@ -452,9 +471,9 @@ static struct lm90_data *lm90_update_device(struct device *dev) | |||
452 | lm90_read_reg(client, LM90_REG_R_REMOTE_CRIT, &data->temp8[3]); | 471 | lm90_read_reg(client, LM90_REG_R_REMOTE_CRIT, &data->temp8[3]); |
453 | lm90_read_reg(client, LM90_REG_R_TCRIT_HYST, &data->temp_hyst); | 472 | lm90_read_reg(client, LM90_REG_R_TCRIT_HYST, &data->temp_hyst); |
454 | 473 | ||
455 | if (data->flags & LM90_HAVE_LOCAL_EXT) { | 474 | if (data->reg_local_ext) { |
456 | lm90_read16(client, LM90_REG_R_LOCAL_TEMP, | 475 | lm90_read16(client, LM90_REG_R_LOCAL_TEMP, |
457 | MAX6657_REG_R_LOCAL_TEMPL, | 476 | data->reg_local_ext, |
458 | &data->temp11[4]); | 477 | &data->temp11[4]); |
459 | } else { | 478 | } else { |
460 | if (lm90_read_reg(client, LM90_REG_R_LOCAL_TEMP, | 479 | if (lm90_read_reg(client, LM90_REG_R_LOCAL_TEMP, |
@@ -1092,7 +1111,7 @@ static int lm90_detect(struct i2c_client *new_client, | |||
1092 | struct i2c_adapter *adapter = new_client->adapter; | 1111 | struct i2c_adapter *adapter = new_client->adapter; |
1093 | int address = new_client->addr; | 1112 | int address = new_client->addr; |
1094 | const char *name = NULL; | 1113 | const char *name = NULL; |
1095 | int man_id, chip_id, reg_config1, reg_convrate; | 1114 | int man_id, chip_id, reg_config1, reg_config2, reg_convrate; |
1096 | 1115 | ||
1097 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | 1116 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) |
1098 | return -ENODEV; | 1117 | return -ENODEV; |
@@ -1108,15 +1127,16 @@ static int lm90_detect(struct i2c_client *new_client, | |||
1108 | LM90_REG_R_CONVRATE)) < 0) | 1127 | LM90_REG_R_CONVRATE)) < 0) |
1109 | return -ENODEV; | 1128 | return -ENODEV; |
1110 | 1129 | ||
1111 | if ((address == 0x4C || address == 0x4D) | 1130 | if (man_id == 0x01 || man_id == 0x5C || man_id == 0x41) { |
1112 | && man_id == 0x01) { /* National Semiconductor */ | ||
1113 | int reg_config2; | ||
1114 | |||
1115 | reg_config2 = i2c_smbus_read_byte_data(new_client, | 1131 | reg_config2 = i2c_smbus_read_byte_data(new_client, |
1116 | LM90_REG_R_CONFIG2); | 1132 | LM90_REG_R_CONFIG2); |
1117 | if (reg_config2 < 0) | 1133 | if (reg_config2 < 0) |
1118 | return -ENODEV; | 1134 | return -ENODEV; |
1135 | } else | ||
1136 | reg_config2 = 0; /* Make compiler happy */ | ||
1119 | 1137 | ||
1138 | if ((address == 0x4C || address == 0x4D) | ||
1139 | && man_id == 0x01) { /* National Semiconductor */ | ||
1120 | if ((reg_config1 & 0x2A) == 0x00 | 1140 | if ((reg_config1 & 0x2A) == 0x00 |
1121 | && (reg_config2 & 0xF8) == 0x00 | 1141 | && (reg_config2 & 0xF8) == 0x00 |
1122 | && reg_convrate <= 0x09) { | 1142 | && reg_convrate <= 0x09) { |
@@ -1245,13 +1265,6 @@ static int lm90_detect(struct i2c_client *new_client, | |||
1245 | } else | 1265 | } else |
1246 | if (address == 0x4C | 1266 | if (address == 0x4C |
1247 | && man_id == 0x5C) { /* Winbond/Nuvoton */ | 1267 | && man_id == 0x5C) { /* Winbond/Nuvoton */ |
1248 | int reg_config2; | ||
1249 | |||
1250 | reg_config2 = i2c_smbus_read_byte_data(new_client, | ||
1251 | LM90_REG_R_CONFIG2); | ||
1252 | if (reg_config2 < 0) | ||
1253 | return -ENODEV; | ||
1254 | |||
1255 | if ((reg_config1 & 0x2A) == 0x00 | 1268 | if ((reg_config1 & 0x2A) == 0x00 |
1256 | && (reg_config2 & 0xF8) == 0x00) { | 1269 | && (reg_config2 & 0xF8) == 0x00) { |
1257 | if (chip_id == 0x01 /* W83L771W/G */ | 1270 | if (chip_id == 0x01 /* W83L771W/G */ |
@@ -1263,6 +1276,15 @@ static int lm90_detect(struct i2c_client *new_client, | |||
1263 | name = "w83l771"; | 1276 | name = "w83l771"; |
1264 | } | 1277 | } |
1265 | } | 1278 | } |
1279 | } else | ||
1280 | if (address >= 0x48 && address <= 0x4F | ||
1281 | && man_id == 0xA1) { /* NXP Semiconductor/Philips */ | ||
1282 | if (chip_id == 0x00 | ||
1283 | && (reg_config1 & 0x2A) == 0x00 | ||
1284 | && (reg_config2 & 0xFE) == 0x00 | ||
1285 | && reg_convrate <= 0x09) { | ||
1286 | name = "sa56004"; | ||
1287 | } | ||
1266 | } | 1288 | } |
1267 | 1289 | ||
1268 | if (!name) { /* identification failed */ | 1290 | if (!name) { /* identification failed */ |
@@ -1368,6 +1390,7 @@ static int lm90_probe(struct i2c_client *new_client, | |||
1368 | 1390 | ||
1369 | /* Set chip capabilities */ | 1391 | /* Set chip capabilities */ |
1370 | data->flags = lm90_params[data->kind].flags; | 1392 | data->flags = lm90_params[data->kind].flags; |
1393 | data->reg_local_ext = lm90_params[data->kind].reg_local_ext; | ||
1371 | 1394 | ||
1372 | /* Set maximum conversion rate */ | 1395 | /* Set maximum conversion rate */ |
1373 | data->max_convrate = lm90_params[data->kind].max_convrate; | 1396 | data->max_convrate = lm90_params[data->kind].max_convrate; |
diff --git a/drivers/hwmon/lm95241.c b/drivers/hwmon/lm95241.c index d3b464b74ced..513901d592a9 100644 --- a/drivers/hwmon/lm95241.c +++ b/drivers/hwmon/lm95241.c | |||
@@ -74,8 +74,9 @@ static const unsigned short normal_i2c[] = { | |||
74 | #define TT_OFF 0 | 74 | #define TT_OFF 0 |
75 | #define TT_ON 1 | 75 | #define TT_ON 1 |
76 | #define TT_MASK 7 | 76 | #define TT_MASK 7 |
77 | #define MANUFACTURER_ID 0x01 | 77 | #define NATSEMI_MAN_ID 0x01 |
78 | #define DEFAULT_REVISION 0xA4 | 78 | #define LM95231_CHIP_ID 0xA1 |
79 | #define LM95241_CHIP_ID 0xA4 | ||
79 | 80 | ||
80 | static const u8 lm95241_reg_address[] = { | 81 | static const u8 lm95241_reg_address[] = { |
81 | LM95241_REG_R_LOCAL_TEMPH, | 82 | LM95241_REG_R_LOCAL_TEMPH, |
@@ -338,20 +339,25 @@ static int lm95241_detect(struct i2c_client *new_client, | |||
338 | struct i2c_board_info *info) | 339 | struct i2c_board_info *info) |
339 | { | 340 | { |
340 | struct i2c_adapter *adapter = new_client->adapter; | 341 | struct i2c_adapter *adapter = new_client->adapter; |
341 | int address = new_client->addr; | ||
342 | const char *name; | 342 | const char *name; |
343 | int mfg_id, chip_id; | ||
343 | 344 | ||
344 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | 345 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) |
345 | return -ENODEV; | 346 | return -ENODEV; |
346 | 347 | ||
347 | if ((i2c_smbus_read_byte_data(new_client, LM95241_REG_R_MAN_ID) | 348 | mfg_id = i2c_smbus_read_byte_data(new_client, LM95241_REG_R_MAN_ID); |
348 | == MANUFACTURER_ID) | 349 | if (mfg_id != NATSEMI_MAN_ID) |
349 | && (i2c_smbus_read_byte_data(new_client, LM95241_REG_R_CHIP_ID) | 350 | return -ENODEV; |
350 | == DEFAULT_REVISION)) { | 351 | |
351 | name = DEVNAME; | 352 | chip_id = i2c_smbus_read_byte_data(new_client, LM95241_REG_R_CHIP_ID); |
352 | } else { | 353 | switch (chip_id) { |
353 | dev_dbg(&adapter->dev, "LM95241 detection failed at 0x%02x\n", | 354 | case LM95231_CHIP_ID: |
354 | address); | 355 | name = "lm95231"; |
356 | break; | ||
357 | case LM95241_CHIP_ID: | ||
358 | name = "lm95241"; | ||
359 | break; | ||
360 | default: | ||
355 | return -ENODEV; | 361 | return -ENODEV; |
356 | } | 362 | } |
357 | 363 | ||
@@ -431,7 +437,8 @@ static int lm95241_remove(struct i2c_client *client) | |||
431 | 437 | ||
432 | /* Driver data (common to all clients) */ | 438 | /* Driver data (common to all clients) */ |
433 | static const struct i2c_device_id lm95241_id[] = { | 439 | static const struct i2c_device_id lm95241_id[] = { |
434 | { DEVNAME, 0 }, | 440 | { "lm95231", 0 }, |
441 | { "lm95241", 0 }, | ||
435 | { } | 442 | { } |
436 | }; | 443 | }; |
437 | MODULE_DEVICE_TABLE(i2c, lm95241_id); | 444 | MODULE_DEVICE_TABLE(i2c, lm95241_id); |
diff --git a/drivers/hwmon/lm95245.c b/drivers/hwmon/lm95245.c new file mode 100644 index 000000000000..dce9e68241e6 --- /dev/null +++ b/drivers/hwmon/lm95245.c | |||
@@ -0,0 +1,543 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2011 Alexander Stein <alexander.stein@systec-electronic.com> | ||
3 | * | ||
4 | * The LM95245 is a sensor chip made by National Semiconductors. | ||
5 | * It reports up to two temperatures (its own plus an external one). | ||
6 | * Complete datasheet can be obtained from National's website at: | ||
7 | * http://www.national.com/ds.cgi/LM/LM95245.pdf | ||
8 | * | ||
9 | * This driver is based on lm95241.c | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; either version 2 of the License, or | ||
14 | * (at your option) any later version. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | * GNU General Public License for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License | ||
22 | * along with this program; if not, write to the Free Software | ||
23 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
24 | */ | ||
25 | |||
26 | #include <linux/module.h> | ||
27 | #include <linux/init.h> | ||
28 | #include <linux/slab.h> | ||
29 | #include <linux/jiffies.h> | ||
30 | #include <linux/i2c.h> | ||
31 | #include <linux/hwmon.h> | ||
32 | #include <linux/hwmon-sysfs.h> | ||
33 | #include <linux/err.h> | ||
34 | #include <linux/mutex.h> | ||
35 | #include <linux/sysfs.h> | ||
36 | |||
37 | #define DEVNAME "lm95245" | ||
38 | |||
39 | static const unsigned short normal_i2c[] = { | ||
40 | 0x18, 0x19, 0x29, 0x4c, 0x4d, I2C_CLIENT_END }; | ||
41 | |||
42 | /* LM95245 registers */ | ||
43 | /* general registers */ | ||
44 | #define LM95245_REG_RW_CONFIG1 0x03 | ||
45 | #define LM95245_REG_RW_CONVERS_RATE 0x04 | ||
46 | #define LM95245_REG_W_ONE_SHOT 0x0F | ||
47 | |||
48 | /* diode configuration */ | ||
49 | #define LM95245_REG_RW_CONFIG2 0xBF | ||
50 | #define LM95245_REG_RW_REMOTE_OFFH 0x11 | ||
51 | #define LM95245_REG_RW_REMOTE_OFFL 0x12 | ||
52 | |||
53 | /* status registers */ | ||
54 | #define LM95245_REG_R_STATUS1 0x02 | ||
55 | #define LM95245_REG_R_STATUS2 0x33 | ||
56 | |||
57 | /* limit registers */ | ||
58 | #define LM95245_REG_RW_REMOTE_OS_LIMIT 0x07 | ||
59 | #define LM95245_REG_RW_LOCAL_OS_TCRIT_LIMIT 0x20 | ||
60 | #define LM95245_REG_RW_REMOTE_TCRIT_LIMIT 0x19 | ||
61 | #define LM95245_REG_RW_COMMON_HYSTERESIS 0x21 | ||
62 | |||
63 | /* temperature signed */ | ||
64 | #define LM95245_REG_R_LOCAL_TEMPH_S 0x00 | ||
65 | #define LM95245_REG_R_LOCAL_TEMPL_S 0x30 | ||
66 | #define LM95245_REG_R_REMOTE_TEMPH_S 0x01 | ||
67 | #define LM95245_REG_R_REMOTE_TEMPL_S 0x10 | ||
68 | /* temperature unsigned */ | ||
69 | #define LM95245_REG_R_REMOTE_TEMPH_U 0x31 | ||
70 | #define LM95245_REG_R_REMOTE_TEMPL_U 0x32 | ||
71 | |||
72 | /* id registers */ | ||
73 | #define LM95245_REG_R_MAN_ID 0xFE | ||
74 | #define LM95245_REG_R_CHIP_ID 0xFF | ||
75 | |||
76 | /* LM95245 specific bitfields */ | ||
77 | #define CFG_STOP 0x40 | ||
78 | #define CFG_REMOTE_TCRIT_MASK 0x10 | ||
79 | #define CFG_REMOTE_OS_MASK 0x08 | ||
80 | #define CFG_LOCAL_TCRIT_MASK 0x04 | ||
81 | #define CFG_LOCAL_OS_MASK 0x02 | ||
82 | |||
83 | #define CFG2_OS_A0 0x40 | ||
84 | #define CFG2_DIODE_FAULT_OS 0x20 | ||
85 | #define CFG2_DIODE_FAULT_TCRIT 0x10 | ||
86 | #define CFG2_REMOTE_TT 0x08 | ||
87 | #define CFG2_REMOTE_FILTER_DIS 0x00 | ||
88 | #define CFG2_REMOTE_FILTER_EN 0x06 | ||
89 | |||
90 | /* conversation rate in ms */ | ||
91 | #define RATE_CR0063 0x00 | ||
92 | #define RATE_CR0364 0x01 | ||
93 | #define RATE_CR1000 0x02 | ||
94 | #define RATE_CR2500 0x03 | ||
95 | |||
96 | #define STATUS1_DIODE_FAULT 0x04 | ||
97 | #define STATUS1_RTCRIT 0x02 | ||
98 | #define STATUS1_LOC 0x01 | ||
99 | |||
100 | #define MANUFACTURER_ID 0x01 | ||
101 | #define DEFAULT_REVISION 0xB3 | ||
102 | |||
103 | static const u8 lm95245_reg_address[] = { | ||
104 | LM95245_REG_R_LOCAL_TEMPH_S, | ||
105 | LM95245_REG_R_LOCAL_TEMPL_S, | ||
106 | LM95245_REG_R_REMOTE_TEMPH_S, | ||
107 | LM95245_REG_R_REMOTE_TEMPL_S, | ||
108 | LM95245_REG_R_REMOTE_TEMPH_U, | ||
109 | LM95245_REG_R_REMOTE_TEMPL_U, | ||
110 | LM95245_REG_RW_LOCAL_OS_TCRIT_LIMIT, | ||
111 | LM95245_REG_RW_REMOTE_TCRIT_LIMIT, | ||
112 | LM95245_REG_RW_COMMON_HYSTERESIS, | ||
113 | LM95245_REG_R_STATUS1, | ||
114 | }; | ||
115 | |||
116 | /* Client data (each client gets its own) */ | ||
117 | struct lm95245_data { | ||
118 | struct device *hwmon_dev; | ||
119 | struct mutex update_lock; | ||
120 | unsigned long last_updated; /* in jiffies */ | ||
121 | unsigned long interval; /* in msecs */ | ||
122 | bool valid; /* zero until following fields are valid */ | ||
123 | /* registers values */ | ||
124 | u8 regs[ARRAY_SIZE(lm95245_reg_address)]; | ||
125 | u8 config1, config2; | ||
126 | }; | ||
127 | |||
128 | /* Conversions */ | ||
129 | static int temp_from_reg_unsigned(u8 val_h, u8 val_l) | ||
130 | { | ||
131 | return val_h * 1000 + val_l * 1000 / 256; | ||
132 | } | ||
133 | |||
134 | static int temp_from_reg_signed(u8 val_h, u8 val_l) | ||
135 | { | ||
136 | if (val_h & 0x80) | ||
137 | return (val_h - 0x100) * 1000; | ||
138 | return temp_from_reg_unsigned(val_h, val_l); | ||
139 | } | ||
140 | |||
141 | static struct lm95245_data *lm95245_update_device(struct device *dev) | ||
142 | { | ||
143 | struct i2c_client *client = to_i2c_client(dev); | ||
144 | struct lm95245_data *data = i2c_get_clientdata(client); | ||
145 | |||
146 | mutex_lock(&data->update_lock); | ||
147 | |||
148 | if (time_after(jiffies, data->last_updated | ||
149 | + msecs_to_jiffies(data->interval)) || !data->valid) { | ||
150 | int i; | ||
151 | |||
152 | dev_dbg(&client->dev, "Updating lm95245 data.\n"); | ||
153 | for (i = 0; i < ARRAY_SIZE(lm95245_reg_address); i++) | ||
154 | data->regs[i] | ||
155 | = i2c_smbus_read_byte_data(client, | ||
156 | lm95245_reg_address[i]); | ||
157 | data->last_updated = jiffies; | ||
158 | data->valid = 1; | ||
159 | } | ||
160 | |||
161 | mutex_unlock(&data->update_lock); | ||
162 | |||
163 | return data; | ||
164 | } | ||
165 | |||
166 | static unsigned long lm95245_read_conversion_rate(struct i2c_client *client) | ||
167 | { | ||
168 | int rate; | ||
169 | unsigned long interval; | ||
170 | |||
171 | rate = i2c_smbus_read_byte_data(client, LM95245_REG_RW_CONVERS_RATE); | ||
172 | |||
173 | switch (rate) { | ||
174 | case RATE_CR0063: | ||
175 | interval = 63; | ||
176 | break; | ||
177 | case RATE_CR0364: | ||
178 | interval = 364; | ||
179 | break; | ||
180 | case RATE_CR1000: | ||
181 | interval = 1000; | ||
182 | break; | ||
183 | case RATE_CR2500: | ||
184 | default: | ||
185 | interval = 2500; | ||
186 | break; | ||
187 | } | ||
188 | |||
189 | return interval; | ||
190 | } | ||
191 | |||
192 | static unsigned long lm95245_set_conversion_rate(struct i2c_client *client, | ||
193 | unsigned long interval) | ||
194 | { | ||
195 | int rate; | ||
196 | |||
197 | if (interval <= 63) { | ||
198 | interval = 63; | ||
199 | rate = RATE_CR0063; | ||
200 | } else if (interval <= 364) { | ||
201 | interval = 364; | ||
202 | rate = RATE_CR0364; | ||
203 | } else if (interval <= 1000) { | ||
204 | interval = 1000; | ||
205 | rate = RATE_CR1000; | ||
206 | } else { | ||
207 | interval = 2500; | ||
208 | rate = RATE_CR2500; | ||
209 | } | ||
210 | |||
211 | i2c_smbus_write_byte_data(client, LM95245_REG_RW_CONVERS_RATE, rate); | ||
212 | |||
213 | return interval; | ||
214 | } | ||
215 | |||
216 | /* Sysfs stuff */ | ||
217 | static ssize_t show_input(struct device *dev, struct device_attribute *attr, | ||
218 | char *buf) | ||
219 | { | ||
220 | struct lm95245_data *data = lm95245_update_device(dev); | ||
221 | int temp; | ||
222 | int index = to_sensor_dev_attr(attr)->index; | ||
223 | |||
224 | /* | ||
225 | * Index 0 (Local temp) is always signed | ||
226 | * Index 2 (Remote temp) has both signed and unsigned data | ||
227 | * use signed calculation for remote if signed bit is set | ||
228 | */ | ||
229 | if (index == 0 || data->regs[index] & 0x80) | ||
230 | temp = temp_from_reg_signed(data->regs[index], | ||
231 | data->regs[index + 1]); | ||
232 | else | ||
233 | temp = temp_from_reg_unsigned(data->regs[index + 2], | ||
234 | data->regs[index + 3]); | ||
235 | |||
236 | return snprintf(buf, PAGE_SIZE - 1, "%d\n", temp); | ||
237 | } | ||
238 | |||
239 | static ssize_t show_limit(struct device *dev, struct device_attribute *attr, | ||
240 | char *buf) | ||
241 | { | ||
242 | struct lm95245_data *data = lm95245_update_device(dev); | ||
243 | int index = to_sensor_dev_attr(attr)->index; | ||
244 | |||
245 | return snprintf(buf, PAGE_SIZE - 1, "%d\n", | ||
246 | data->regs[index] * 1000); | ||
247 | } | ||
248 | |||
249 | static ssize_t set_limit(struct device *dev, struct device_attribute *attr, | ||
250 | const char *buf, size_t count) | ||
251 | { | ||
252 | struct i2c_client *client = to_i2c_client(dev); | ||
253 | struct lm95245_data *data = i2c_get_clientdata(client); | ||
254 | int index = to_sensor_dev_attr(attr)->index; | ||
255 | unsigned long val; | ||
256 | |||
257 | if (strict_strtoul(buf, 10, &val) < 0) | ||
258 | return -EINVAL; | ||
259 | |||
260 | val /= 1000; | ||
261 | |||
262 | val = SENSORS_LIMIT(val, 0, (index == 6 ? 127 : 255)); | ||
263 | |||
264 | mutex_lock(&data->update_lock); | ||
265 | |||
266 | data->valid = 0; | ||
267 | |||
268 | i2c_smbus_write_byte_data(client, lm95245_reg_address[index], val); | ||
269 | |||
270 | mutex_unlock(&data->update_lock); | ||
271 | |||
272 | return count; | ||
273 | } | ||
274 | |||
275 | static ssize_t set_crit_hyst(struct device *dev, struct device_attribute *attr, | ||
276 | const char *buf, size_t count) | ||
277 | { | ||
278 | struct i2c_client *client = to_i2c_client(dev); | ||
279 | struct lm95245_data *data = i2c_get_clientdata(client); | ||
280 | unsigned long val; | ||
281 | |||
282 | if (strict_strtoul(buf, 10, &val) < 0) | ||
283 | return -EINVAL; | ||
284 | |||
285 | val /= 1000; | ||
286 | |||
287 | val = SENSORS_LIMIT(val, 0, 31); | ||
288 | |||
289 | mutex_lock(&data->update_lock); | ||
290 | |||
291 | data->valid = 0; | ||
292 | |||
293 | /* shared crit hysteresis */ | ||
294 | i2c_smbus_write_byte_data(client, LM95245_REG_RW_COMMON_HYSTERESIS, | ||
295 | val); | ||
296 | |||
297 | mutex_unlock(&data->update_lock); | ||
298 | |||
299 | return count; | ||
300 | } | ||
301 | |||
302 | static ssize_t show_type(struct device *dev, struct device_attribute *attr, | ||
303 | char *buf) | ||
304 | { | ||
305 | struct i2c_client *client = to_i2c_client(dev); | ||
306 | struct lm95245_data *data = i2c_get_clientdata(client); | ||
307 | |||
308 | return snprintf(buf, PAGE_SIZE - 1, | ||
309 | data->config2 & CFG2_REMOTE_TT ? "1\n" : "2\n"); | ||
310 | } | ||
311 | |||
312 | static ssize_t set_type(struct device *dev, struct device_attribute *attr, | ||
313 | const char *buf, size_t count) | ||
314 | { | ||
315 | struct i2c_client *client = to_i2c_client(dev); | ||
316 | struct lm95245_data *data = i2c_get_clientdata(client); | ||
317 | unsigned long val; | ||
318 | |||
319 | if (strict_strtoul(buf, 10, &val) < 0) | ||
320 | return -EINVAL; | ||
321 | if (val != 1 && val != 2) | ||
322 | return -EINVAL; | ||
323 | |||
324 | mutex_lock(&data->update_lock); | ||
325 | |||
326 | if (val == 1) | ||
327 | data->config2 |= CFG2_REMOTE_TT; | ||
328 | else | ||
329 | data->config2 &= ~CFG2_REMOTE_TT; | ||
330 | |||
331 | data->valid = 0; | ||
332 | |||
333 | i2c_smbus_write_byte_data(client, LM95245_REG_RW_CONFIG2, | ||
334 | data->config2); | ||
335 | |||
336 | mutex_unlock(&data->update_lock); | ||
337 | |||
338 | return count; | ||
339 | } | ||
340 | |||
341 | static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, | ||
342 | char *buf) | ||
343 | { | ||
344 | struct lm95245_data *data = lm95245_update_device(dev); | ||
345 | int index = to_sensor_dev_attr(attr)->index; | ||
346 | |||
347 | return snprintf(buf, PAGE_SIZE - 1, "%d\n", | ||
348 | !!(data->regs[9] & index)); | ||
349 | } | ||
350 | |||
351 | static ssize_t show_interval(struct device *dev, struct device_attribute *attr, | ||
352 | char *buf) | ||
353 | { | ||
354 | struct lm95245_data *data = lm95245_update_device(dev); | ||
355 | |||
356 | return snprintf(buf, PAGE_SIZE - 1, "%lu\n", data->interval); | ||
357 | } | ||
358 | |||
359 | static ssize_t set_interval(struct device *dev, struct device_attribute *attr, | ||
360 | const char *buf, size_t count) | ||
361 | { | ||
362 | struct i2c_client *client = to_i2c_client(dev); | ||
363 | struct lm95245_data *data = i2c_get_clientdata(client); | ||
364 | unsigned long val; | ||
365 | |||
366 | if (strict_strtoul(buf, 10, &val) < 0) | ||
367 | return -EINVAL; | ||
368 | |||
369 | mutex_lock(&data->update_lock); | ||
370 | |||
371 | data->interval = lm95245_set_conversion_rate(client, val); | ||
372 | |||
373 | mutex_unlock(&data->update_lock); | ||
374 | |||
375 | return count; | ||
376 | } | ||
377 | |||
378 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_input, NULL, 0); | ||
379 | static SENSOR_DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, show_limit, | ||
380 | set_limit, 6); | ||
381 | static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_limit, | ||
382 | set_crit_hyst, 8); | ||
383 | static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, | ||
384 | STATUS1_LOC); | ||
385 | |||
386 | static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_input, NULL, 2); | ||
387 | static SENSOR_DEVICE_ATTR(temp2_crit, S_IWUSR | S_IRUGO, show_limit, | ||
388 | set_limit, 7); | ||
389 | static SENSOR_DEVICE_ATTR(temp2_crit_hyst, S_IWUSR | S_IRUGO, show_limit, | ||
390 | set_crit_hyst, 8); | ||
391 | static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, | ||
392 | STATUS1_RTCRIT); | ||
393 | static SENSOR_DEVICE_ATTR(temp2_type, S_IWUSR | S_IRUGO, show_type, | ||
394 | set_type, 0); | ||
395 | static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, | ||
396 | STATUS1_DIODE_FAULT); | ||
397 | |||
398 | static DEVICE_ATTR(update_interval, S_IWUSR | S_IRUGO, show_interval, | ||
399 | set_interval); | ||
400 | |||
401 | static struct attribute *lm95245_attributes[] = { | ||
402 | &sensor_dev_attr_temp1_input.dev_attr.attr, | ||
403 | &sensor_dev_attr_temp1_crit.dev_attr.attr, | ||
404 | &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr, | ||
405 | &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, | ||
406 | &sensor_dev_attr_temp2_input.dev_attr.attr, | ||
407 | &sensor_dev_attr_temp2_crit.dev_attr.attr, | ||
408 | &sensor_dev_attr_temp2_crit_hyst.dev_attr.attr, | ||
409 | &sensor_dev_attr_temp2_crit_alarm.dev_attr.attr, | ||
410 | &sensor_dev_attr_temp2_type.dev_attr.attr, | ||
411 | &sensor_dev_attr_temp2_fault.dev_attr.attr, | ||
412 | &dev_attr_update_interval.attr, | ||
413 | NULL | ||
414 | }; | ||
415 | |||
416 | static const struct attribute_group lm95245_group = { | ||
417 | .attrs = lm95245_attributes, | ||
418 | }; | ||
419 | |||
420 | /* Return 0 if detection is successful, -ENODEV otherwise */ | ||
421 | static int lm95245_detect(struct i2c_client *new_client, | ||
422 | struct i2c_board_info *info) | ||
423 | { | ||
424 | struct i2c_adapter *adapter = new_client->adapter; | ||
425 | |||
426 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | ||
427 | return -ENODEV; | ||
428 | |||
429 | if (i2c_smbus_read_byte_data(new_client, LM95245_REG_R_MAN_ID) | ||
430 | != MANUFACTURER_ID | ||
431 | || i2c_smbus_read_byte_data(new_client, LM95245_REG_R_CHIP_ID) | ||
432 | != DEFAULT_REVISION) | ||
433 | return -ENODEV; | ||
434 | |||
435 | strlcpy(info->type, DEVNAME, I2C_NAME_SIZE); | ||
436 | return 0; | ||
437 | } | ||
438 | |||
439 | static void lm95245_init_client(struct i2c_client *client) | ||
440 | { | ||
441 | struct lm95245_data *data = i2c_get_clientdata(client); | ||
442 | |||
443 | data->valid = 0; | ||
444 | data->interval = lm95245_read_conversion_rate(client); | ||
445 | |||
446 | data->config1 = i2c_smbus_read_byte_data(client, | ||
447 | LM95245_REG_RW_CONFIG1); | ||
448 | data->config2 = i2c_smbus_read_byte_data(client, | ||
449 | LM95245_REG_RW_CONFIG2); | ||
450 | |||
451 | if (data->config1 & CFG_STOP) { | ||
452 | /* Clear the standby bit */ | ||
453 | data->config1 &= ~CFG_STOP; | ||
454 | i2c_smbus_write_byte_data(client, LM95245_REG_RW_CONFIG1, | ||
455 | data->config1); | ||
456 | } | ||
457 | } | ||
458 | |||
459 | static int lm95245_probe(struct i2c_client *new_client, | ||
460 | const struct i2c_device_id *id) | ||
461 | { | ||
462 | struct lm95245_data *data; | ||
463 | int err; | ||
464 | |||
465 | data = kzalloc(sizeof(struct lm95245_data), GFP_KERNEL); | ||
466 | if (!data) { | ||
467 | err = -ENOMEM; | ||
468 | goto exit; | ||
469 | } | ||
470 | |||
471 | i2c_set_clientdata(new_client, data); | ||
472 | mutex_init(&data->update_lock); | ||
473 | |||
474 | /* Initialize the LM95245 chip */ | ||
475 | lm95245_init_client(new_client); | ||
476 | |||
477 | /* Register sysfs hooks */ | ||
478 | err = sysfs_create_group(&new_client->dev.kobj, &lm95245_group); | ||
479 | if (err) | ||
480 | goto exit_free; | ||
481 | |||
482 | data->hwmon_dev = hwmon_device_register(&new_client->dev); | ||
483 | if (IS_ERR(data->hwmon_dev)) { | ||
484 | err = PTR_ERR(data->hwmon_dev); | ||
485 | goto exit_remove_files; | ||
486 | } | ||
487 | |||
488 | return 0; | ||
489 | |||
490 | exit_remove_files: | ||
491 | sysfs_remove_group(&new_client->dev.kobj, &lm95245_group); | ||
492 | exit_free: | ||
493 | kfree(data); | ||
494 | exit: | ||
495 | return err; | ||
496 | } | ||
497 | |||
498 | static int lm95245_remove(struct i2c_client *client) | ||
499 | { | ||
500 | struct lm95245_data *data = i2c_get_clientdata(client); | ||
501 | |||
502 | hwmon_device_unregister(data->hwmon_dev); | ||
503 | sysfs_remove_group(&client->dev.kobj, &lm95245_group); | ||
504 | |||
505 | kfree(data); | ||
506 | return 0; | ||
507 | } | ||
508 | |||
509 | /* Driver data (common to all clients) */ | ||
510 | static const struct i2c_device_id lm95245_id[] = { | ||
511 | { DEVNAME, 0 }, | ||
512 | { } | ||
513 | }; | ||
514 | MODULE_DEVICE_TABLE(i2c, lm95245_id); | ||
515 | |||
516 | static struct i2c_driver lm95245_driver = { | ||
517 | .class = I2C_CLASS_HWMON, | ||
518 | .driver = { | ||
519 | .name = DEVNAME, | ||
520 | }, | ||
521 | .probe = lm95245_probe, | ||
522 | .remove = lm95245_remove, | ||
523 | .id_table = lm95245_id, | ||
524 | .detect = lm95245_detect, | ||
525 | .address_list = normal_i2c, | ||
526 | }; | ||
527 | |||
528 | static int __init sensors_lm95245_init(void) | ||
529 | { | ||
530 | return i2c_add_driver(&lm95245_driver); | ||
531 | } | ||
532 | |||
533 | static void __exit sensors_lm95245_exit(void) | ||
534 | { | ||
535 | i2c_del_driver(&lm95245_driver); | ||
536 | } | ||
537 | |||
538 | MODULE_AUTHOR("Alexander Stein <alexander.stein@systec-electronic.com>"); | ||
539 | MODULE_DESCRIPTION("LM95245 sensor driver"); | ||
540 | MODULE_LICENSE("GPL"); | ||
541 | |||
542 | module_init(sensors_lm95245_init); | ||
543 | module_exit(sensors_lm95245_exit); | ||
diff --git a/drivers/hwmon/max1668.c b/drivers/hwmon/max1668.c new file mode 100644 index 000000000000..20d1b2ddffb6 --- /dev/null +++ b/drivers/hwmon/max1668.c | |||
@@ -0,0 +1,502 @@ | |||
1 | /* | ||
2 | Copyright (c) 2011 David George <david.george@ska.ac.za> | ||
3 | |||
4 | based on adm1021.c | ||
5 | some credit to Christoph Scheurer, but largely a rewrite | ||
6 | |||
7 | This program is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation; either version 2 of the License, or | ||
10 | (at your option) any later version. | ||
11 | |||
12 | This program is distributed in the hope that it will be useful, | ||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | GNU General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU General Public License | ||
18 | along with this program; if not, write to the Free Software | ||
19 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | */ | ||
21 | |||
22 | #include <linux/module.h> | ||
23 | #include <linux/init.h> | ||
24 | #include <linux/slab.h> | ||
25 | #include <linux/jiffies.h> | ||
26 | #include <linux/i2c.h> | ||
27 | #include <linux/hwmon.h> | ||
28 | #include <linux/hwmon-sysfs.h> | ||
29 | #include <linux/err.h> | ||
30 | #include <linux/mutex.h> | ||
31 | |||
32 | /* Addresses to scan */ | ||
33 | static unsigned short max1668_addr_list[] = { | ||
34 | 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, 0x4c, 0x4d, 0x4e, I2C_CLIENT_END }; | ||
35 | |||
36 | /* max1668 registers */ | ||
37 | |||
38 | #define MAX1668_REG_TEMP(nr) (nr) | ||
39 | #define MAX1668_REG_STAT1 0x05 | ||
40 | #define MAX1668_REG_STAT2 0x06 | ||
41 | #define MAX1668_REG_MAN_ID 0xfe | ||
42 | #define MAX1668_REG_DEV_ID 0xff | ||
43 | |||
44 | /* limits */ | ||
45 | |||
46 | /* write high limits */ | ||
47 | #define MAX1668_REG_LIMH_WR(nr) (0x13 + 2 * (nr)) | ||
48 | /* write low limits */ | ||
49 | #define MAX1668_REG_LIML_WR(nr) (0x14 + 2 * (nr)) | ||
50 | /* read high limits */ | ||
51 | #define MAX1668_REG_LIMH_RD(nr) (0x08 + 2 * (nr)) | ||
52 | /* read low limits */ | ||
53 | #define MAX1668_REG_LIML_RD(nr) (0x09 + 2 * (nr)) | ||
54 | |||
55 | /* manufacturer and device ID Constants */ | ||
56 | #define MAN_ID_MAXIM 0x4d | ||
57 | #define DEV_ID_MAX1668 0x3 | ||
58 | #define DEV_ID_MAX1805 0x5 | ||
59 | #define DEV_ID_MAX1989 0xb | ||
60 | |||
61 | /* read only mode module parameter */ | ||
62 | static int read_only; | ||
63 | module_param(read_only, bool, 0); | ||
64 | MODULE_PARM_DESC(read_only, "Don't set any values, read only mode"); | ||
65 | |||
66 | enum chips { max1668, max1805, max1989 }; | ||
67 | |||
68 | struct max1668_data { | ||
69 | struct device *hwmon_dev; | ||
70 | enum chips type; | ||
71 | |||
72 | struct mutex update_lock; | ||
73 | char valid; /* !=0 if following fields are valid */ | ||
74 | unsigned long last_updated; /* In jiffies */ | ||
75 | |||
76 | /* 1x local and 4x remote */ | ||
77 | s8 temp_max[5]; | ||
78 | s8 temp_min[5]; | ||
79 | s8 temp[5]; | ||
80 | u16 alarms; | ||
81 | }; | ||
82 | |||
83 | static struct max1668_data *max1668_update_device(struct device *dev) | ||
84 | { | ||
85 | struct i2c_client *client = to_i2c_client(dev); | ||
86 | struct max1668_data *data = i2c_get_clientdata(client); | ||
87 | struct max1668_data *ret = data; | ||
88 | s32 val; | ||
89 | int i; | ||
90 | |||
91 | mutex_lock(&data->update_lock); | ||
92 | |||
93 | if (data->valid && !time_after(jiffies, | ||
94 | data->last_updated + HZ + HZ / 2)) | ||
95 | goto abort; | ||
96 | |||
97 | for (i = 0; i < 5; i++) { | ||
98 | val = i2c_smbus_read_byte_data(client, MAX1668_REG_TEMP(i)); | ||
99 | if (unlikely(val < 0)) { | ||
100 | ret = ERR_PTR(val); | ||
101 | goto abort; | ||
102 | } | ||
103 | data->temp[i] = (s8) val; | ||
104 | |||
105 | val = i2c_smbus_read_byte_data(client, MAX1668_REG_LIMH_RD(i)); | ||
106 | if (unlikely(val < 0)) { | ||
107 | ret = ERR_PTR(val); | ||
108 | goto abort; | ||
109 | } | ||
110 | data->temp_max[i] = (s8) val; | ||
111 | |||
112 | val = i2c_smbus_read_byte_data(client, MAX1668_REG_LIML_RD(i)); | ||
113 | if (unlikely(val < 0)) { | ||
114 | ret = ERR_PTR(val); | ||
115 | goto abort; | ||
116 | } | ||
117 | data->temp_min[i] = (s8) val; | ||
118 | } | ||
119 | |||
120 | val = i2c_smbus_read_byte_data(client, MAX1668_REG_STAT1); | ||
121 | if (unlikely(val < 0)) { | ||
122 | ret = ERR_PTR(val); | ||
123 | goto abort; | ||
124 | } | ||
125 | data->alarms = val << 8; | ||
126 | |||
127 | val = i2c_smbus_read_byte_data(client, MAX1668_REG_STAT2); | ||
128 | if (unlikely(val < 0)) { | ||
129 | ret = ERR_PTR(val); | ||
130 | goto abort; | ||
131 | } | ||
132 | data->alarms |= val; | ||
133 | |||
134 | data->last_updated = jiffies; | ||
135 | data->valid = 1; | ||
136 | abort: | ||
137 | mutex_unlock(&data->update_lock); | ||
138 | |||
139 | return ret; | ||
140 | } | ||
141 | |||
142 | static ssize_t show_temp(struct device *dev, | ||
143 | struct device_attribute *devattr, char *buf) | ||
144 | { | ||
145 | int index = to_sensor_dev_attr(devattr)->index; | ||
146 | struct max1668_data *data = max1668_update_device(dev); | ||
147 | |||
148 | if (IS_ERR(data)) | ||
149 | return PTR_ERR(data); | ||
150 | |||
151 | return sprintf(buf, "%d\n", data->temp[index] * 1000); | ||
152 | } | ||
153 | |||
154 | static ssize_t show_temp_max(struct device *dev, | ||
155 | struct device_attribute *devattr, char *buf) | ||
156 | { | ||
157 | int index = to_sensor_dev_attr(devattr)->index; | ||
158 | struct max1668_data *data = max1668_update_device(dev); | ||
159 | |||
160 | if (IS_ERR(data)) | ||
161 | return PTR_ERR(data); | ||
162 | |||
163 | return sprintf(buf, "%d\n", data->temp_max[index] * 1000); | ||
164 | } | ||
165 | |||
166 | static ssize_t show_temp_min(struct device *dev, | ||
167 | struct device_attribute *devattr, char *buf) | ||
168 | { | ||
169 | int index = to_sensor_dev_attr(devattr)->index; | ||
170 | struct max1668_data *data = max1668_update_device(dev); | ||
171 | |||
172 | if (IS_ERR(data)) | ||
173 | return PTR_ERR(data); | ||
174 | |||
175 | return sprintf(buf, "%d\n", data->temp_min[index] * 1000); | ||
176 | } | ||
177 | |||
178 | static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, | ||
179 | char *buf) | ||
180 | { | ||
181 | int index = to_sensor_dev_attr(attr)->index; | ||
182 | struct max1668_data *data = max1668_update_device(dev); | ||
183 | |||
184 | if (IS_ERR(data)) | ||
185 | return PTR_ERR(data); | ||
186 | |||
187 | return sprintf(buf, "%u\n", (data->alarms >> index) & 0x1); | ||
188 | } | ||
189 | |||
190 | static ssize_t show_fault(struct device *dev, | ||
191 | struct device_attribute *devattr, char *buf) | ||
192 | { | ||
193 | int index = to_sensor_dev_attr(devattr)->index; | ||
194 | struct max1668_data *data = max1668_update_device(dev); | ||
195 | |||
196 | if (IS_ERR(data)) | ||
197 | return PTR_ERR(data); | ||
198 | |||
199 | return sprintf(buf, "%u\n", | ||
200 | (data->alarms & (1 << 12)) && data->temp[index] == 127); | ||
201 | } | ||
202 | |||
203 | static ssize_t set_temp_max(struct device *dev, | ||
204 | struct device_attribute *devattr, | ||
205 | const char *buf, size_t count) | ||
206 | { | ||
207 | int index = to_sensor_dev_attr(devattr)->index; | ||
208 | struct i2c_client *client = to_i2c_client(dev); | ||
209 | struct max1668_data *data = i2c_get_clientdata(client); | ||
210 | long temp; | ||
211 | int ret; | ||
212 | |||
213 | ret = kstrtol(buf, 10, &temp); | ||
214 | if (ret < 0) | ||
215 | return ret; | ||
216 | |||
217 | mutex_lock(&data->update_lock); | ||
218 | data->temp_max[index] = SENSORS_LIMIT(temp/1000, -128, 127); | ||
219 | if (i2c_smbus_write_byte_data(client, | ||
220 | MAX1668_REG_LIMH_WR(index), | ||
221 | data->temp_max[index])) | ||
222 | count = -EIO; | ||
223 | mutex_unlock(&data->update_lock); | ||
224 | |||
225 | return count; | ||
226 | } | ||
227 | |||
228 | static ssize_t set_temp_min(struct device *dev, | ||
229 | struct device_attribute *devattr, | ||
230 | const char *buf, size_t count) | ||
231 | { | ||
232 | int index = to_sensor_dev_attr(devattr)->index; | ||
233 | struct i2c_client *client = to_i2c_client(dev); | ||
234 | struct max1668_data *data = i2c_get_clientdata(client); | ||
235 | long temp; | ||
236 | int ret; | ||
237 | |||
238 | ret = kstrtol(buf, 10, &temp); | ||
239 | if (ret < 0) | ||
240 | return ret; | ||
241 | |||
242 | mutex_lock(&data->update_lock); | ||
243 | data->temp_min[index] = SENSORS_LIMIT(temp/1000, -128, 127); | ||
244 | if (i2c_smbus_write_byte_data(client, | ||
245 | MAX1668_REG_LIML_WR(index), | ||
246 | data->temp_max[index])) | ||
247 | count = -EIO; | ||
248 | mutex_unlock(&data->update_lock); | ||
249 | |||
250 | return count; | ||
251 | } | ||
252 | |||
253 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); | ||
254 | static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, show_temp_max, | ||
255 | set_temp_max, 0); | ||
256 | static SENSOR_DEVICE_ATTR(temp1_min, S_IRUGO, show_temp_min, | ||
257 | set_temp_min, 0); | ||
258 | static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1); | ||
259 | static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO, show_temp_max, | ||
260 | set_temp_max, 1); | ||
261 | static SENSOR_DEVICE_ATTR(temp2_min, S_IRUGO, show_temp_min, | ||
262 | set_temp_min, 1); | ||
263 | static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2); | ||
264 | static SENSOR_DEVICE_ATTR(temp3_max, S_IRUGO, show_temp_max, | ||
265 | set_temp_max, 2); | ||
266 | static SENSOR_DEVICE_ATTR(temp3_min, S_IRUGO, show_temp_min, | ||
267 | set_temp_min, 2); | ||
268 | static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp, NULL, 3); | ||
269 | static SENSOR_DEVICE_ATTR(temp4_max, S_IRUGO, show_temp_max, | ||
270 | set_temp_max, 3); | ||
271 | static SENSOR_DEVICE_ATTR(temp4_min, S_IRUGO, show_temp_min, | ||
272 | set_temp_min, 3); | ||
273 | static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_temp, NULL, 4); | ||
274 | static SENSOR_DEVICE_ATTR(temp5_max, S_IRUGO, show_temp_max, | ||
275 | set_temp_max, 4); | ||
276 | static SENSOR_DEVICE_ATTR(temp5_min, S_IRUGO, show_temp_min, | ||
277 | set_temp_min, 4); | ||
278 | |||
279 | static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 14); | ||
280 | static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, 13); | ||
281 | static SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO, show_alarm, NULL, 7); | ||
282 | static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 6); | ||
283 | static SENSOR_DEVICE_ATTR(temp3_min_alarm, S_IRUGO, show_alarm, NULL, 5); | ||
284 | static SENSOR_DEVICE_ATTR(temp3_max_alarm, S_IRUGO, show_alarm, NULL, 4); | ||
285 | static SENSOR_DEVICE_ATTR(temp4_min_alarm, S_IRUGO, show_alarm, NULL, 3); | ||
286 | static SENSOR_DEVICE_ATTR(temp4_max_alarm, S_IRUGO, show_alarm, NULL, 2); | ||
287 | static SENSOR_DEVICE_ATTR(temp5_min_alarm, S_IRUGO, show_alarm, NULL, 1); | ||
288 | static SENSOR_DEVICE_ATTR(temp5_max_alarm, S_IRUGO, show_alarm, NULL, 0); | ||
289 | |||
290 | static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_fault, NULL, 1); | ||
291 | static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_fault, NULL, 2); | ||
292 | static SENSOR_DEVICE_ATTR(temp4_fault, S_IRUGO, show_fault, NULL, 3); | ||
293 | static SENSOR_DEVICE_ATTR(temp5_fault, S_IRUGO, show_fault, NULL, 4); | ||
294 | |||
295 | /* Attributes common to MAX1668, MAX1989 and MAX1805 */ | ||
296 | static struct attribute *max1668_attribute_common[] = { | ||
297 | &sensor_dev_attr_temp1_max.dev_attr.attr, | ||
298 | &sensor_dev_attr_temp1_min.dev_attr.attr, | ||
299 | &sensor_dev_attr_temp1_input.dev_attr.attr, | ||
300 | &sensor_dev_attr_temp2_max.dev_attr.attr, | ||
301 | &sensor_dev_attr_temp2_min.dev_attr.attr, | ||
302 | &sensor_dev_attr_temp2_input.dev_attr.attr, | ||
303 | &sensor_dev_attr_temp3_max.dev_attr.attr, | ||
304 | &sensor_dev_attr_temp3_min.dev_attr.attr, | ||
305 | &sensor_dev_attr_temp3_input.dev_attr.attr, | ||
306 | |||
307 | &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, | ||
308 | &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, | ||
309 | &sensor_dev_attr_temp2_max_alarm.dev_attr.attr, | ||
310 | &sensor_dev_attr_temp2_min_alarm.dev_attr.attr, | ||
311 | &sensor_dev_attr_temp3_max_alarm.dev_attr.attr, | ||
312 | &sensor_dev_attr_temp3_min_alarm.dev_attr.attr, | ||
313 | |||
314 | &sensor_dev_attr_temp2_fault.dev_attr.attr, | ||
315 | &sensor_dev_attr_temp3_fault.dev_attr.attr, | ||
316 | NULL | ||
317 | }; | ||
318 | |||
319 | /* Attributes not present on MAX1805 */ | ||
320 | static struct attribute *max1668_attribute_unique[] = { | ||
321 | &sensor_dev_attr_temp4_max.dev_attr.attr, | ||
322 | &sensor_dev_attr_temp4_min.dev_attr.attr, | ||
323 | &sensor_dev_attr_temp4_input.dev_attr.attr, | ||
324 | &sensor_dev_attr_temp5_max.dev_attr.attr, | ||
325 | &sensor_dev_attr_temp5_min.dev_attr.attr, | ||
326 | &sensor_dev_attr_temp5_input.dev_attr.attr, | ||
327 | |||
328 | &sensor_dev_attr_temp4_max_alarm.dev_attr.attr, | ||
329 | &sensor_dev_attr_temp4_min_alarm.dev_attr.attr, | ||
330 | &sensor_dev_attr_temp5_max_alarm.dev_attr.attr, | ||
331 | &sensor_dev_attr_temp5_min_alarm.dev_attr.attr, | ||
332 | |||
333 | &sensor_dev_attr_temp4_fault.dev_attr.attr, | ||
334 | &sensor_dev_attr_temp5_fault.dev_attr.attr, | ||
335 | NULL | ||
336 | }; | ||
337 | |||
338 | static mode_t max1668_attribute_mode(struct kobject *kobj, | ||
339 | struct attribute *attr, int index) | ||
340 | { | ||
341 | int ret = S_IRUGO; | ||
342 | if (read_only) | ||
343 | return ret; | ||
344 | if (attr == &sensor_dev_attr_temp1_max.dev_attr.attr || | ||
345 | attr == &sensor_dev_attr_temp2_max.dev_attr.attr || | ||
346 | attr == &sensor_dev_attr_temp3_max.dev_attr.attr || | ||
347 | attr == &sensor_dev_attr_temp4_max.dev_attr.attr || | ||
348 | attr == &sensor_dev_attr_temp5_max.dev_attr.attr || | ||
349 | attr == &sensor_dev_attr_temp1_min.dev_attr.attr || | ||
350 | attr == &sensor_dev_attr_temp2_min.dev_attr.attr || | ||
351 | attr == &sensor_dev_attr_temp3_min.dev_attr.attr || | ||
352 | attr == &sensor_dev_attr_temp4_min.dev_attr.attr || | ||
353 | attr == &sensor_dev_attr_temp5_min.dev_attr.attr) | ||
354 | ret |= S_IWUSR; | ||
355 | return ret; | ||
356 | } | ||
357 | |||
358 | static const struct attribute_group max1668_group_common = { | ||
359 | .attrs = max1668_attribute_common, | ||
360 | .is_visible = max1668_attribute_mode | ||
361 | }; | ||
362 | |||
363 | static const struct attribute_group max1668_group_unique = { | ||
364 | .attrs = max1668_attribute_unique, | ||
365 | .is_visible = max1668_attribute_mode | ||
366 | }; | ||
367 | |||
368 | /* Return 0 if detection is successful, -ENODEV otherwise */ | ||
369 | static int max1668_detect(struct i2c_client *client, | ||
370 | struct i2c_board_info *info) | ||
371 | { | ||
372 | struct i2c_adapter *adapter = client->adapter; | ||
373 | const char *type_name; | ||
374 | int man_id, dev_id; | ||
375 | |||
376 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | ||
377 | return -ENODEV; | ||
378 | |||
379 | /* Check for unsupported part */ | ||
380 | man_id = i2c_smbus_read_byte_data(client, MAX1668_REG_MAN_ID); | ||
381 | if (man_id != MAN_ID_MAXIM) | ||
382 | return -ENODEV; | ||
383 | |||
384 | dev_id = i2c_smbus_read_byte_data(client, MAX1668_REG_DEV_ID); | ||
385 | if (dev_id < 0) | ||
386 | return -ENODEV; | ||
387 | |||
388 | type_name = NULL; | ||
389 | if (dev_id == DEV_ID_MAX1668) | ||
390 | type_name = "max1668"; | ||
391 | else if (dev_id == DEV_ID_MAX1805) | ||
392 | type_name = "max1805"; | ||
393 | else if (dev_id == DEV_ID_MAX1989) | ||
394 | type_name = "max1989"; | ||
395 | |||
396 | if (!type_name) | ||
397 | return -ENODEV; | ||
398 | |||
399 | strlcpy(info->type, type_name, I2C_NAME_SIZE); | ||
400 | |||
401 | return 0; | ||
402 | } | ||
403 | |||
404 | static int max1668_probe(struct i2c_client *client, | ||
405 | const struct i2c_device_id *id) | ||
406 | { | ||
407 | struct i2c_adapter *adapter = client->adapter; | ||
408 | struct max1668_data *data; | ||
409 | int err; | ||
410 | |||
411 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | ||
412 | return -ENODEV; | ||
413 | |||
414 | data = kzalloc(sizeof(struct max1668_data), GFP_KERNEL); | ||
415 | if (!data) | ||
416 | return -ENOMEM; | ||
417 | |||
418 | i2c_set_clientdata(client, data); | ||
419 | data->type = id->driver_data; | ||
420 | mutex_init(&data->update_lock); | ||
421 | |||
422 | /* Register sysfs hooks */ | ||
423 | err = sysfs_create_group(&client->dev.kobj, &max1668_group_common); | ||
424 | if (err) | ||
425 | goto error_free; | ||
426 | |||
427 | if (data->type == max1668 || data->type == max1989) { | ||
428 | err = sysfs_create_group(&client->dev.kobj, | ||
429 | &max1668_group_unique); | ||
430 | if (err) | ||
431 | goto error_sysrem0; | ||
432 | } | ||
433 | |||
434 | data->hwmon_dev = hwmon_device_register(&client->dev); | ||
435 | if (IS_ERR(data->hwmon_dev)) { | ||
436 | err = PTR_ERR(data->hwmon_dev); | ||
437 | goto error_sysrem1; | ||
438 | } | ||
439 | |||
440 | return 0; | ||
441 | |||
442 | error_sysrem1: | ||
443 | if (data->type == max1668 || data->type == max1989) | ||
444 | sysfs_remove_group(&client->dev.kobj, &max1668_group_unique); | ||
445 | error_sysrem0: | ||
446 | sysfs_remove_group(&client->dev.kobj, &max1668_group_common); | ||
447 | error_free: | ||
448 | kfree(data); | ||
449 | return err; | ||
450 | } | ||
451 | |||
452 | static int max1668_remove(struct i2c_client *client) | ||
453 | { | ||
454 | struct max1668_data *data = i2c_get_clientdata(client); | ||
455 | |||
456 | hwmon_device_unregister(data->hwmon_dev); | ||
457 | if (data->type == max1668 || data->type == max1989) | ||
458 | sysfs_remove_group(&client->dev.kobj, &max1668_group_unique); | ||
459 | |||
460 | sysfs_remove_group(&client->dev.kobj, &max1668_group_common); | ||
461 | |||
462 | kfree(data); | ||
463 | return 0; | ||
464 | } | ||
465 | |||
466 | static const struct i2c_device_id max1668_id[] = { | ||
467 | { "max1668", max1668 }, | ||
468 | { "max1805", max1805 }, | ||
469 | { "max1989", max1989 }, | ||
470 | { } | ||
471 | }; | ||
472 | MODULE_DEVICE_TABLE(i2c, max1668_id); | ||
473 | |||
474 | /* This is the driver that will be inserted */ | ||
475 | static struct i2c_driver max1668_driver = { | ||
476 | .class = I2C_CLASS_HWMON, | ||
477 | .driver = { | ||
478 | .name = "max1668", | ||
479 | }, | ||
480 | .probe = max1668_probe, | ||
481 | .remove = max1668_remove, | ||
482 | .id_table = max1668_id, | ||
483 | .detect = max1668_detect, | ||
484 | .address_list = max1668_addr_list, | ||
485 | }; | ||
486 | |||
487 | static int __init sensors_max1668_init(void) | ||
488 | { | ||
489 | return i2c_add_driver(&max1668_driver); | ||
490 | } | ||
491 | |||
492 | static void __exit sensors_max1668_exit(void) | ||
493 | { | ||
494 | i2c_del_driver(&max1668_driver); | ||
495 | } | ||
496 | |||
497 | MODULE_AUTHOR("David George <david.george@ska.ac.za>"); | ||
498 | MODULE_DESCRIPTION("MAX1668 remote temperature sensor driver"); | ||
499 | MODULE_LICENSE("GPL"); | ||
500 | |||
501 | module_init(sensors_max1668_init) | ||
502 | module_exit(sensors_max1668_exit) | ||
diff --git a/drivers/hwmon/ntc_thermistor.c b/drivers/hwmon/ntc_thermistor.c new file mode 100644 index 000000000000..d7926f4336b5 --- /dev/null +++ b/drivers/hwmon/ntc_thermistor.c | |||
@@ -0,0 +1,453 @@ | |||
1 | /* | ||
2 | * ntc_thermistor.c - NTC Thermistors | ||
3 | * | ||
4 | * Copyright (C) 2010 Samsung Electronics | ||
5 | * MyungJoo Ham <myungjoo.ham@samsung.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | #include <linux/slab.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/pm_runtime.h> | ||
26 | #include <linux/math64.h> | ||
27 | #include <linux/platform_device.h> | ||
28 | #include <linux/err.h> | ||
29 | |||
30 | #include <linux/platform_data/ntc_thermistor.h> | ||
31 | |||
32 | #include <linux/hwmon.h> | ||
33 | #include <linux/hwmon-sysfs.h> | ||
34 | |||
35 | struct ntc_compensation { | ||
36 | int temp_C; | ||
37 | unsigned int ohm; | ||
38 | }; | ||
39 | |||
40 | /* | ||
41 | * A compensation table should be sorted by the values of .ohm | ||
42 | * in descending order. | ||
43 | * The following compensation tables are from the specification of Murata NTC | ||
44 | * Thermistors Datasheet | ||
45 | */ | ||
46 | const struct ntc_compensation ncpXXwb473[] = { | ||
47 | { .temp_C = -40, .ohm = 1747920 }, | ||
48 | { .temp_C = -35, .ohm = 1245428 }, | ||
49 | { .temp_C = -30, .ohm = 898485 }, | ||
50 | { .temp_C = -25, .ohm = 655802 }, | ||
51 | { .temp_C = -20, .ohm = 483954 }, | ||
52 | { .temp_C = -15, .ohm = 360850 }, | ||
53 | { .temp_C = -10, .ohm = 271697 }, | ||
54 | { .temp_C = -5, .ohm = 206463 }, | ||
55 | { .temp_C = 0, .ohm = 158214 }, | ||
56 | { .temp_C = 5, .ohm = 122259 }, | ||
57 | { .temp_C = 10, .ohm = 95227 }, | ||
58 | { .temp_C = 15, .ohm = 74730 }, | ||
59 | { .temp_C = 20, .ohm = 59065 }, | ||
60 | { .temp_C = 25, .ohm = 47000 }, | ||
61 | { .temp_C = 30, .ohm = 37643 }, | ||
62 | { .temp_C = 35, .ohm = 30334 }, | ||
63 | { .temp_C = 40, .ohm = 24591 }, | ||
64 | { .temp_C = 45, .ohm = 20048 }, | ||
65 | { .temp_C = 50, .ohm = 16433 }, | ||
66 | { .temp_C = 55, .ohm = 13539 }, | ||
67 | { .temp_C = 60, .ohm = 11209 }, | ||
68 | { .temp_C = 65, .ohm = 9328 }, | ||
69 | { .temp_C = 70, .ohm = 7798 }, | ||
70 | { .temp_C = 75, .ohm = 6544 }, | ||
71 | { .temp_C = 80, .ohm = 5518 }, | ||
72 | { .temp_C = 85, .ohm = 4674 }, | ||
73 | { .temp_C = 90, .ohm = 3972 }, | ||
74 | { .temp_C = 95, .ohm = 3388 }, | ||
75 | { .temp_C = 100, .ohm = 2902 }, | ||
76 | { .temp_C = 105, .ohm = 2494 }, | ||
77 | { .temp_C = 110, .ohm = 2150 }, | ||
78 | { .temp_C = 115, .ohm = 1860 }, | ||
79 | { .temp_C = 120, .ohm = 1615 }, | ||
80 | { .temp_C = 125, .ohm = 1406 }, | ||
81 | }; | ||
82 | const struct ntc_compensation ncpXXwl333[] = { | ||
83 | { .temp_C = -40, .ohm = 1610154 }, | ||
84 | { .temp_C = -35, .ohm = 1130850 }, | ||
85 | { .temp_C = -30, .ohm = 802609 }, | ||
86 | { .temp_C = -25, .ohm = 575385 }, | ||
87 | { .temp_C = -20, .ohm = 416464 }, | ||
88 | { .temp_C = -15, .ohm = 304219 }, | ||
89 | { .temp_C = -10, .ohm = 224193 }, | ||
90 | { .temp_C = -5, .ohm = 166623 }, | ||
91 | { .temp_C = 0, .ohm = 124850 }, | ||
92 | { .temp_C = 5, .ohm = 94287 }, | ||
93 | { .temp_C = 10, .ohm = 71747 }, | ||
94 | { .temp_C = 15, .ohm = 54996 }, | ||
95 | { .temp_C = 20, .ohm = 42455 }, | ||
96 | { .temp_C = 25, .ohm = 33000 }, | ||
97 | { .temp_C = 30, .ohm = 25822 }, | ||
98 | { .temp_C = 35, .ohm = 20335 }, | ||
99 | { .temp_C = 40, .ohm = 16115 }, | ||
100 | { .temp_C = 45, .ohm = 12849 }, | ||
101 | { .temp_C = 50, .ohm = 10306 }, | ||
102 | { .temp_C = 55, .ohm = 8314 }, | ||
103 | { .temp_C = 60, .ohm = 6746 }, | ||
104 | { .temp_C = 65, .ohm = 5503 }, | ||
105 | { .temp_C = 70, .ohm = 4513 }, | ||
106 | { .temp_C = 75, .ohm = 3721 }, | ||
107 | { .temp_C = 80, .ohm = 3084 }, | ||
108 | { .temp_C = 85, .ohm = 2569 }, | ||
109 | { .temp_C = 90, .ohm = 2151 }, | ||
110 | { .temp_C = 95, .ohm = 1809 }, | ||
111 | { .temp_C = 100, .ohm = 1529 }, | ||
112 | { .temp_C = 105, .ohm = 1299 }, | ||
113 | { .temp_C = 110, .ohm = 1108 }, | ||
114 | { .temp_C = 115, .ohm = 949 }, | ||
115 | { .temp_C = 120, .ohm = 817 }, | ||
116 | { .temp_C = 125, .ohm = 707 }, | ||
117 | }; | ||
118 | |||
119 | struct ntc_data { | ||
120 | struct device *hwmon_dev; | ||
121 | struct ntc_thermistor_platform_data *pdata; | ||
122 | const struct ntc_compensation *comp; | ||
123 | struct device *dev; | ||
124 | int n_comp; | ||
125 | char name[PLATFORM_NAME_SIZE]; | ||
126 | }; | ||
127 | |||
128 | static inline u64 div64_u64_safe(u64 dividend, u64 divisor) | ||
129 | { | ||
130 | if (divisor == 0 && dividend == 0) | ||
131 | return 0; | ||
132 | if (divisor == 0) | ||
133 | return UINT_MAX; | ||
134 | return div64_u64(dividend, divisor); | ||
135 | } | ||
136 | |||
137 | static unsigned int get_ohm_of_thermistor(struct ntc_data *data, | ||
138 | unsigned int uV) | ||
139 | { | ||
140 | struct ntc_thermistor_platform_data *pdata = data->pdata; | ||
141 | u64 mV = uV / 1000; | ||
142 | u64 pmV = pdata->pullup_uV / 1000; | ||
143 | u64 N, puO, pdO; | ||
144 | puO = pdata->pullup_ohm; | ||
145 | pdO = pdata->pulldown_ohm; | ||
146 | |||
147 | if (mV == 0) { | ||
148 | if (pdata->connect == NTC_CONNECTED_POSITIVE) | ||
149 | return UINT_MAX; | ||
150 | return 0; | ||
151 | } | ||
152 | if (mV >= pmV) | ||
153 | return (pdata->connect == NTC_CONNECTED_POSITIVE) ? | ||
154 | 0 : UINT_MAX; | ||
155 | |||
156 | if (pdata->connect == NTC_CONNECTED_POSITIVE && puO == 0) | ||
157 | N = div64_u64_safe(pdO * (pmV - mV), mV); | ||
158 | else if (pdata->connect == NTC_CONNECTED_GROUND && pdO == 0) | ||
159 | N = div64_u64_safe(puO * mV, pmV - mV); | ||
160 | else if (pdata->connect == NTC_CONNECTED_POSITIVE) | ||
161 | N = div64_u64_safe(pdO * puO * (pmV - mV), | ||
162 | puO * mV - pdO * (pmV - mV)); | ||
163 | else | ||
164 | N = div64_u64_safe(pdO * puO * mV, pdO * (pmV - mV) - puO * mV); | ||
165 | |||
166 | return (unsigned int) N; | ||
167 | } | ||
168 | |||
169 | static int lookup_comp(struct ntc_data *data, | ||
170 | unsigned int ohm, int *i_low, int *i_high) | ||
171 | { | ||
172 | int start, end, mid = -1; | ||
173 | |||
174 | /* Do a binary search on compensation table */ | ||
175 | start = 0; | ||
176 | end = data->n_comp; | ||
177 | |||
178 | while (end > start) { | ||
179 | mid = start + (end - start) / 2; | ||
180 | if (data->comp[mid].ohm < ohm) | ||
181 | end = mid; | ||
182 | else if (data->comp[mid].ohm > ohm) | ||
183 | start = mid + 1; | ||
184 | else | ||
185 | break; | ||
186 | } | ||
187 | |||
188 | if (mid == 0) { | ||
189 | if (data->comp[mid].ohm > ohm) { | ||
190 | *i_high = mid; | ||
191 | *i_low = mid + 1; | ||
192 | return 0; | ||
193 | } else { | ||
194 | *i_low = mid; | ||
195 | *i_high = -1; | ||
196 | return -EINVAL; | ||
197 | } | ||
198 | } | ||
199 | if (mid == (data->n_comp - 1)) { | ||
200 | if (data->comp[mid].ohm <= ohm) { | ||
201 | *i_low = mid; | ||
202 | *i_high = mid - 1; | ||
203 | return 0; | ||
204 | } else { | ||
205 | *i_low = -1; | ||
206 | *i_high = mid; | ||
207 | return -EINVAL; | ||
208 | } | ||
209 | } | ||
210 | |||
211 | if (data->comp[mid].ohm <= ohm) { | ||
212 | *i_low = mid; | ||
213 | *i_high = mid - 1; | ||
214 | } | ||
215 | if (data->comp[mid].ohm > ohm) { | ||
216 | *i_low = mid + 1; | ||
217 | *i_high = mid; | ||
218 | } | ||
219 | |||
220 | return 0; | ||
221 | } | ||
222 | |||
223 | static int get_temp_mC(struct ntc_data *data, unsigned int ohm, int *temp) | ||
224 | { | ||
225 | int low, high; | ||
226 | int ret; | ||
227 | |||
228 | ret = lookup_comp(data, ohm, &low, &high); | ||
229 | if (ret) { | ||
230 | /* Unable to use linear approximation */ | ||
231 | if (low != -1) | ||
232 | *temp = data->comp[low].temp_C * 1000; | ||
233 | else if (high != -1) | ||
234 | *temp = data->comp[high].temp_C * 1000; | ||
235 | else | ||
236 | return ret; | ||
237 | } else { | ||
238 | *temp = data->comp[low].temp_C * 1000 + | ||
239 | ((data->comp[high].temp_C - data->comp[low].temp_C) * | ||
240 | 1000 * ((int)ohm - (int)data->comp[low].ohm)) / | ||
241 | ((int)data->comp[high].ohm - (int)data->comp[low].ohm); | ||
242 | } | ||
243 | |||
244 | return 0; | ||
245 | } | ||
246 | |||
247 | static int ntc_thermistor_read(struct ntc_data *data, int *temp) | ||
248 | { | ||
249 | int ret; | ||
250 | int read_ohm, read_uV; | ||
251 | unsigned int ohm = 0; | ||
252 | |||
253 | if (data->pdata->read_ohm) { | ||
254 | read_ohm = data->pdata->read_ohm(); | ||
255 | if (read_ohm < 0) | ||
256 | return read_ohm; | ||
257 | ohm = (unsigned int)read_ohm; | ||
258 | } | ||
259 | |||
260 | if (data->pdata->read_uV) { | ||
261 | read_uV = data->pdata->read_uV(); | ||
262 | if (read_uV < 0) | ||
263 | return read_uV; | ||
264 | ohm = get_ohm_of_thermistor(data, (unsigned int)read_uV); | ||
265 | } | ||
266 | |||
267 | ret = get_temp_mC(data, ohm, temp); | ||
268 | if (ret) { | ||
269 | dev_dbg(data->dev, "Sensor reading function not available.\n"); | ||
270 | return ret; | ||
271 | } | ||
272 | |||
273 | return 0; | ||
274 | } | ||
275 | |||
276 | static ssize_t ntc_show_name(struct device *dev, | ||
277 | struct device_attribute *attr, char *buf) | ||
278 | { | ||
279 | struct ntc_data *data = dev_get_drvdata(dev); | ||
280 | |||
281 | return sprintf(buf, "%s\n", data->name); | ||
282 | } | ||
283 | |||
284 | static ssize_t ntc_show_type(struct device *dev, | ||
285 | struct device_attribute *attr, char *buf) | ||
286 | { | ||
287 | return sprintf(buf, "4\n"); | ||
288 | } | ||
289 | |||
290 | static ssize_t ntc_show_temp(struct device *dev, | ||
291 | struct device_attribute *attr, char *buf) | ||
292 | { | ||
293 | struct ntc_data *data = dev_get_drvdata(dev); | ||
294 | int temp, ret; | ||
295 | |||
296 | ret = ntc_thermistor_read(data, &temp); | ||
297 | if (ret) | ||
298 | return ret; | ||
299 | return sprintf(buf, "%d\n", temp); | ||
300 | } | ||
301 | |||
302 | static SENSOR_DEVICE_ATTR(temp1_type, S_IRUGO, ntc_show_type, NULL, 0); | ||
303 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, ntc_show_temp, NULL, 0); | ||
304 | static DEVICE_ATTR(name, S_IRUGO, ntc_show_name, NULL); | ||
305 | |||
306 | static struct attribute *ntc_attributes[] = { | ||
307 | &dev_attr_name.attr, | ||
308 | &sensor_dev_attr_temp1_type.dev_attr.attr, | ||
309 | &sensor_dev_attr_temp1_input.dev_attr.attr, | ||
310 | NULL, | ||
311 | }; | ||
312 | |||
313 | static const struct attribute_group ntc_attr_group = { | ||
314 | .attrs = ntc_attributes, | ||
315 | }; | ||
316 | |||
317 | static int __devinit ntc_thermistor_probe(struct platform_device *pdev) | ||
318 | { | ||
319 | struct ntc_data *data; | ||
320 | struct ntc_thermistor_platform_data *pdata = pdev->dev.platform_data; | ||
321 | int ret = 0; | ||
322 | |||
323 | if (!pdata) { | ||
324 | dev_err(&pdev->dev, "No platform init data supplied.\n"); | ||
325 | return -ENODEV; | ||
326 | } | ||
327 | |||
328 | /* Either one of the two is required. */ | ||
329 | if (!pdata->read_uV && !pdata->read_ohm) { | ||
330 | dev_err(&pdev->dev, "Both read_uV and read_ohm missing." | ||
331 | "Need either one of the two.\n"); | ||
332 | return -EINVAL; | ||
333 | } | ||
334 | |||
335 | if (pdata->read_uV && pdata->read_ohm) { | ||
336 | dev_warn(&pdev->dev, "Only one of read_uV and read_ohm " | ||
337 | "is needed; ignoring read_uV.\n"); | ||
338 | pdata->read_uV = NULL; | ||
339 | } | ||
340 | |||
341 | if (pdata->read_uV && (pdata->pullup_uV == 0 || | ||
342 | (pdata->pullup_ohm == 0 && pdata->connect == | ||
343 | NTC_CONNECTED_GROUND) || | ||
344 | (pdata->pulldown_ohm == 0 && pdata->connect == | ||
345 | NTC_CONNECTED_POSITIVE) || | ||
346 | (pdata->connect != NTC_CONNECTED_POSITIVE && | ||
347 | pdata->connect != NTC_CONNECTED_GROUND))) { | ||
348 | dev_err(&pdev->dev, "Required data to use read_uV not " | ||
349 | "supplied.\n"); | ||
350 | return -EINVAL; | ||
351 | } | ||
352 | |||
353 | data = kzalloc(sizeof(struct ntc_data), GFP_KERNEL); | ||
354 | if (!data) | ||
355 | return -ENOMEM; | ||
356 | |||
357 | data->dev = &pdev->dev; | ||
358 | data->pdata = pdata; | ||
359 | strncpy(data->name, pdev->id_entry->name, PLATFORM_NAME_SIZE); | ||
360 | |||
361 | switch (pdev->id_entry->driver_data) { | ||
362 | case TYPE_NCPXXWB473: | ||
363 | data->comp = ncpXXwb473; | ||
364 | data->n_comp = ARRAY_SIZE(ncpXXwb473); | ||
365 | break; | ||
366 | case TYPE_NCPXXWL333: | ||
367 | data->comp = ncpXXwl333; | ||
368 | data->n_comp = ARRAY_SIZE(ncpXXwl333); | ||
369 | break; | ||
370 | default: | ||
371 | dev_err(&pdev->dev, "Unknown device type: %lu(%s)\n", | ||
372 | pdev->id_entry->driver_data, | ||
373 | pdev->id_entry->name); | ||
374 | ret = -EINVAL; | ||
375 | goto err; | ||
376 | } | ||
377 | |||
378 | platform_set_drvdata(pdev, data); | ||
379 | |||
380 | ret = sysfs_create_group(&data->dev->kobj, &ntc_attr_group); | ||
381 | if (ret) { | ||
382 | dev_err(data->dev, "unable to create sysfs files\n"); | ||
383 | goto err; | ||
384 | } | ||
385 | |||
386 | data->hwmon_dev = hwmon_device_register(data->dev); | ||
387 | if (IS_ERR_OR_NULL(data->hwmon_dev)) { | ||
388 | dev_err(data->dev, "unable to register as hwmon device.\n"); | ||
389 | ret = -EINVAL; | ||
390 | goto err_after_sysfs; | ||
391 | } | ||
392 | |||
393 | dev_info(&pdev->dev, "Thermistor %s:%d (type: %s/%lu) successfully probed.\n", | ||
394 | pdev->name, pdev->id, pdev->id_entry->name, | ||
395 | pdev->id_entry->driver_data); | ||
396 | return 0; | ||
397 | err_after_sysfs: | ||
398 | sysfs_remove_group(&data->dev->kobj, &ntc_attr_group); | ||
399 | err: | ||
400 | kfree(data); | ||
401 | return ret; | ||
402 | } | ||
403 | |||
404 | static int __devexit ntc_thermistor_remove(struct platform_device *pdev) | ||
405 | { | ||
406 | struct ntc_data *data = platform_get_drvdata(pdev); | ||
407 | |||
408 | hwmon_device_unregister(data->hwmon_dev); | ||
409 | sysfs_remove_group(&data->dev->kobj, &ntc_attr_group); | ||
410 | platform_set_drvdata(pdev, NULL); | ||
411 | |||
412 | kfree(data); | ||
413 | |||
414 | return 0; | ||
415 | } | ||
416 | |||
417 | static const struct platform_device_id ntc_thermistor_id[] = { | ||
418 | { "ncp15wb473", TYPE_NCPXXWB473 }, | ||
419 | { "ncp18wb473", TYPE_NCPXXWB473 }, | ||
420 | { "ncp21wb473", TYPE_NCPXXWB473 }, | ||
421 | { "ncp03wb473", TYPE_NCPXXWB473 }, | ||
422 | { "ncp15wl333", TYPE_NCPXXWL333 }, | ||
423 | { }, | ||
424 | }; | ||
425 | |||
426 | static struct platform_driver ntc_thermistor_driver = { | ||
427 | .driver = { | ||
428 | .name = "ntc-thermistor", | ||
429 | .owner = THIS_MODULE, | ||
430 | }, | ||
431 | .probe = ntc_thermistor_probe, | ||
432 | .remove = __devexit_p(ntc_thermistor_remove), | ||
433 | .id_table = ntc_thermistor_id, | ||
434 | }; | ||
435 | |||
436 | static int __init ntc_thermistor_init(void) | ||
437 | { | ||
438 | return platform_driver_register(&ntc_thermistor_driver); | ||
439 | } | ||
440 | |||
441 | module_init(ntc_thermistor_init); | ||
442 | |||
443 | static void __exit ntc_thermistor_cleanup(void) | ||
444 | { | ||
445 | platform_driver_unregister(&ntc_thermistor_driver); | ||
446 | } | ||
447 | |||
448 | module_exit(ntc_thermistor_cleanup); | ||
449 | |||
450 | MODULE_DESCRIPTION("NTC Thermistor Driver"); | ||
451 | MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>"); | ||
452 | MODULE_LICENSE("GPL"); | ||
453 | MODULE_ALIAS("platform:ntc-thermistor"); | ||
diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig new file mode 100644 index 000000000000..c9237b9dcff2 --- /dev/null +++ b/drivers/hwmon/pmbus/Kconfig | |||
@@ -0,0 +1,100 @@ | |||
1 | # | ||
2 | # PMBus chip drivers configuration | ||
3 | # | ||
4 | |||
5 | menuconfig PMBUS | ||
6 | tristate "PMBus support" | ||
7 | depends on I2C && EXPERIMENTAL | ||
8 | default n | ||
9 | help | ||
10 | Say yes here if you want to enable PMBus support. | ||
11 | |||
12 | This driver can also be built as a module. If so, the module will | ||
13 | be called pmbus_core. | ||
14 | |||
15 | if PMBUS | ||
16 | |||
17 | config SENSORS_PMBUS | ||
18 | tristate "Generic PMBus devices" | ||
19 | default y | ||
20 | help | ||
21 | If you say yes here you get hardware monitoring support for generic | ||
22 | PMBus devices, including but not limited to ADP4000, BMR450, BMR451, | ||
23 | BMR453, BMR454, LTC2978, NCP4200, and NCP4208. | ||
24 | |||
25 | This driver can also be built as a module. If so, the module will | ||
26 | be called pmbus. | ||
27 | |||
28 | config SENSORS_ADM1275 | ||
29 | tristate "Analog Devices ADM1275" | ||
30 | default n | ||
31 | help | ||
32 | If you say yes here you get hardware monitoring support for Analog | ||
33 | Devices ADM1275 Hot-Swap Controller and Digital Power Monitor. | ||
34 | |||
35 | This driver can also be built as a module. If so, the module will | ||
36 | be called adm1275. | ||
37 | |||
38 | config SENSORS_LM25066 | ||
39 | tristate "National Semiconductor LM25066 and compatibles" | ||
40 | default n | ||
41 | help | ||
42 | If you say yes here you get hardware monitoring support for National | ||
43 | Semiconductor LM25066, LM5064, and LM5066. | ||
44 | |||
45 | This driver can also be built as a module. If so, the module will | ||
46 | be called lm25066. | ||
47 | |||
48 | config SENSORS_MAX16064 | ||
49 | tristate "Maxim MAX16064" | ||
50 | default n | ||
51 | help | ||
52 | If you say yes here you get hardware monitoring support for Maxim | ||
53 | MAX16064. | ||
54 | |||
55 | This driver can also be built as a module. If so, the module will | ||
56 | be called max16064. | ||
57 | |||
58 | config SENSORS_MAX34440 | ||
59 | tristate "Maxim MAX34440/MAX34441" | ||
60 | default n | ||
61 | help | ||
62 | If you say yes here you get hardware monitoring support for Maxim | ||
63 | MAX34440 and MAX34441. | ||
64 | |||
65 | This driver can also be built as a module. If so, the module will | ||
66 | be called max34440. | ||
67 | |||
68 | config SENSORS_MAX8688 | ||
69 | tristate "Maxim MAX8688" | ||
70 | default n | ||
71 | help | ||
72 | If you say yes here you get hardware monitoring support for Maxim | ||
73 | MAX8688. | ||
74 | |||
75 | This driver can also be built as a module. If so, the module will | ||
76 | be called max8688. | ||
77 | |||
78 | config SENSORS_UCD9000 | ||
79 | tristate "TI UCD90120, UCD90124, UCD9090, UCD90910" | ||
80 | default n | ||
81 | help | ||
82 | If you say yes here you get hardware monitoring support for TI | ||
83 | UCD90120, UCD90124, UCD9090, UCD90910 Sequencer and System Health | ||
84 | Controllers. | ||
85 | |||
86 | This driver can also be built as a module. If so, the module will | ||
87 | be called ucd9000. | ||
88 | |||
89 | config SENSORS_UCD9200 | ||
90 | tristate "TI UCD9220, UCD9222, UCD9224, UCD9240, UCD9244, UCD9246, UCD9248" | ||
91 | default n | ||
92 | help | ||
93 | If you say yes here you get hardware monitoring support for TI | ||
94 | UCD9220, UCD9222, UCD9224, UCD9240, UCD9244, UCD9246, and UCD9248 | ||
95 | Digital PWM System Controllers. | ||
96 | |||
97 | This driver can also be built as a module. If so, the module will | ||
98 | be called ucd9200. | ||
99 | |||
100 | endif # PMBUS | ||
diff --git a/drivers/hwmon/pmbus/Makefile b/drivers/hwmon/pmbus/Makefile new file mode 100644 index 000000000000..623eedb1ed9a --- /dev/null +++ b/drivers/hwmon/pmbus/Makefile | |||
@@ -0,0 +1,13 @@ | |||
1 | # | ||
2 | # Makefile for PMBus chip drivers. | ||
3 | # | ||
4 | |||
5 | obj-$(CONFIG_PMBUS) += pmbus_core.o | ||
6 | obj-$(CONFIG_SENSORS_PMBUS) += pmbus.o | ||
7 | obj-$(CONFIG_SENSORS_ADM1275) += adm1275.o | ||
8 | obj-$(CONFIG_SENSORS_LM25066) += lm25066.o | ||
9 | obj-$(CONFIG_SENSORS_MAX16064) += max16064.o | ||
10 | obj-$(CONFIG_SENSORS_MAX34440) += max34440.o | ||
11 | obj-$(CONFIG_SENSORS_MAX8688) += max8688.o | ||
12 | obj-$(CONFIG_SENSORS_UCD9000) += ucd9000.o | ||
13 | obj-$(CONFIG_SENSORS_UCD9200) += ucd9200.o | ||
diff --git a/drivers/hwmon/adm1275.c b/drivers/hwmon/pmbus/adm1275.c index 8bc1bd663721..c936e2782309 100644 --- a/drivers/hwmon/adm1275.c +++ b/drivers/hwmon/pmbus/adm1275.c | |||
@@ -23,11 +23,68 @@ | |||
23 | #include <linux/i2c.h> | 23 | #include <linux/i2c.h> |
24 | #include "pmbus.h" | 24 | #include "pmbus.h" |
25 | 25 | ||
26 | #define ADM1275_PEAK_IOUT 0xd0 | ||
27 | #define ADM1275_PEAK_VIN 0xd1 | ||
28 | #define ADM1275_PEAK_VOUT 0xd2 | ||
26 | #define ADM1275_PMON_CONFIG 0xd4 | 29 | #define ADM1275_PMON_CONFIG 0xd4 |
27 | 30 | ||
28 | #define ADM1275_VIN_VOUT_SELECT (1 << 6) | 31 | #define ADM1275_VIN_VOUT_SELECT (1 << 6) |
29 | #define ADM1275_VRANGE (1 << 5) | 32 | #define ADM1275_VRANGE (1 << 5) |
30 | 33 | ||
34 | static int adm1275_read_word_data(struct i2c_client *client, int page, int reg) | ||
35 | { | ||
36 | int ret; | ||
37 | |||
38 | if (page) | ||
39 | return -EINVAL; | ||
40 | |||
41 | switch (reg) { | ||
42 | case PMBUS_VIRT_READ_IOUT_MAX: | ||
43 | ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_IOUT); | ||
44 | break; | ||
45 | case PMBUS_VIRT_READ_VOUT_MAX: | ||
46 | ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_VOUT); | ||
47 | break; | ||
48 | case PMBUS_VIRT_READ_VIN_MAX: | ||
49 | ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_VIN); | ||
50 | break; | ||
51 | case PMBUS_VIRT_RESET_IOUT_HISTORY: | ||
52 | case PMBUS_VIRT_RESET_VOUT_HISTORY: | ||
53 | case PMBUS_VIRT_RESET_VIN_HISTORY: | ||
54 | ret = 0; | ||
55 | break; | ||
56 | default: | ||
57 | ret = -ENODATA; | ||
58 | break; | ||
59 | } | ||
60 | return ret; | ||
61 | } | ||
62 | |||
63 | static int adm1275_write_word_data(struct i2c_client *client, int page, int reg, | ||
64 | u16 word) | ||
65 | { | ||
66 | int ret; | ||
67 | |||
68 | if (page) | ||
69 | return -EINVAL; | ||
70 | |||
71 | switch (reg) { | ||
72 | case PMBUS_VIRT_RESET_IOUT_HISTORY: | ||
73 | ret = pmbus_write_word_data(client, 0, ADM1275_PEAK_IOUT, 0); | ||
74 | break; | ||
75 | case PMBUS_VIRT_RESET_VOUT_HISTORY: | ||
76 | ret = pmbus_write_word_data(client, 0, ADM1275_PEAK_VOUT, 0); | ||
77 | break; | ||
78 | case PMBUS_VIRT_RESET_VIN_HISTORY: | ||
79 | ret = pmbus_write_word_data(client, 0, ADM1275_PEAK_VIN, 0); | ||
80 | break; | ||
81 | default: | ||
82 | ret = -ENODATA; | ||
83 | break; | ||
84 | } | ||
85 | return ret; | ||
86 | } | ||
87 | |||
31 | static int adm1275_probe(struct i2c_client *client, | 88 | static int adm1275_probe(struct i2c_client *client, |
32 | const struct i2c_device_id *id) | 89 | const struct i2c_device_id *id) |
33 | { | 90 | { |
@@ -50,14 +107,17 @@ static int adm1275_probe(struct i2c_client *client, | |||
50 | } | 107 | } |
51 | 108 | ||
52 | info->pages = 1; | 109 | info->pages = 1; |
53 | info->direct[PSC_VOLTAGE_IN] = true; | 110 | info->format[PSC_VOLTAGE_IN] = direct; |
54 | info->direct[PSC_VOLTAGE_OUT] = true; | 111 | info->format[PSC_VOLTAGE_OUT] = direct; |
55 | info->direct[PSC_CURRENT_OUT] = true; | 112 | info->format[PSC_CURRENT_OUT] = direct; |
56 | info->m[PSC_CURRENT_OUT] = 807; | 113 | info->m[PSC_CURRENT_OUT] = 807; |
57 | info->b[PSC_CURRENT_OUT] = 20475; | 114 | info->b[PSC_CURRENT_OUT] = 20475; |
58 | info->R[PSC_CURRENT_OUT] = -1; | 115 | info->R[PSC_CURRENT_OUT] = -1; |
59 | info->func[0] = PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT; | 116 | info->func[0] = PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT; |
60 | 117 | ||
118 | info->read_word_data = adm1275_read_word_data; | ||
119 | info->write_word_data = adm1275_write_word_data; | ||
120 | |||
61 | if (config & ADM1275_VRANGE) { | 121 | if (config & ADM1275_VRANGE) { |
62 | info->m[PSC_VOLTAGE_IN] = 19199; | 122 | info->m[PSC_VOLTAGE_IN] = 19199; |
63 | info->b[PSC_VOLTAGE_IN] = 0; | 123 | info->b[PSC_VOLTAGE_IN] = 0; |
diff --git a/drivers/hwmon/pmbus/lm25066.c b/drivers/hwmon/pmbus/lm25066.c new file mode 100644 index 000000000000..d4bc114572de --- /dev/null +++ b/drivers/hwmon/pmbus/lm25066.c | |||
@@ -0,0 +1,340 @@ | |||
1 | /* | ||
2 | * Hardware monitoring driver for LM25066 / LM5064 / LM5066 | ||
3 | * | ||
4 | * Copyright (c) 2011 Ericsson AB. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/init.h> | ||
24 | #include <linux/err.h> | ||
25 | #include <linux/slab.h> | ||
26 | #include <linux/i2c.h> | ||
27 | #include "pmbus.h" | ||
28 | |||
29 | enum chips { lm25066, lm5064, lm5066 }; | ||
30 | |||
31 | #define LM25066_READ_VAUX 0xd0 | ||
32 | #define LM25066_MFR_READ_IIN 0xd1 | ||
33 | #define LM25066_MFR_READ_PIN 0xd2 | ||
34 | #define LM25066_MFR_IIN_OC_WARN_LIMIT 0xd3 | ||
35 | #define LM25066_MFR_PIN_OP_WARN_LIMIT 0xd4 | ||
36 | #define LM25066_READ_PIN_PEAK 0xd5 | ||
37 | #define LM25066_CLEAR_PIN_PEAK 0xd6 | ||
38 | #define LM25066_DEVICE_SETUP 0xd9 | ||
39 | #define LM25066_READ_AVG_VIN 0xdc | ||
40 | #define LM25066_READ_AVG_VOUT 0xdd | ||
41 | #define LM25066_READ_AVG_IIN 0xde | ||
42 | #define LM25066_READ_AVG_PIN 0xdf | ||
43 | |||
44 | #define LM25066_DEV_SETUP_CL (1 << 4) /* Current limit */ | ||
45 | |||
46 | struct lm25066_data { | ||
47 | int id; | ||
48 | struct pmbus_driver_info info; | ||
49 | }; | ||
50 | |||
51 | #define to_lm25066_data(x) container_of(x, struct lm25066_data, info) | ||
52 | |||
53 | static int lm25066_read_word_data(struct i2c_client *client, int page, int reg) | ||
54 | { | ||
55 | const struct pmbus_driver_info *info = pmbus_get_driver_info(client); | ||
56 | const struct lm25066_data *data = to_lm25066_data(info); | ||
57 | int ret; | ||
58 | |||
59 | if (page > 1) | ||
60 | return -EINVAL; | ||
61 | |||
62 | /* Map READ_VAUX into READ_VOUT register on page 1 */ | ||
63 | if (page == 1) { | ||
64 | switch (reg) { | ||
65 | case PMBUS_READ_VOUT: | ||
66 | ret = pmbus_read_word_data(client, 0, | ||
67 | LM25066_READ_VAUX); | ||
68 | if (ret < 0) | ||
69 | break; | ||
70 | /* Adjust returned value to match VOUT coefficients */ | ||
71 | switch (data->id) { | ||
72 | case lm25066: | ||
73 | /* VOUT: 4.54 mV VAUX: 283.2 uV LSB */ | ||
74 | ret = DIV_ROUND_CLOSEST(ret * 2832, 45400); | ||
75 | break; | ||
76 | case lm5064: | ||
77 | /* VOUT: 4.53 mV VAUX: 700 uV LSB */ | ||
78 | ret = DIV_ROUND_CLOSEST(ret * 70, 453); | ||
79 | break; | ||
80 | case lm5066: | ||
81 | /* VOUT: 2.18 mV VAUX: 725 uV LSB */ | ||
82 | ret = DIV_ROUND_CLOSEST(ret * 725, 2180); | ||
83 | break; | ||
84 | } | ||
85 | break; | ||
86 | default: | ||
87 | /* No other valid registers on page 1 */ | ||
88 | ret = -EINVAL; | ||
89 | break; | ||
90 | } | ||
91 | goto done; | ||
92 | } | ||
93 | |||
94 | switch (reg) { | ||
95 | case PMBUS_READ_IIN: | ||
96 | ret = pmbus_read_word_data(client, 0, LM25066_MFR_READ_IIN); | ||
97 | break; | ||
98 | case PMBUS_READ_PIN: | ||
99 | ret = pmbus_read_word_data(client, 0, LM25066_MFR_READ_PIN); | ||
100 | break; | ||
101 | case PMBUS_IIN_OC_WARN_LIMIT: | ||
102 | ret = pmbus_read_word_data(client, 0, | ||
103 | LM25066_MFR_IIN_OC_WARN_LIMIT); | ||
104 | break; | ||
105 | case PMBUS_PIN_OP_WARN_LIMIT: | ||
106 | ret = pmbus_read_word_data(client, 0, | ||
107 | LM25066_MFR_PIN_OP_WARN_LIMIT); | ||
108 | break; | ||
109 | case PMBUS_VIRT_READ_VIN_AVG: | ||
110 | ret = pmbus_read_word_data(client, 0, LM25066_READ_AVG_VIN); | ||
111 | break; | ||
112 | case PMBUS_VIRT_READ_VOUT_AVG: | ||
113 | ret = pmbus_read_word_data(client, 0, LM25066_READ_AVG_VOUT); | ||
114 | break; | ||
115 | case PMBUS_VIRT_READ_IIN_AVG: | ||
116 | ret = pmbus_read_word_data(client, 0, LM25066_READ_AVG_IIN); | ||
117 | break; | ||
118 | case PMBUS_VIRT_READ_PIN_AVG: | ||
119 | ret = pmbus_read_word_data(client, 0, LM25066_READ_AVG_PIN); | ||
120 | break; | ||
121 | case PMBUS_VIRT_READ_PIN_MAX: | ||
122 | ret = pmbus_read_word_data(client, 0, LM25066_READ_PIN_PEAK); | ||
123 | break; | ||
124 | case PMBUS_VIRT_RESET_PIN_HISTORY: | ||
125 | ret = 0; | ||
126 | break; | ||
127 | default: | ||
128 | ret = -ENODATA; | ||
129 | break; | ||
130 | } | ||
131 | done: | ||
132 | return ret; | ||
133 | } | ||
134 | |||
135 | static int lm25066_write_word_data(struct i2c_client *client, int page, int reg, | ||
136 | u16 word) | ||
137 | { | ||
138 | int ret; | ||
139 | |||
140 | if (page > 1) | ||
141 | return -EINVAL; | ||
142 | |||
143 | switch (reg) { | ||
144 | case PMBUS_IIN_OC_WARN_LIMIT: | ||
145 | ret = pmbus_write_word_data(client, 0, | ||
146 | LM25066_MFR_IIN_OC_WARN_LIMIT, | ||
147 | word); | ||
148 | break; | ||
149 | case PMBUS_PIN_OP_WARN_LIMIT: | ||
150 | ret = pmbus_write_word_data(client, 0, | ||
151 | LM25066_MFR_PIN_OP_WARN_LIMIT, | ||
152 | word); | ||
153 | break; | ||
154 | case PMBUS_VIRT_RESET_PIN_HISTORY: | ||
155 | ret = pmbus_write_byte(client, 0, LM25066_CLEAR_PIN_PEAK); | ||
156 | break; | ||
157 | default: | ||
158 | ret = -ENODATA; | ||
159 | break; | ||
160 | } | ||
161 | return ret; | ||
162 | } | ||
163 | |||
164 | static int lm25066_probe(struct i2c_client *client, | ||
165 | const struct i2c_device_id *id) | ||
166 | { | ||
167 | int config; | ||
168 | int ret; | ||
169 | struct lm25066_data *data; | ||
170 | struct pmbus_driver_info *info; | ||
171 | |||
172 | if (!i2c_check_functionality(client->adapter, | ||
173 | I2C_FUNC_SMBUS_READ_BYTE_DATA)) | ||
174 | return -ENODEV; | ||
175 | |||
176 | data = kzalloc(sizeof(struct lm25066_data), GFP_KERNEL); | ||
177 | if (!data) | ||
178 | return -ENOMEM; | ||
179 | |||
180 | config = i2c_smbus_read_byte_data(client, LM25066_DEVICE_SETUP); | ||
181 | if (config < 0) { | ||
182 | ret = config; | ||
183 | goto err_mem; | ||
184 | } | ||
185 | |||
186 | data->id = id->driver_data; | ||
187 | info = &data->info; | ||
188 | |||
189 | info->pages = 2; | ||
190 | info->format[PSC_VOLTAGE_IN] = direct; | ||
191 | info->format[PSC_VOLTAGE_OUT] = direct; | ||
192 | info->format[PSC_CURRENT_IN] = direct; | ||
193 | info->format[PSC_TEMPERATURE] = direct; | ||
194 | info->format[PSC_POWER] = direct; | ||
195 | |||
196 | info->m[PSC_TEMPERATURE] = 16; | ||
197 | info->b[PSC_TEMPERATURE] = 0; | ||
198 | info->R[PSC_TEMPERATURE] = 0; | ||
199 | |||
200 | info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | ||
201 | | PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_PIN | PMBUS_HAVE_IIN | ||
202 | | PMBUS_HAVE_STATUS_INPUT | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP; | ||
203 | info->func[1] = PMBUS_HAVE_VOUT; | ||
204 | |||
205 | info->read_word_data = lm25066_read_word_data; | ||
206 | info->write_word_data = lm25066_write_word_data; | ||
207 | |||
208 | switch (id->driver_data) { | ||
209 | case lm25066: | ||
210 | info->m[PSC_VOLTAGE_IN] = 22070; | ||
211 | info->b[PSC_VOLTAGE_IN] = 0; | ||
212 | info->R[PSC_VOLTAGE_IN] = -2; | ||
213 | info->m[PSC_VOLTAGE_OUT] = 22070; | ||
214 | info->b[PSC_VOLTAGE_OUT] = 0; | ||
215 | info->R[PSC_VOLTAGE_OUT] = -2; | ||
216 | |||
217 | if (config & LM25066_DEV_SETUP_CL) { | ||
218 | info->m[PSC_CURRENT_IN] = 6852; | ||
219 | info->b[PSC_CURRENT_IN] = 0; | ||
220 | info->R[PSC_CURRENT_IN] = -2; | ||
221 | info->m[PSC_POWER] = 369; | ||
222 | info->b[PSC_POWER] = 0; | ||
223 | info->R[PSC_POWER] = -2; | ||
224 | } else { | ||
225 | info->m[PSC_CURRENT_IN] = 13661; | ||
226 | info->b[PSC_CURRENT_IN] = 0; | ||
227 | info->R[PSC_CURRENT_IN] = -2; | ||
228 | info->m[PSC_POWER] = 736; | ||
229 | info->b[PSC_POWER] = 0; | ||
230 | info->R[PSC_POWER] = -2; | ||
231 | } | ||
232 | break; | ||
233 | case lm5064: | ||
234 | info->m[PSC_VOLTAGE_IN] = 22075; | ||
235 | info->b[PSC_VOLTAGE_IN] = 0; | ||
236 | info->R[PSC_VOLTAGE_IN] = -2; | ||
237 | info->m[PSC_VOLTAGE_OUT] = 22075; | ||
238 | info->b[PSC_VOLTAGE_OUT] = 0; | ||
239 | info->R[PSC_VOLTAGE_OUT] = -2; | ||
240 | |||
241 | if (config & LM25066_DEV_SETUP_CL) { | ||
242 | info->m[PSC_CURRENT_IN] = 6713; | ||
243 | info->b[PSC_CURRENT_IN] = 0; | ||
244 | info->R[PSC_CURRENT_IN] = -2; | ||
245 | info->m[PSC_POWER] = 3619; | ||
246 | info->b[PSC_POWER] = 0; | ||
247 | info->R[PSC_POWER] = -3; | ||
248 | } else { | ||
249 | info->m[PSC_CURRENT_IN] = 13426; | ||
250 | info->b[PSC_CURRENT_IN] = 0; | ||
251 | info->R[PSC_CURRENT_IN] = -2; | ||
252 | info->m[PSC_POWER] = 7238; | ||
253 | info->b[PSC_POWER] = 0; | ||
254 | info->R[PSC_POWER] = -3; | ||
255 | } | ||
256 | break; | ||
257 | case lm5066: | ||
258 | info->m[PSC_VOLTAGE_IN] = 4587; | ||
259 | info->b[PSC_VOLTAGE_IN] = 0; | ||
260 | info->R[PSC_VOLTAGE_IN] = -2; | ||
261 | info->m[PSC_VOLTAGE_OUT] = 4587; | ||
262 | info->b[PSC_VOLTAGE_OUT] = 0; | ||
263 | info->R[PSC_VOLTAGE_OUT] = -2; | ||
264 | |||
265 | if (config & LM25066_DEV_SETUP_CL) { | ||
266 | info->m[PSC_CURRENT_IN] = 10753; | ||
267 | info->b[PSC_CURRENT_IN] = 0; | ||
268 | info->R[PSC_CURRENT_IN] = -2; | ||
269 | info->m[PSC_POWER] = 1204; | ||
270 | info->b[PSC_POWER] = 0; | ||
271 | info->R[PSC_POWER] = -3; | ||
272 | } else { | ||
273 | info->m[PSC_CURRENT_IN] = 5405; | ||
274 | info->b[PSC_CURRENT_IN] = 0; | ||
275 | info->R[PSC_CURRENT_IN] = -2; | ||
276 | info->m[PSC_POWER] = 605; | ||
277 | info->b[PSC_POWER] = 0; | ||
278 | info->R[PSC_POWER] = -3; | ||
279 | } | ||
280 | break; | ||
281 | default: | ||
282 | ret = -ENODEV; | ||
283 | goto err_mem; | ||
284 | } | ||
285 | |||
286 | ret = pmbus_do_probe(client, id, info); | ||
287 | if (ret) | ||
288 | goto err_mem; | ||
289 | return 0; | ||
290 | |||
291 | err_mem: | ||
292 | kfree(data); | ||
293 | return ret; | ||
294 | } | ||
295 | |||
296 | static int lm25066_remove(struct i2c_client *client) | ||
297 | { | ||
298 | const struct pmbus_driver_info *info = pmbus_get_driver_info(client); | ||
299 | const struct lm25066_data *data = to_lm25066_data(info); | ||
300 | int ret; | ||
301 | |||
302 | ret = pmbus_do_remove(client); | ||
303 | kfree(data); | ||
304 | return ret; | ||
305 | } | ||
306 | |||
307 | static const struct i2c_device_id lm25066_id[] = { | ||
308 | {"lm25066", lm25066}, | ||
309 | {"lm5064", lm5064}, | ||
310 | {"lm5066", lm5066}, | ||
311 | { } | ||
312 | }; | ||
313 | |||
314 | MODULE_DEVICE_TABLE(i2c, lm25066_id); | ||
315 | |||
316 | /* This is the driver that will be inserted */ | ||
317 | static struct i2c_driver lm25066_driver = { | ||
318 | .driver = { | ||
319 | .name = "lm25066", | ||
320 | }, | ||
321 | .probe = lm25066_probe, | ||
322 | .remove = lm25066_remove, | ||
323 | .id_table = lm25066_id, | ||
324 | }; | ||
325 | |||
326 | static int __init lm25066_init(void) | ||
327 | { | ||
328 | return i2c_add_driver(&lm25066_driver); | ||
329 | } | ||
330 | |||
331 | static void __exit lm25066_exit(void) | ||
332 | { | ||
333 | i2c_del_driver(&lm25066_driver); | ||
334 | } | ||
335 | |||
336 | MODULE_AUTHOR("Guenter Roeck"); | ||
337 | MODULE_DESCRIPTION("PMBus driver for LM25066/LM5064/LM5066"); | ||
338 | MODULE_LICENSE("GPL"); | ||
339 | module_init(lm25066_init); | ||
340 | module_exit(lm25066_exit); | ||
diff --git a/drivers/hwmon/max16064.c b/drivers/hwmon/pmbus/max16064.c index 1d6d717060d3..e50b296e8db4 100644 --- a/drivers/hwmon/max16064.c +++ b/drivers/hwmon/pmbus/max16064.c | |||
@@ -25,11 +25,60 @@ | |||
25 | #include <linux/i2c.h> | 25 | #include <linux/i2c.h> |
26 | #include "pmbus.h" | 26 | #include "pmbus.h" |
27 | 27 | ||
28 | #define MAX16064_MFR_VOUT_PEAK 0xd4 | ||
29 | #define MAX16064_MFR_TEMPERATURE_PEAK 0xd6 | ||
30 | |||
31 | static int max16064_read_word_data(struct i2c_client *client, int page, int reg) | ||
32 | { | ||
33 | int ret; | ||
34 | |||
35 | switch (reg) { | ||
36 | case PMBUS_VIRT_READ_VOUT_MAX: | ||
37 | ret = pmbus_read_word_data(client, page, | ||
38 | MAX16064_MFR_VOUT_PEAK); | ||
39 | break; | ||
40 | case PMBUS_VIRT_READ_TEMP_MAX: | ||
41 | ret = pmbus_read_word_data(client, page, | ||
42 | MAX16064_MFR_TEMPERATURE_PEAK); | ||
43 | break; | ||
44 | case PMBUS_VIRT_RESET_VOUT_HISTORY: | ||
45 | case PMBUS_VIRT_RESET_TEMP_HISTORY: | ||
46 | ret = 0; | ||
47 | break; | ||
48 | default: | ||
49 | ret = -ENODATA; | ||
50 | break; | ||
51 | } | ||
52 | return ret; | ||
53 | } | ||
54 | |||
55 | static int max16064_write_word_data(struct i2c_client *client, int page, | ||
56 | int reg, u16 word) | ||
57 | { | ||
58 | int ret; | ||
59 | |||
60 | switch (reg) { | ||
61 | case PMBUS_VIRT_RESET_VOUT_HISTORY: | ||
62 | ret = pmbus_write_word_data(client, page, | ||
63 | MAX16064_MFR_VOUT_PEAK, 0); | ||
64 | break; | ||
65 | case PMBUS_VIRT_RESET_TEMP_HISTORY: | ||
66 | ret = pmbus_write_word_data(client, page, | ||
67 | MAX16064_MFR_TEMPERATURE_PEAK, | ||
68 | 0xffff); | ||
69 | break; | ||
70 | default: | ||
71 | ret = -ENODATA; | ||
72 | break; | ||
73 | } | ||
74 | return ret; | ||
75 | } | ||
76 | |||
28 | static struct pmbus_driver_info max16064_info = { | 77 | static struct pmbus_driver_info max16064_info = { |
29 | .pages = 4, | 78 | .pages = 4, |
30 | .direct[PSC_VOLTAGE_IN] = true, | 79 | .format[PSC_VOLTAGE_IN] = direct, |
31 | .direct[PSC_VOLTAGE_OUT] = true, | 80 | .format[PSC_VOLTAGE_OUT] = direct, |
32 | .direct[PSC_TEMPERATURE] = true, | 81 | .format[PSC_TEMPERATURE] = direct, |
33 | .m[PSC_VOLTAGE_IN] = 19995, | 82 | .m[PSC_VOLTAGE_IN] = 19995, |
34 | .b[PSC_VOLTAGE_IN] = 0, | 83 | .b[PSC_VOLTAGE_IN] = 0, |
35 | .R[PSC_VOLTAGE_IN] = -1, | 84 | .R[PSC_VOLTAGE_IN] = -1, |
@@ -44,6 +93,8 @@ static struct pmbus_driver_info max16064_info = { | |||
44 | .func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, | 93 | .func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, |
45 | .func[2] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, | 94 | .func[2] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, |
46 | .func[3] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, | 95 | .func[3] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, |
96 | .read_word_data = max16064_read_word_data, | ||
97 | .write_word_data = max16064_write_word_data, | ||
47 | }; | 98 | }; |
48 | 99 | ||
49 | static int max16064_probe(struct i2c_client *client, | 100 | static int max16064_probe(struct i2c_client *client, |
diff --git a/drivers/hwmon/max34440.c b/drivers/hwmon/pmbus/max34440.c index db11e1a175b2..fda621d2e458 100644 --- a/drivers/hwmon/max34440.c +++ b/drivers/hwmon/pmbus/max34440.c | |||
@@ -27,11 +27,70 @@ | |||
27 | 27 | ||
28 | enum chips { max34440, max34441 }; | 28 | enum chips { max34440, max34441 }; |
29 | 29 | ||
30 | #define MAX34440_MFR_VOUT_PEAK 0xd4 | ||
31 | #define MAX34440_MFR_IOUT_PEAK 0xd5 | ||
32 | #define MAX34440_MFR_TEMPERATURE_PEAK 0xd6 | ||
33 | |||
30 | #define MAX34440_STATUS_OC_WARN (1 << 0) | 34 | #define MAX34440_STATUS_OC_WARN (1 << 0) |
31 | #define MAX34440_STATUS_OC_FAULT (1 << 1) | 35 | #define MAX34440_STATUS_OC_FAULT (1 << 1) |
32 | #define MAX34440_STATUS_OT_FAULT (1 << 5) | 36 | #define MAX34440_STATUS_OT_FAULT (1 << 5) |
33 | #define MAX34440_STATUS_OT_WARN (1 << 6) | 37 | #define MAX34440_STATUS_OT_WARN (1 << 6) |
34 | 38 | ||
39 | static int max34440_read_word_data(struct i2c_client *client, int page, int reg) | ||
40 | { | ||
41 | int ret; | ||
42 | |||
43 | switch (reg) { | ||
44 | case PMBUS_VIRT_READ_VOUT_MAX: | ||
45 | ret = pmbus_read_word_data(client, page, | ||
46 | MAX34440_MFR_VOUT_PEAK); | ||
47 | break; | ||
48 | case PMBUS_VIRT_READ_IOUT_MAX: | ||
49 | ret = pmbus_read_word_data(client, page, | ||
50 | MAX34440_MFR_IOUT_PEAK); | ||
51 | break; | ||
52 | case PMBUS_VIRT_READ_TEMP_MAX: | ||
53 | ret = pmbus_read_word_data(client, page, | ||
54 | MAX34440_MFR_TEMPERATURE_PEAK); | ||
55 | break; | ||
56 | case PMBUS_VIRT_RESET_VOUT_HISTORY: | ||
57 | case PMBUS_VIRT_RESET_IOUT_HISTORY: | ||
58 | case PMBUS_VIRT_RESET_TEMP_HISTORY: | ||
59 | ret = 0; | ||
60 | break; | ||
61 | default: | ||
62 | ret = -ENODATA; | ||
63 | break; | ||
64 | } | ||
65 | return ret; | ||
66 | } | ||
67 | |||
68 | static int max34440_write_word_data(struct i2c_client *client, int page, | ||
69 | int reg, u16 word) | ||
70 | { | ||
71 | int ret; | ||
72 | |||
73 | switch (reg) { | ||
74 | case PMBUS_VIRT_RESET_VOUT_HISTORY: | ||
75 | ret = pmbus_write_word_data(client, page, | ||
76 | MAX34440_MFR_VOUT_PEAK, 0); | ||
77 | break; | ||
78 | case PMBUS_VIRT_RESET_IOUT_HISTORY: | ||
79 | ret = pmbus_write_word_data(client, page, | ||
80 | MAX34440_MFR_IOUT_PEAK, 0); | ||
81 | break; | ||
82 | case PMBUS_VIRT_RESET_TEMP_HISTORY: | ||
83 | ret = pmbus_write_word_data(client, page, | ||
84 | MAX34440_MFR_TEMPERATURE_PEAK, | ||
85 | 0xffff); | ||
86 | break; | ||
87 | default: | ||
88 | ret = -ENODATA; | ||
89 | break; | ||
90 | } | ||
91 | return ret; | ||
92 | } | ||
93 | |||
35 | static int max34440_read_byte_data(struct i2c_client *client, int page, int reg) | 94 | static int max34440_read_byte_data(struct i2c_client *client, int page, int reg) |
36 | { | 95 | { |
37 | int ret; | 96 | int ret; |
@@ -72,10 +131,10 @@ static int max34440_read_byte_data(struct i2c_client *client, int page, int reg) | |||
72 | static struct pmbus_driver_info max34440_info[] = { | 131 | static struct pmbus_driver_info max34440_info[] = { |
73 | [max34440] = { | 132 | [max34440] = { |
74 | .pages = 14, | 133 | .pages = 14, |
75 | .direct[PSC_VOLTAGE_IN] = true, | 134 | .format[PSC_VOLTAGE_IN] = direct, |
76 | .direct[PSC_VOLTAGE_OUT] = true, | 135 | .format[PSC_VOLTAGE_OUT] = direct, |
77 | .direct[PSC_TEMPERATURE] = true, | 136 | .format[PSC_TEMPERATURE] = direct, |
78 | .direct[PSC_CURRENT_OUT] = true, | 137 | .format[PSC_CURRENT_OUT] = direct, |
79 | .m[PSC_VOLTAGE_IN] = 1, | 138 | .m[PSC_VOLTAGE_IN] = 1, |
80 | .b[PSC_VOLTAGE_IN] = 0, | 139 | .b[PSC_VOLTAGE_IN] = 0, |
81 | .R[PSC_VOLTAGE_IN] = 3, /* R = 0 in datasheet reflects mV */ | 140 | .R[PSC_VOLTAGE_IN] = 3, /* R = 0 in datasheet reflects mV */ |
@@ -109,14 +168,16 @@ static struct pmbus_driver_info max34440_info[] = { | |||
109 | .func[12] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, | 168 | .func[12] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, |
110 | .func[13] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, | 169 | .func[13] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, |
111 | .read_byte_data = max34440_read_byte_data, | 170 | .read_byte_data = max34440_read_byte_data, |
171 | .read_word_data = max34440_read_word_data, | ||
172 | .write_word_data = max34440_write_word_data, | ||
112 | }, | 173 | }, |
113 | [max34441] = { | 174 | [max34441] = { |
114 | .pages = 12, | 175 | .pages = 12, |
115 | .direct[PSC_VOLTAGE_IN] = true, | 176 | .format[PSC_VOLTAGE_IN] = direct, |
116 | .direct[PSC_VOLTAGE_OUT] = true, | 177 | .format[PSC_VOLTAGE_OUT] = direct, |
117 | .direct[PSC_TEMPERATURE] = true, | 178 | .format[PSC_TEMPERATURE] = direct, |
118 | .direct[PSC_CURRENT_OUT] = true, | 179 | .format[PSC_CURRENT_OUT] = direct, |
119 | .direct[PSC_FAN] = true, | 180 | .format[PSC_FAN] = direct, |
120 | .m[PSC_VOLTAGE_IN] = 1, | 181 | .m[PSC_VOLTAGE_IN] = 1, |
121 | .b[PSC_VOLTAGE_IN] = 0, | 182 | .b[PSC_VOLTAGE_IN] = 0, |
122 | .R[PSC_VOLTAGE_IN] = 3, | 183 | .R[PSC_VOLTAGE_IN] = 3, |
@@ -150,6 +211,8 @@ static struct pmbus_driver_info max34440_info[] = { | |||
150 | .func[10] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, | 211 | .func[10] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, |
151 | .func[11] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, | 212 | .func[11] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, |
152 | .read_byte_data = max34440_read_byte_data, | 213 | .read_byte_data = max34440_read_byte_data, |
214 | .read_word_data = max34440_read_word_data, | ||
215 | .write_word_data = max34440_write_word_data, | ||
153 | }, | 216 | }, |
154 | }; | 217 | }; |
155 | 218 | ||
diff --git a/drivers/hwmon/max8688.c b/drivers/hwmon/pmbus/max8688.c index 7fb93f4e9f21..c3e72f1a3cfb 100644 --- a/drivers/hwmon/max8688.c +++ b/drivers/hwmon/pmbus/max8688.c | |||
@@ -25,6 +25,9 @@ | |||
25 | #include <linux/i2c.h> | 25 | #include <linux/i2c.h> |
26 | #include "pmbus.h" | 26 | #include "pmbus.h" |
27 | 27 | ||
28 | #define MAX8688_MFR_VOUT_PEAK 0xd4 | ||
29 | #define MAX8688_MFR_IOUT_PEAK 0xd5 | ||
30 | #define MAX8688_MFR_TEMPERATURE_PEAK 0xd6 | ||
28 | #define MAX8688_MFG_STATUS 0xd8 | 31 | #define MAX8688_MFG_STATUS 0xd8 |
29 | 32 | ||
30 | #define MAX8688_STATUS_OC_FAULT (1 << 4) | 33 | #define MAX8688_STATUS_OC_FAULT (1 << 4) |
@@ -37,6 +40,62 @@ | |||
37 | #define MAX8688_STATUS_OT_FAULT (1 << 13) | 40 | #define MAX8688_STATUS_OT_FAULT (1 << 13) |
38 | #define MAX8688_STATUS_OT_WARNING (1 << 14) | 41 | #define MAX8688_STATUS_OT_WARNING (1 << 14) |
39 | 42 | ||
43 | static int max8688_read_word_data(struct i2c_client *client, int page, int reg) | ||
44 | { | ||
45 | int ret; | ||
46 | |||
47 | if (page) | ||
48 | return -EINVAL; | ||
49 | |||
50 | switch (reg) { | ||
51 | case PMBUS_VIRT_READ_VOUT_MAX: | ||
52 | ret = pmbus_read_word_data(client, 0, MAX8688_MFR_VOUT_PEAK); | ||
53 | break; | ||
54 | case PMBUS_VIRT_READ_IOUT_MAX: | ||
55 | ret = pmbus_read_word_data(client, 0, MAX8688_MFR_IOUT_PEAK); | ||
56 | break; | ||
57 | case PMBUS_VIRT_READ_TEMP_MAX: | ||
58 | ret = pmbus_read_word_data(client, 0, | ||
59 | MAX8688_MFR_TEMPERATURE_PEAK); | ||
60 | break; | ||
61 | case PMBUS_VIRT_RESET_VOUT_HISTORY: | ||
62 | case PMBUS_VIRT_RESET_IOUT_HISTORY: | ||
63 | case PMBUS_VIRT_RESET_TEMP_HISTORY: | ||
64 | ret = 0; | ||
65 | break; | ||
66 | default: | ||
67 | ret = -ENODATA; | ||
68 | break; | ||
69 | } | ||
70 | return ret; | ||
71 | } | ||
72 | |||
73 | static int max8688_write_word_data(struct i2c_client *client, int page, int reg, | ||
74 | u16 word) | ||
75 | { | ||
76 | int ret; | ||
77 | |||
78 | switch (reg) { | ||
79 | case PMBUS_VIRT_RESET_VOUT_HISTORY: | ||
80 | ret = pmbus_write_word_data(client, 0, MAX8688_MFR_VOUT_PEAK, | ||
81 | 0); | ||
82 | break; | ||
83 | case PMBUS_VIRT_RESET_IOUT_HISTORY: | ||
84 | ret = pmbus_write_word_data(client, 0, MAX8688_MFR_IOUT_PEAK, | ||
85 | 0); | ||
86 | break; | ||
87 | case PMBUS_VIRT_RESET_TEMP_HISTORY: | ||
88 | ret = pmbus_write_word_data(client, 0, | ||
89 | MAX8688_MFR_TEMPERATURE_PEAK, | ||
90 | 0xffff); | ||
91 | break; | ||
92 | default: | ||
93 | ret = -ENODATA; | ||
94 | break; | ||
95 | } | ||
96 | return ret; | ||
97 | } | ||
98 | |||
40 | static int max8688_read_byte_data(struct i2c_client *client, int page, int reg) | 99 | static int max8688_read_byte_data(struct i2c_client *client, int page, int reg) |
41 | { | 100 | { |
42 | int ret = 0; | 101 | int ret = 0; |
@@ -91,10 +150,10 @@ static int max8688_read_byte_data(struct i2c_client *client, int page, int reg) | |||
91 | 150 | ||
92 | static struct pmbus_driver_info max8688_info = { | 151 | static struct pmbus_driver_info max8688_info = { |
93 | .pages = 1, | 152 | .pages = 1, |
94 | .direct[PSC_VOLTAGE_IN] = true, | 153 | .format[PSC_VOLTAGE_IN] = direct, |
95 | .direct[PSC_VOLTAGE_OUT] = true, | 154 | .format[PSC_VOLTAGE_OUT] = direct, |
96 | .direct[PSC_TEMPERATURE] = true, | 155 | .format[PSC_TEMPERATURE] = direct, |
97 | .direct[PSC_CURRENT_OUT] = true, | 156 | .format[PSC_CURRENT_OUT] = direct, |
98 | .m[PSC_VOLTAGE_IN] = 19995, | 157 | .m[PSC_VOLTAGE_IN] = 19995, |
99 | .b[PSC_VOLTAGE_IN] = 0, | 158 | .b[PSC_VOLTAGE_IN] = 0, |
100 | .R[PSC_VOLTAGE_IN] = -1, | 159 | .R[PSC_VOLTAGE_IN] = -1, |
@@ -111,6 +170,8 @@ static struct pmbus_driver_info max8688_info = { | |||
111 | | PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_IOUT | 170 | | PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_IOUT |
112 | | PMBUS_HAVE_STATUS_TEMP, | 171 | | PMBUS_HAVE_STATUS_TEMP, |
113 | .read_byte_data = max8688_read_byte_data, | 172 | .read_byte_data = max8688_read_byte_data, |
173 | .read_word_data = max8688_read_word_data, | ||
174 | .write_word_data = max8688_write_word_data, | ||
114 | }; | 175 | }; |
115 | 176 | ||
116 | static int max8688_probe(struct i2c_client *client, | 177 | static int max8688_probe(struct i2c_client *client, |
diff --git a/drivers/hwmon/pmbus.c b/drivers/hwmon/pmbus/pmbus.c index 9b1f0c37ef77..73de9f1f3194 100644 --- a/drivers/hwmon/pmbus.c +++ b/drivers/hwmon/pmbus/pmbus.c | |||
@@ -96,6 +96,8 @@ static void pmbus_find_sensor_groups(struct i2c_client *client, | |||
96 | static int pmbus_identify(struct i2c_client *client, | 96 | static int pmbus_identify(struct i2c_client *client, |
97 | struct pmbus_driver_info *info) | 97 | struct pmbus_driver_info *info) |
98 | { | 98 | { |
99 | int ret = 0; | ||
100 | |||
99 | if (!info->pages) { | 101 | if (!info->pages) { |
100 | /* | 102 | /* |
101 | * Check if the PAGE command is supported. If it is, | 103 | * Check if the PAGE command is supported. If it is, |
@@ -117,6 +119,27 @@ static int pmbus_identify(struct i2c_client *client, | |||
117 | } | 119 | } |
118 | } | 120 | } |
119 | 121 | ||
122 | if (pmbus_check_byte_register(client, 0, PMBUS_VOUT_MODE)) { | ||
123 | int vout_mode; | ||
124 | |||
125 | vout_mode = pmbus_read_byte_data(client, 0, PMBUS_VOUT_MODE); | ||
126 | if (vout_mode >= 0 && vout_mode != 0xff) { | ||
127 | switch (vout_mode >> 5) { | ||
128 | case 0: | ||
129 | break; | ||
130 | case 1: | ||
131 | info->format[PSC_VOLTAGE_OUT] = vid; | ||
132 | break; | ||
133 | case 2: | ||
134 | info->format[PSC_VOLTAGE_OUT] = direct; | ||
135 | break; | ||
136 | default: | ||
137 | ret = -ENODEV; | ||
138 | goto abort; | ||
139 | } | ||
140 | } | ||
141 | } | ||
142 | |||
120 | /* | 143 | /* |
121 | * We should check if the COEFFICIENTS register is supported. | 144 | * We should check if the COEFFICIENTS register is supported. |
122 | * If it is, and the chip is configured for direct mode, we can read | 145 | * If it is, and the chip is configured for direct mode, we can read |
@@ -125,13 +148,18 @@ static int pmbus_identify(struct i2c_client *client, | |||
125 | * | 148 | * |
126 | * To do this, we will need access to a chip which actually supports the | 149 | * To do this, we will need access to a chip which actually supports the |
127 | * COEFFICIENTS command, since the command is too complex to implement | 150 | * COEFFICIENTS command, since the command is too complex to implement |
128 | * without testing it. | 151 | * without testing it. Until then, abort if a chip configured for direct |
152 | * mode was detected. | ||
129 | */ | 153 | */ |
154 | if (info->format[PSC_VOLTAGE_OUT] == direct) { | ||
155 | ret = -ENODEV; | ||
156 | goto abort; | ||
157 | } | ||
130 | 158 | ||
131 | /* Try to find sensor groups */ | 159 | /* Try to find sensor groups */ |
132 | pmbus_find_sensor_groups(client, info); | 160 | pmbus_find_sensor_groups(client, info); |
133 | 161 | abort: | |
134 | return 0; | 162 | return ret; |
135 | } | 163 | } |
136 | 164 | ||
137 | static int pmbus_probe(struct i2c_client *client, | 165 | static int pmbus_probe(struct i2c_client *client, |
@@ -172,11 +200,14 @@ static int pmbus_remove(struct i2c_client *client) | |||
172 | * Use driver_data to set the number of pages supported by the chip. | 200 | * Use driver_data to set the number of pages supported by the chip. |
173 | */ | 201 | */ |
174 | static const struct i2c_device_id pmbus_id[] = { | 202 | static const struct i2c_device_id pmbus_id[] = { |
203 | {"adp4000", 1}, | ||
175 | {"bmr450", 1}, | 204 | {"bmr450", 1}, |
176 | {"bmr451", 1}, | 205 | {"bmr451", 1}, |
177 | {"bmr453", 1}, | 206 | {"bmr453", 1}, |
178 | {"bmr454", 1}, | 207 | {"bmr454", 1}, |
179 | {"ltc2978", 8}, | 208 | {"ltc2978", 8}, |
209 | {"ncp4200", 1}, | ||
210 | {"ncp4208", 1}, | ||
180 | {"pmbus", 0}, | 211 | {"pmbus", 0}, |
181 | {} | 212 | {} |
182 | }; | 213 | }; |
diff --git a/drivers/hwmon/pmbus.h b/drivers/hwmon/pmbus/pmbus.h index 50647ab7235a..0808d986d75b 100644 --- a/drivers/hwmon/pmbus.h +++ b/drivers/hwmon/pmbus/pmbus.h | |||
@@ -126,6 +126,42 @@ | |||
126 | #define PMBUS_MFR_SERIAL 0x9E | 126 | #define PMBUS_MFR_SERIAL 0x9E |
127 | 127 | ||
128 | /* | 128 | /* |
129 | * Virtual registers. | ||
130 | * Useful to support attributes which are not supported by standard PMBus | ||
131 | * registers but exist as manufacturer specific registers on individual chips. | ||
132 | * Must be mapped to real registers in device specific code. | ||
133 | * | ||
134 | * Semantics: | ||
135 | * Virtual registers are all word size. | ||
136 | * READ registers are read-only; writes are either ignored or return an error. | ||
137 | * RESET registers are read/write. Reading returns zero (used for detection), | ||
138 | * writing any value causes the associated history to be reset. | ||
139 | */ | ||
140 | #define PMBUS_VIRT_BASE 0x100 | ||
141 | #define PMBUS_VIRT_READ_TEMP_MIN (PMBUS_VIRT_BASE + 0) | ||
142 | #define PMBUS_VIRT_READ_TEMP_MAX (PMBUS_VIRT_BASE + 1) | ||
143 | #define PMBUS_VIRT_RESET_TEMP_HISTORY (PMBUS_VIRT_BASE + 2) | ||
144 | #define PMBUS_VIRT_READ_VIN_AVG (PMBUS_VIRT_BASE + 3) | ||
145 | #define PMBUS_VIRT_READ_VIN_MIN (PMBUS_VIRT_BASE + 4) | ||
146 | #define PMBUS_VIRT_READ_VIN_MAX (PMBUS_VIRT_BASE + 5) | ||
147 | #define PMBUS_VIRT_RESET_VIN_HISTORY (PMBUS_VIRT_BASE + 6) | ||
148 | #define PMBUS_VIRT_READ_IIN_AVG (PMBUS_VIRT_BASE + 7) | ||
149 | #define PMBUS_VIRT_READ_IIN_MIN (PMBUS_VIRT_BASE + 8) | ||
150 | #define PMBUS_VIRT_READ_IIN_MAX (PMBUS_VIRT_BASE + 9) | ||
151 | #define PMBUS_VIRT_RESET_IIN_HISTORY (PMBUS_VIRT_BASE + 10) | ||
152 | #define PMBUS_VIRT_READ_PIN_AVG (PMBUS_VIRT_BASE + 11) | ||
153 | #define PMBUS_VIRT_READ_PIN_MAX (PMBUS_VIRT_BASE + 12) | ||
154 | #define PMBUS_VIRT_RESET_PIN_HISTORY (PMBUS_VIRT_BASE + 13) | ||
155 | #define PMBUS_VIRT_READ_VOUT_AVG (PMBUS_VIRT_BASE + 14) | ||
156 | #define PMBUS_VIRT_READ_VOUT_MIN (PMBUS_VIRT_BASE + 15) | ||
157 | #define PMBUS_VIRT_READ_VOUT_MAX (PMBUS_VIRT_BASE + 16) | ||
158 | #define PMBUS_VIRT_RESET_VOUT_HISTORY (PMBUS_VIRT_BASE + 17) | ||
159 | #define PMBUS_VIRT_READ_IOUT_AVG (PMBUS_VIRT_BASE + 18) | ||
160 | #define PMBUS_VIRT_READ_IOUT_MIN (PMBUS_VIRT_BASE + 19) | ||
161 | #define PMBUS_VIRT_READ_IOUT_MAX (PMBUS_VIRT_BASE + 20) | ||
162 | #define PMBUS_VIRT_RESET_IOUT_HISTORY (PMBUS_VIRT_BASE + 21) | ||
163 | |||
164 | /* | ||
129 | * CAPABILITY | 165 | * CAPABILITY |
130 | */ | 166 | */ |
131 | #define PB_CAPABILITY_SMBALERT (1<<4) | 167 | #define PB_CAPABILITY_SMBALERT (1<<4) |
@@ -266,11 +302,11 @@ enum pmbus_sensor_classes { | |||
266 | #define PMBUS_HAVE_STATUS_FAN12 (1 << 16) | 302 | #define PMBUS_HAVE_STATUS_FAN12 (1 << 16) |
267 | #define PMBUS_HAVE_STATUS_FAN34 (1 << 17) | 303 | #define PMBUS_HAVE_STATUS_FAN34 (1 << 17) |
268 | 304 | ||
305 | enum pmbus_data_format { linear = 0, direct, vid }; | ||
306 | |||
269 | struct pmbus_driver_info { | 307 | struct pmbus_driver_info { |
270 | int pages; /* Total number of pages */ | 308 | int pages; /* Total number of pages */ |
271 | bool direct[PSC_NUM_CLASSES]; | 309 | enum pmbus_data_format format[PSC_NUM_CLASSES]; |
272 | /* true if device uses direct data format | ||
273 | for the given sensor class */ | ||
274 | /* | 310 | /* |
275 | * Support one set of coefficients for each sensor type | 311 | * Support one set of coefficients for each sensor type |
276 | * Used for chips providing data in direct mode. | 312 | * Used for chips providing data in direct mode. |
@@ -286,6 +322,9 @@ struct pmbus_driver_info { | |||
286 | * necessary. | 322 | * necessary. |
287 | */ | 323 | */ |
288 | int (*read_byte_data)(struct i2c_client *client, int page, int reg); | 324 | int (*read_byte_data)(struct i2c_client *client, int page, int reg); |
325 | int (*read_word_data)(struct i2c_client *client, int page, int reg); | ||
326 | int (*write_word_data)(struct i2c_client *client, int page, int reg, | ||
327 | u16 word); | ||
289 | /* | 328 | /* |
290 | * The identify function determines supported PMBus functionality. | 329 | * The identify function determines supported PMBus functionality. |
291 | * This function is only necessary if a chip driver supports multiple | 330 | * This function is only necessary if a chip driver supports multiple |
@@ -299,6 +338,9 @@ struct pmbus_driver_info { | |||
299 | 338 | ||
300 | int pmbus_set_page(struct i2c_client *client, u8 page); | 339 | int pmbus_set_page(struct i2c_client *client, u8 page); |
301 | int pmbus_read_word_data(struct i2c_client *client, u8 page, u8 reg); | 340 | int pmbus_read_word_data(struct i2c_client *client, u8 page, u8 reg); |
341 | int pmbus_write_word_data(struct i2c_client *client, u8 page, u8 reg, u16 word); | ||
342 | int pmbus_read_byte_data(struct i2c_client *client, int page, u8 reg); | ||
343 | int pmbus_write_byte(struct i2c_client *client, int page, u8 value); | ||
302 | void pmbus_clear_faults(struct i2c_client *client); | 344 | void pmbus_clear_faults(struct i2c_client *client); |
303 | bool pmbus_check_byte_register(struct i2c_client *client, int page, int reg); | 345 | bool pmbus_check_byte_register(struct i2c_client *client, int page, int reg); |
304 | bool pmbus_check_word_register(struct i2c_client *client, int page, int reg); | 346 | bool pmbus_check_word_register(struct i2c_client *client, int page, int reg); |
diff --git a/drivers/hwmon/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c index 8e31a8e2c746..5c1b6cf31701 100644 --- a/drivers/hwmon/pmbus_core.c +++ b/drivers/hwmon/pmbus/pmbus_core.c | |||
@@ -33,14 +33,18 @@ | |||
33 | /* | 33 | /* |
34 | * Constants needed to determine number of sensors, booleans, and labels. | 34 | * Constants needed to determine number of sensors, booleans, and labels. |
35 | */ | 35 | */ |
36 | #define PMBUS_MAX_INPUT_SENSORS 11 /* 6*volt, 3*curr, 2*power */ | 36 | #define PMBUS_MAX_INPUT_SENSORS 22 /* 10*volt, 7*curr, 5*power */ |
37 | #define PMBUS_VOUT_SENSORS_PER_PAGE 5 /* input, min, max, lcrit, | 37 | #define PMBUS_VOUT_SENSORS_PER_PAGE 9 /* input, min, max, lcrit, |
38 | crit */ | 38 | crit, lowest, highest, avg, |
39 | #define PMBUS_IOUT_SENSORS_PER_PAGE 4 /* input, min, max, crit */ | 39 | reset */ |
40 | #define PMBUS_IOUT_SENSORS_PER_PAGE 8 /* input, min, max, crit, | ||
41 | lowest, highest, avg, | ||
42 | reset */ | ||
40 | #define PMBUS_POUT_SENSORS_PER_PAGE 4 /* input, cap, max, crit */ | 43 | #define PMBUS_POUT_SENSORS_PER_PAGE 4 /* input, cap, max, crit */ |
41 | #define PMBUS_MAX_SENSORS_PER_FAN 1 /* input */ | 44 | #define PMBUS_MAX_SENSORS_PER_FAN 1 /* input */ |
42 | #define PMBUS_MAX_SENSORS_PER_TEMP 5 /* input, min, max, lcrit, | 45 | #define PMBUS_MAX_SENSORS_PER_TEMP 8 /* input, min, max, lcrit, |
43 | crit */ | 46 | crit, lowest, highest, |
47 | reset */ | ||
44 | 48 | ||
45 | #define PMBUS_MAX_INPUT_BOOLEANS 7 /* v: min_alarm, max_alarm, | 49 | #define PMBUS_MAX_INPUT_BOOLEANS 7 /* v: min_alarm, max_alarm, |
46 | lcrit_alarm, crit_alarm; | 50 | lcrit_alarm, crit_alarm; |
@@ -74,11 +78,13 @@ | |||
74 | #define PB_STATUS_INPUT_BASE (PB_STATUS_FAN34_BASE + PMBUS_PAGES) | 78 | #define PB_STATUS_INPUT_BASE (PB_STATUS_FAN34_BASE + PMBUS_PAGES) |
75 | #define PB_STATUS_TEMP_BASE (PB_STATUS_INPUT_BASE + 1) | 79 | #define PB_STATUS_TEMP_BASE (PB_STATUS_INPUT_BASE + 1) |
76 | 80 | ||
81 | #define PMBUS_NAME_SIZE 24 | ||
82 | |||
77 | struct pmbus_sensor { | 83 | struct pmbus_sensor { |
78 | char name[I2C_NAME_SIZE]; /* sysfs sensor name */ | 84 | char name[PMBUS_NAME_SIZE]; /* sysfs sensor name */ |
79 | struct sensor_device_attribute attribute; | 85 | struct sensor_device_attribute attribute; |
80 | u8 page; /* page number */ | 86 | u8 page; /* page number */ |
81 | u8 reg; /* register */ | 87 | u16 reg; /* register */ |
82 | enum pmbus_sensor_classes class; /* sensor class */ | 88 | enum pmbus_sensor_classes class; /* sensor class */ |
83 | bool update; /* runtime sensor update needed */ | 89 | bool update; /* runtime sensor update needed */ |
84 | int data; /* Sensor data. | 90 | int data; /* Sensor data. |
@@ -86,14 +92,14 @@ struct pmbus_sensor { | |||
86 | }; | 92 | }; |
87 | 93 | ||
88 | struct pmbus_boolean { | 94 | struct pmbus_boolean { |
89 | char name[I2C_NAME_SIZE]; /* sysfs boolean name */ | 95 | char name[PMBUS_NAME_SIZE]; /* sysfs boolean name */ |
90 | struct sensor_device_attribute attribute; | 96 | struct sensor_device_attribute attribute; |
91 | }; | 97 | }; |
92 | 98 | ||
93 | struct pmbus_label { | 99 | struct pmbus_label { |
94 | char name[I2C_NAME_SIZE]; /* sysfs label name */ | 100 | char name[PMBUS_NAME_SIZE]; /* sysfs label name */ |
95 | struct sensor_device_attribute attribute; | 101 | struct sensor_device_attribute attribute; |
96 | char label[I2C_NAME_SIZE]; /* label */ | 102 | char label[PMBUS_NAME_SIZE]; /* label */ |
97 | }; | 103 | }; |
98 | 104 | ||
99 | struct pmbus_data { | 105 | struct pmbus_data { |
@@ -162,19 +168,21 @@ int pmbus_set_page(struct i2c_client *client, u8 page) | |||
162 | } | 168 | } |
163 | EXPORT_SYMBOL_GPL(pmbus_set_page); | 169 | EXPORT_SYMBOL_GPL(pmbus_set_page); |
164 | 170 | ||
165 | static int pmbus_write_byte(struct i2c_client *client, u8 page, u8 value) | 171 | int pmbus_write_byte(struct i2c_client *client, int page, u8 value) |
166 | { | 172 | { |
167 | int rv; | 173 | int rv; |
168 | 174 | ||
169 | rv = pmbus_set_page(client, page); | 175 | if (page >= 0) { |
170 | if (rv < 0) | 176 | rv = pmbus_set_page(client, page); |
171 | return rv; | 177 | if (rv < 0) |
178 | return rv; | ||
179 | } | ||
172 | 180 | ||
173 | return i2c_smbus_write_byte(client, value); | 181 | return i2c_smbus_write_byte(client, value); |
174 | } | 182 | } |
183 | EXPORT_SYMBOL_GPL(pmbus_write_byte); | ||
175 | 184 | ||
176 | static int pmbus_write_word_data(struct i2c_client *client, u8 page, u8 reg, | 185 | int pmbus_write_word_data(struct i2c_client *client, u8 page, u8 reg, u16 word) |
177 | u16 word) | ||
178 | { | 186 | { |
179 | int rv; | 187 | int rv; |
180 | 188 | ||
@@ -184,6 +192,28 @@ static int pmbus_write_word_data(struct i2c_client *client, u8 page, u8 reg, | |||
184 | 192 | ||
185 | return i2c_smbus_write_word_data(client, reg, word); | 193 | return i2c_smbus_write_word_data(client, reg, word); |
186 | } | 194 | } |
195 | EXPORT_SYMBOL_GPL(pmbus_write_word_data); | ||
196 | |||
197 | /* | ||
198 | * _pmbus_write_word_data() is similar to pmbus_write_word_data(), but checks if | ||
199 | * a device specific mapping function exists and calls it if necessary. | ||
200 | */ | ||
201 | static int _pmbus_write_word_data(struct i2c_client *client, int page, int reg, | ||
202 | u16 word) | ||
203 | { | ||
204 | struct pmbus_data *data = i2c_get_clientdata(client); | ||
205 | const struct pmbus_driver_info *info = data->info; | ||
206 | int status; | ||
207 | |||
208 | if (info->write_word_data) { | ||
209 | status = info->write_word_data(client, page, reg, word); | ||
210 | if (status != -ENODATA) | ||
211 | return status; | ||
212 | } | ||
213 | if (reg >= PMBUS_VIRT_BASE) | ||
214 | return -EINVAL; | ||
215 | return pmbus_write_word_data(client, page, reg, word); | ||
216 | } | ||
187 | 217 | ||
188 | int pmbus_read_word_data(struct i2c_client *client, u8 page, u8 reg) | 218 | int pmbus_read_word_data(struct i2c_client *client, u8 page, u8 reg) |
189 | { | 219 | { |
@@ -197,16 +227,57 @@ int pmbus_read_word_data(struct i2c_client *client, u8 page, u8 reg) | |||
197 | } | 227 | } |
198 | EXPORT_SYMBOL_GPL(pmbus_read_word_data); | 228 | EXPORT_SYMBOL_GPL(pmbus_read_word_data); |
199 | 229 | ||
200 | static int pmbus_read_byte_data(struct i2c_client *client, u8 page, u8 reg) | 230 | /* |
231 | * _pmbus_read_word_data() is similar to pmbus_read_word_data(), but checks if | ||
232 | * a device specific mapping function exists and calls it if necessary. | ||
233 | */ | ||
234 | static int _pmbus_read_word_data(struct i2c_client *client, int page, int reg) | ||
235 | { | ||
236 | struct pmbus_data *data = i2c_get_clientdata(client); | ||
237 | const struct pmbus_driver_info *info = data->info; | ||
238 | int status; | ||
239 | |||
240 | if (info->read_word_data) { | ||
241 | status = info->read_word_data(client, page, reg); | ||
242 | if (status != -ENODATA) | ||
243 | return status; | ||
244 | } | ||
245 | if (reg >= PMBUS_VIRT_BASE) | ||
246 | return -EINVAL; | ||
247 | return pmbus_read_word_data(client, page, reg); | ||
248 | } | ||
249 | |||
250 | int pmbus_read_byte_data(struct i2c_client *client, int page, u8 reg) | ||
201 | { | 251 | { |
202 | int rv; | 252 | int rv; |
203 | 253 | ||
204 | rv = pmbus_set_page(client, page); | 254 | if (page >= 0) { |
205 | if (rv < 0) | 255 | rv = pmbus_set_page(client, page); |
206 | return rv; | 256 | if (rv < 0) |
257 | return rv; | ||
258 | } | ||
207 | 259 | ||
208 | return i2c_smbus_read_byte_data(client, reg); | 260 | return i2c_smbus_read_byte_data(client, reg); |
209 | } | 261 | } |
262 | EXPORT_SYMBOL_GPL(pmbus_read_byte_data); | ||
263 | |||
264 | /* | ||
265 | * _pmbus_read_byte_data() is similar to pmbus_read_byte_data(), but checks if | ||
266 | * a device specific mapping function exists and calls it if necessary. | ||
267 | */ | ||
268 | static int _pmbus_read_byte_data(struct i2c_client *client, int page, int reg) | ||
269 | { | ||
270 | struct pmbus_data *data = i2c_get_clientdata(client); | ||
271 | const struct pmbus_driver_info *info = data->info; | ||
272 | int status; | ||
273 | |||
274 | if (info->read_byte_data) { | ||
275 | status = info->read_byte_data(client, page, reg); | ||
276 | if (status != -ENODATA) | ||
277 | return status; | ||
278 | } | ||
279 | return pmbus_read_byte_data(client, page, reg); | ||
280 | } | ||
210 | 281 | ||
211 | static void pmbus_clear_fault_page(struct i2c_client *client, int page) | 282 | static void pmbus_clear_fault_page(struct i2c_client *client, int page) |
212 | { | 283 | { |
@@ -223,13 +294,13 @@ void pmbus_clear_faults(struct i2c_client *client) | |||
223 | } | 294 | } |
224 | EXPORT_SYMBOL_GPL(pmbus_clear_faults); | 295 | EXPORT_SYMBOL_GPL(pmbus_clear_faults); |
225 | 296 | ||
226 | static int pmbus_check_status_cml(struct i2c_client *client, int page) | 297 | static int pmbus_check_status_cml(struct i2c_client *client) |
227 | { | 298 | { |
228 | int status, status2; | 299 | int status, status2; |
229 | 300 | ||
230 | status = pmbus_read_byte_data(client, page, PMBUS_STATUS_BYTE); | 301 | status = pmbus_read_byte_data(client, -1, PMBUS_STATUS_BYTE); |
231 | if (status < 0 || (status & PB_STATUS_CML)) { | 302 | if (status < 0 || (status & PB_STATUS_CML)) { |
232 | status2 = pmbus_read_byte_data(client, page, PMBUS_STATUS_CML); | 303 | status2 = pmbus_read_byte_data(client, -1, PMBUS_STATUS_CML); |
233 | if (status2 < 0 || (status2 & PB_CML_FAULT_INVALID_COMMAND)) | 304 | if (status2 < 0 || (status2 & PB_CML_FAULT_INVALID_COMMAND)) |
234 | return -EINVAL; | 305 | return -EINVAL; |
235 | } | 306 | } |
@@ -241,10 +312,10 @@ bool pmbus_check_byte_register(struct i2c_client *client, int page, int reg) | |||
241 | int rv; | 312 | int rv; |
242 | struct pmbus_data *data = i2c_get_clientdata(client); | 313 | struct pmbus_data *data = i2c_get_clientdata(client); |
243 | 314 | ||
244 | rv = pmbus_read_byte_data(client, page, reg); | 315 | rv = _pmbus_read_byte_data(client, page, reg); |
245 | if (rv >= 0 && !(data->flags & PMBUS_SKIP_STATUS_CHECK)) | 316 | if (rv >= 0 && !(data->flags & PMBUS_SKIP_STATUS_CHECK)) |
246 | rv = pmbus_check_status_cml(client, page); | 317 | rv = pmbus_check_status_cml(client); |
247 | pmbus_clear_fault_page(client, page); | 318 | pmbus_clear_fault_page(client, -1); |
248 | return rv >= 0; | 319 | return rv >= 0; |
249 | } | 320 | } |
250 | EXPORT_SYMBOL_GPL(pmbus_check_byte_register); | 321 | EXPORT_SYMBOL_GPL(pmbus_check_byte_register); |
@@ -254,10 +325,10 @@ bool pmbus_check_word_register(struct i2c_client *client, int page, int reg) | |||
254 | int rv; | 325 | int rv; |
255 | struct pmbus_data *data = i2c_get_clientdata(client); | 326 | struct pmbus_data *data = i2c_get_clientdata(client); |
256 | 327 | ||
257 | rv = pmbus_read_word_data(client, page, reg); | 328 | rv = _pmbus_read_word_data(client, page, reg); |
258 | if (rv >= 0 && !(data->flags & PMBUS_SKIP_STATUS_CHECK)) | 329 | if (rv >= 0 && !(data->flags & PMBUS_SKIP_STATUS_CHECK)) |
259 | rv = pmbus_check_status_cml(client, page); | 330 | rv = pmbus_check_status_cml(client); |
260 | pmbus_clear_fault_page(client, page); | 331 | pmbus_clear_fault_page(client, -1); |
261 | return rv >= 0; | 332 | return rv >= 0; |
262 | } | 333 | } |
263 | EXPORT_SYMBOL_GPL(pmbus_check_word_register); | 334 | EXPORT_SYMBOL_GPL(pmbus_check_word_register); |
@@ -270,24 +341,6 @@ const struct pmbus_driver_info *pmbus_get_driver_info(struct i2c_client *client) | |||
270 | } | 341 | } |
271 | EXPORT_SYMBOL_GPL(pmbus_get_driver_info); | 342 | EXPORT_SYMBOL_GPL(pmbus_get_driver_info); |
272 | 343 | ||
273 | /* | ||
274 | * _pmbus_read_byte_data() is similar to pmbus_read_byte_data(), but checks if | ||
275 | * a device specific mapping funcion exists and calls it if necessary. | ||
276 | */ | ||
277 | static int _pmbus_read_byte_data(struct i2c_client *client, int page, int reg) | ||
278 | { | ||
279 | struct pmbus_data *data = i2c_get_clientdata(client); | ||
280 | const struct pmbus_driver_info *info = data->info; | ||
281 | int status; | ||
282 | |||
283 | if (info->read_byte_data) { | ||
284 | status = info->read_byte_data(client, page, reg); | ||
285 | if (status != -ENODATA) | ||
286 | return status; | ||
287 | } | ||
288 | return pmbus_read_byte_data(client, page, reg); | ||
289 | } | ||
290 | |||
291 | static struct pmbus_data *pmbus_update_device(struct device *dev) | 344 | static struct pmbus_data *pmbus_update_device(struct device *dev) |
292 | { | 345 | { |
293 | struct i2c_client *client = to_i2c_client(dev); | 346 | struct i2c_client *client = to_i2c_client(dev); |
@@ -347,8 +400,9 @@ static struct pmbus_data *pmbus_update_device(struct device *dev) | |||
347 | 400 | ||
348 | if (!data->valid || sensor->update) | 401 | if (!data->valid || sensor->update) |
349 | sensor->data | 402 | sensor->data |
350 | = pmbus_read_word_data(client, sensor->page, | 403 | = _pmbus_read_word_data(client, |
351 | sensor->reg); | 404 | sensor->page, |
405 | sensor->reg); | ||
352 | } | 406 | } |
353 | pmbus_clear_faults(client); | 407 | pmbus_clear_faults(client); |
354 | data->last_updated = jiffies; | 408 | data->last_updated = jiffies; |
@@ -443,15 +497,37 @@ static long pmbus_reg2data_direct(struct pmbus_data *data, | |||
443 | return (val - b) / m; | 497 | return (val - b) / m; |
444 | } | 498 | } |
445 | 499 | ||
500 | /* | ||
501 | * Convert VID sensor values to milli- or micro-units | ||
502 | * depending on sensor type. | ||
503 | * We currently only support VR11. | ||
504 | */ | ||
505 | static long pmbus_reg2data_vid(struct pmbus_data *data, | ||
506 | struct pmbus_sensor *sensor) | ||
507 | { | ||
508 | long val = sensor->data; | ||
509 | |||
510 | if (val < 0x02 || val > 0xb2) | ||
511 | return 0; | ||
512 | return DIV_ROUND_CLOSEST(160000 - (val - 2) * 625, 100); | ||
513 | } | ||
514 | |||
446 | static long pmbus_reg2data(struct pmbus_data *data, struct pmbus_sensor *sensor) | 515 | static long pmbus_reg2data(struct pmbus_data *data, struct pmbus_sensor *sensor) |
447 | { | 516 | { |
448 | long val; | 517 | long val; |
449 | 518 | ||
450 | if (data->info->direct[sensor->class]) | 519 | switch (data->info->format[sensor->class]) { |
520 | case direct: | ||
451 | val = pmbus_reg2data_direct(data, sensor); | 521 | val = pmbus_reg2data_direct(data, sensor); |
452 | else | 522 | break; |
523 | case vid: | ||
524 | val = pmbus_reg2data_vid(data, sensor); | ||
525 | break; | ||
526 | case linear: | ||
527 | default: | ||
453 | val = pmbus_reg2data_linear(data, sensor); | 528 | val = pmbus_reg2data_linear(data, sensor); |
454 | 529 | break; | |
530 | } | ||
455 | return val; | 531 | return val; |
456 | } | 532 | } |
457 | 533 | ||
@@ -561,16 +637,31 @@ static u16 pmbus_data2reg_direct(struct pmbus_data *data, | |||
561 | return val; | 637 | return val; |
562 | } | 638 | } |
563 | 639 | ||
640 | static u16 pmbus_data2reg_vid(struct pmbus_data *data, | ||
641 | enum pmbus_sensor_classes class, long val) | ||
642 | { | ||
643 | val = SENSORS_LIMIT(val, 500, 1600); | ||
644 | |||
645 | return 2 + DIV_ROUND_CLOSEST((1600 - val) * 100, 625); | ||
646 | } | ||
647 | |||
564 | static u16 pmbus_data2reg(struct pmbus_data *data, | 648 | static u16 pmbus_data2reg(struct pmbus_data *data, |
565 | enum pmbus_sensor_classes class, long val) | 649 | enum pmbus_sensor_classes class, long val) |
566 | { | 650 | { |
567 | u16 regval; | 651 | u16 regval; |
568 | 652 | ||
569 | if (data->info->direct[class]) | 653 | switch (data->info->format[class]) { |
654 | case direct: | ||
570 | regval = pmbus_data2reg_direct(data, class, val); | 655 | regval = pmbus_data2reg_direct(data, class, val); |
571 | else | 656 | break; |
657 | case vid: | ||
658 | regval = pmbus_data2reg_vid(data, class, val); | ||
659 | break; | ||
660 | case linear: | ||
661 | default: | ||
572 | regval = pmbus_data2reg_linear(data, class, val); | 662 | regval = pmbus_data2reg_linear(data, class, val); |
573 | 663 | break; | |
664 | } | ||
574 | return regval; | 665 | return regval; |
575 | } | 666 | } |
576 | 667 | ||
@@ -682,7 +773,7 @@ static ssize_t pmbus_set_sensor(struct device *dev, | |||
682 | 773 | ||
683 | mutex_lock(&data->update_lock); | 774 | mutex_lock(&data->update_lock); |
684 | regval = pmbus_data2reg(data, sensor->class, val); | 775 | regval = pmbus_data2reg(data, sensor->class, val); |
685 | ret = pmbus_write_word_data(client, sensor->page, sensor->reg, regval); | 776 | ret = _pmbus_write_word_data(client, sensor->page, sensor->reg, regval); |
686 | if (ret < 0) | 777 | if (ret < 0) |
687 | rv = ret; | 778 | rv = ret; |
688 | else | 779 | else |
@@ -867,7 +958,8 @@ static void pmbus_find_max_attr(struct i2c_client *client, | |||
867 | * and its associated alarm attribute. | 958 | * and its associated alarm attribute. |
868 | */ | 959 | */ |
869 | struct pmbus_limit_attr { | 960 | struct pmbus_limit_attr { |
870 | u8 reg; /* Limit register */ | 961 | u16 reg; /* Limit register */ |
962 | bool update; /* True if register needs updates */ | ||
871 | const char *attr; /* Attribute name */ | 963 | const char *attr; /* Attribute name */ |
872 | const char *alarm; /* Alarm attribute name */ | 964 | const char *alarm; /* Alarm attribute name */ |
873 | u32 sbit; /* Alarm attribute status bit */ | 965 | u32 sbit; /* Alarm attribute status bit */ |
@@ -912,9 +1004,10 @@ static bool pmbus_add_limit_attrs(struct i2c_client *client, | |||
912 | if (pmbus_check_word_register(client, page, l->reg)) { | 1004 | if (pmbus_check_word_register(client, page, l->reg)) { |
913 | cindex = data->num_sensors; | 1005 | cindex = data->num_sensors; |
914 | pmbus_add_sensor(data, name, l->attr, index, page, | 1006 | pmbus_add_sensor(data, name, l->attr, index, page, |
915 | l->reg, attr->class, attr->update, | 1007 | l->reg, attr->class, |
1008 | attr->update || l->update, | ||
916 | false); | 1009 | false); |
917 | if (info->func[page] & attr->sfunc) { | 1010 | if (l->sbit && (info->func[page] & attr->sfunc)) { |
918 | if (attr->compare) { | 1011 | if (attr->compare) { |
919 | pmbus_add_boolean_cmp(data, name, | 1012 | pmbus_add_boolean_cmp(data, name, |
920 | l->alarm, index, | 1013 | l->alarm, index, |
@@ -953,9 +1046,11 @@ static void pmbus_add_sensor_attrs_one(struct i2c_client *client, | |||
953 | index, page, cbase, attr); | 1046 | index, page, cbase, attr); |
954 | /* | 1047 | /* |
955 | * Add generic alarm attribute only if there are no individual | 1048 | * Add generic alarm attribute only if there are no individual |
956 | * alarm attributes, and if there is a global alarm bit. | 1049 | * alarm attributes, if there is a global alarm bit, and if |
1050 | * the generic status register for this page is accessible. | ||
957 | */ | 1051 | */ |
958 | if (!have_alarm && attr->gbit) | 1052 | if (!have_alarm && attr->gbit && |
1053 | pmbus_check_byte_register(client, page, PMBUS_STATUS_BYTE)) | ||
959 | pmbus_add_boolean_reg(data, name, "alarm", index, | 1054 | pmbus_add_boolean_reg(data, name, "alarm", index, |
960 | PB_STATUS_BASE + page, | 1055 | PB_STATUS_BASE + page, |
961 | attr->gbit); | 1056 | attr->gbit); |
@@ -1008,6 +1103,21 @@ static const struct pmbus_limit_attr vin_limit_attrs[] = { | |||
1008 | .attr = "crit", | 1103 | .attr = "crit", |
1009 | .alarm = "crit_alarm", | 1104 | .alarm = "crit_alarm", |
1010 | .sbit = PB_VOLTAGE_OV_FAULT, | 1105 | .sbit = PB_VOLTAGE_OV_FAULT, |
1106 | }, { | ||
1107 | .reg = PMBUS_VIRT_READ_VIN_AVG, | ||
1108 | .update = true, | ||
1109 | .attr = "average", | ||
1110 | }, { | ||
1111 | .reg = PMBUS_VIRT_READ_VIN_MIN, | ||
1112 | .update = true, | ||
1113 | .attr = "lowest", | ||
1114 | }, { | ||
1115 | .reg = PMBUS_VIRT_READ_VIN_MAX, | ||
1116 | .update = true, | ||
1117 | .attr = "highest", | ||
1118 | }, { | ||
1119 | .reg = PMBUS_VIRT_RESET_VIN_HISTORY, | ||
1120 | .attr = "reset_history", | ||
1011 | }, | 1121 | }, |
1012 | }; | 1122 | }; |
1013 | 1123 | ||
@@ -1032,6 +1142,21 @@ static const struct pmbus_limit_attr vout_limit_attrs[] = { | |||
1032 | .attr = "crit", | 1142 | .attr = "crit", |
1033 | .alarm = "crit_alarm", | 1143 | .alarm = "crit_alarm", |
1034 | .sbit = PB_VOLTAGE_OV_FAULT, | 1144 | .sbit = PB_VOLTAGE_OV_FAULT, |
1145 | }, { | ||
1146 | .reg = PMBUS_VIRT_READ_VOUT_AVG, | ||
1147 | .update = true, | ||
1148 | .attr = "average", | ||
1149 | }, { | ||
1150 | .reg = PMBUS_VIRT_READ_VOUT_MIN, | ||
1151 | .update = true, | ||
1152 | .attr = "lowest", | ||
1153 | }, { | ||
1154 | .reg = PMBUS_VIRT_READ_VOUT_MAX, | ||
1155 | .update = true, | ||
1156 | .attr = "highest", | ||
1157 | }, { | ||
1158 | .reg = PMBUS_VIRT_RESET_VOUT_HISTORY, | ||
1159 | .attr = "reset_history", | ||
1035 | } | 1160 | } |
1036 | }; | 1161 | }; |
1037 | 1162 | ||
@@ -1078,6 +1203,21 @@ static const struct pmbus_limit_attr iin_limit_attrs[] = { | |||
1078 | .attr = "crit", | 1203 | .attr = "crit", |
1079 | .alarm = "crit_alarm", | 1204 | .alarm = "crit_alarm", |
1080 | .sbit = PB_IIN_OC_FAULT, | 1205 | .sbit = PB_IIN_OC_FAULT, |
1206 | }, { | ||
1207 | .reg = PMBUS_VIRT_READ_IIN_AVG, | ||
1208 | .update = true, | ||
1209 | .attr = "average", | ||
1210 | }, { | ||
1211 | .reg = PMBUS_VIRT_READ_IIN_MIN, | ||
1212 | .update = true, | ||
1213 | .attr = "lowest", | ||
1214 | }, { | ||
1215 | .reg = PMBUS_VIRT_READ_IIN_MAX, | ||
1216 | .update = true, | ||
1217 | .attr = "highest", | ||
1218 | }, { | ||
1219 | .reg = PMBUS_VIRT_RESET_IIN_HISTORY, | ||
1220 | .attr = "reset_history", | ||
1081 | } | 1221 | } |
1082 | }; | 1222 | }; |
1083 | 1223 | ||
@@ -1097,6 +1237,21 @@ static const struct pmbus_limit_attr iout_limit_attrs[] = { | |||
1097 | .attr = "crit", | 1237 | .attr = "crit", |
1098 | .alarm = "crit_alarm", | 1238 | .alarm = "crit_alarm", |
1099 | .sbit = PB_IOUT_OC_FAULT, | 1239 | .sbit = PB_IOUT_OC_FAULT, |
1240 | }, { | ||
1241 | .reg = PMBUS_VIRT_READ_IOUT_AVG, | ||
1242 | .update = true, | ||
1243 | .attr = "average", | ||
1244 | }, { | ||
1245 | .reg = PMBUS_VIRT_READ_IOUT_MIN, | ||
1246 | .update = true, | ||
1247 | .attr = "lowest", | ||
1248 | }, { | ||
1249 | .reg = PMBUS_VIRT_READ_IOUT_MAX, | ||
1250 | .update = true, | ||
1251 | .attr = "highest", | ||
1252 | }, { | ||
1253 | .reg = PMBUS_VIRT_RESET_IOUT_HISTORY, | ||
1254 | .attr = "reset_history", | ||
1100 | } | 1255 | } |
1101 | }; | 1256 | }; |
1102 | 1257 | ||
@@ -1132,6 +1287,17 @@ static const struct pmbus_limit_attr pin_limit_attrs[] = { | |||
1132 | .attr = "max", | 1287 | .attr = "max", |
1133 | .alarm = "alarm", | 1288 | .alarm = "alarm", |
1134 | .sbit = PB_PIN_OP_WARNING, | 1289 | .sbit = PB_PIN_OP_WARNING, |
1290 | }, { | ||
1291 | .reg = PMBUS_VIRT_READ_PIN_AVG, | ||
1292 | .update = true, | ||
1293 | .attr = "average", | ||
1294 | }, { | ||
1295 | .reg = PMBUS_VIRT_READ_PIN_MAX, | ||
1296 | .update = true, | ||
1297 | .attr = "input_highest", | ||
1298 | }, { | ||
1299 | .reg = PMBUS_VIRT_RESET_PIN_HISTORY, | ||
1300 | .attr = "reset_history", | ||
1135 | } | 1301 | } |
1136 | }; | 1302 | }; |
1137 | 1303 | ||
@@ -1200,6 +1366,39 @@ static const struct pmbus_limit_attr temp_limit_attrs[] = { | |||
1200 | .attr = "crit", | 1366 | .attr = "crit", |
1201 | .alarm = "crit_alarm", | 1367 | .alarm = "crit_alarm", |
1202 | .sbit = PB_TEMP_OT_FAULT, | 1368 | .sbit = PB_TEMP_OT_FAULT, |
1369 | }, { | ||
1370 | .reg = PMBUS_VIRT_READ_TEMP_MIN, | ||
1371 | .attr = "lowest", | ||
1372 | }, { | ||
1373 | .reg = PMBUS_VIRT_READ_TEMP_MAX, | ||
1374 | .attr = "highest", | ||
1375 | }, { | ||
1376 | .reg = PMBUS_VIRT_RESET_TEMP_HISTORY, | ||
1377 | .attr = "reset_history", | ||
1378 | } | ||
1379 | }; | ||
1380 | |||
1381 | static const struct pmbus_limit_attr temp_limit_attrs23[] = { | ||
1382 | { | ||
1383 | .reg = PMBUS_UT_WARN_LIMIT, | ||
1384 | .attr = "min", | ||
1385 | .alarm = "min_alarm", | ||
1386 | .sbit = PB_TEMP_UT_WARNING, | ||
1387 | }, { | ||
1388 | .reg = PMBUS_UT_FAULT_LIMIT, | ||
1389 | .attr = "lcrit", | ||
1390 | .alarm = "lcrit_alarm", | ||
1391 | .sbit = PB_TEMP_UT_FAULT, | ||
1392 | }, { | ||
1393 | .reg = PMBUS_OT_WARN_LIMIT, | ||
1394 | .attr = "max", | ||
1395 | .alarm = "max_alarm", | ||
1396 | .sbit = PB_TEMP_OT_WARNING, | ||
1397 | }, { | ||
1398 | .reg = PMBUS_OT_FAULT_LIMIT, | ||
1399 | .attr = "crit", | ||
1400 | .alarm = "crit_alarm", | ||
1401 | .sbit = PB_TEMP_OT_FAULT, | ||
1203 | } | 1402 | } |
1204 | }; | 1403 | }; |
1205 | 1404 | ||
@@ -1226,8 +1425,8 @@ static const struct pmbus_sensor_attr temp_attributes[] = { | |||
1226 | .sfunc = PMBUS_HAVE_STATUS_TEMP, | 1425 | .sfunc = PMBUS_HAVE_STATUS_TEMP, |
1227 | .sbase = PB_STATUS_TEMP_BASE, | 1426 | .sbase = PB_STATUS_TEMP_BASE, |
1228 | .gbit = PB_STATUS_TEMPERATURE, | 1427 | .gbit = PB_STATUS_TEMPERATURE, |
1229 | .limit = temp_limit_attrs, | 1428 | .limit = temp_limit_attrs23, |
1230 | .nlimit = ARRAY_SIZE(temp_limit_attrs), | 1429 | .nlimit = ARRAY_SIZE(temp_limit_attrs23), |
1231 | }, { | 1430 | }, { |
1232 | .reg = PMBUS_READ_TEMPERATURE_3, | 1431 | .reg = PMBUS_READ_TEMPERATURE_3, |
1233 | .class = PSC_TEMPERATURE, | 1432 | .class = PSC_TEMPERATURE, |
@@ -1238,8 +1437,8 @@ static const struct pmbus_sensor_attr temp_attributes[] = { | |||
1238 | .sfunc = PMBUS_HAVE_STATUS_TEMP, | 1437 | .sfunc = PMBUS_HAVE_STATUS_TEMP, |
1239 | .sbase = PB_STATUS_TEMP_BASE, | 1438 | .sbase = PB_STATUS_TEMP_BASE, |
1240 | .gbit = PB_STATUS_TEMPERATURE, | 1439 | .gbit = PB_STATUS_TEMPERATURE, |
1241 | .limit = temp_limit_attrs, | 1440 | .limit = temp_limit_attrs23, |
1242 | .nlimit = ARRAY_SIZE(temp_limit_attrs), | 1441 | .nlimit = ARRAY_SIZE(temp_limit_attrs23), |
1243 | } | 1442 | } |
1244 | }; | 1443 | }; |
1245 | 1444 | ||
@@ -1380,7 +1579,7 @@ static int pmbus_identify_common(struct i2c_client *client, | |||
1380 | */ | 1579 | */ |
1381 | switch (vout_mode >> 5) { | 1580 | switch (vout_mode >> 5) { |
1382 | case 0: /* linear mode */ | 1581 | case 0: /* linear mode */ |
1383 | if (data->info->direct[PSC_VOLTAGE_OUT]) | 1582 | if (data->info->format[PSC_VOLTAGE_OUT] != linear) |
1384 | return -ENODEV; | 1583 | return -ENODEV; |
1385 | 1584 | ||
1386 | exponent = vout_mode & 0x1f; | 1585 | exponent = vout_mode & 0x1f; |
@@ -1389,8 +1588,12 @@ static int pmbus_identify_common(struct i2c_client *client, | |||
1389 | exponent |= ~0x1f; | 1588 | exponent |= ~0x1f; |
1390 | data->exponent = exponent; | 1589 | data->exponent = exponent; |
1391 | break; | 1590 | break; |
1591 | case 1: /* VID mode */ | ||
1592 | if (data->info->format[PSC_VOLTAGE_OUT] != vid) | ||
1593 | return -ENODEV; | ||
1594 | break; | ||
1392 | case 2: /* direct mode */ | 1595 | case 2: /* direct mode */ |
1393 | if (!data->info->direct[PSC_VOLTAGE_OUT]) | 1596 | if (data->info->format[PSC_VOLTAGE_OUT] != direct) |
1394 | return -ENODEV; | 1597 | return -ENODEV; |
1395 | break; | 1598 | break; |
1396 | default: | 1599 | default: |
@@ -1457,18 +1660,6 @@ int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id, | |||
1457 | ret = -EINVAL; | 1660 | ret = -EINVAL; |
1458 | goto out_data; | 1661 | goto out_data; |
1459 | } | 1662 | } |
1460 | /* | ||
1461 | * Bail out if more than one page was configured, but we can not | ||
1462 | * select the highest page. This is an indication that the wrong | ||
1463 | * chip type was selected. Better bail out now than keep | ||
1464 | * returning errors later on. | ||
1465 | */ | ||
1466 | if (info->pages > 1 && pmbus_set_page(client, info->pages - 1) < 0) { | ||
1467 | dev_err(&client->dev, "Failed to select page %d\n", | ||
1468 | info->pages - 1); | ||
1469 | ret = -EINVAL; | ||
1470 | goto out_data; | ||
1471 | } | ||
1472 | 1663 | ||
1473 | ret = pmbus_identify_common(client, data); | 1664 | ret = pmbus_identify_common(client, data); |
1474 | if (ret < 0) { | 1665 | if (ret < 0) { |
diff --git a/drivers/hwmon/ucd9000.c b/drivers/hwmon/pmbus/ucd9000.c index ace1c7319734..ace1c7319734 100644 --- a/drivers/hwmon/ucd9000.c +++ b/drivers/hwmon/pmbus/ucd9000.c | |||
diff --git a/drivers/hwmon/ucd9200.c b/drivers/hwmon/pmbus/ucd9200.c index ffcc1cf3609d..ffcc1cf3609d 100644 --- a/drivers/hwmon/ucd9200.c +++ b/drivers/hwmon/pmbus/ucd9200.c | |||
diff --git a/include/linux/platform_data/ntc_thermistor.h b/include/linux/platform_data/ntc_thermistor.h new file mode 100644 index 000000000000..abd286215279 --- /dev/null +++ b/include/linux/platform_data/ntc_thermistor.h | |||
@@ -0,0 +1,53 @@ | |||
1 | /* | ||
2 | * ntc_thermistor.h - NTC Thermistors | ||
3 | * | ||
4 | * Copyright (C) 2010 Samsung Electronics | ||
5 | * MyungJoo Ham <myungjoo.ham@samsung.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | #ifndef _LINUX_NTC_H | ||
22 | #define _LINUX_NTC_H | ||
23 | |||
24 | enum ntc_thermistor_type { | ||
25 | TYPE_NCPXXWB473, | ||
26 | TYPE_NCPXXWL333, | ||
27 | }; | ||
28 | |||
29 | struct ntc_thermistor_platform_data { | ||
30 | /* | ||
31 | * One (not both) of read_uV and read_ohm should be provided and only | ||
32 | * one of the two should be provided. | ||
33 | * Both functions should return negative value for an error case. | ||
34 | * | ||
35 | * pullup_uV, pullup_ohm, pulldown_ohm, and connect are required to use | ||
36 | * read_uV() | ||
37 | * | ||
38 | * How to setup pullup_ohm, pulldown_ohm, and connect is | ||
39 | * described at Documentation/hwmon/ntc | ||
40 | * | ||
41 | * pullup/down_ohm: 0 for infinite / not-connected | ||
42 | */ | ||
43 | int (*read_uV)(void); | ||
44 | unsigned int pullup_uV; | ||
45 | |||
46 | unsigned int pullup_ohm; | ||
47 | unsigned int pulldown_ohm; | ||
48 | enum { NTC_CONNECTED_POSITIVE, NTC_CONNECTED_GROUND } connect; | ||
49 | |||
50 | int (*read_ohm)(void); | ||
51 | }; | ||
52 | |||
53 | #endif /* _LINUX_NTC_H */ | ||