]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blob - drivers/hwmon/pmbus/zl6100.c
UBUNTU: [Config] CONFIG_SND_I2S_HI6210_I2S=m
[mirror_ubuntu-artful-kernel.git] / drivers / hwmon / pmbus / zl6100.c
1 /*
2 * Hardware monitoring driver for ZL6100 and compatibles
3 *
4 * Copyright (c) 2011 Ericsson AB.
5 * Copyright (c) 2012 Guenter Roeck
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/bitops.h>
23 #include <linux/kernel.h>
24 #include <linux/module.h>
25 #include <linux/init.h>
26 #include <linux/err.h>
27 #include <linux/slab.h>
28 #include <linux/i2c.h>
29 #include <linux/ktime.h>
30 #include <linux/delay.h>
31 #include "pmbus.h"
32
33 enum chips { zl2004, zl2005, zl2006, zl2008, zl2105, zl2106, zl6100, zl6105,
34 zl9101, zl9117 };
35
36 struct zl6100_data {
37 int id;
38 ktime_t access; /* chip access time */
39 int delay; /* Delay between chip accesses in uS */
40 struct pmbus_driver_info info;
41 };
42
43 #define to_zl6100_data(x) container_of(x, struct zl6100_data, info)
44
45 #define ZL6100_MFR_CONFIG 0xd0
46 #define ZL6100_DEVICE_ID 0xe4
47
48 #define ZL6100_MFR_XTEMP_ENABLE BIT(7)
49
50 #define MFR_VMON_OV_FAULT_LIMIT 0xf5
51 #define MFR_VMON_UV_FAULT_LIMIT 0xf6
52 #define MFR_READ_VMON 0xf7
53
54 #define VMON_UV_WARNING BIT(5)
55 #define VMON_OV_WARNING BIT(4)
56 #define VMON_UV_FAULT BIT(1)
57 #define VMON_OV_FAULT BIT(0)
58
59 #define ZL6100_WAIT_TIME 1000 /* uS */
60
61 static ushort delay = ZL6100_WAIT_TIME;
62 module_param(delay, ushort, 0644);
63 MODULE_PARM_DESC(delay, "Delay between chip accesses in uS");
64
65 /* Convert linear sensor value to milli-units */
66 static long zl6100_l2d(s16 l)
67 {
68 s16 exponent;
69 s32 mantissa;
70 long val;
71
72 exponent = l >> 11;
73 mantissa = ((s16)((l & 0x7ff) << 5)) >> 5;
74
75 val = mantissa;
76
77 /* scale result to milli-units */
78 val = val * 1000L;
79
80 if (exponent >= 0)
81 val <<= exponent;
82 else
83 val >>= -exponent;
84
85 return val;
86 }
87
88 #define MAX_MANTISSA (1023 * 1000)
89 #define MIN_MANTISSA (511 * 1000)
90
91 static u16 zl6100_d2l(long val)
92 {
93 s16 exponent = 0, mantissa;
94 bool negative = false;
95
96 /* simple case */
97 if (val == 0)
98 return 0;
99
100 if (val < 0) {
101 negative = true;
102 val = -val;
103 }
104
105 /* Reduce large mantissa until it fits into 10 bit */
106 while (val >= MAX_MANTISSA && exponent < 15) {
107 exponent++;
108 val >>= 1;
109 }
110 /* Increase small mantissa to improve precision */
111 while (val < MIN_MANTISSA && exponent > -15) {
112 exponent--;
113 val <<= 1;
114 }
115
116 /* Convert mantissa from milli-units to units */
117 mantissa = DIV_ROUND_CLOSEST(val, 1000);
118
119 /* Ensure that resulting number is within range */
120 if (mantissa > 0x3ff)
121 mantissa = 0x3ff;
122
123 /* restore sign */
124 if (negative)
125 mantissa = -mantissa;
126
127 /* Convert to 5 bit exponent, 11 bit mantissa */
128 return (mantissa & 0x7ff) | ((exponent << 11) & 0xf800);
129 }
130
131 /* Some chips need a delay between accesses */
132 static inline void zl6100_wait(const struct zl6100_data *data)
133 {
134 if (data->delay) {
135 s64 delta = ktime_us_delta(ktime_get(), data->access);
136 if (delta < data->delay)
137 udelay(data->delay - delta);
138 }
139 }
140
141 static int zl6100_read_word_data(struct i2c_client *client, int page, int reg)
142 {
143 const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
144 struct zl6100_data *data = to_zl6100_data(info);
145 int ret, vreg;
146
147 if (page > 0)
148 return -ENXIO;
149
150 if (data->id == zl2005) {
151 /*
152 * Limit register detection is not reliable on ZL2005.
153 * Make sure registers are not erroneously detected.
154 */
155 switch (reg) {
156 case PMBUS_VOUT_OV_WARN_LIMIT:
157 case PMBUS_VOUT_UV_WARN_LIMIT:
158 case PMBUS_IOUT_OC_WARN_LIMIT:
159 return -ENXIO;
160 }
161 }
162
163 switch (reg) {
164 case PMBUS_VIRT_READ_VMON:
165 vreg = MFR_READ_VMON;
166 break;
167 case PMBUS_VIRT_VMON_OV_WARN_LIMIT:
168 case PMBUS_VIRT_VMON_OV_FAULT_LIMIT:
169 vreg = MFR_VMON_OV_FAULT_LIMIT;
170 break;
171 case PMBUS_VIRT_VMON_UV_WARN_LIMIT:
172 case PMBUS_VIRT_VMON_UV_FAULT_LIMIT:
173 vreg = MFR_VMON_UV_FAULT_LIMIT;
174 break;
175 default:
176 if (reg >= PMBUS_VIRT_BASE)
177 return -ENXIO;
178 vreg = reg;
179 break;
180 }
181
182 zl6100_wait(data);
183 ret = pmbus_read_word_data(client, page, vreg);
184 data->access = ktime_get();
185 if (ret < 0)
186 return ret;
187
188 switch (reg) {
189 case PMBUS_VIRT_VMON_OV_WARN_LIMIT:
190 ret = zl6100_d2l(DIV_ROUND_CLOSEST(zl6100_l2d(ret) * 9, 10));
191 break;
192 case PMBUS_VIRT_VMON_UV_WARN_LIMIT:
193 ret = zl6100_d2l(DIV_ROUND_CLOSEST(zl6100_l2d(ret) * 11, 10));
194 break;
195 }
196
197 return ret;
198 }
199
200 static int zl6100_read_byte_data(struct i2c_client *client, int page, int reg)
201 {
202 const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
203 struct zl6100_data *data = to_zl6100_data(info);
204 int ret, status;
205
206 if (page > 0)
207 return -ENXIO;
208
209 zl6100_wait(data);
210
211 switch (reg) {
212 case PMBUS_VIRT_STATUS_VMON:
213 ret = pmbus_read_byte_data(client, 0,
214 PMBUS_STATUS_MFR_SPECIFIC);
215 if (ret < 0)
216 break;
217
218 status = 0;
219 if (ret & VMON_UV_WARNING)
220 status |= PB_VOLTAGE_UV_WARNING;
221 if (ret & VMON_OV_WARNING)
222 status |= PB_VOLTAGE_OV_WARNING;
223 if (ret & VMON_UV_FAULT)
224 status |= PB_VOLTAGE_UV_FAULT;
225 if (ret & VMON_OV_FAULT)
226 status |= PB_VOLTAGE_OV_FAULT;
227 ret = status;
228 break;
229 default:
230 ret = pmbus_read_byte_data(client, page, reg);
231 break;
232 }
233 data->access = ktime_get();
234
235 return ret;
236 }
237
238 static int zl6100_write_word_data(struct i2c_client *client, int page, int reg,
239 u16 word)
240 {
241 const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
242 struct zl6100_data *data = to_zl6100_data(info);
243 int ret, vreg;
244
245 if (page > 0)
246 return -ENXIO;
247
248 switch (reg) {
249 case PMBUS_VIRT_VMON_OV_WARN_LIMIT:
250 word = zl6100_d2l(DIV_ROUND_CLOSEST(zl6100_l2d(word) * 10, 9));
251 vreg = MFR_VMON_OV_FAULT_LIMIT;
252 pmbus_clear_cache(client);
253 break;
254 case PMBUS_VIRT_VMON_OV_FAULT_LIMIT:
255 vreg = MFR_VMON_OV_FAULT_LIMIT;
256 pmbus_clear_cache(client);
257 break;
258 case PMBUS_VIRT_VMON_UV_WARN_LIMIT:
259 word = zl6100_d2l(DIV_ROUND_CLOSEST(zl6100_l2d(word) * 10, 11));
260 vreg = MFR_VMON_UV_FAULT_LIMIT;
261 pmbus_clear_cache(client);
262 break;
263 case PMBUS_VIRT_VMON_UV_FAULT_LIMIT:
264 vreg = MFR_VMON_UV_FAULT_LIMIT;
265 pmbus_clear_cache(client);
266 break;
267 default:
268 if (reg >= PMBUS_VIRT_BASE)
269 return -ENXIO;
270 vreg = reg;
271 }
272
273 zl6100_wait(data);
274 ret = pmbus_write_word_data(client, page, vreg, word);
275 data->access = ktime_get();
276
277 return ret;
278 }
279
280 static int zl6100_write_byte(struct i2c_client *client, int page, u8 value)
281 {
282 const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
283 struct zl6100_data *data = to_zl6100_data(info);
284 int ret;
285
286 if (page > 0)
287 return -ENXIO;
288
289 zl6100_wait(data);
290 ret = pmbus_write_byte(client, page, value);
291 data->access = ktime_get();
292
293 return ret;
294 }
295
296 static const struct i2c_device_id zl6100_id[] = {
297 {"bmr450", zl2005},
298 {"bmr451", zl2005},
299 {"bmr462", zl2008},
300 {"bmr463", zl2008},
301 {"bmr464", zl2008},
302 {"zl2004", zl2004},
303 {"zl2005", zl2005},
304 {"zl2006", zl2006},
305 {"zl2008", zl2008},
306 {"zl2105", zl2105},
307 {"zl2106", zl2106},
308 {"zl6100", zl6100},
309 {"zl6105", zl6105},
310 {"zl9101", zl9101},
311 {"zl9117", zl9117},
312 { }
313 };
314 MODULE_DEVICE_TABLE(i2c, zl6100_id);
315
316 static int zl6100_probe(struct i2c_client *client,
317 const struct i2c_device_id *id)
318 {
319 int ret;
320 struct zl6100_data *data;
321 struct pmbus_driver_info *info;
322 u8 device_id[I2C_SMBUS_BLOCK_MAX + 1];
323 const struct i2c_device_id *mid;
324
325 if (!i2c_check_functionality(client->adapter,
326 I2C_FUNC_SMBUS_READ_WORD_DATA
327 | I2C_FUNC_SMBUS_READ_BLOCK_DATA))
328 return -ENODEV;
329
330 ret = i2c_smbus_read_block_data(client, ZL6100_DEVICE_ID,
331 device_id);
332 if (ret < 0) {
333 dev_err(&client->dev, "Failed to read device ID\n");
334 return ret;
335 }
336 device_id[ret] = '\0';
337 dev_info(&client->dev, "Device ID %s\n", device_id);
338
339 mid = NULL;
340 for (mid = zl6100_id; mid->name[0]; mid++) {
341 if (!strncasecmp(mid->name, device_id, strlen(mid->name)))
342 break;
343 }
344 if (!mid->name[0]) {
345 dev_err(&client->dev, "Unsupported device\n");
346 return -ENODEV;
347 }
348 if (id->driver_data != mid->driver_data)
349 dev_notice(&client->dev,
350 "Device mismatch: Configured %s, detected %s\n",
351 id->name, mid->name);
352
353 data = devm_kzalloc(&client->dev, sizeof(struct zl6100_data),
354 GFP_KERNEL);
355 if (!data)
356 return -ENOMEM;
357
358 data->id = mid->driver_data;
359
360 /*
361 * According to information from the chip vendor, all currently
362 * supported chips are known to require a wait time between I2C
363 * accesses.
364 */
365 data->delay = delay;
366
367 /*
368 * Since there was a direct I2C device access above, wait before
369 * accessing the chip again.
370 */
371 data->access = ktime_get();
372 zl6100_wait(data);
373
374 info = &data->info;
375
376 info->pages = 1;
377 info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT
378 | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
379 | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT
380 | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
381
382 /*
383 * ZL2004, ZL9101M, and ZL9117M support monitoring an extra voltage
384 * (VMON for ZL2004, VDRV for ZL9101M and ZL9117M). Report it as vmon.
385 */
386 if (data->id == zl2004 || data->id == zl9101 || data->id == zl9117)
387 info->func[0] |= PMBUS_HAVE_VMON | PMBUS_HAVE_STATUS_VMON;
388
389 ret = i2c_smbus_read_word_data(client, ZL6100_MFR_CONFIG);
390 if (ret < 0)
391 return ret;
392
393 if (ret & ZL6100_MFR_XTEMP_ENABLE)
394 info->func[0] |= PMBUS_HAVE_TEMP2;
395
396 data->access = ktime_get();
397 zl6100_wait(data);
398
399 info->read_word_data = zl6100_read_word_data;
400 info->read_byte_data = zl6100_read_byte_data;
401 info->write_word_data = zl6100_write_word_data;
402 info->write_byte = zl6100_write_byte;
403
404 return pmbus_do_probe(client, mid, info);
405 }
406
407 static struct i2c_driver zl6100_driver = {
408 .driver = {
409 .name = "zl6100",
410 },
411 .probe = zl6100_probe,
412 .remove = pmbus_do_remove,
413 .id_table = zl6100_id,
414 };
415
416 module_i2c_driver(zl6100_driver);
417
418 MODULE_AUTHOR("Guenter Roeck");
419 MODULE_DESCRIPTION("PMBus driver for ZL6100 and compatibles");
420 MODULE_LICENSE("GPL");