diff options
Diffstat (limited to 'drivers/hwmon/pmbus')
-rw-r--r-- | drivers/hwmon/pmbus/Kconfig | 28 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/Makefile | 2 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/adm1275.c | 159 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/lm25066.c | 17 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/ltc2978.c | 408 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/max16064.c | 3 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/max34440.c | 13 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/max8688.c | 9 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/pmbus.c | 10 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/pmbus.h | 23 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/pmbus_core.c | 85 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/ucd9000.c | 13 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/ucd9200.c | 5 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/zl6100.c | 256 |
14 files changed, 944 insertions, 87 deletions
diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig index c9237b9dcff2..4b26f51920ba 100644 --- a/drivers/hwmon/pmbus/Kconfig +++ b/drivers/hwmon/pmbus/Kconfig | |||
@@ -20,17 +20,18 @@ config SENSORS_PMBUS | |||
20 | help | 20 | help |
21 | If you say yes here you get hardware monitoring support for generic | 21 | If you say yes here you get hardware monitoring support for generic |
22 | PMBus devices, including but not limited to ADP4000, BMR450, BMR451, | 22 | PMBus devices, including but not limited to ADP4000, BMR450, BMR451, |
23 | BMR453, BMR454, LTC2978, NCP4200, and NCP4208. | 23 | BMR453, BMR454, NCP4200, and NCP4208. |
24 | 24 | ||
25 | This driver can also be built as a module. If so, the module will | 25 | This driver can also be built as a module. If so, the module will |
26 | be called pmbus. | 26 | be called pmbus. |
27 | 27 | ||
28 | config SENSORS_ADM1275 | 28 | config SENSORS_ADM1275 |
29 | tristate "Analog Devices ADM1275" | 29 | tristate "Analog Devices ADM1275 and compatibles" |
30 | default n | 30 | default n |
31 | help | 31 | help |
32 | If you say yes here you get hardware monitoring support for Analog | 32 | If you say yes here you get hardware monitoring support for Analog |
33 | Devices ADM1275 Hot-Swap Controller and Digital Power Monitor. | 33 | Devices ADM1275 and ADM1276 Hot-Swap Controller and Digital Power |
34 | Monitor. | ||
34 | 35 | ||
35 | This driver can also be built as a module. If so, the module will | 36 | This driver can also be built as a module. If so, the module will |
36 | be called adm1275. | 37 | be called adm1275. |
@@ -45,6 +46,16 @@ config SENSORS_LM25066 | |||
45 | This driver can also be built as a module. If so, the module will | 46 | This driver can also be built as a module. If so, the module will |
46 | be called lm25066. | 47 | be called lm25066. |
47 | 48 | ||
49 | config SENSORS_LTC2978 | ||
50 | tristate "Linear Technologies LTC2978 and LTC3880" | ||
51 | default n | ||
52 | help | ||
53 | If you say yes here you get hardware monitoring support for Linear | ||
54 | Technology LTC2978 and LTC3880. | ||
55 | |||
56 | This driver can also be built as a module. If so, the module will | ||
57 | be called ltc2978. | ||
58 | |||
48 | config SENSORS_MAX16064 | 59 | config SENSORS_MAX16064 |
49 | tristate "Maxim MAX16064" | 60 | tristate "Maxim MAX16064" |
50 | default n | 61 | default n |
@@ -97,4 +108,15 @@ config SENSORS_UCD9200 | |||
97 | This driver can also be built as a module. If so, the module will | 108 | This driver can also be built as a module. If so, the module will |
98 | be called ucd9200. | 109 | be called ucd9200. |
99 | 110 | ||
111 | config SENSORS_ZL6100 | ||
112 | tristate "Intersil ZL6100 and compatibles" | ||
113 | default n | ||
114 | help | ||
115 | If you say yes here you get hardware monitoring support for Intersil | ||
116 | ZL2004, ZL2006, ZL2008, ZL2105, ZL2106, ZL6100, and ZL6105 Digital | ||
117 | DC/DC Controllers. | ||
118 | |||
119 | This driver can also be built as a module. If so, the module will | ||
120 | be called zl6100. | ||
121 | |||
100 | endif # PMBUS | 122 | endif # PMBUS |
diff --git a/drivers/hwmon/pmbus/Makefile b/drivers/hwmon/pmbus/Makefile index 623eedb1ed9a..789376c85dbb 100644 --- a/drivers/hwmon/pmbus/Makefile +++ b/drivers/hwmon/pmbus/Makefile | |||
@@ -6,8 +6,10 @@ obj-$(CONFIG_PMBUS) += pmbus_core.o | |||
6 | obj-$(CONFIG_SENSORS_PMBUS) += pmbus.o | 6 | obj-$(CONFIG_SENSORS_PMBUS) += pmbus.o |
7 | obj-$(CONFIG_SENSORS_ADM1275) += adm1275.o | 7 | obj-$(CONFIG_SENSORS_ADM1275) += adm1275.o |
8 | obj-$(CONFIG_SENSORS_LM25066) += lm25066.o | 8 | obj-$(CONFIG_SENSORS_LM25066) += lm25066.o |
9 | obj-$(CONFIG_SENSORS_LTC2978) += ltc2978.o | ||
9 | obj-$(CONFIG_SENSORS_MAX16064) += max16064.o | 10 | obj-$(CONFIG_SENSORS_MAX16064) += max16064.o |
10 | obj-$(CONFIG_SENSORS_MAX34440) += max34440.o | 11 | obj-$(CONFIG_SENSORS_MAX34440) += max34440.o |
11 | obj-$(CONFIG_SENSORS_MAX8688) += max8688.o | 12 | obj-$(CONFIG_SENSORS_MAX8688) += max8688.o |
12 | obj-$(CONFIG_SENSORS_UCD9000) += ucd9000.o | 13 | obj-$(CONFIG_SENSORS_UCD9000) += ucd9000.o |
13 | obj-$(CONFIG_SENSORS_UCD9200) += ucd9200.o | 14 | obj-$(CONFIG_SENSORS_UCD9200) += ucd9200.o |
15 | obj-$(CONFIG_SENSORS_ZL6100) += zl6100.o | ||
diff --git a/drivers/hwmon/pmbus/adm1275.c b/drivers/hwmon/pmbus/adm1275.c index c936e2782309..980a4d9d5028 100644 --- a/drivers/hwmon/pmbus/adm1275.c +++ b/drivers/hwmon/pmbus/adm1275.c | |||
@@ -23,6 +23,8 @@ | |||
23 | #include <linux/i2c.h> | 23 | #include <linux/i2c.h> |
24 | #include "pmbus.h" | 24 | #include "pmbus.h" |
25 | 25 | ||
26 | enum chips { adm1275, adm1276 }; | ||
27 | |||
26 | #define ADM1275_PEAK_IOUT 0xd0 | 28 | #define ADM1275_PEAK_IOUT 0xd0 |
27 | #define ADM1275_PEAK_VIN 0xd1 | 29 | #define ADM1275_PEAK_VIN 0xd1 |
28 | #define ADM1275_PEAK_VOUT 0xd2 | 30 | #define ADM1275_PEAK_VOUT 0xd2 |
@@ -31,14 +33,47 @@ | |||
31 | #define ADM1275_VIN_VOUT_SELECT (1 << 6) | 33 | #define ADM1275_VIN_VOUT_SELECT (1 << 6) |
32 | #define ADM1275_VRANGE (1 << 5) | 34 | #define ADM1275_VRANGE (1 << 5) |
33 | 35 | ||
36 | #define ADM1275_IOUT_WARN2_LIMIT 0xd7 | ||
37 | #define ADM1275_DEVICE_CONFIG 0xd8 | ||
38 | |||
39 | #define ADM1275_IOUT_WARN2_SELECT (1 << 4) | ||
40 | |||
41 | #define ADM1276_PEAK_PIN 0xda | ||
42 | |||
43 | #define ADM1275_MFR_STATUS_IOUT_WARN2 (1 << 0) | ||
44 | |||
45 | struct adm1275_data { | ||
46 | int id; | ||
47 | bool have_oc_fault; | ||
48 | struct pmbus_driver_info info; | ||
49 | }; | ||
50 | |||
51 | #define to_adm1275_data(x) container_of(x, struct adm1275_data, info) | ||
52 | |||
34 | static int adm1275_read_word_data(struct i2c_client *client, int page, int reg) | 53 | static int adm1275_read_word_data(struct i2c_client *client, int page, int reg) |
35 | { | 54 | { |
36 | int ret; | 55 | const struct pmbus_driver_info *info = pmbus_get_driver_info(client); |
56 | const struct adm1275_data *data = to_adm1275_data(info); | ||
57 | int ret = 0; | ||
37 | 58 | ||
38 | if (page) | 59 | if (page) |
39 | return -EINVAL; | 60 | return -ENXIO; |
40 | 61 | ||
41 | switch (reg) { | 62 | switch (reg) { |
63 | case PMBUS_IOUT_UC_FAULT_LIMIT: | ||
64 | if (data->have_oc_fault) { | ||
65 | ret = -ENXIO; | ||
66 | break; | ||
67 | } | ||
68 | ret = pmbus_read_word_data(client, 0, ADM1275_IOUT_WARN2_LIMIT); | ||
69 | break; | ||
70 | case PMBUS_IOUT_OC_FAULT_LIMIT: | ||
71 | if (!data->have_oc_fault) { | ||
72 | ret = -ENXIO; | ||
73 | break; | ||
74 | } | ||
75 | ret = pmbus_read_word_data(client, 0, ADM1275_IOUT_WARN2_LIMIT); | ||
76 | break; | ||
42 | case PMBUS_VIRT_READ_IOUT_MAX: | 77 | case PMBUS_VIRT_READ_IOUT_MAX: |
43 | ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_IOUT); | 78 | ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_IOUT); |
44 | break; | 79 | break; |
@@ -48,10 +83,20 @@ static int adm1275_read_word_data(struct i2c_client *client, int page, int reg) | |||
48 | case PMBUS_VIRT_READ_VIN_MAX: | 83 | case PMBUS_VIRT_READ_VIN_MAX: |
49 | ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_VIN); | 84 | ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_VIN); |
50 | break; | 85 | break; |
86 | case PMBUS_VIRT_READ_PIN_MAX: | ||
87 | if (data->id != adm1276) { | ||
88 | ret = -ENXIO; | ||
89 | break; | ||
90 | } | ||
91 | ret = pmbus_read_word_data(client, 0, ADM1276_PEAK_PIN); | ||
92 | break; | ||
51 | case PMBUS_VIRT_RESET_IOUT_HISTORY: | 93 | case PMBUS_VIRT_RESET_IOUT_HISTORY: |
52 | case PMBUS_VIRT_RESET_VOUT_HISTORY: | 94 | case PMBUS_VIRT_RESET_VOUT_HISTORY: |
53 | case PMBUS_VIRT_RESET_VIN_HISTORY: | 95 | case PMBUS_VIRT_RESET_VIN_HISTORY: |
54 | ret = 0; | 96 | break; |
97 | case PMBUS_VIRT_RESET_PIN_HISTORY: | ||
98 | if (data->id != adm1276) | ||
99 | ret = -ENXIO; | ||
55 | break; | 100 | break; |
56 | default: | 101 | default: |
57 | ret = -ENODATA; | 102 | ret = -ENODATA; |
@@ -66,9 +111,14 @@ static int adm1275_write_word_data(struct i2c_client *client, int page, int reg, | |||
66 | int ret; | 111 | int ret; |
67 | 112 | ||
68 | if (page) | 113 | if (page) |
69 | return -EINVAL; | 114 | return -ENXIO; |
70 | 115 | ||
71 | switch (reg) { | 116 | switch (reg) { |
117 | case PMBUS_IOUT_UC_FAULT_LIMIT: | ||
118 | case PMBUS_IOUT_OC_FAULT_LIMIT: | ||
119 | ret = pmbus_write_word_data(client, 0, ADM1275_IOUT_WARN2_LIMIT, | ||
120 | word); | ||
121 | break; | ||
72 | case PMBUS_VIRT_RESET_IOUT_HISTORY: | 122 | case PMBUS_VIRT_RESET_IOUT_HISTORY: |
73 | ret = pmbus_write_word_data(client, 0, ADM1275_PEAK_IOUT, 0); | 123 | ret = pmbus_write_word_data(client, 0, ADM1275_PEAK_IOUT, 0); |
74 | break; | 124 | break; |
@@ -78,6 +128,41 @@ static int adm1275_write_word_data(struct i2c_client *client, int page, int reg, | |||
78 | case PMBUS_VIRT_RESET_VIN_HISTORY: | 128 | case PMBUS_VIRT_RESET_VIN_HISTORY: |
79 | ret = pmbus_write_word_data(client, 0, ADM1275_PEAK_VIN, 0); | 129 | ret = pmbus_write_word_data(client, 0, ADM1275_PEAK_VIN, 0); |
80 | break; | 130 | break; |
131 | case PMBUS_VIRT_RESET_PIN_HISTORY: | ||
132 | ret = pmbus_write_word_data(client, 0, ADM1276_PEAK_PIN, 0); | ||
133 | break; | ||
134 | default: | ||
135 | ret = -ENODATA; | ||
136 | break; | ||
137 | } | ||
138 | return ret; | ||
139 | } | ||
140 | |||
141 | static int adm1275_read_byte_data(struct i2c_client *client, int page, int reg) | ||
142 | { | ||
143 | const struct pmbus_driver_info *info = pmbus_get_driver_info(client); | ||
144 | const struct adm1275_data *data = to_adm1275_data(info); | ||
145 | int mfr_status, ret; | ||
146 | |||
147 | if (page > 0) | ||
148 | return -ENXIO; | ||
149 | |||
150 | switch (reg) { | ||
151 | case PMBUS_STATUS_IOUT: | ||
152 | ret = pmbus_read_byte_data(client, page, PMBUS_STATUS_IOUT); | ||
153 | if (ret < 0) | ||
154 | break; | ||
155 | mfr_status = pmbus_read_byte_data(client, page, | ||
156 | PMBUS_STATUS_MFR_SPECIFIC); | ||
157 | if (mfr_status < 0) { | ||
158 | ret = mfr_status; | ||
159 | break; | ||
160 | } | ||
161 | if (mfr_status & ADM1275_MFR_STATUS_IOUT_WARN2) { | ||
162 | ret |= data->have_oc_fault ? | ||
163 | PB_IOUT_OC_FAULT : PB_IOUT_UC_FAULT; | ||
164 | } | ||
165 | break; | ||
81 | default: | 166 | default: |
82 | ret = -ENODATA; | 167 | ret = -ENODATA; |
83 | break; | 168 | break; |
@@ -88,16 +173,17 @@ static int adm1275_write_word_data(struct i2c_client *client, int page, int reg, | |||
88 | static int adm1275_probe(struct i2c_client *client, | 173 | static int adm1275_probe(struct i2c_client *client, |
89 | const struct i2c_device_id *id) | 174 | const struct i2c_device_id *id) |
90 | { | 175 | { |
91 | int config; | 176 | int config, device_config; |
92 | int ret; | 177 | int ret; |
93 | struct pmbus_driver_info *info; | 178 | struct pmbus_driver_info *info; |
179 | struct adm1275_data *data; | ||
94 | 180 | ||
95 | if (!i2c_check_functionality(client->adapter, | 181 | if (!i2c_check_functionality(client->adapter, |
96 | I2C_FUNC_SMBUS_READ_BYTE_DATA)) | 182 | I2C_FUNC_SMBUS_READ_BYTE_DATA)) |
97 | return -ENODEV; | 183 | return -ENODEV; |
98 | 184 | ||
99 | info = kzalloc(sizeof(struct pmbus_driver_info), GFP_KERNEL); | 185 | data = kzalloc(sizeof(struct adm1275_data), GFP_KERNEL); |
100 | if (!info) | 186 | if (!data) |
101 | return -ENOMEM; | 187 | return -ENOMEM; |
102 | 188 | ||
103 | config = i2c_smbus_read_byte_data(client, ADM1275_PMON_CONFIG); | 189 | config = i2c_smbus_read_byte_data(client, ADM1275_PMON_CONFIG); |
@@ -106,6 +192,15 @@ static int adm1275_probe(struct i2c_client *client, | |||
106 | goto err_mem; | 192 | goto err_mem; |
107 | } | 193 | } |
108 | 194 | ||
195 | device_config = i2c_smbus_read_byte_data(client, ADM1275_DEVICE_CONFIG); | ||
196 | if (device_config < 0) { | ||
197 | ret = device_config; | ||
198 | goto err_mem; | ||
199 | } | ||
200 | |||
201 | data->id = id->driver_data; | ||
202 | info = &data->info; | ||
203 | |||
109 | info->pages = 1; | 204 | info->pages = 1; |
110 | info->format[PSC_VOLTAGE_IN] = direct; | 205 | info->format[PSC_VOLTAGE_IN] = direct; |
111 | info->format[PSC_VOLTAGE_OUT] = direct; | 206 | info->format[PSC_VOLTAGE_OUT] = direct; |
@@ -116,6 +211,7 @@ static int adm1275_probe(struct i2c_client *client, | |||
116 | info->func[0] = PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT; | 211 | info->func[0] = PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT; |
117 | 212 | ||
118 | info->read_word_data = adm1275_read_word_data; | 213 | info->read_word_data = adm1275_read_word_data; |
214 | info->read_byte_data = adm1275_read_byte_data; | ||
119 | info->write_word_data = adm1275_write_word_data; | 215 | info->write_word_data = adm1275_write_word_data; |
120 | 216 | ||
121 | if (config & ADM1275_VRANGE) { | 217 | if (config & ADM1275_VRANGE) { |
@@ -134,10 +230,36 @@ static int adm1275_probe(struct i2c_client *client, | |||
134 | info->R[PSC_VOLTAGE_OUT] = -1; | 230 | info->R[PSC_VOLTAGE_OUT] = -1; |
135 | } | 231 | } |
136 | 232 | ||
137 | if (config & ADM1275_VIN_VOUT_SELECT) | 233 | if (device_config & ADM1275_IOUT_WARN2_SELECT) |
138 | info->func[0] |= PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT; | 234 | data->have_oc_fault = true; |
139 | else | 235 | |
140 | info->func[0] |= PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT; | 236 | switch (id->driver_data) { |
237 | case adm1275: | ||
238 | if (config & ADM1275_VIN_VOUT_SELECT) | ||
239 | info->func[0] |= | ||
240 | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT; | ||
241 | else | ||
242 | info->func[0] |= | ||
243 | PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT; | ||
244 | break; | ||
245 | case adm1276: | ||
246 | info->format[PSC_POWER] = direct; | ||
247 | info->func[0] |= PMBUS_HAVE_VIN | PMBUS_HAVE_PIN | ||
248 | | PMBUS_HAVE_STATUS_INPUT; | ||
249 | if (config & ADM1275_VIN_VOUT_SELECT) | ||
250 | info->func[0] |= | ||
251 | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT; | ||
252 | if (config & ADM1275_VRANGE) { | ||
253 | info->m[PSC_POWER] = 6043; | ||
254 | info->b[PSC_POWER] = 0; | ||
255 | info->R[PSC_POWER] = -2; | ||
256 | } else { | ||
257 | info->m[PSC_POWER] = 2115; | ||
258 | info->b[PSC_POWER] = 0; | ||
259 | info->R[PSC_POWER] = -1; | ||
260 | } | ||
261 | break; | ||
262 | } | ||
141 | 263 | ||
142 | ret = pmbus_do_probe(client, id, info); | 264 | ret = pmbus_do_probe(client, id, info); |
143 | if (ret) | 265 | if (ret) |
@@ -145,22 +267,23 @@ static int adm1275_probe(struct i2c_client *client, | |||
145 | return 0; | 267 | return 0; |
146 | 268 | ||
147 | err_mem: | 269 | err_mem: |
148 | kfree(info); | 270 | kfree(data); |
149 | return ret; | 271 | return ret; |
150 | } | 272 | } |
151 | 273 | ||
152 | static int adm1275_remove(struct i2c_client *client) | 274 | static int adm1275_remove(struct i2c_client *client) |
153 | { | 275 | { |
154 | const struct pmbus_driver_info *info = pmbus_get_driver_info(client); | 276 | const struct pmbus_driver_info *info = pmbus_get_driver_info(client); |
155 | int ret; | 277 | const struct adm1275_data *data = to_adm1275_data(info); |
156 | 278 | ||
157 | ret = pmbus_do_remove(client); | 279 | pmbus_do_remove(client); |
158 | kfree(info); | 280 | kfree(data); |
159 | return ret; | 281 | return 0; |
160 | } | 282 | } |
161 | 283 | ||
162 | static const struct i2c_device_id adm1275_id[] = { | 284 | static const struct i2c_device_id adm1275_id[] = { |
163 | {"adm1275", 0}, | 285 | { "adm1275", adm1275 }, |
286 | { "adm1276", adm1276 }, | ||
164 | { } | 287 | { } |
165 | }; | 288 | }; |
166 | MODULE_DEVICE_TABLE(i2c, adm1275_id); | 289 | MODULE_DEVICE_TABLE(i2c, adm1275_id); |
@@ -185,7 +308,7 @@ static void __exit adm1275_exit(void) | |||
185 | } | 308 | } |
186 | 309 | ||
187 | MODULE_AUTHOR("Guenter Roeck"); | 310 | MODULE_AUTHOR("Guenter Roeck"); |
188 | MODULE_DESCRIPTION("PMBus driver for Analog Devices ADM1275"); | 311 | MODULE_DESCRIPTION("PMBus driver for Analog Devices ADM1275 and compatibles"); |
189 | MODULE_LICENSE("GPL"); | 312 | MODULE_LICENSE("GPL"); |
190 | module_init(adm1275_init); | 313 | module_init(adm1275_init); |
191 | module_exit(adm1275_exit); | 314 | module_exit(adm1275_exit); |
diff --git a/drivers/hwmon/pmbus/lm25066.c b/drivers/hwmon/pmbus/lm25066.c index ac254fba551b..84a37f0c8db6 100644 --- a/drivers/hwmon/pmbus/lm25066.c +++ b/drivers/hwmon/pmbus/lm25066.c | |||
@@ -57,7 +57,7 @@ static int lm25066_read_word_data(struct i2c_client *client, int page, int reg) | |||
57 | int ret; | 57 | int ret; |
58 | 58 | ||
59 | if (page > 1) | 59 | if (page > 1) |
60 | return -EINVAL; | 60 | return -ENXIO; |
61 | 61 | ||
62 | /* Map READ_VAUX into READ_VOUT register on page 1 */ | 62 | /* Map READ_VAUX into READ_VOUT register on page 1 */ |
63 | if (page == 1) { | 63 | if (page == 1) { |
@@ -85,7 +85,7 @@ static int lm25066_read_word_data(struct i2c_client *client, int page, int reg) | |||
85 | break; | 85 | break; |
86 | default: | 86 | default: |
87 | /* No other valid registers on page 1 */ | 87 | /* No other valid registers on page 1 */ |
88 | ret = -EINVAL; | 88 | ret = -ENXIO; |
89 | break; | 89 | break; |
90 | } | 90 | } |
91 | goto done; | 91 | goto done; |
@@ -138,7 +138,7 @@ static int lm25066_write_word_data(struct i2c_client *client, int page, int reg, | |||
138 | int ret; | 138 | int ret; |
139 | 139 | ||
140 | if (page > 1) | 140 | if (page > 1) |
141 | return -EINVAL; | 141 | return -ENXIO; |
142 | 142 | ||
143 | switch (reg) { | 143 | switch (reg) { |
144 | case PMBUS_IIN_OC_WARN_LIMIT: | 144 | case PMBUS_IIN_OC_WARN_LIMIT: |
@@ -164,10 +164,10 @@ static int lm25066_write_word_data(struct i2c_client *client, int page, int reg, | |||
164 | static int lm25066_write_byte(struct i2c_client *client, int page, u8 value) | 164 | static int lm25066_write_byte(struct i2c_client *client, int page, u8 value) |
165 | { | 165 | { |
166 | if (page > 1) | 166 | if (page > 1) |
167 | return -EINVAL; | 167 | return -ENXIO; |
168 | 168 | ||
169 | if (page == 0) | 169 | if (page <= 0) |
170 | return pmbus_write_byte(client, 0, value); | 170 | return pmbus_write_byte(client, page, value); |
171 | 171 | ||
172 | return 0; | 172 | return 0; |
173 | } | 173 | } |
@@ -309,11 +309,10 @@ static int lm25066_remove(struct i2c_client *client) | |||
309 | { | 309 | { |
310 | const struct pmbus_driver_info *info = pmbus_get_driver_info(client); | 310 | const struct pmbus_driver_info *info = pmbus_get_driver_info(client); |
311 | const struct lm25066_data *data = to_lm25066_data(info); | 311 | const struct lm25066_data *data = to_lm25066_data(info); |
312 | int ret; | ||
313 | 312 | ||
314 | ret = pmbus_do_remove(client); | 313 | pmbus_do_remove(client); |
315 | kfree(data); | 314 | kfree(data); |
316 | return ret; | 315 | return 0; |
317 | } | 316 | } |
318 | 317 | ||
319 | static const struct i2c_device_id lm25066_id[] = { | 318 | static const struct i2c_device_id lm25066_id[] = { |
diff --git a/drivers/hwmon/pmbus/ltc2978.c b/drivers/hwmon/pmbus/ltc2978.c new file mode 100644 index 000000000000..820fff48910b --- /dev/null +++ b/drivers/hwmon/pmbus/ltc2978.c | |||
@@ -0,0 +1,408 @@ | |||
1 | /* | ||
2 | * Hardware monitoring driver for LTC2978 and LTC3880 | ||
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 { ltc2978, ltc3880 }; | ||
30 | |||
31 | /* LTC2978 and LTC3880 */ | ||
32 | #define LTC2978_MFR_VOUT_PEAK 0xdd | ||
33 | #define LTC2978_MFR_VIN_PEAK 0xde | ||
34 | #define LTC2978_MFR_TEMPERATURE_PEAK 0xdf | ||
35 | #define LTC2978_MFR_SPECIAL_ID 0xe7 | ||
36 | |||
37 | /* LTC2978 only */ | ||
38 | #define LTC2978_MFR_VOUT_MIN 0xfb | ||
39 | #define LTC2978_MFR_VIN_MIN 0xfc | ||
40 | #define LTC2978_MFR_TEMPERATURE_MIN 0xfd | ||
41 | |||
42 | /* LTC3880 only */ | ||
43 | #define LTC3880_MFR_IOUT_PEAK 0xd7 | ||
44 | #define LTC3880_MFR_CLEAR_PEAKS 0xe3 | ||
45 | #define LTC3880_MFR_TEMPERATURE2_PEAK 0xf4 | ||
46 | |||
47 | #define LTC2978_ID_REV1 0x0121 | ||
48 | #define LTC2978_ID_REV2 0x0122 | ||
49 | #define LTC3880_ID 0x4000 | ||
50 | #define LTC3880_ID_MASK 0xff00 | ||
51 | |||
52 | /* | ||
53 | * LTC2978 clears peak data whenever the CLEAR_FAULTS command is executed, which | ||
54 | * happens pretty much each time chip data is updated. Raw peak data therefore | ||
55 | * does not provide much value. To be able to provide useful peak data, keep an | ||
56 | * internal cache of measured peak data, which is only cleared if an explicit | ||
57 | * "clear peak" command is executed for the sensor in question. | ||
58 | */ | ||
59 | struct ltc2978_data { | ||
60 | enum chips id; | ||
61 | int vin_min, vin_max; | ||
62 | int temp_min, temp_max; | ||
63 | int vout_min[8], vout_max[8]; | ||
64 | int iout_max[2]; | ||
65 | int temp2_max[2]; | ||
66 | struct pmbus_driver_info info; | ||
67 | }; | ||
68 | |||
69 | #define to_ltc2978_data(x) container_of(x, struct ltc2978_data, info) | ||
70 | |||
71 | static inline int lin11_to_val(int data) | ||
72 | { | ||
73 | s16 e = ((s16)data) >> 11; | ||
74 | s32 m = (((s16)(data << 5)) >> 5); | ||
75 | |||
76 | /* | ||
77 | * mantissa is 10 bit + sign, exponent adds up to 15 bit. | ||
78 | * Add 6 bit to exponent for maximum accuracy (10 + 15 + 6 = 31). | ||
79 | */ | ||
80 | e += 6; | ||
81 | return (e < 0 ? m >> -e : m << e); | ||
82 | } | ||
83 | |||
84 | static int ltc2978_read_word_data_common(struct i2c_client *client, int page, | ||
85 | int reg) | ||
86 | { | ||
87 | const struct pmbus_driver_info *info = pmbus_get_driver_info(client); | ||
88 | struct ltc2978_data *data = to_ltc2978_data(info); | ||
89 | int ret; | ||
90 | |||
91 | switch (reg) { | ||
92 | case PMBUS_VIRT_READ_VIN_MAX: | ||
93 | ret = pmbus_read_word_data(client, page, LTC2978_MFR_VIN_PEAK); | ||
94 | if (ret >= 0) { | ||
95 | if (lin11_to_val(ret) > lin11_to_val(data->vin_max)) | ||
96 | data->vin_max = ret; | ||
97 | ret = data->vin_max; | ||
98 | } | ||
99 | break; | ||
100 | case PMBUS_VIRT_READ_VOUT_MAX: | ||
101 | ret = pmbus_read_word_data(client, page, LTC2978_MFR_VOUT_PEAK); | ||
102 | if (ret >= 0) { | ||
103 | /* | ||
104 | * VOUT is 16 bit unsigned with fixed exponent, | ||
105 | * so we can compare it directly | ||
106 | */ | ||
107 | if (ret > data->vout_max[page]) | ||
108 | data->vout_max[page] = ret; | ||
109 | ret = data->vout_max[page]; | ||
110 | } | ||
111 | break; | ||
112 | case PMBUS_VIRT_READ_TEMP_MAX: | ||
113 | ret = pmbus_read_word_data(client, page, | ||
114 | LTC2978_MFR_TEMPERATURE_PEAK); | ||
115 | if (ret >= 0) { | ||
116 | if (lin11_to_val(ret) > lin11_to_val(data->temp_max)) | ||
117 | data->temp_max = ret; | ||
118 | ret = data->temp_max; | ||
119 | } | ||
120 | break; | ||
121 | case PMBUS_VIRT_RESET_VOUT_HISTORY: | ||
122 | case PMBUS_VIRT_RESET_VIN_HISTORY: | ||
123 | case PMBUS_VIRT_RESET_TEMP_HISTORY: | ||
124 | ret = 0; | ||
125 | break; | ||
126 | default: | ||
127 | ret = -ENODATA; | ||
128 | break; | ||
129 | } | ||
130 | return ret; | ||
131 | } | ||
132 | |||
133 | static int ltc2978_read_word_data(struct i2c_client *client, int page, int reg) | ||
134 | { | ||
135 | const struct pmbus_driver_info *info = pmbus_get_driver_info(client); | ||
136 | struct ltc2978_data *data = to_ltc2978_data(info); | ||
137 | int ret; | ||
138 | |||
139 | switch (reg) { | ||
140 | case PMBUS_VIRT_READ_VIN_MIN: | ||
141 | ret = pmbus_read_word_data(client, page, LTC2978_MFR_VIN_MIN); | ||
142 | if (ret >= 0) { | ||
143 | if (lin11_to_val(ret) < lin11_to_val(data->vin_min)) | ||
144 | data->vin_min = ret; | ||
145 | ret = data->vin_min; | ||
146 | } | ||
147 | break; | ||
148 | case PMBUS_VIRT_READ_VOUT_MIN: | ||
149 | ret = pmbus_read_word_data(client, page, LTC2978_MFR_VOUT_MIN); | ||
150 | if (ret >= 0) { | ||
151 | /* | ||
152 | * VOUT_MIN is known to not be supported on some lots | ||
153 | * of LTC2978 revision 1, and will return the maximum | ||
154 | * possible voltage if read. If VOUT_MAX is valid and | ||
155 | * lower than the reading of VOUT_MIN, use it instead. | ||
156 | */ | ||
157 | if (data->vout_max[page] && ret > data->vout_max[page]) | ||
158 | ret = data->vout_max[page]; | ||
159 | if (ret < data->vout_min[page]) | ||
160 | data->vout_min[page] = ret; | ||
161 | ret = data->vout_min[page]; | ||
162 | } | ||
163 | break; | ||
164 | case PMBUS_VIRT_READ_TEMP_MIN: | ||
165 | ret = pmbus_read_word_data(client, page, | ||
166 | LTC2978_MFR_TEMPERATURE_MIN); | ||
167 | if (ret >= 0) { | ||
168 | if (lin11_to_val(ret) | ||
169 | < lin11_to_val(data->temp_min)) | ||
170 | data->temp_min = ret; | ||
171 | ret = data->temp_min; | ||
172 | } | ||
173 | break; | ||
174 | case PMBUS_VIRT_READ_IOUT_MAX: | ||
175 | case PMBUS_VIRT_RESET_IOUT_HISTORY: | ||
176 | case PMBUS_VIRT_READ_TEMP2_MAX: | ||
177 | case PMBUS_VIRT_RESET_TEMP2_HISTORY: | ||
178 | ret = -ENXIO; | ||
179 | break; | ||
180 | default: | ||
181 | ret = ltc2978_read_word_data_common(client, page, reg); | ||
182 | break; | ||
183 | } | ||
184 | return ret; | ||
185 | } | ||
186 | |||
187 | static int ltc3880_read_word_data(struct i2c_client *client, int page, int reg) | ||
188 | { | ||
189 | const struct pmbus_driver_info *info = pmbus_get_driver_info(client); | ||
190 | struct ltc2978_data *data = to_ltc2978_data(info); | ||
191 | int ret; | ||
192 | |||
193 | switch (reg) { | ||
194 | case PMBUS_VIRT_READ_IOUT_MAX: | ||
195 | ret = pmbus_read_word_data(client, page, LTC3880_MFR_IOUT_PEAK); | ||
196 | if (ret >= 0) { | ||
197 | if (lin11_to_val(ret) | ||
198 | > lin11_to_val(data->iout_max[page])) | ||
199 | data->iout_max[page] = ret; | ||
200 | ret = data->iout_max[page]; | ||
201 | } | ||
202 | break; | ||
203 | case PMBUS_VIRT_READ_TEMP2_MAX: | ||
204 | ret = pmbus_read_word_data(client, page, | ||
205 | LTC3880_MFR_TEMPERATURE2_PEAK); | ||
206 | if (ret >= 0) { | ||
207 | if (lin11_to_val(ret) | ||
208 | > lin11_to_val(data->temp2_max[page])) | ||
209 | data->temp2_max[page] = ret; | ||
210 | ret = data->temp2_max[page]; | ||
211 | } | ||
212 | break; | ||
213 | case PMBUS_VIRT_READ_VIN_MIN: | ||
214 | case PMBUS_VIRT_READ_VOUT_MIN: | ||
215 | case PMBUS_VIRT_READ_TEMP_MIN: | ||
216 | ret = -ENXIO; | ||
217 | break; | ||
218 | case PMBUS_VIRT_RESET_IOUT_HISTORY: | ||
219 | case PMBUS_VIRT_RESET_TEMP2_HISTORY: | ||
220 | ret = 0; | ||
221 | break; | ||
222 | default: | ||
223 | ret = ltc2978_read_word_data_common(client, page, reg); | ||
224 | break; | ||
225 | } | ||
226 | return ret; | ||
227 | } | ||
228 | |||
229 | static int ltc2978_clear_peaks(struct i2c_client *client, int page, | ||
230 | enum chips id) | ||
231 | { | ||
232 | int ret; | ||
233 | |||
234 | if (id == ltc2978) | ||
235 | ret = pmbus_write_byte(client, page, PMBUS_CLEAR_FAULTS); | ||
236 | else | ||
237 | ret = pmbus_write_byte(client, 0, LTC3880_MFR_CLEAR_PEAKS); | ||
238 | |||
239 | return ret; | ||
240 | } | ||
241 | |||
242 | static int ltc2978_write_word_data(struct i2c_client *client, int page, | ||
243 | int reg, u16 word) | ||
244 | { | ||
245 | const struct pmbus_driver_info *info = pmbus_get_driver_info(client); | ||
246 | struct ltc2978_data *data = to_ltc2978_data(info); | ||
247 | int ret; | ||
248 | |||
249 | switch (reg) { | ||
250 | case PMBUS_VIRT_RESET_IOUT_HISTORY: | ||
251 | data->iout_max[page] = 0x7fff; | ||
252 | ret = ltc2978_clear_peaks(client, page, data->id); | ||
253 | break; | ||
254 | case PMBUS_VIRT_RESET_TEMP2_HISTORY: | ||
255 | data->temp2_max[page] = 0x7fff; | ||
256 | ret = ltc2978_clear_peaks(client, page, data->id); | ||
257 | break; | ||
258 | case PMBUS_VIRT_RESET_VOUT_HISTORY: | ||
259 | data->vout_min[page] = 0xffff; | ||
260 | data->vout_max[page] = 0; | ||
261 | ret = ltc2978_clear_peaks(client, page, data->id); | ||
262 | break; | ||
263 | case PMBUS_VIRT_RESET_VIN_HISTORY: | ||
264 | data->vin_min = 0x7bff; | ||
265 | data->vin_max = 0; | ||
266 | ret = ltc2978_clear_peaks(client, page, data->id); | ||
267 | break; | ||
268 | case PMBUS_VIRT_RESET_TEMP_HISTORY: | ||
269 | data->temp_min = 0x7bff; | ||
270 | data->temp_max = 0x7fff; | ||
271 | ret = ltc2978_clear_peaks(client, page, data->id); | ||
272 | break; | ||
273 | default: | ||
274 | ret = -ENODATA; | ||
275 | break; | ||
276 | } | ||
277 | return ret; | ||
278 | } | ||
279 | |||
280 | static const struct i2c_device_id ltc2978_id[] = { | ||
281 | {"ltc2978", ltc2978}, | ||
282 | {"ltc3880", ltc3880}, | ||
283 | {} | ||
284 | }; | ||
285 | MODULE_DEVICE_TABLE(i2c, ltc2978_id); | ||
286 | |||
287 | static int ltc2978_probe(struct i2c_client *client, | ||
288 | const struct i2c_device_id *id) | ||
289 | { | ||
290 | int chip_id, ret, i; | ||
291 | struct ltc2978_data *data; | ||
292 | struct pmbus_driver_info *info; | ||
293 | |||
294 | if (!i2c_check_functionality(client->adapter, | ||
295 | I2C_FUNC_SMBUS_READ_WORD_DATA)) | ||
296 | return -ENODEV; | ||
297 | |||
298 | data = kzalloc(sizeof(struct ltc2978_data), GFP_KERNEL); | ||
299 | if (!data) | ||
300 | return -ENOMEM; | ||
301 | |||
302 | chip_id = i2c_smbus_read_word_data(client, LTC2978_MFR_SPECIAL_ID); | ||
303 | if (chip_id < 0) { | ||
304 | ret = chip_id; | ||
305 | goto err_mem; | ||
306 | } | ||
307 | |||
308 | if (chip_id == LTC2978_ID_REV1 || chip_id == LTC2978_ID_REV2) { | ||
309 | data->id = ltc2978; | ||
310 | } else if ((chip_id & LTC3880_ID_MASK) == LTC3880_ID) { | ||
311 | data->id = ltc3880; | ||
312 | } else { | ||
313 | dev_err(&client->dev, "Unsupported chip ID 0x%x\n", chip_id); | ||
314 | ret = -ENODEV; | ||
315 | goto err_mem; | ||
316 | } | ||
317 | if (data->id != id->driver_data) | ||
318 | dev_warn(&client->dev, | ||
319 | "Device mismatch: Configured %s, detected %s\n", | ||
320 | id->name, | ||
321 | ltc2978_id[data->id].name); | ||
322 | |||
323 | info = &data->info; | ||
324 | info->write_word_data = ltc2978_write_word_data; | ||
325 | |||
326 | data->vout_min[0] = 0xffff; | ||
327 | data->vin_min = 0x7bff; | ||
328 | data->temp_min = 0x7bff; | ||
329 | data->temp_max = 0x7fff; | ||
330 | |||
331 | switch (id->driver_data) { | ||
332 | case ltc2978: | ||
333 | info->read_word_data = ltc2978_read_word_data; | ||
334 | info->pages = 8; | ||
335 | info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT | ||
336 | | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | ||
337 | | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP; | ||
338 | for (i = 1; i < 8; i++) { | ||
339 | info->func[i] = PMBUS_HAVE_VOUT | ||
340 | | PMBUS_HAVE_STATUS_VOUT; | ||
341 | data->vout_min[i] = 0xffff; | ||
342 | } | ||
343 | break; | ||
344 | case ltc3880: | ||
345 | info->read_word_data = ltc3880_read_word_data; | ||
346 | info->pages = 2; | ||
347 | info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_IIN | ||
348 | | PMBUS_HAVE_STATUS_INPUT | ||
349 | | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | ||
350 | | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | ||
351 | | PMBUS_HAVE_POUT | PMBUS_HAVE_TEMP | ||
352 | | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP; | ||
353 | info->func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | ||
354 | | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | ||
355 | | PMBUS_HAVE_POUT | ||
356 | | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP; | ||
357 | data->vout_min[1] = 0xffff; | ||
358 | break; | ||
359 | default: | ||
360 | ret = -ENODEV; | ||
361 | goto err_mem; | ||
362 | } | ||
363 | |||
364 | ret = pmbus_do_probe(client, id, info); | ||
365 | if (ret) | ||
366 | goto err_mem; | ||
367 | return 0; | ||
368 | |||
369 | err_mem: | ||
370 | kfree(data); | ||
371 | return ret; | ||
372 | } | ||
373 | |||
374 | static int ltc2978_remove(struct i2c_client *client) | ||
375 | { | ||
376 | const struct pmbus_driver_info *info = pmbus_get_driver_info(client); | ||
377 | const struct ltc2978_data *data = to_ltc2978_data(info); | ||
378 | |||
379 | pmbus_do_remove(client); | ||
380 | kfree(data); | ||
381 | return 0; | ||
382 | } | ||
383 | |||
384 | /* This is the driver that will be inserted */ | ||
385 | static struct i2c_driver ltc2978_driver = { | ||
386 | .driver = { | ||
387 | .name = "ltc2978", | ||
388 | }, | ||
389 | .probe = ltc2978_probe, | ||
390 | .remove = ltc2978_remove, | ||
391 | .id_table = ltc2978_id, | ||
392 | }; | ||
393 | |||
394 | static int __init ltc2978_init(void) | ||
395 | { | ||
396 | return i2c_add_driver(<c2978_driver); | ||
397 | } | ||
398 | |||
399 | static void __exit ltc2978_exit(void) | ||
400 | { | ||
401 | i2c_del_driver(<c2978_driver); | ||
402 | } | ||
403 | |||
404 | MODULE_AUTHOR("Guenter Roeck"); | ||
405 | MODULE_DESCRIPTION("PMBus driver for LTC2978 and LTC3880"); | ||
406 | MODULE_LICENSE("GPL"); | ||
407 | module_init(ltc2978_init); | ||
408 | module_exit(ltc2978_exit); | ||
diff --git a/drivers/hwmon/pmbus/max16064.c b/drivers/hwmon/pmbus/max16064.c index e50b296e8db4..1d77cf4d2d44 100644 --- a/drivers/hwmon/pmbus/max16064.c +++ b/drivers/hwmon/pmbus/max16064.c | |||
@@ -105,7 +105,8 @@ static int max16064_probe(struct i2c_client *client, | |||
105 | 105 | ||
106 | static int max16064_remove(struct i2c_client *client) | 106 | static int max16064_remove(struct i2c_client *client) |
107 | { | 107 | { |
108 | return pmbus_do_remove(client); | 108 | pmbus_do_remove(client); |
109 | return 0; | ||
109 | } | 110 | } |
110 | 111 | ||
111 | static const struct i2c_device_id max16064_id[] = { | 112 | static const struct i2c_device_id max16064_id[] = { |
diff --git a/drivers/hwmon/pmbus/max34440.c b/drivers/hwmon/pmbus/max34440.c index fda621d2e458..beaf5a8d9c45 100644 --- a/drivers/hwmon/pmbus/max34440.c +++ b/drivers/hwmon/pmbus/max34440.c | |||
@@ -93,12 +93,14 @@ static int max34440_write_word_data(struct i2c_client *client, int page, | |||
93 | 93 | ||
94 | 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) |
95 | { | 95 | { |
96 | int ret; | 96 | int ret = 0; |
97 | int mfg_status; | 97 | int mfg_status; |
98 | 98 | ||
99 | ret = pmbus_set_page(client, page); | 99 | if (page >= 0) { |
100 | if (ret < 0) | 100 | ret = pmbus_set_page(client, page); |
101 | return ret; | 101 | if (ret < 0) |
102 | return ret; | ||
103 | } | ||
102 | 104 | ||
103 | switch (reg) { | 105 | switch (reg) { |
104 | case PMBUS_STATUS_IOUT: | 106 | case PMBUS_STATUS_IOUT: |
@@ -224,7 +226,8 @@ static int max34440_probe(struct i2c_client *client, | |||
224 | 226 | ||
225 | static int max34440_remove(struct i2c_client *client) | 227 | static int max34440_remove(struct i2c_client *client) |
226 | { | 228 | { |
227 | return pmbus_do_remove(client); | 229 | pmbus_do_remove(client); |
230 | return 0; | ||
228 | } | 231 | } |
229 | 232 | ||
230 | static const struct i2c_device_id max34440_id[] = { | 233 | static const struct i2c_device_id max34440_id[] = { |
diff --git a/drivers/hwmon/pmbus/max8688.c b/drivers/hwmon/pmbus/max8688.c index c3e72f1a3cfb..e2b74bb399ba 100644 --- a/drivers/hwmon/pmbus/max8688.c +++ b/drivers/hwmon/pmbus/max8688.c | |||
@@ -45,7 +45,7 @@ static int max8688_read_word_data(struct i2c_client *client, int page, int reg) | |||
45 | int ret; | 45 | int ret; |
46 | 46 | ||
47 | if (page) | 47 | if (page) |
48 | return -EINVAL; | 48 | return -ENXIO; |
49 | 49 | ||
50 | switch (reg) { | 50 | switch (reg) { |
51 | case PMBUS_VIRT_READ_VOUT_MAX: | 51 | case PMBUS_VIRT_READ_VOUT_MAX: |
@@ -101,8 +101,8 @@ static int max8688_read_byte_data(struct i2c_client *client, int page, int reg) | |||
101 | int ret = 0; | 101 | int ret = 0; |
102 | int mfg_status; | 102 | int mfg_status; |
103 | 103 | ||
104 | if (page) | 104 | if (page > 0) |
105 | return -EINVAL; | 105 | return -ENXIO; |
106 | 106 | ||
107 | switch (reg) { | 107 | switch (reg) { |
108 | case PMBUS_STATUS_VOUT: | 108 | case PMBUS_STATUS_VOUT: |
@@ -182,7 +182,8 @@ static int max8688_probe(struct i2c_client *client, | |||
182 | 182 | ||
183 | static int max8688_remove(struct i2c_client *client) | 183 | static int max8688_remove(struct i2c_client *client) |
184 | { | 184 | { |
185 | return pmbus_do_remove(client); | 185 | pmbus_do_remove(client); |
186 | return 0; | ||
186 | } | 187 | } |
187 | 188 | ||
188 | static const struct i2c_device_id max8688_id[] = { | 189 | static const struct i2c_device_id max8688_id[] = { |
diff --git a/drivers/hwmon/pmbus/pmbus.c b/drivers/hwmon/pmbus/pmbus.c index 73de9f1f3194..995e873197e3 100644 --- a/drivers/hwmon/pmbus/pmbus.c +++ b/drivers/hwmon/pmbus/pmbus.c | |||
@@ -187,13 +187,12 @@ out: | |||
187 | 187 | ||
188 | static int pmbus_remove(struct i2c_client *client) | 188 | static int pmbus_remove(struct i2c_client *client) |
189 | { | 189 | { |
190 | int ret; | ||
191 | const struct pmbus_driver_info *info; | 190 | const struct pmbus_driver_info *info; |
192 | 191 | ||
193 | info = pmbus_get_driver_info(client); | 192 | info = pmbus_get_driver_info(client); |
194 | ret = pmbus_do_remove(client); | 193 | pmbus_do_remove(client); |
195 | kfree(info); | 194 | kfree(info); |
196 | return ret; | 195 | return 0; |
197 | } | 196 | } |
198 | 197 | ||
199 | /* | 198 | /* |
@@ -205,10 +204,13 @@ static const struct i2c_device_id pmbus_id[] = { | |||
205 | {"bmr451", 1}, | 204 | {"bmr451", 1}, |
206 | {"bmr453", 1}, | 205 | {"bmr453", 1}, |
207 | {"bmr454", 1}, | 206 | {"bmr454", 1}, |
208 | {"ltc2978", 8}, | ||
209 | {"ncp4200", 1}, | 207 | {"ncp4200", 1}, |
210 | {"ncp4208", 1}, | 208 | {"ncp4208", 1}, |
209 | {"pdt003", 1}, | ||
210 | {"pdt006", 1}, | ||
211 | {"pdt012", 1}, | ||
211 | {"pmbus", 0}, | 212 | {"pmbus", 0}, |
213 | {"udt020", 1}, | ||
212 | {} | 214 | {} |
213 | }; | 215 | }; |
214 | 216 | ||
diff --git a/drivers/hwmon/pmbus/pmbus.h b/drivers/hwmon/pmbus/pmbus.h index a6ae20ffef6b..5d31d1c2c0f5 100644 --- a/drivers/hwmon/pmbus/pmbus.h +++ b/drivers/hwmon/pmbus/pmbus.h | |||
@@ -134,8 +134,16 @@ | |||
134 | * Semantics: | 134 | * Semantics: |
135 | * Virtual registers are all word size. | 135 | * Virtual registers are all word size. |
136 | * READ registers are read-only; writes are either ignored or return an error. | 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), | 137 | * RESET registers are read/write. Reading reset registers returns zero |
138 | * writing any value causes the associated history to be reset. | 138 | * (used for detection), writing any value causes the associated history to be |
139 | * reset. | ||
140 | * Virtual registers have to be handled in device specific driver code. Chip | ||
141 | * driver code returns non-negative register values if a virtual register is | ||
142 | * supported, or a negative error code if not. The chip driver may return | ||
143 | * -ENODATA or any other error code in this case, though an error code other | ||
144 | * than -ENODATA is handled more efficiently and thus preferred. Either case, | ||
145 | * the calling PMBus core code will abort if the chip driver returns an error | ||
146 | * code when reading or writing virtual registers. | ||
139 | */ | 147 | */ |
140 | #define PMBUS_VIRT_BASE 0x100 | 148 | #define PMBUS_VIRT_BASE 0x100 |
141 | #define PMBUS_VIRT_READ_TEMP_MIN (PMBUS_VIRT_BASE + 0) | 149 | #define PMBUS_VIRT_READ_TEMP_MIN (PMBUS_VIRT_BASE + 0) |
@@ -160,6 +168,9 @@ | |||
160 | #define PMBUS_VIRT_READ_IOUT_MIN (PMBUS_VIRT_BASE + 19) | 168 | #define PMBUS_VIRT_READ_IOUT_MIN (PMBUS_VIRT_BASE + 19) |
161 | #define PMBUS_VIRT_READ_IOUT_MAX (PMBUS_VIRT_BASE + 20) | 169 | #define PMBUS_VIRT_READ_IOUT_MAX (PMBUS_VIRT_BASE + 20) |
162 | #define PMBUS_VIRT_RESET_IOUT_HISTORY (PMBUS_VIRT_BASE + 21) | 170 | #define PMBUS_VIRT_RESET_IOUT_HISTORY (PMBUS_VIRT_BASE + 21) |
171 | #define PMBUS_VIRT_READ_TEMP2_MIN (PMBUS_VIRT_BASE + 22) | ||
172 | #define PMBUS_VIRT_READ_TEMP2_MAX (PMBUS_VIRT_BASE + 23) | ||
173 | #define PMBUS_VIRT_RESET_TEMP2_HISTORY (PMBUS_VIRT_BASE + 24) | ||
163 | 174 | ||
164 | /* | 175 | /* |
165 | * CAPABILITY | 176 | * CAPABILITY |
@@ -320,6 +331,12 @@ struct pmbus_driver_info { | |||
320 | * The following functions map manufacturing specific register values | 331 | * The following functions map manufacturing specific register values |
321 | * to PMBus standard register values. Specify only if mapping is | 332 | * to PMBus standard register values. Specify only if mapping is |
322 | * necessary. | 333 | * necessary. |
334 | * Functions return the register value (read) or zero (write) if | ||
335 | * successful. A return value of -ENODATA indicates that there is no | ||
336 | * manufacturer specific register, but that a standard PMBus register | ||
337 | * may exist. Any other negative return value indicates that the | ||
338 | * register does not exist, and that no attempt should be made to read | ||
339 | * the standard register. | ||
323 | */ | 340 | */ |
324 | int (*read_byte_data)(struct i2c_client *client, int page, int reg); | 341 | 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); | 342 | int (*read_word_data)(struct i2c_client *client, int page, int reg); |
@@ -347,7 +364,7 @@ bool pmbus_check_byte_register(struct i2c_client *client, int page, int reg); | |||
347 | bool pmbus_check_word_register(struct i2c_client *client, int page, int reg); | 364 | bool pmbus_check_word_register(struct i2c_client *client, int page, int reg); |
348 | int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id, | 365 | int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id, |
349 | struct pmbus_driver_info *info); | 366 | struct pmbus_driver_info *info); |
350 | int pmbus_do_remove(struct i2c_client *client); | 367 | void pmbus_do_remove(struct i2c_client *client); |
351 | const struct pmbus_driver_info *pmbus_get_driver_info(struct i2c_client | 368 | const struct pmbus_driver_info *pmbus_get_driver_info(struct i2c_client |
352 | *client); | 369 | *client); |
353 | 370 | ||
diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c index 397fc59b5682..00460d8d8423 100644 --- a/drivers/hwmon/pmbus/pmbus_core.c +++ b/drivers/hwmon/pmbus/pmbus_core.c | |||
@@ -160,7 +160,7 @@ int pmbus_set_page(struct i2c_client *client, u8 page) | |||
160 | rv = i2c_smbus_write_byte_data(client, PMBUS_PAGE, page); | 160 | rv = i2c_smbus_write_byte_data(client, PMBUS_PAGE, page); |
161 | newpage = i2c_smbus_read_byte_data(client, PMBUS_PAGE); | 161 | newpage = i2c_smbus_read_byte_data(client, PMBUS_PAGE); |
162 | if (newpage != page) | 162 | if (newpage != page) |
163 | rv = -EINVAL; | 163 | rv = -EIO; |
164 | else | 164 | else |
165 | data->currpage = page; | 165 | data->currpage = page; |
166 | } | 166 | } |
@@ -229,7 +229,7 @@ static int _pmbus_write_word_data(struct i2c_client *client, int page, int reg, | |||
229 | return status; | 229 | return status; |
230 | } | 230 | } |
231 | if (reg >= PMBUS_VIRT_BASE) | 231 | if (reg >= PMBUS_VIRT_BASE) |
232 | return -EINVAL; | 232 | return -ENXIO; |
233 | return pmbus_write_word_data(client, page, reg, word); | 233 | return pmbus_write_word_data(client, page, reg, word); |
234 | } | 234 | } |
235 | 235 | ||
@@ -261,7 +261,7 @@ static int _pmbus_read_word_data(struct i2c_client *client, int page, int reg) | |||
261 | return status; | 261 | return status; |
262 | } | 262 | } |
263 | if (reg >= PMBUS_VIRT_BASE) | 263 | if (reg >= PMBUS_VIRT_BASE) |
264 | return -EINVAL; | 264 | return -ENXIO; |
265 | return pmbus_read_word_data(client, page, reg); | 265 | return pmbus_read_word_data(client, page, reg); |
266 | } | 266 | } |
267 | 267 | ||
@@ -316,11 +316,11 @@ static int pmbus_check_status_cml(struct i2c_client *client) | |||
316 | { | 316 | { |
317 | int status, status2; | 317 | int status, status2; |
318 | 318 | ||
319 | status = pmbus_read_byte_data(client, -1, PMBUS_STATUS_BYTE); | 319 | status = _pmbus_read_byte_data(client, -1, PMBUS_STATUS_BYTE); |
320 | if (status < 0 || (status & PB_STATUS_CML)) { | 320 | if (status < 0 || (status & PB_STATUS_CML)) { |
321 | status2 = pmbus_read_byte_data(client, -1, PMBUS_STATUS_CML); | 321 | status2 = _pmbus_read_byte_data(client, -1, PMBUS_STATUS_CML); |
322 | if (status2 < 0 || (status2 & PB_CML_FAULT_INVALID_COMMAND)) | 322 | if (status2 < 0 || (status2 & PB_CML_FAULT_INVALID_COMMAND)) |
323 | return -EINVAL; | 323 | return -EIO; |
324 | } | 324 | } |
325 | return 0; | 325 | return 0; |
326 | } | 326 | } |
@@ -371,8 +371,8 @@ static struct pmbus_data *pmbus_update_device(struct device *dev) | |||
371 | 371 | ||
372 | for (i = 0; i < info->pages; i++) | 372 | for (i = 0; i < info->pages; i++) |
373 | data->status[PB_STATUS_BASE + i] | 373 | data->status[PB_STATUS_BASE + i] |
374 | = pmbus_read_byte_data(client, i, | 374 | = _pmbus_read_byte_data(client, i, |
375 | PMBUS_STATUS_BYTE); | 375 | PMBUS_STATUS_BYTE); |
376 | for (i = 0; i < info->pages; i++) { | 376 | for (i = 0; i < info->pages; i++) { |
377 | if (!(info->func[i] & PMBUS_HAVE_STATUS_VOUT)) | 377 | if (!(info->func[i] & PMBUS_HAVE_STATUS_VOUT)) |
378 | continue; | 378 | continue; |
@@ -445,13 +445,8 @@ static long pmbus_reg2data_linear(struct pmbus_data *data, | |||
445 | exponent = data->exponent; | 445 | exponent = data->exponent; |
446 | mantissa = (u16) sensor->data; | 446 | mantissa = (u16) sensor->data; |
447 | } else { /* LINEAR11 */ | 447 | } else { /* LINEAR11 */ |
448 | exponent = (sensor->data >> 11) & 0x001f; | 448 | exponent = ((s16)sensor->data) >> 11; |
449 | mantissa = sensor->data & 0x07ff; | 449 | mantissa = ((s16)((sensor->data & 0x7ff) << 5)) >> 5; |
450 | |||
451 | if (exponent > 0x0f) | ||
452 | exponent |= 0xffe0; /* sign extend exponent */ | ||
453 | if (mantissa > 0x03ff) | ||
454 | mantissa |= 0xfffff800; /* sign extend mantissa */ | ||
455 | } | 450 | } |
456 | 451 | ||
457 | val = mantissa; | 452 | val = mantissa; |
@@ -1401,7 +1396,42 @@ static const struct pmbus_limit_attr temp_limit_attrs[] = { | |||
1401 | } | 1396 | } |
1402 | }; | 1397 | }; |
1403 | 1398 | ||
1404 | static const struct pmbus_limit_attr temp_limit_attrs23[] = { | 1399 | static const struct pmbus_limit_attr temp_limit_attrs2[] = { |
1400 | { | ||
1401 | .reg = PMBUS_UT_WARN_LIMIT, | ||
1402 | .low = true, | ||
1403 | .attr = "min", | ||
1404 | .alarm = "min_alarm", | ||
1405 | .sbit = PB_TEMP_UT_WARNING, | ||
1406 | }, { | ||
1407 | .reg = PMBUS_UT_FAULT_LIMIT, | ||
1408 | .low = true, | ||
1409 | .attr = "lcrit", | ||
1410 | .alarm = "lcrit_alarm", | ||
1411 | .sbit = PB_TEMP_UT_FAULT, | ||
1412 | }, { | ||
1413 | .reg = PMBUS_OT_WARN_LIMIT, | ||
1414 | .attr = "max", | ||
1415 | .alarm = "max_alarm", | ||
1416 | .sbit = PB_TEMP_OT_WARNING, | ||
1417 | }, { | ||
1418 | .reg = PMBUS_OT_FAULT_LIMIT, | ||
1419 | .attr = "crit", | ||
1420 | .alarm = "crit_alarm", | ||
1421 | .sbit = PB_TEMP_OT_FAULT, | ||
1422 | }, { | ||
1423 | .reg = PMBUS_VIRT_READ_TEMP2_MIN, | ||
1424 | .attr = "lowest", | ||
1425 | }, { | ||
1426 | .reg = PMBUS_VIRT_READ_TEMP2_MAX, | ||
1427 | .attr = "highest", | ||
1428 | }, { | ||
1429 | .reg = PMBUS_VIRT_RESET_TEMP2_HISTORY, | ||
1430 | .attr = "reset_history", | ||
1431 | } | ||
1432 | }; | ||
1433 | |||
1434 | static const struct pmbus_limit_attr temp_limit_attrs3[] = { | ||
1405 | { | 1435 | { |
1406 | .reg = PMBUS_UT_WARN_LIMIT, | 1436 | .reg = PMBUS_UT_WARN_LIMIT, |
1407 | .low = true, | 1437 | .low = true, |
@@ -1450,8 +1480,8 @@ static const struct pmbus_sensor_attr temp_attributes[] = { | |||
1450 | .sfunc = PMBUS_HAVE_STATUS_TEMP, | 1480 | .sfunc = PMBUS_HAVE_STATUS_TEMP, |
1451 | .sbase = PB_STATUS_TEMP_BASE, | 1481 | .sbase = PB_STATUS_TEMP_BASE, |
1452 | .gbit = PB_STATUS_TEMPERATURE, | 1482 | .gbit = PB_STATUS_TEMPERATURE, |
1453 | .limit = temp_limit_attrs23, | 1483 | .limit = temp_limit_attrs2, |
1454 | .nlimit = ARRAY_SIZE(temp_limit_attrs23), | 1484 | .nlimit = ARRAY_SIZE(temp_limit_attrs2), |
1455 | }, { | 1485 | }, { |
1456 | .reg = PMBUS_READ_TEMPERATURE_3, | 1486 | .reg = PMBUS_READ_TEMPERATURE_3, |
1457 | .class = PSC_TEMPERATURE, | 1487 | .class = PSC_TEMPERATURE, |
@@ -1462,8 +1492,8 @@ static const struct pmbus_sensor_attr temp_attributes[] = { | |||
1462 | .sfunc = PMBUS_HAVE_STATUS_TEMP, | 1492 | .sfunc = PMBUS_HAVE_STATUS_TEMP, |
1463 | .sbase = PB_STATUS_TEMP_BASE, | 1493 | .sbase = PB_STATUS_TEMP_BASE, |
1464 | .gbit = PB_STATUS_TEMPERATURE, | 1494 | .gbit = PB_STATUS_TEMPERATURE, |
1465 | .limit = temp_limit_attrs23, | 1495 | .limit = temp_limit_attrs3, |
1466 | .nlimit = ARRAY_SIZE(temp_limit_attrs23), | 1496 | .nlimit = ARRAY_SIZE(temp_limit_attrs3), |
1467 | } | 1497 | } |
1468 | }; | 1498 | }; |
1469 | 1499 | ||
@@ -1593,10 +1623,10 @@ static void pmbus_find_attributes(struct i2c_client *client, | |||
1593 | static int pmbus_identify_common(struct i2c_client *client, | 1623 | static int pmbus_identify_common(struct i2c_client *client, |
1594 | struct pmbus_data *data) | 1624 | struct pmbus_data *data) |
1595 | { | 1625 | { |
1596 | int vout_mode = -1, exponent; | 1626 | int vout_mode = -1; |
1597 | 1627 | ||
1598 | if (pmbus_check_byte_register(client, 0, PMBUS_VOUT_MODE)) | 1628 | if (pmbus_check_byte_register(client, 0, PMBUS_VOUT_MODE)) |
1599 | vout_mode = pmbus_read_byte_data(client, 0, PMBUS_VOUT_MODE); | 1629 | vout_mode = _pmbus_read_byte_data(client, 0, PMBUS_VOUT_MODE); |
1600 | if (vout_mode >= 0 && vout_mode != 0xff) { | 1630 | if (vout_mode >= 0 && vout_mode != 0xff) { |
1601 | /* | 1631 | /* |
1602 | * Not all chips support the VOUT_MODE command, | 1632 | * Not all chips support the VOUT_MODE command, |
@@ -1607,11 +1637,7 @@ static int pmbus_identify_common(struct i2c_client *client, | |||
1607 | if (data->info->format[PSC_VOLTAGE_OUT] != linear) | 1637 | if (data->info->format[PSC_VOLTAGE_OUT] != linear) |
1608 | return -ENODEV; | 1638 | return -ENODEV; |
1609 | 1639 | ||
1610 | exponent = vout_mode & 0x1f; | 1640 | data->exponent = ((s8)(vout_mode << 3)) >> 3; |
1611 | /* and sign-extend it */ | ||
1612 | if (exponent & 0x10) | ||
1613 | exponent |= ~0x1f; | ||
1614 | data->exponent = exponent; | ||
1615 | break; | 1641 | break; |
1616 | case 1: /* VID mode */ | 1642 | case 1: /* VID mode */ |
1617 | if (data->info->format[PSC_VOLTAGE_OUT] != vid) | 1643 | if (data->info->format[PSC_VOLTAGE_OUT] != vid) |
@@ -1682,7 +1708,7 @@ int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id, | |||
1682 | if (info->pages <= 0 || info->pages > PMBUS_PAGES) { | 1708 | if (info->pages <= 0 || info->pages > PMBUS_PAGES) { |
1683 | dev_err(&client->dev, "Bad number of PMBus pages: %d\n", | 1709 | dev_err(&client->dev, "Bad number of PMBus pages: %d\n", |
1684 | info->pages); | 1710 | info->pages); |
1685 | ret = -EINVAL; | 1711 | ret = -ENODEV; |
1686 | goto out_data; | 1712 | goto out_data; |
1687 | } | 1713 | } |
1688 | 1714 | ||
@@ -1764,7 +1790,7 @@ out_data: | |||
1764 | } | 1790 | } |
1765 | EXPORT_SYMBOL_GPL(pmbus_do_probe); | 1791 | EXPORT_SYMBOL_GPL(pmbus_do_probe); |
1766 | 1792 | ||
1767 | int pmbus_do_remove(struct i2c_client *client) | 1793 | void pmbus_do_remove(struct i2c_client *client) |
1768 | { | 1794 | { |
1769 | struct pmbus_data *data = i2c_get_clientdata(client); | 1795 | struct pmbus_data *data = i2c_get_clientdata(client); |
1770 | hwmon_device_unregister(data->hwmon_dev); | 1796 | hwmon_device_unregister(data->hwmon_dev); |
@@ -1774,7 +1800,6 @@ int pmbus_do_remove(struct i2c_client *client) | |||
1774 | kfree(data->booleans); | 1800 | kfree(data->booleans); |
1775 | kfree(data->sensors); | 1801 | kfree(data->sensors); |
1776 | kfree(data); | 1802 | kfree(data); |
1777 | return 0; | ||
1778 | } | 1803 | } |
1779 | EXPORT_SYMBOL_GPL(pmbus_do_remove); | 1804 | EXPORT_SYMBOL_GPL(pmbus_do_remove); |
1780 | 1805 | ||
diff --git a/drivers/hwmon/pmbus/ucd9000.c b/drivers/hwmon/pmbus/ucd9000.c index d0ddb60155c9..4ff6cf289f85 100644 --- a/drivers/hwmon/pmbus/ucd9000.c +++ b/drivers/hwmon/pmbus/ucd9000.c | |||
@@ -74,8 +74,8 @@ static int ucd9000_read_byte_data(struct i2c_client *client, int page, int reg) | |||
74 | 74 | ||
75 | switch (reg) { | 75 | switch (reg) { |
76 | case PMBUS_FAN_CONFIG_12: | 76 | case PMBUS_FAN_CONFIG_12: |
77 | if (page) | 77 | if (page > 0) |
78 | return -EINVAL; | 78 | return -ENXIO; |
79 | 79 | ||
80 | ret = ucd9000_get_fan_config(client, 0); | 80 | ret = ucd9000_get_fan_config(client, 0); |
81 | if (ret < 0) | 81 | if (ret < 0) |
@@ -88,8 +88,8 @@ static int ucd9000_read_byte_data(struct i2c_client *client, int page, int reg) | |||
88 | ret = fan_config; | 88 | ret = fan_config; |
89 | break; | 89 | break; |
90 | case PMBUS_FAN_CONFIG_34: | 90 | case PMBUS_FAN_CONFIG_34: |
91 | if (page) | 91 | if (page > 0) |
92 | return -EINVAL; | 92 | return -ENXIO; |
93 | 93 | ||
94 | ret = ucd9000_get_fan_config(client, 2); | 94 | ret = ucd9000_get_fan_config(client, 2); |
95 | if (ret < 0) | 95 | if (ret < 0) |
@@ -239,13 +239,12 @@ out: | |||
239 | 239 | ||
240 | static int ucd9000_remove(struct i2c_client *client) | 240 | static int ucd9000_remove(struct i2c_client *client) |
241 | { | 241 | { |
242 | int ret; | ||
243 | struct ucd9000_data *data; | 242 | struct ucd9000_data *data; |
244 | 243 | ||
245 | data = to_ucd9000_data(pmbus_get_driver_info(client)); | 244 | data = to_ucd9000_data(pmbus_get_driver_info(client)); |
246 | ret = pmbus_do_remove(client); | 245 | pmbus_do_remove(client); |
247 | kfree(data); | 246 | kfree(data); |
248 | return ret; | 247 | return 0; |
249 | } | 248 | } |
250 | 249 | ||
251 | 250 | ||
diff --git a/drivers/hwmon/pmbus/ucd9200.c b/drivers/hwmon/pmbus/ucd9200.c index c65e9da707cc..6e1c1a80ab85 100644 --- a/drivers/hwmon/pmbus/ucd9200.c +++ b/drivers/hwmon/pmbus/ucd9200.c | |||
@@ -171,13 +171,12 @@ out: | |||
171 | 171 | ||
172 | static int ucd9200_remove(struct i2c_client *client) | 172 | static int ucd9200_remove(struct i2c_client *client) |
173 | { | 173 | { |
174 | int ret; | ||
175 | const struct pmbus_driver_info *info; | 174 | const struct pmbus_driver_info *info; |
176 | 175 | ||
177 | info = pmbus_get_driver_info(client); | 176 | info = pmbus_get_driver_info(client); |
178 | ret = pmbus_do_remove(client); | 177 | pmbus_do_remove(client); |
179 | kfree(info); | 178 | kfree(info); |
180 | return ret; | 179 | return 0; |
181 | } | 180 | } |
182 | 181 | ||
183 | 182 | ||
diff --git a/drivers/hwmon/pmbus/zl6100.c b/drivers/hwmon/pmbus/zl6100.c new file mode 100644 index 000000000000..2bc980006f83 --- /dev/null +++ b/drivers/hwmon/pmbus/zl6100.c | |||
@@ -0,0 +1,256 @@ | |||
1 | /* | ||
2 | * Hardware monitoring driver for ZL6100 and compatibles | ||
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 <linux/ktime.h> | ||
28 | #include <linux/delay.h> | ||
29 | #include "pmbus.h" | ||
30 | |||
31 | enum chips { zl2004, zl2006, zl2008, zl2105, zl2106, zl6100, zl6105 }; | ||
32 | |||
33 | struct zl6100_data { | ||
34 | int id; | ||
35 | ktime_t access; /* chip access time */ | ||
36 | struct pmbus_driver_info info; | ||
37 | }; | ||
38 | |||
39 | #define to_zl6100_data(x) container_of(x, struct zl6100_data, info) | ||
40 | |||
41 | #define ZL6100_DEVICE_ID 0xe4 | ||
42 | |||
43 | #define ZL6100_WAIT_TIME 1000 /* uS */ | ||
44 | |||
45 | static ushort delay = ZL6100_WAIT_TIME; | ||
46 | module_param(delay, ushort, 0644); | ||
47 | MODULE_PARM_DESC(delay, "Delay between chip accesses in uS"); | ||
48 | |||
49 | /* Some chips need a delay between accesses */ | ||
50 | static inline void zl6100_wait(const struct zl6100_data *data) | ||
51 | { | ||
52 | if (delay) { | ||
53 | s64 delta = ktime_us_delta(ktime_get(), data->access); | ||
54 | if (delta < delay) | ||
55 | udelay(delay - delta); | ||
56 | } | ||
57 | } | ||
58 | |||
59 | static int zl6100_read_word_data(struct i2c_client *client, int page, int reg) | ||
60 | { | ||
61 | const struct pmbus_driver_info *info = pmbus_get_driver_info(client); | ||
62 | struct zl6100_data *data = to_zl6100_data(info); | ||
63 | int ret; | ||
64 | |||
65 | if (page || reg >= PMBUS_VIRT_BASE) | ||
66 | return -ENXIO; | ||
67 | |||
68 | zl6100_wait(data); | ||
69 | ret = pmbus_read_word_data(client, page, reg); | ||
70 | data->access = ktime_get(); | ||
71 | |||
72 | return ret; | ||
73 | } | ||
74 | |||
75 | static int zl6100_read_byte_data(struct i2c_client *client, int page, int reg) | ||
76 | { | ||
77 | const struct pmbus_driver_info *info = pmbus_get_driver_info(client); | ||
78 | struct zl6100_data *data = to_zl6100_data(info); | ||
79 | int ret; | ||
80 | |||
81 | if (page > 0) | ||
82 | return -ENXIO; | ||
83 | |||
84 | zl6100_wait(data); | ||
85 | ret = pmbus_read_byte_data(client, page, reg); | ||
86 | data->access = ktime_get(); | ||
87 | |||
88 | return ret; | ||
89 | } | ||
90 | |||
91 | static int zl6100_write_word_data(struct i2c_client *client, int page, int reg, | ||
92 | u16 word) | ||
93 | { | ||
94 | const struct pmbus_driver_info *info = pmbus_get_driver_info(client); | ||
95 | struct zl6100_data *data = to_zl6100_data(info); | ||
96 | int ret; | ||
97 | |||
98 | if (page || reg >= PMBUS_VIRT_BASE) | ||
99 | return -ENXIO; | ||
100 | |||
101 | zl6100_wait(data); | ||
102 | ret = pmbus_write_word_data(client, page, reg, word); | ||
103 | data->access = ktime_get(); | ||
104 | |||
105 | return ret; | ||
106 | } | ||
107 | |||
108 | static int zl6100_write_byte(struct i2c_client *client, int page, u8 value) | ||
109 | { | ||
110 | const struct pmbus_driver_info *info = pmbus_get_driver_info(client); | ||
111 | struct zl6100_data *data = to_zl6100_data(info); | ||
112 | int ret; | ||
113 | |||
114 | if (page > 0) | ||
115 | return -ENXIO; | ||
116 | |||
117 | zl6100_wait(data); | ||
118 | ret = pmbus_write_byte(client, page, value); | ||
119 | data->access = ktime_get(); | ||
120 | |||
121 | return ret; | ||
122 | } | ||
123 | |||
124 | static const struct i2c_device_id zl6100_id[] = { | ||
125 | {"zl2004", zl2004}, | ||
126 | {"zl2006", zl2006}, | ||
127 | {"zl2008", zl2008}, | ||
128 | {"zl2105", zl2105}, | ||
129 | {"zl2106", zl2106}, | ||
130 | {"zl6100", zl6100}, | ||
131 | {"zl6105", zl6105}, | ||
132 | { } | ||
133 | }; | ||
134 | MODULE_DEVICE_TABLE(i2c, zl6100_id); | ||
135 | |||
136 | static int zl6100_probe(struct i2c_client *client, | ||
137 | const struct i2c_device_id *id) | ||
138 | { | ||
139 | int ret; | ||
140 | struct zl6100_data *data; | ||
141 | struct pmbus_driver_info *info; | ||
142 | u8 device_id[I2C_SMBUS_BLOCK_MAX + 1]; | ||
143 | const struct i2c_device_id *mid; | ||
144 | |||
145 | if (!i2c_check_functionality(client->adapter, | ||
146 | I2C_FUNC_SMBUS_READ_BYTE_DATA | ||
147 | | I2C_FUNC_SMBUS_READ_BLOCK_DATA)) | ||
148 | return -ENODEV; | ||
149 | |||
150 | ret = i2c_smbus_read_block_data(client, ZL6100_DEVICE_ID, | ||
151 | device_id); | ||
152 | if (ret < 0) { | ||
153 | dev_err(&client->dev, "Failed to read device ID\n"); | ||
154 | return ret; | ||
155 | } | ||
156 | device_id[ret] = '\0'; | ||
157 | dev_info(&client->dev, "Device ID %s\n", device_id); | ||
158 | |||
159 | mid = NULL; | ||
160 | for (mid = zl6100_id; mid->name[0]; mid++) { | ||
161 | if (!strncasecmp(mid->name, device_id, strlen(mid->name))) | ||
162 | break; | ||
163 | } | ||
164 | if (!mid->name[0]) { | ||
165 | dev_err(&client->dev, "Unsupported device\n"); | ||
166 | return -ENODEV; | ||
167 | } | ||
168 | if (id->driver_data != mid->driver_data) | ||
169 | dev_notice(&client->dev, | ||
170 | "Device mismatch: Configured %s, detected %s\n", | ||
171 | id->name, mid->name); | ||
172 | |||
173 | data = kzalloc(sizeof(struct zl6100_data), GFP_KERNEL); | ||
174 | if (!data) | ||
175 | return -ENOMEM; | ||
176 | |||
177 | data->id = mid->driver_data; | ||
178 | |||
179 | /* | ||
180 | * ZL2008, ZL2105, and ZL6100 are known to require a wait time | ||
181 | * between I2C accesses. ZL2004 and ZL6105 are known to be safe. | ||
182 | * | ||
183 | * Only clear the wait time for chips known to be safe. The wait time | ||
184 | * can be cleared later for additional chips if tests show that it | ||
185 | * is not needed (in other words, better be safe than sorry). | ||
186 | */ | ||
187 | if (data->id == zl2004 || data->id == zl6105) | ||
188 | delay = 0; | ||
189 | |||
190 | /* | ||
191 | * Since there was a direct I2C device access above, wait before | ||
192 | * accessing the chip again. | ||
193 | * Set the timestamp, wait, then set it again. This should provide | ||
194 | * enough buffer time to be safe. | ||
195 | */ | ||
196 | data->access = ktime_get(); | ||
197 | zl6100_wait(data); | ||
198 | data->access = ktime_get(); | ||
199 | |||
200 | info = &data->info; | ||
201 | |||
202 | info->pages = 1; | ||
203 | info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT | ||
204 | | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | ||
205 | | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | ||
206 | | PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP; | ||
207 | |||
208 | info->read_word_data = zl6100_read_word_data; | ||
209 | info->read_byte_data = zl6100_read_byte_data; | ||
210 | info->write_word_data = zl6100_write_word_data; | ||
211 | info->write_byte = zl6100_write_byte; | ||
212 | |||
213 | ret = pmbus_do_probe(client, mid, info); | ||
214 | if (ret) | ||
215 | goto err_mem; | ||
216 | return 0; | ||
217 | |||
218 | err_mem: | ||
219 | kfree(data); | ||
220 | return ret; | ||
221 | } | ||
222 | |||
223 | static int zl6100_remove(struct i2c_client *client) | ||
224 | { | ||
225 | const struct pmbus_driver_info *info = pmbus_get_driver_info(client); | ||
226 | const struct zl6100_data *data = to_zl6100_data(info); | ||
227 | |||
228 | pmbus_do_remove(client); | ||
229 | kfree(data); | ||
230 | return 0; | ||
231 | } | ||
232 | |||
233 | static struct i2c_driver zl6100_driver = { | ||
234 | .driver = { | ||
235 | .name = "zl6100", | ||
236 | }, | ||
237 | .probe = zl6100_probe, | ||
238 | .remove = zl6100_remove, | ||
239 | .id_table = zl6100_id, | ||
240 | }; | ||
241 | |||
242 | static int __init zl6100_init(void) | ||
243 | { | ||
244 | return i2c_add_driver(&zl6100_driver); | ||
245 | } | ||
246 | |||
247 | static void __exit zl6100_exit(void) | ||
248 | { | ||
249 | i2c_del_driver(&zl6100_driver); | ||
250 | } | ||
251 | |||
252 | MODULE_AUTHOR("Guenter Roeck"); | ||
253 | MODULE_DESCRIPTION("PMBus driver for ZL6100 and compatibles"); | ||
254 | MODULE_LICENSE("GPL"); | ||
255 | module_init(zl6100_init); | ||
256 | module_exit(zl6100_exit); | ||