blob: fc3277fe7ba507ef9e37ab310d7dd9dcdd25ae9e [file] [log] [blame]
David Collinsfc3cde52012-10-19 17:13:48 -07001/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#define pr_fmt(fmt) "%s: " fmt, __func__
14
15#include <linux/i2c.h>
16#include <linux/module.h>
17#include <linux/mutex.h>
18#include <linux/of.h>
19#include <linux/of_device.h>
20#include <linux/power_supply.h>
21#include <linux/slab.h>
22
23struct smb137c_chip {
24 struct i2c_client *client;
25 struct power_supply psy;
26 struct power_supply *usb_psy;
27 struct mutex lock;
28 int charge_current_limit_ua;
29 int input_current_limit_ua;
30 int term_current_ua;
31 bool charging_enabled;
32 bool otg_mode_enabled;
33 bool charging_allowed;
David Collins81fe8a52012-11-16 17:48:06 -080034 bool usb_suspend_enabled;
David Collinsfc3cde52012-10-19 17:13:48 -070035};
36
37struct input_current_config {
38 int current_limit_ua;
39 u8 cmd_b_reg;
40 u8 var_func_reg;
41 u8 input_cur_reg;
42};
43
44struct term_current_config {
45 int term_current_ua;
46 u8 charge_cur_reg;
47};
48
49#define INPUT_CURRENT(_current_limit_ua, _cmd_b_reg, _var_func_reg, \
50 _input_cur_reg) \
51 { \
52 .current_limit_ua = _current_limit_ua, \
53 .cmd_b_reg = _cmd_b_reg, \
54 .var_func_reg = _var_func_reg, \
55 .input_cur_reg = _input_cur_reg, \
56 }
57
58#define CHARGE_CURRENT_REG 0x00
59#define CHARGE_CURRENT_FAST_CHG_MASK 0xE0
60#define CHARGE_CURRENT_FAST_CHG_SHIFT 5
61#define CHARGE_CURRENT_PRE_CHG_MASK 0x18
62#define CHARGE_CURRENT_PRE_CHG_SHIFT 3
63#define CHARGE_CURRENT_TERM_CUR_MASK 0x06
64
65#define INPUT_CURRENT_REG 0x01
66#define INPUT_CURRENT_LIMIT_MASK 0xE0
67
68#define FLOAT_VOLTAGE_REG 0x02
69#define FLOAT_VOLTAGE_MASK 0x7F
70#define FLOAT_VOLTAGE_SHIFT 0
71
72#define CTRL_A_REG 0x03
73#define CTRL_A_AUTO_RECHARGE_MASK 0x80
74#define CTRL_A_AUTO_RECHARGE_ENABLED 0x00
75#define CTRL_A_AUTO_RECHARGE_DISABLED 0x80
76#define CTRL_A_TERM_CUR_MASK 0x40
77#define CTRL_A_TERM_CUR_ENABLED 0x00
78#define CTRL_A_TERM_CUR_DISABLED 0x40
79#define CTRL_A_THRESH_VOLTAGE_MASK 0x38
80#define CTRL_A_THRESH_VOLTAGE_SHIFT 3
81#define CTRL_A_VOUTL_MASK 0x02
82#define CTRL_A_VOUTL_4250MV 0x00
83#define CTRL_A_VOUTL_4460MV 0x02
84#define CTRL_A_THERM_MONITOR_MASK 0x01
85#define CTRL_A_THERM_MONITOR_ENABLED 0x01
86#define CTRL_A_THERM_MONITOR_DISABLED 0x00
87
88#define PIN_CTRL_REG 0x05
89#define PIN_CTRL_DEAD_BATT_CHG_MASK 0x80
90#define PIN_CTRL_DEAD_BATT_CHG_ENABLED 0x80
91#define PIN_CTRL_DEAD_BATT_CHG_DISABLED 0x00
92#define PIN_CTRL_OTG_LBR_MASK 0x20
93#define PIN_CTRL_OTG 0x00
94#define PIN_CTRL_LBR 0x20
95#define PIN_CTRL_USB_CUR_LIMIT_MASK 0x10
96#define PIN_CTRL_USB_CUR_LIMIT_REG 0x00
97#define PIN_CTRL_USB_CUR_LIMIT_PIN 0x10
98#define PIN_CTRL_CHG_EN_MASK 0x0C
99#define PIN_CTRL_CHG_EN_REG_LOW 0x00
100#define PIN_CTRL_CHG_EN_REG_HIGH 0x04
101#define PIN_CTRL_CHG_EN_PIN_LOW 0x08
102#define PIN_CTRL_CHG_EN_PIN_HIGH 0x0C
103#define PIN_CTRL_OTG_CTRL_MASK 0x02
104#define PIN_CTRL_OTG_CTRL_REG 0x00
105#define PIN_CTRL_OTG_CTRL_PIN 0x02
106
107#define OTG_CTRL_REG 0x06
108#define OTG_CTRL_BMD_MASK 0x80
109#define OTG_CTRL_BMD_ENABLED 0x80
110#define OTG_CTRL_BMD_DISABLED 0x00
111#define OTG_CTRL_AUTO_RECHARGE_MASK 0x40
112#define OTG_CTRL_AUTO_RECHARGE_75MV 0x00
113#define OTG_CTRL_AUTO_RECHARGE_120MV 0x40
114
115#define TEMP_MON_REG 0x08
116#define TEMP_MON_THERM_CURRENT_MASK 0xC0
117#define TEMP_MON_THERM_CURRENT_SHIFT 6
118#define TEMP_MON_TEMP_LOW_MASK 0x38
119#define TEMP_MON_TEMP_LOW_SHIFT 3
120#define TEMP_MON_TEMP_HIGH_MASK 0x07
121#define TEMP_MON_TEMP_HIGH_SHIFT 0
122
123#define SAFETY_TIMER_REG 0x09
124#define SAFETY_TIMER_RELOAD_MASK 0x40
125#define SAFETY_TIMER_RELOAD_ENABLED 0x40
126#define SAFETY_TIMER_RELOAD_DISABLED 0x00
127#define SAFETY_TIMER_CHG_TIMEOUT_MASK 0x0C
128#define SAFETY_TIMER_CHG_TIMEOUT_SHIFT 2
129#define SAFETY_TIMER_PRE_CHG_TIME_MASK 0x03
130#define SAFETY_TIMER_PRE_CHG_TIME_SHIFT 0
131
132#define VAR_FUNC_REG 0x0C
133#define VAR_FUNC_USB_MODE_MASK 0x80
David Collins81fe8a52012-11-16 17:48:06 -0800134#define VAR_FUNC_USB_SUSPEND_CTRL_MASK 0x20
135#define VAR_FUNC_USB_SUSPEND_CTRL_REG 0x00
136#define VAR_FUNC_USB_SUSPEND_CTRL_PIN 0x20
David Collinsfc3cde52012-10-19 17:13:48 -0700137#define VAR_FUNC_BMD_MASK 0x0C
138#define VAR_FUNC_BMD_DISABLED 0x00
139#define VAR_FUNC_BMD_ALGO_PERIODIC 0x04
140#define VAR_FUNC_BMD_ALGO 0x08
141#define VAR_FUNC_BMD_THERM 0x0C
142
143#define CMD_A_REG 0x30
144#define CMD_A_VOLATILE_WRITE_MASK 0x80
145#define CMD_A_VOLATILE_WRITE_ALLOW 0x80
146#define CMD_A_VOLATILE_WRITE_DISALLOW 0x00
147#define CMD_A_FAST_CHG_MASK 0x40
148#define CMD_A_FAST_CHG_ALLOW 0x40
149#define CMD_A_FAST_CHG_DISALLOW 0x00
150#define CMD_A_OTG_MASK 0x10
151#define CMD_A_OTG_ENABLED 0x10
152#define CMD_A_OTG_DISABLED 0x00
David Collins81fe8a52012-11-16 17:48:06 -0800153#define CMD_A_USB_SUSPEND_MASK 0x04
154#define CMD_A_USB_SUSPEND_DISABLED 0x00
155#define CMD_A_USB_SUSPEND_ENABLED 0x04
David Collinsfc3cde52012-10-19 17:13:48 -0700156#define CMD_A_CHARGING_MASK 0x02
157#define CMD_A_CHARGING_ENABLED 0x00
158#define CMD_A_CHARGING_DISABLED 0x02
159
160#define CMD_B_REG 0x31
161#define CMD_B_USB_MODE_MASK 0x03
162
163#define DEV_ID_REG 0x33
164#define DEV_ID_PART_MASK 0x80
165#define DEV_ID_PART_SMB137C 0x00
166#define DEV_ID_GUI_REV_MASK 0x70
167#define DEV_ID_GUI_REV_SHIFT 4
168#define DEV_ID_SILICON_REV_MASK 0x0F
169#define DEV_ID_SILICON_REV_SHIFT 0
170
171#define IRQ_STAT_A_REG 0x35
172#define IRQ_STAT_A_BATT_HOT 0x40
173#define IRQ_STAT_A_BATT_COLD 0x10
174
175#define IRQ_STAT_B_REG 0x36
176#define IRQ_STAT_B_BATT_OVERVOLT 0x40
177#define IRQ_STAT_B_BATT_MISSING 0x10
178#define IRQ_STAT_B_BATT_UNDERVOLT 0x04
179
180#define STAT_C_REG 0x3D
181#define STAT_C_CHG_ERROR 0x40
182#define STAT_C_VBATT_LEVEL_BELOW_2P1V 0x10
183#define STAT_C_CHG_STAT_MASK 0x06
184#define STAT_C_CHG_STAT_SHIFT 1
185#define STAT_C_CHG_ENABLED 0x01
186
187/* Charge status register values */
188enum smb137c_charge_status {
189 CHARGE_STAT_NO_CHG = 0,
190 CHARGE_STAT_PRE_CHG = 1,
191 CHARGE_STAT_FAST_CHG = 2,
192 CHARGE_STAT_TAPER_CHG = 3,
193};
194
195#define PRE_CHARGE_CURRENT_MIN_UA 50000
196#define PRE_CHARGE_CURRENT_MAX_UA 200000
197#define PRE_CHARGE_CURRENT_STEP_UA 50000
198
199#define FLOAT_VOLTAGE_MIN_UV 3460000
200#define FLOAT_VOLTAGE_MAX_UV 4730000
201#define FLOAT_VOLTAGE_STEP_UV 10000
202
203#define PRE_CHG_THRESH_VOLTAGE_MIN_UV 2400000
204#define PRE_CHG_THRESH_VOLTAGE_MAX_UV 3100000
205#define PRE_CHG_THRESH_VOLTAGE_STEP_UV 100000
206
207#define USB_MIN_CURRENT_UA 100000
208
209static int smb137c_read_reg(struct smb137c_chip *chip, u8 reg, u8 *val)
210{
211 int rc;
212
213 rc = i2c_smbus_read_byte_data(chip->client, reg);
214 if (rc < 0) {
215 pr_err("i2c_smbus_read_byte_data failed. reg=0x%02X, rc=%d\n",
216 reg, rc);
217 } else {
218 *val = rc;
219 rc = 0;
220 pr_debug("read(0x%02X)=0x%02X\n", reg, *val);
221 }
222
223 return rc;
224}
225
226static int smb137c_write_reg(struct smb137c_chip *chip, u8 reg, u8 val)
227{
228 int rc;
229
230 rc = i2c_smbus_write_byte_data(chip->client, reg, val);
231 if (rc < 0)
232 pr_err("i2c_smbus_write_byte_data failed. reg=0x%02X, rc=%d\n",
233 reg, rc);
234 else
235 pr_debug("write(0x%02X)=0x%02X\n", reg, val);
236
237 return rc;
238}
239
240static int smb137c_masked_write_reg(struct smb137c_chip *chip, u8 reg, u8 mask,
241 u8 val)
242{
243 u8 reg_val;
244 int rc;
245
246 pr_debug("masked write(0x%02X), mask=0x%02X, value=0x%02X\n", reg, mask,
247 val);
248
249 rc = smb137c_read_reg(chip, reg, &reg_val);
250 if (rc < 0)
251 return rc;
252
253 val = (reg_val & ~mask) | (val & mask);
254
255 if (val != reg_val)
256 rc = smb137c_write_reg(chip, reg, val);
257
258 return rc;
259}
260
261static int smb137c_enable_charging(struct smb137c_chip *chip)
262{
263 int rc = 0;
264
265 chip->charging_allowed = true;
266
David Collins81fe8a52012-11-16 17:48:06 -0800267 if (!chip->charging_enabled && chip->charge_current_limit_ua > 0) {
268 rc = smb137c_masked_write_reg(chip, CMD_A_REG,
269 CMD_A_CHARGING_MASK, CMD_A_CHARGING_ENABLED);
David Collinsfc3cde52012-10-19 17:13:48 -0700270 if (!rc)
David Collins81fe8a52012-11-16 17:48:06 -0800271 chip->charging_enabled = true;
David Collinsfc3cde52012-10-19 17:13:48 -0700272 }
273
David Collins81fe8a52012-11-16 17:48:06 -0800274 if (!rc)
275 dev_dbg(&chip->client->dev, "%s\n", __func__);
276
David Collinsfc3cde52012-10-19 17:13:48 -0700277 return rc;
278}
279
280static int smb137c_disable_charging(struct smb137c_chip *chip)
281{
282 int rc = 0;
283
284 chip->charging_allowed = false;
285
286 if (chip->charging_enabled) {
287 rc = smb137c_masked_write_reg(chip, CMD_A_REG,
288 CMD_A_CHARGING_MASK, CMD_A_CHARGING_DISABLED);
David Collins81fe8a52012-11-16 17:48:06 -0800289 if (!rc)
290 chip->charging_enabled = false;
David Collinsfc3cde52012-10-19 17:13:48 -0700291 }
292
David Collinsfc3cde52012-10-19 17:13:48 -0700293 if (!rc)
294 dev_dbg(&chip->client->dev, "%s\n", __func__);
295
296 return rc;
297}
298
299static int smb137c_enable_otg_mode(struct smb137c_chip *chip)
300{
301 int rc = 0;
302
303 if (!chip->otg_mode_enabled) {
304 rc = smb137c_masked_write_reg(chip, CMD_A_REG, CMD_A_OTG_MASK,
305 CMD_A_OTG_ENABLED);
David Collins81fe8a52012-11-16 17:48:06 -0800306 if (!rc)
307 chip->otg_mode_enabled = true;
David Collinsfc3cde52012-10-19 17:13:48 -0700308 }
309
310 if (!rc)
311 dev_dbg(&chip->client->dev, "%s\n", __func__);
312
313 return rc;
314}
315
316static int smb137c_disable_otg_mode(struct smb137c_chip *chip)
317{
318 int rc = 0;
319
320 if (chip->otg_mode_enabled) {
321 rc = smb137c_masked_write_reg(chip, CMD_A_REG, CMD_A_OTG_MASK,
322 CMD_A_OTG_DISABLED);
David Collins81fe8a52012-11-16 17:48:06 -0800323 if (!rc)
324 chip->otg_mode_enabled = false;
325 }
326
327 if (!rc)
328 dev_dbg(&chip->client->dev, "%s\n", __func__);
329
330 return rc;
331}
332
333static int smb137c_enable_usb_suspend(struct smb137c_chip *chip)
334{
335 int rc = 0;
336
337 if (!chip->usb_suspend_enabled) {
338 rc = smb137c_masked_write_reg(chip, CMD_A_REG,
339 CMD_A_USB_SUSPEND_MASK, CMD_A_USB_SUSPEND_ENABLED);
340 if (!rc)
341 chip->usb_suspend_enabled = true;
342 }
343
344 if (!rc)
345 dev_dbg(&chip->client->dev, "%s\n", __func__);
346
347 return rc;
348}
349
350static int smb137c_disable_usb_suspend(struct smb137c_chip *chip)
351{
352 int rc = 0;
353
354 if (chip->input_current_limit_ua > 0 && chip->usb_suspend_enabled) {
355 rc = smb137c_masked_write_reg(chip, CMD_A_REG,
356 CMD_A_USB_SUSPEND_MASK, CMD_A_USB_SUSPEND_DISABLED);
357 if (!rc)
358 chip->usb_suspend_enabled = false;
David Collinsfc3cde52012-10-19 17:13:48 -0700359 }
360
361 if (!rc)
362 dev_dbg(&chip->client->dev, "%s\n", __func__);
363
364 return rc;
365}
366
367static struct input_current_config supported_input_current[] = {
368 INPUT_CURRENT(100000, 0x00, 0x00, 0x00),
369 INPUT_CURRENT(150000, 0x00, 0x80, 0x00),
370 INPUT_CURRENT(500000, 0x02, 0x00, 0x00),
371 INPUT_CURRENT(700000, 0x01, 0x00, 0x00),
372 INPUT_CURRENT(800000, 0x01, 0x00, 0x20),
373 INPUT_CURRENT(900000, 0x01, 0x00, 0x40),
374 INPUT_CURRENT(1000000, 0x01, 0x00, 0x60),
375 INPUT_CURRENT(1100000, 0x01, 0x00, 0x80),
376 INPUT_CURRENT(1200000, 0x01, 0x00, 0xA0),
377 INPUT_CURRENT(1300000, 0x01, 0x00, 0xC0),
378 INPUT_CURRENT(1500000, 0x01, 0x00, 0xE0),
379};
380
381static int smb137c_set_usb_input_current_limit(struct smb137c_chip *chip,
382 int current_limit_ua)
383{
384 struct input_current_config *config = NULL;
385 int rc = 0;
386 int i;
387
388 for (i = ARRAY_SIZE(supported_input_current) - 1; i >= 0; i--) {
389 if (current_limit_ua
390 >= supported_input_current[i].current_limit_ua) {
391 config = &supported_input_current[i];
392 break;
393 }
394 }
395
396 if (config) {
397 if (chip->input_current_limit_ua != config->current_limit_ua) {
398 rc = smb137c_masked_write_reg(chip, INPUT_CURRENT_REG,
399 INPUT_CURRENT_LIMIT_MASK, config->input_cur_reg);
400 if (rc)
401 return rc;
402
403 rc = smb137c_masked_write_reg(chip, VAR_FUNC_REG,
404 VAR_FUNC_USB_MODE_MASK, config->var_func_reg);
405 if (rc)
406 return rc;
407
408 rc = smb137c_masked_write_reg(chip, CMD_B_REG,
409 CMD_B_USB_MODE_MASK, config->cmd_b_reg);
410 if (rc)
411 return rc;
412
413 chip->input_current_limit_ua = config->current_limit_ua;
414 }
415
David Collins81fe8a52012-11-16 17:48:06 -0800416 rc = smb137c_disable_usb_suspend(chip);
David Collinsfc3cde52012-10-19 17:13:48 -0700417 } else {
David Collinsfc3cde52012-10-19 17:13:48 -0700418 chip->input_current_limit_ua = 0;
419
David Collins81fe8a52012-11-16 17:48:06 -0800420 rc = smb137c_enable_usb_suspend(chip);
David Collinsfc3cde52012-10-19 17:13:48 -0700421 }
422
423 if (!rc)
424 dev_dbg(&chip->client->dev, "%s: current=%d uA\n", __func__,
425 chip->input_current_limit_ua);
426
427 return rc;
428}
429
430static int fast_charge_current_ua[] = {
431 500000,
432 650000,
433 750000,
434 850000,
435 950000,
436 1100000,
437 1300000,
438 1500000,
439};
440
441static int smb137c_set_charge_current_limit(struct smb137c_chip *chip,
442 int current_limit_ua)
443{
444 int fast_charge_limit_ua = 0;
445 int rc = 0;
446 u8 val = 0;
447 int i;
448
449 for (i = ARRAY_SIZE(fast_charge_current_ua) - 1; i >= 0; i--) {
450 if (current_limit_ua >= fast_charge_current_ua[i]) {
451 val = i << CHARGE_CURRENT_FAST_CHG_SHIFT;
452 fast_charge_limit_ua = fast_charge_current_ua[i];
453 break;
454 }
455 }
456
457 if (fast_charge_limit_ua
458 && chip->charge_current_limit_ua != fast_charge_limit_ua)
459 rc = smb137c_masked_write_reg(chip, CHARGE_CURRENT_REG,
460 CHARGE_CURRENT_FAST_CHG_MASK, val);
461 else if (fast_charge_limit_ua == 0)
462 rc = smb137c_disable_charging(chip);
463
464 chip->charge_current_limit_ua = fast_charge_limit_ua;
465
466 if (!rc)
467 dev_dbg(&chip->client->dev, "%s: current=%d uA\n", __func__,
468 fast_charge_limit_ua);
469
470 return rc;
471}
472
473static int smb137c_get_charge_current_limit(struct smb137c_chip *chip)
474{
475 int fast_charge_limit_ua = 0;
476 u8 val = 0;
477 int rc, i;
478
479 rc = smb137c_read_reg(chip, CHARGE_CURRENT_REG, &val);
480 if (rc)
481 return rc;
482
483 i = (val & CHARGE_CURRENT_FAST_CHG_MASK)
484 >> CHARGE_CURRENT_FAST_CHG_SHIFT;
485
486 if (i >= 0 && i < ARRAY_SIZE(fast_charge_current_ua))
487 fast_charge_limit_ua = fast_charge_current_ua[i];
488
489 dev_dbg(&chip->client->dev, "%s: current=%d uA\n", __func__,
490 fast_charge_limit_ua);
491
492 return fast_charge_limit_ua;
493}
494
495static struct term_current_config term_current_ua[] = {
496 { 35000, 0x06},
497 { 50000, 0x00},
498 {100000, 0x02},
499 {150000, 0x04},
500};
501
502static int smb137c_set_term_current(struct smb137c_chip *chip,
503 int current_limit_ua)
504{
505 int term_current_limit_ua = 0;
506 int rc = 0;
507 u8 val = 0;
508 int i;
509
510 for (i = ARRAY_SIZE(term_current_ua) - 1; i >= 0; i--) {
511 if (current_limit_ua >= term_current_ua[i].term_current_ua) {
512 val = term_current_ua[i].charge_cur_reg;
513 term_current_limit_ua
514 = term_current_ua[i].term_current_ua;
515 break;
516 }
517 }
518
519 if (term_current_limit_ua) {
520 rc = smb137c_masked_write_reg(chip, CHARGE_CURRENT_REG,
521 CHARGE_CURRENT_TERM_CUR_MASK, val);
522 if (rc)
523 return rc;
524 rc = smb137c_masked_write_reg(chip, CTRL_A_REG,
525 CTRL_A_TERM_CUR_MASK, CTRL_A_TERM_CUR_ENABLED);
526 } else {
527 rc = smb137c_masked_write_reg(chip, CTRL_A_REG,
528 CTRL_A_TERM_CUR_MASK, CTRL_A_TERM_CUR_DISABLED);
529 }
530
531 if (!rc)
532 dev_dbg(&chip->client->dev, "%s: current=%d uA\n", __func__,
533 term_current_limit_ua);
534
535 return rc;
536}
537
538static int smb137c_set_pre_charge_current_limit(struct smb137c_chip *chip,
539 int current_limit_ua)
540{
541 int setpoint, rc;
542 u8 val;
543
544 if (current_limit_ua < PRE_CHARGE_CURRENT_MIN_UA ||
545 current_limit_ua > PRE_CHARGE_CURRENT_MAX_UA) {
546 dev_err(&chip->client->dev, "%s: current limit out of bounds: %d\n",
547 __func__, current_limit_ua);
548 return -EINVAL;
549 }
550
551 setpoint = (current_limit_ua - PRE_CHARGE_CURRENT_MIN_UA)
552 / PRE_CHARGE_CURRENT_STEP_UA;
553 val = setpoint << CHARGE_CURRENT_PRE_CHG_SHIFT;
554
555 rc = smb137c_masked_write_reg(chip, CHARGE_CURRENT_REG,
556 CHARGE_CURRENT_PRE_CHG_MASK, val);
557
558 if (!rc)
559 dev_dbg(&chip->client->dev, "%s: current=%d uA\n", __func__,
560 setpoint * PRE_CHARGE_CURRENT_STEP_UA
561 + PRE_CHARGE_CURRENT_MIN_UA);
562
563 return rc;
564}
565
566static int smb137c_set_float_voltage(struct smb137c_chip *chip, int voltage_uv)
567{
568 int setpoint, rc;
569 u8 val;
570
571 if (voltage_uv < FLOAT_VOLTAGE_MIN_UV ||
572 voltage_uv > FLOAT_VOLTAGE_MAX_UV) {
573 dev_err(&chip->client->dev, "%s: voltage out of bounds: %d\n",
574 __func__, voltage_uv);
575 return -EINVAL;
576 }
577
578 setpoint = (voltage_uv - FLOAT_VOLTAGE_MIN_UV) / FLOAT_VOLTAGE_STEP_UV;
579 val = setpoint << FLOAT_VOLTAGE_SHIFT;
580
581 rc = smb137c_masked_write_reg(chip, FLOAT_VOLTAGE_REG,
582 FLOAT_VOLTAGE_MASK, val);
583
584 if (!rc)
585 dev_dbg(&chip->client->dev, "%s: voltage=%d uV\n", __func__,
586 setpoint * FLOAT_VOLTAGE_STEP_UV + FLOAT_VOLTAGE_MIN_UV);
587
588 return rc;
589}
590
591static int smb137c_set_pre_charge_threshold_voltage(struct smb137c_chip *chip,
592 int voltage_uv)
593{
594 int setpoint, rc;
595 u8 val;
596
597 if (voltage_uv < PRE_CHG_THRESH_VOLTAGE_MIN_UV ||
598 voltage_uv > PRE_CHG_THRESH_VOLTAGE_MAX_UV) {
599 dev_err(&chip->client->dev, "%s: voltage out of bounds: %d\n",
600 __func__, voltage_uv);
601 return -EINVAL;
602 }
603
604 setpoint = (voltage_uv - PRE_CHG_THRESH_VOLTAGE_MIN_UV)
605 / PRE_CHG_THRESH_VOLTAGE_STEP_UV;
606 val = setpoint << CTRL_A_THRESH_VOLTAGE_SHIFT;
607
608 rc = smb137c_masked_write_reg(chip, CTRL_A_REG,
609 CTRL_A_THRESH_VOLTAGE_MASK, val);
610
611 if (!rc)
612 dev_dbg(&chip->client->dev, "%s: voltage=%d uV\n", __func__,
613 setpoint * PRE_CHG_THRESH_VOLTAGE_STEP_UV
614 + PRE_CHG_THRESH_VOLTAGE_MIN_UV);
615
616 return rc;
617}
618
619static int smb137c_set_recharge_threshold_voltage(struct smb137c_chip *chip,
620 int voltage_uv)
621{
622 int rc;
623 u8 val;
624
625 if (voltage_uv == 75000) {
626 val = OTG_CTRL_AUTO_RECHARGE_75MV;
627 } else if (voltage_uv == 120000) {
628 val = OTG_CTRL_AUTO_RECHARGE_120MV;
629 } else {
630 dev_err(&chip->client->dev, "%s: voltage out of bounds: %d\n",
631 __func__, voltage_uv);
632 return -EINVAL;
633 }
634
635 rc = smb137c_masked_write_reg(chip, OTG_CTRL_REG,
636 OTG_CTRL_AUTO_RECHARGE_MASK, val);
637
638 if (!rc)
639 dev_dbg(&chip->client->dev, "%s: voltage=%d uV\n", __func__,
640 voltage_uv);
641
642 return rc;
643}
644
645static int smb137c_set_system_voltage(struct smb137c_chip *chip, int voltage_uv)
646{
647 int rc;
648 u8 val;
649
650 if (voltage_uv == 4250000) {
651 val = CTRL_A_VOUTL_4250MV;
652 } else if (voltage_uv == 4460000) {
653 val = CTRL_A_VOUTL_4460MV;
654 } else {
655 dev_err(&chip->client->dev, "%s: voltage out of bounds: %d\n",
656 __func__, voltage_uv);
657 return -EINVAL;
658 }
659
660 rc = smb137c_masked_write_reg(chip, CTRL_A_REG, CTRL_A_VOUTL_MASK, val);
661
662 if (!rc)
663 dev_dbg(&chip->client->dev, "%s: voltage=%d uV\n", __func__,
664 voltage_uv);
665
666 return rc;
667}
668
669static int charging_timeout[] = {
670 382,
671 764,
672 1527,
673};
674
675static int smb137c_set_charging_timeout(struct smb137c_chip *chip, int timeout)
676{
677 int timeout_chosen = 0;
678 u8 val = 3 << SAFETY_TIMER_CHG_TIMEOUT_SHIFT;
679 int rc, i;
680
681 for (i = ARRAY_SIZE(charging_timeout) - 1; i >= 0; i--) {
682 if (timeout >= charging_timeout[i]) {
683 val = i << SAFETY_TIMER_CHG_TIMEOUT_SHIFT;
684 timeout_chosen = charging_timeout[i];
685 break;
686 }
687 }
688
689 rc = smb137c_masked_write_reg(chip, SAFETY_TIMER_REG,
690 SAFETY_TIMER_CHG_TIMEOUT_MASK, val);
691
692 if (!rc)
693 dev_dbg(&chip->client->dev, "%s: timeout=%d min\n", __func__,
694 timeout_chosen);
695
696 return rc;
697}
698
699static int pre_charge_timeout[] = {
700 48,
701 95,
702 191,
703};
704
705static int smb137c_set_pre_charge_timeout(struct smb137c_chip *chip,
706 int timeout)
707{
708 int timeout_chosen = 0;
709 u8 val = 3 << SAFETY_TIMER_PRE_CHG_TIME_SHIFT;
710 int rc, i;
711
712 for (i = ARRAY_SIZE(pre_charge_timeout) - 1; i >= 0; i--) {
713 if (timeout >= pre_charge_timeout[i]) {
714 val = i << SAFETY_TIMER_PRE_CHG_TIME_SHIFT;
715 timeout_chosen = pre_charge_timeout[i];
716 break;
717 }
718 }
719
720 rc = smb137c_masked_write_reg(chip, SAFETY_TIMER_REG,
721 SAFETY_TIMER_PRE_CHG_TIME_MASK, val);
722
723 if (!rc)
724 dev_dbg(&chip->client->dev, "%s: timeout=%d min\n", __func__,
725 timeout_chosen);
726
727 return rc;
728}
729
730static int thermistor_current[] = {
731 100,
732 40,
733 20,
734 10,
735};
736
737static int smb137c_set_thermistor_current(struct smb137c_chip *chip,
738 int current_ua)
739{
740 bool found = false;
741 u8 val = 0;
742 int rc, i;
743
744 for (i = 0; i < ARRAY_SIZE(thermistor_current); i++) {
745 if (current_ua == thermistor_current[i]) {
746 found = true;
747 val = i << TEMP_MON_THERM_CURRENT_SHIFT;
748 }
749 }
750
751 if (!found) {
752 dev_err(&chip->client->dev, "%s: current out of bounds: %d\n",
753 __func__, current_ua);
754 return -EINVAL;
755 }
756
757 rc = smb137c_masked_write_reg(chip, TEMP_MON_REG,
758 TEMP_MON_THERM_CURRENT_MASK, val);
759
760 if (!rc)
761 dev_dbg(&chip->client->dev, "%s: current=%d uA\n", __func__,
762 current_ua);
763
764 return 0;
765}
766
767static int smb137c_set_temperature_low_limit(struct smb137c_chip *chip,
768 int value)
769{
770 int rc;
771
772 if (value < 0 || value > 7) {
773 dev_err(&chip->client->dev, "%s: temperature value out of bounds: %d\n",
774 __func__, value);
775 return -EINVAL;
776 }
777
778 rc = smb137c_masked_write_reg(chip, TEMP_MON_REG,
779 TEMP_MON_TEMP_LOW_MASK, value << TEMP_MON_TEMP_LOW_SHIFT);
780
781 if (!rc)
782 dev_dbg(&chip->client->dev, "%s: temperature value=%d\n",
783 __func__, value);
784
785 return rc;
786}
787
788static int smb137c_set_temperature_high_limit(struct smb137c_chip *chip,
789 int value)
790{
791 int rc;
792
793 if (value < 0 || value > 7) {
794 dev_err(&chip->client->dev, "%s: temperature value out of bounds: %d\n",
795 __func__, value);
796 return -EINVAL;
797 }
798
799 rc = smb137c_masked_write_reg(chip, TEMP_MON_REG,
800 TEMP_MON_TEMP_HIGH_MASK, value << TEMP_MON_TEMP_HIGH_SHIFT);
801
802 if (!rc)
803 dev_dbg(&chip->client->dev, "%s: temperature value=%d\n",
804 __func__, value);
805
806 return rc;
807}
808
809static int charge_status_type_map[] = {
810 [CHARGE_STAT_NO_CHG] = POWER_SUPPLY_CHARGE_TYPE_NONE,
811 [CHARGE_STAT_PRE_CHG] = POWER_SUPPLY_CHARGE_TYPE_TRICKLE,
812 [CHARGE_STAT_FAST_CHG] = POWER_SUPPLY_CHARGE_TYPE_FAST,
813 [CHARGE_STAT_TAPER_CHG] = POWER_SUPPLY_CHARGE_TYPE_FAST,
814};
815
816static const char * const charge_status_name[] = {
817 [CHARGE_STAT_NO_CHG] = "none",
818 [CHARGE_STAT_PRE_CHG] = "pre-charge",
819 [CHARGE_STAT_FAST_CHG] = "fast-charge",
820 [CHARGE_STAT_TAPER_CHG] = "taper-charge",
821};
822
823static int smb137c_get_property_status(struct smb137c_chip *chip)
824{
825 int status = POWER_SUPPLY_STATUS_DISCHARGING;
826 enum smb137c_charge_status charging_status;
827 bool charging_enabled;
828 bool charging_error;
829 int rc;
830 u8 val;
831
832 rc = smb137c_read_reg(chip, STAT_C_REG, &val);
833 if (rc)
834 return POWER_SUPPLY_STATUS_UNKNOWN;
835
836 charging_enabled = val & STAT_C_CHG_ENABLED;
837 charging_error = val & STAT_C_CHG_ERROR;
838 charging_status = (val & STAT_C_CHG_STAT_MASK) >> STAT_C_CHG_STAT_SHIFT;
839
840 if (charging_enabled && !charging_error
841 && charging_status != CHARGE_STAT_NO_CHG)
842 status = POWER_SUPPLY_STATUS_CHARGING;
843
844 dev_dbg(&chip->client->dev, "%s: status=%s\n", __func__,
845 (status == POWER_SUPPLY_STATUS_CHARGING ? "charging"
846 : "discharging"));
847
848 return status;
849}
850
851static int smb137c_get_property_battery_present(struct smb137c_chip *chip)
852{
853 int rc;
854 u8 val;
855
856 rc = smb137c_read_reg(chip, IRQ_STAT_B_REG, &val);
857 if (rc || (val & IRQ_STAT_B_BATT_MISSING))
858 return 0;
859
860 /* Treat battery voltage less than 2.1 V as battery not present. */
861 rc = smb137c_read_reg(chip, STAT_C_REG, &val);
862 if (rc || (val & STAT_C_VBATT_LEVEL_BELOW_2P1V))
863 return 0;
864
865 return 1;
866}
867
868static int smb137c_get_property_battery_health(struct smb137c_chip *chip)
869{
870 int rc;
871 u8 val;
872
873 /* The health of a disconnected battery is unknown. */
874 if (!smb137c_get_property_battery_present(chip))
875 return POWER_SUPPLY_HEALTH_UNKNOWN;
876
877 rc = smb137c_read_reg(chip, IRQ_STAT_B_REG, &val);
878 if (rc)
879 return POWER_SUPPLY_HEALTH_UNKNOWN;
880
881 if (val & IRQ_STAT_B_BATT_OVERVOLT)
882 return POWER_SUPPLY_HEALTH_OVERVOLTAGE;
883 else if (val & IRQ_STAT_B_BATT_UNDERVOLT)
884 return POWER_SUPPLY_HEALTH_DEAD;
885
886 rc = smb137c_read_reg(chip, IRQ_STAT_A_REG, &val);
887 if (rc)
888 return POWER_SUPPLY_HEALTH_UNKNOWN;
889
890 if (val & IRQ_STAT_A_BATT_HOT)
891 return POWER_SUPPLY_HEALTH_OVERHEAT;
892 else if (val & IRQ_STAT_A_BATT_COLD)
893 return POWER_SUPPLY_HEALTH_COLD;
894
895 return POWER_SUPPLY_HEALTH_GOOD;
896}
897
898static int smb137c_get_property_charge_type(struct smb137c_chip *chip)
899{
900 enum smb137c_charge_status status;
901 int charge_type = POWER_SUPPLY_CHARGE_TYPE_NONE;
902 bool charging_enabled;
903 bool charging_error;
904 int rc;
905 u8 val;
906
907 rc = smb137c_read_reg(chip, STAT_C_REG, &val);
908 if (rc)
909 return POWER_SUPPLY_CHARGE_TYPE_UNKNOWN;
910
911 charging_enabled = val & STAT_C_CHG_ENABLED;
912 charging_error = val & STAT_C_CHG_ERROR;
913 status = (val & STAT_C_CHG_STAT_MASK) >> STAT_C_CHG_STAT_SHIFT;
914
915 if (!charging_enabled) {
916 dev_dbg(&chip->client->dev, "%s: not charging\n", __func__);
917 } else if (charging_error) {
918 dev_warn(&chip->client->dev, "%s: charger error detected\n",
919 __func__);
920 } else {
921 charge_type = charge_status_type_map[status];
922 }
923
924 dev_dbg(&chip->client->dev, "%s: charging status=%s\n", __func__,
925 charge_status_name[status]);
926
927 return charge_type;
928}
929
930static enum power_supply_property smb137c_power_properties[] = {
931 POWER_SUPPLY_PROP_STATUS,
932 POWER_SUPPLY_PROP_HEALTH,
933 POWER_SUPPLY_PROP_PRESENT,
934 POWER_SUPPLY_PROP_CHARGING_ENABLED,
935 POWER_SUPPLY_PROP_CHARGE_TYPE,
936 POWER_SUPPLY_PROP_CURRENT_MAX,
937 POWER_SUPPLY_PROP_TECHNOLOGY,
938 POWER_SUPPLY_PROP_MODEL_NAME,
939 POWER_SUPPLY_PROP_MANUFACTURER,
940};
941
942static int smb137c_property_is_writeable(struct power_supply *psy,
943 enum power_supply_property psp)
944{
945 switch (psp) {
946 case POWER_SUPPLY_PROP_CHARGING_ENABLED:
947 case POWER_SUPPLY_PROP_CURRENT_MAX:
948 return 1;
949 default:
950 break;
951 }
952
953 return 0;
954}
955
956static int smb137c_power_set_property(struct power_supply *psy,
957 enum power_supply_property psp,
958 const union power_supply_propval *val)
959{
960 struct smb137c_chip *chip = container_of(psy, struct smb137c_chip, psy);
961
962 mutex_lock(&chip->lock);
963
964 switch (psp) {
965 case POWER_SUPPLY_PROP_CHARGING_ENABLED:
966 if (val->intval)
967 smb137c_enable_charging(chip);
968 else
969 smb137c_disable_charging(chip);
970 break;
971 case POWER_SUPPLY_PROP_CURRENT_MAX:
972 smb137c_set_charge_current_limit(chip, val->intval);
973 break;
974 default:
975 mutex_unlock(&chip->lock);
976 return -EINVAL;
977 }
978
979 mutex_unlock(&chip->lock);
980
981 power_supply_changed(&chip->psy);
982 return 0;
983}
984
985static int smb137c_power_get_property(struct power_supply *psy,
986 enum power_supply_property psp,
987 union power_supply_propval *val)
988{
989 struct smb137c_chip *chip = container_of(psy, struct smb137c_chip, psy);
990
991 mutex_lock(&chip->lock);
992
993 switch (psp) {
994 case POWER_SUPPLY_PROP_STATUS:
995 val->intval = smb137c_get_property_status(chip);
996 break;
997 case POWER_SUPPLY_PROP_HEALTH:
998 val->intval = smb137c_get_property_battery_health(chip);
999 break;
1000 case POWER_SUPPLY_PROP_PRESENT:
1001 val->intval = smb137c_get_property_battery_present(chip);
1002 break;
1003 case POWER_SUPPLY_PROP_CHARGING_ENABLED:
1004 val->intval = chip->charging_enabled;
1005 break;
1006 case POWER_SUPPLY_PROP_CHARGE_TYPE:
1007 val->intval = smb137c_get_property_charge_type(chip);
1008 break;
1009 case POWER_SUPPLY_PROP_CURRENT_MAX:
1010 val->intval = chip->charge_current_limit_ua;
1011 break;
1012 case POWER_SUPPLY_PROP_TECHNOLOGY:
1013 val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
1014 break;
1015 case POWER_SUPPLY_PROP_MODEL_NAME:
1016 val->strval = "SMB137C";
1017 break;
1018 case POWER_SUPPLY_PROP_MANUFACTURER:
1019 val->strval = "Summit Microelectronics";
1020 break;
1021 default:
1022 mutex_unlock(&chip->lock);
1023 return -EINVAL;
1024 }
1025
1026 mutex_unlock(&chip->lock);
1027
1028 return 0;
1029}
1030
1031static void smb137c_external_power_changed(struct power_supply *psy)
1032{
1033 struct smb137c_chip *chip = container_of(psy, struct smb137c_chip, psy);
1034 union power_supply_propval prop = {0,};
David Collinsce321a22012-11-14 14:29:55 -08001035 int scope = POWER_SUPPLY_SCOPE_DEVICE;
David Collins81fe8a52012-11-16 17:48:06 -08001036 int current_limit = 0;
David Collinsce321a22012-11-14 14:29:55 -08001037 int online = 0;
1038 int rc;
David Collinsfc3cde52012-10-19 17:13:48 -07001039
1040 mutex_lock(&chip->lock);
1041 dev_dbg(&chip->client->dev, "%s: start\n", __func__);
1042
David Collinsce321a22012-11-14 14:29:55 -08001043 rc = chip->usb_psy->get_property(chip->usb_psy,
1044 POWER_SUPPLY_PROP_ONLINE, &prop);
1045 if (rc)
1046 dev_err(&chip->client->dev, "%s: could not read USB online property, rc=%d\n",
1047 __func__, rc);
1048 else
1049 online = prop.intval;
David Collinsfc3cde52012-10-19 17:13:48 -07001050
David Collinsce321a22012-11-14 14:29:55 -08001051 rc = chip->usb_psy->get_property(chip->usb_psy, POWER_SUPPLY_PROP_SCOPE,
1052 &prop);
1053 if (rc)
1054 dev_err(&chip->client->dev, "%s: could not read USB scope property, rc=%d\n",
1055 __func__, rc);
1056 else
1057 scope = prop.intval;
1058
1059 rc = chip->usb_psy->get_property(chip->usb_psy,
David Collinsfc3cde52012-10-19 17:13:48 -07001060 POWER_SUPPLY_PROP_CURRENT_MAX, &prop);
David Collinsce321a22012-11-14 14:29:55 -08001061 if (rc)
1062 dev_err(&chip->client->dev, "%s: could not read USB current_max property, rc=%d\n",
1063 __func__, rc);
1064 else
1065 current_limit = prop.intval;
1066
1067 if (scope == POWER_SUPPLY_SCOPE_SYSTEM) {
1068 /* USB host mode */
1069 smb137c_disable_charging(chip);
1070 smb137c_enable_otg_mode(chip);
1071 } else if (online) {
1072 /* USB online in device mode */
1073 smb137c_set_usb_input_current_limit(chip, current_limit);
1074 smb137c_enable_charging(chip);
1075 smb137c_disable_otg_mode(chip);
David Collinsfc3cde52012-10-19 17:13:48 -07001076 } else {
1077 /* USB offline */
1078 smb137c_disable_charging(chip);
1079 smb137c_disable_otg_mode(chip);
David Collins81fe8a52012-11-16 17:48:06 -08001080 smb137c_set_usb_input_current_limit(chip,
1081 min(current_limit, USB_MIN_CURRENT_UA));
David Collinsfc3cde52012-10-19 17:13:48 -07001082 }
1083
1084 dev_dbg(&chip->client->dev, "%s: end\n", __func__);
1085 mutex_unlock(&chip->lock);
1086
1087 power_supply_changed(&chip->psy);
1088}
1089
1090static int __devinit smb137c_set_register_defaults(struct smb137c_chip *chip)
1091{
1092 int rc;
1093 u8 val, mask;
1094
1095 /* Allow volatile register writes. */
1096 rc = smb137c_masked_write_reg(chip, CMD_A_REG,
1097 CMD_A_VOLATILE_WRITE_MASK, CMD_A_VOLATILE_WRITE_ALLOW);
1098 if (rc)
1099 return rc;
1100
1101 /* Do not reset register values on USB reinsertion. */
1102 rc = smb137c_masked_write_reg(chip, SAFETY_TIMER_REG,
1103 SAFETY_TIMER_RELOAD_MASK, SAFETY_TIMER_RELOAD_DISABLED);
1104 if (rc)
1105 return rc;
1106
1107 /* Set various default control parameters. */
1108 val = PIN_CTRL_DEAD_BATT_CHG_ENABLED | PIN_CTRL_OTG
1109 | PIN_CTRL_USB_CUR_LIMIT_REG | PIN_CTRL_CHG_EN_REG_LOW
1110 | PIN_CTRL_OTG_CTRL_REG;
1111 mask = PIN_CTRL_DEAD_BATT_CHG_MASK | PIN_CTRL_OTG_LBR_MASK
1112 | PIN_CTRL_USB_CUR_LIMIT_MASK | PIN_CTRL_CHG_EN_MASK
1113 | PIN_CTRL_OTG_CTRL_MASK;
1114 rc = smb137c_masked_write_reg(chip, PIN_CTRL_REG, mask, val);
1115 if (rc)
1116 return rc;
1117
1118 /* Disable charging, disable OTG mode, and allow fast-charge current. */
1119 val = CMD_A_CHARGING_DISABLED | CMD_A_OTG_DISABLED
1120 | CMD_A_FAST_CHG_ALLOW;
1121 mask = CMD_A_CHARGING_MASK | CMD_A_OTG_MASK | CMD_A_FAST_CHG_MASK;
1122 rc = smb137c_masked_write_reg(chip, CMD_A_REG, mask, val);
1123 if (rc)
1124 return rc;
1125
1126 /* Enable auto recharging and full-time THERM monitor. */
1127 val = CTRL_A_AUTO_RECHARGE_ENABLED | CTRL_A_THERM_MONITOR_ENABLED;
1128 mask = CTRL_A_AUTO_RECHARGE_MASK | CTRL_A_THERM_MONITOR_MASK;
1129 rc = smb137c_masked_write_reg(chip, CTRL_A_REG, mask, val);
David Collins81fe8a52012-11-16 17:48:06 -08001130 if (rc)
1131 return rc;
1132
1133 /* Use register value instead of pin to control USB suspend. */
1134 rc = smb137c_masked_write_reg(chip, VAR_FUNC_REG,
1135 VAR_FUNC_USB_SUSPEND_CTRL_MASK, VAR_FUNC_USB_SUSPEND_CTRL_REG);
1136 if (rc)
1137 return rc;
David Collinsfc3cde52012-10-19 17:13:48 -07001138
1139 return rc;
1140}
1141
1142static int __devinit smb137c_apply_dt_configs(struct smb137c_chip *chip)
1143{
1144 struct device *dev = &chip->client->dev;
1145 struct device_node *node = chip->client->dev.of_node;
1146 int ret, current_ma, voltage_mv, timeout, value;
1147 int rc = 0;
1148
1149 /*
1150 * All device tree parameters are optional so it is ok if read calls
1151 * fail.
1152 */
1153 ret = of_property_read_u32(node, "summit,chg-current-ma", &current_ma);
1154 if (ret == 0) {
1155 rc = smb137c_set_charge_current_limit(chip, current_ma * 1000);
1156 if (rc) {
1157 dev_err(dev, "%s: Failed to set charge current, rc=%d\n",
1158 __func__, rc);
1159 return rc;
1160 }
1161 } else {
1162 chip->charge_current_limit_ua
1163 = smb137c_get_charge_current_limit(chip);
1164 rc = chip->charge_current_limit_ua;
1165 if (rc < 0) {
1166 dev_err(dev, "%s: Failed to get charge current, rc=%d\n",
1167 __func__, rc);
1168 return rc;
1169 }
1170 }
1171
1172 ret = of_property_read_u32(node, "summit,term-current-ma", &current_ma);
1173 if (ret == 0) {
1174 rc = smb137c_set_term_current(chip, current_ma * 1000);
1175 if (rc) {
1176 dev_err(dev, "%s: Failed to set termination current, rc=%d\n",
1177 __func__, rc);
1178 return rc;
1179 }
1180 }
1181
1182 ret = of_property_read_u32(node, "summit,pre-chg-current-ma",
1183 &current_ma);
1184 if (ret == 0) {
1185 rc = smb137c_set_pre_charge_current_limit(chip,
1186 current_ma * 1000);
1187 if (rc) {
1188 dev_err(dev, "%s: Failed to set pre-charge current limit, rc=%d\n",
1189 __func__, rc);
1190 return rc;
1191 }
1192 }
1193
1194 ret = of_property_read_u32(node, "summit,float-voltage-mv",
1195 &voltage_mv);
1196 if (ret == 0) {
1197 rc = smb137c_set_float_voltage(chip, voltage_mv * 1000);
1198 if (rc) {
1199 dev_err(dev, "%s: Failed to set float voltage, rc=%d\n",
1200 __func__, rc);
1201 return rc;
1202 }
1203 }
1204
1205 ret = of_property_read_u32(node, "summit,thresh-voltage-mv",
1206 &voltage_mv);
1207 if (ret == 0) {
1208 rc = smb137c_set_pre_charge_threshold_voltage(chip,
1209 voltage_mv * 1000);
1210 if (rc) {
1211 dev_err(dev, "%s: Failed to set fast-charge threshold voltage, rc=%d\n",
1212 __func__, rc);
1213 return rc;
1214 }
1215 }
1216
1217 ret = of_property_read_u32(node, "summit,recharge-thresh-mv",
1218 &voltage_mv);
1219 if (ret == 0) {
1220 rc = smb137c_set_recharge_threshold_voltage(chip,
1221 voltage_mv * 1000);
1222 if (rc) {
1223 dev_err(dev, "%s: Failed to set recharge threshold voltage, rc=%d\n",
1224 __func__, rc);
1225 return rc;
1226 }
1227 }
1228
1229 ret = of_property_read_u32(node, "summit,system-voltage-mv",
1230 &voltage_mv);
1231 if (ret == 0) {
1232 rc = smb137c_set_system_voltage(chip, voltage_mv * 1000);
1233 if (rc) {
1234 dev_err(dev, "%s: Failed to set system voltage, rc=%d\n",
1235 __func__, rc);
1236 return rc;
1237 }
1238 }
1239
1240 ret = of_property_read_u32(node, "summit,charging-timeout", &timeout);
1241 if (ret == 0) {
1242 rc = smb137c_set_charging_timeout(chip, timeout);
1243 if (rc) {
1244 dev_err(dev, "%s: Failed to set charging timeout, rc=%d\n",
1245 __func__, rc);
1246 return rc;
1247 }
1248 }
1249
1250 ret = of_property_read_u32(node, "summit,pre-charge-timeout", &timeout);
1251 if (ret == 0) {
1252 rc = smb137c_set_pre_charge_timeout(chip, timeout);
1253 if (rc) {
1254 dev_err(dev, "%s: Failed to set pre-charge timeout, rc=%d\n",
1255 __func__, rc);
1256 return rc;
1257 }
1258 }
1259
1260 ret = of_property_read_u32(node, "summit,therm-current-ua", &value);
1261 if (ret == 0) {
1262 rc = smb137c_set_thermistor_current(chip, value);
1263 if (rc) {
1264 dev_err(dev, "%s: Failed to set thermistor current, rc=%d\n",
1265 __func__, rc);
1266 return rc;
1267 }
1268 }
1269
1270 ret = of_property_read_u32(node, "summit,temperature-min", &value);
1271 if (ret == 0) {
1272 rc = smb137c_set_temperature_low_limit(chip, value);
1273 if (rc) {
1274 dev_err(dev, "%s: Failed to set low temperature limit, rc=%d\n",
1275 __func__, rc);
1276 return rc;
1277 }
1278 }
1279
1280 ret = of_property_read_u32(node, "summit,temperature-max", &value);
1281 if (ret == 0) {
1282 rc = smb137c_set_temperature_high_limit(chip, value);
1283 if (rc) {
1284 dev_err(dev, "%s: Failed to set high temperature limit, rc=%d\n",
1285 __func__, rc);
1286 return rc;
1287 }
1288 }
1289
1290 return rc;
1291}
1292
1293static int __devinit smb137c_probe(struct i2c_client *client,
1294 const struct i2c_device_id *id)
1295{
1296 struct smb137c_chip *chip;
1297 struct device *dev = &client->dev;
1298 struct device_node *node = client->dev.of_node;
1299 int rc = 0;
1300 int gui_rev, silicon_rev;
1301 u8 dev_id;
1302
1303 if (!node) {
1304 dev_err(dev, "%s: device tree information missing\n", __func__);
1305 return -ENODEV;
1306 }
1307
1308 if (!i2c_check_functionality(client->adapter,
1309 I2C_FUNC_SMBUS_BYTE_DATA)) {
1310 dev_err(dev, "%s: SMBUS_BYTE_DATA unsupported\n", __func__);
1311 return -EIO;
1312 }
1313
1314 chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
1315 if (!chip) {
1316 dev_err(dev, "%s: devm_kzalloc failed\n", __func__);
1317 return -ENOMEM;
1318 }
1319
1320 mutex_init(&chip->lock);
1321 chip->client = client;
1322 i2c_set_clientdata(client, chip);
1323
1324 chip->usb_psy = power_supply_get_by_name("usb");
1325 if (!chip->usb_psy) {
1326 dev_dbg(dev, "%s: USB supply not found; deferring charger probe\n",
1327 __func__);
1328 return -EPROBE_DEFER;
1329 }
1330
1331 rc = smb137c_read_reg(chip, DEV_ID_REG, &dev_id);
1332 if (rc)
1333 return rc;
1334
1335 if ((dev_id & DEV_ID_PART_MASK) != DEV_ID_PART_SMB137C) {
1336 dev_err(dev, "%s: invalid device ID=0x%02X\n", __func__,
1337 dev_id);
1338 return -ENODEV;
1339 }
1340
1341 gui_rev = (dev_id & DEV_ID_GUI_REV_MASK) >> DEV_ID_GUI_REV_SHIFT;
1342 silicon_rev = (dev_id & DEV_ID_SILICON_REV_MASK)
1343 >> DEV_ID_SILICON_REV_SHIFT;
1344
1345 rc = smb137c_set_register_defaults(chip);
1346 if (rc)
1347 return rc;
1348
1349 rc = smb137c_apply_dt_configs(chip);
1350 if (rc)
1351 return rc;
1352
1353 chip->psy.name = "battery";
1354 chip->psy.type = POWER_SUPPLY_TYPE_BATTERY;
1355 chip->psy.properties = smb137c_power_properties;
1356 chip->psy.num_properties = ARRAY_SIZE(smb137c_power_properties);
1357 chip->psy.get_property = smb137c_power_get_property;
1358 chip->psy.set_property = smb137c_power_set_property;
1359 chip->psy.property_is_writeable = smb137c_property_is_writeable;
1360 chip->psy.external_power_changed = smb137c_external_power_changed;
1361
1362 rc = power_supply_register(dev, &chip->psy);
1363 if (rc < 0) {
1364 dev_err(dev, "%s: power_supply_register failed, rc=%d\n",
1365 __func__, rc);
1366 return rc;
1367 }
1368
1369 smb137c_external_power_changed(&chip->psy);
1370
1371 dev_info(dev, "%s: SMB137C charger probed successfully, gui_rev=%d, silicon_rev=%d\n",
1372 __func__, gui_rev, silicon_rev);
1373
1374 return rc;
1375}
1376
1377static int __devexit smb137c_remove(struct i2c_client *client)
1378{
1379 return 0;
1380}
1381
1382static const struct i2c_device_id smb137c_id[] = {
1383 { .name = "smb137c", },
1384 {},
1385};
1386MODULE_DEVICE_TABLE(i2c, smb137c_id);
1387
David Collinsfc3cde52012-10-19 17:13:48 -07001388static const struct of_device_id smb137c_match[] = {
1389 { .compatible = "summit,smb137c", },
1390 { },
1391};
1392
1393static struct i2c_driver smb137c_driver = {
1394 .driver = {
1395 .name = "smb137c",
1396 .owner = THIS_MODULE,
1397 .of_match_table = smb137c_match,
1398 },
1399 .probe = smb137c_probe,
1400 .remove = __devexit_p(smb137c_remove),
1401 .id_table = smb137c_id,
1402};
1403
1404static int __init smb137c_init(void)
1405{
1406 return i2c_add_driver(&smb137c_driver);
1407}
1408module_init(smb137c_init);
1409
1410static void __exit smb137c_exit(void)
1411{
1412 return i2c_del_driver(&smb137c_driver);
1413}
1414module_exit(smb137c_exit);
1415
1416MODULE_DESCRIPTION("SMB137C Charger");
1417MODULE_LICENSE("GPL v2");
1418MODULE_ALIAS("i2c:smb137c");