4 * Copyright (C) 2011 Samsung Electronics
5 * Ikkeun Kim <iks.kim@samsung.com>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
12 #include <linux/power/smb136_charger_q1.h>
22 static int smb136_i2c_read(struct i2c_client *client, u8 reg, u8 *data)
29 ret = i2c_smbus_read_byte_data(client, reg);
37 static int smb136_i2c_write(struct i2c_client *client, u8 reg, u8 data)
42 return i2c_smbus_write_byte_data(client, reg, data);
45 static void smb136_test_read(struct i2c_client *client)
47 struct smb136_chip *chg = i2c_get_clientdata(client);
51 for (addr = 0; addr < 0x0c; addr++) {
52 smb136_i2c_read(chg->client, addr, &data);
53 dev_info(&client->dev,
54 "SMB136 addr : 0x%02x data : 0x%02x\n", addr, data);
57 for (addr = 0x31; addr < 0x3D; addr++) {
58 smb136_i2c_read(chg->client, addr, &data);
59 dev_info(&client->dev,
60 "SMB136 addr : 0x%02x data : 0x%02x\n", addr, data);
64 static int smb136_get_charging_status(struct i2c_client *client)
66 struct smb136_chip *chg = i2c_get_clientdata(client);
67 int status = POWER_SUPPLY_STATUS_UNKNOWN;
71 smb136_i2c_read(chg->client, 0x36, &data1);
72 smb136_i2c_read(chg->client, 0x39, &data2);
73 dev_info(&client->dev, "%s : 0x36h(0x%02x), 0x39h(0x%02x)\n",
74 __func__, data1, data2);
77 status = POWER_SUPPLY_STATUS_CHARGING;
79 if ((data1 & 0x08) == 0x08) {
80 /* if error bit check,
81 ignore the status of charger-ic */
82 status = POWER_SUPPLY_STATUS_NOT_CHARGING;
83 } else if ((data1 & 0xc0) == 0xc0) {
84 /* At least one charge cycle terminated,
85 Charge current < Termination Current */
86 status = POWER_SUPPLY_STATUS_FULL;
93 static int smb136_charging(struct i2c_client *client)
95 struct smb136_chip *chg = i2c_get_clientdata(client);
99 dev_info(&client->dev, "%s : enable(%d), cable(%d)\n",
100 __func__, chg->is_enable, chg->cable_type);
102 if (chg->is_enable) {
103 switch (chg->cable_type) {
108 smb136_i2c_write(chg->client, SMB_CommandA, data);
111 /* 2. Change USB5/1/HC Control from Pin to I2C */
112 /* 2. EN pin control - active low */
113 smb136_i2c_write(chg->client, SMB_PinControl, 0x8);
116 smb136_i2c_write(chg->client, SMB_CommandA, 0x8c);
119 /* 3. Set charge current to 950mA,
120 termination current to 150mA */
123 smb136_i2c_write(chg->client, SMB_ChargeCurrent, data);
128 /* 1. USBIN 500mA mode */
131 smb136_i2c_write(chg->client, SMB_CommandA, data);
134 /* 2. Change USB5/1/HC Control from Pin to I2C */
135 /* 2. EN pin control - active low */
136 smb136_i2c_write(chg->client, SMB_PinControl, 0x8);
139 smb136_i2c_write(chg->client, SMB_CommandA, 0x88);
142 /* 3. Set charge current to 500mA,
143 termination current to 150mA */
146 smb136_i2c_write(chg->client, SMB_ChargeCurrent, data);
151 /* 3. Enable Automatic Input Current Limit to 1000mA
154 smb136_i2c_write(chg->client, SMB_InputCurrentLimit, data);
157 /* 4. Automatic Recharge Disabed */
159 smb136_i2c_write(chg->client, SMB_ControlA, data);
162 /* 5. Safety timer Disabled */
164 smb136_i2c_write(chg->client, SMB_ControlB, data);
167 /* 6. Disable USB D+/D- Detection */
169 smb136_i2c_write(chg->client, SMB_OTGControl, data);
172 /* 7. Set Output Polarity for STAT */
173 /* 7. Set float voltage to 4.2V */
175 smb136_i2c_write(chg->client, SMB_FloatVoltage, data);
178 /* 8. Re-load Enable */
180 smb136_i2c_write(chg->client, SMB_SafetyTimer, data);
186 /* CHG_EN pin control - active low */
187 gpio = gpio_request(chg->pdata->gpio_chg_en, "CHG_EN");
189 gpio_direction_output(chg->pdata->gpio_chg_en,
191 dev_info(&client->dev, "gpio(CHG_EN)is %d\n",
192 gpio_get_value(chg->pdata->gpio_chg_en));
193 gpio_free(chg->pdata->gpio_chg_en);
195 dev_err(&client->dev,
196 "faile to request gpio(CHG_EN)\n");
198 /* smb136_test_read(client); */
203 static int smb136_get_property(struct power_supply *psy,
204 enum power_supply_property psp,
205 union power_supply_propval *val)
207 struct smb136_chip *chip = container_of(psy,
213 case POWER_SUPPLY_PROP_STATUS:
214 val->intval = smb136_get_charging_status(chip->client);
216 case POWER_SUPPLY_PROP_CHARGE_TYPE:
217 val->intval = chip->cable_type;
219 case POWER_SUPPLY_PROP_ONLINE:
220 val->intval = chip->is_enable;
222 case POWER_SUPPLY_PROP_CURRENT_NOW:
223 smb136_i2c_read(chip->client, SMB_ChargeCurrent, &data);
255 dev_info(&chip->client->dev, "%s: smb136_get_property (%d,%d)\n",
256 __func__, psp, val->intval);
261 static int smb136_set_property(struct power_supply *psy,
262 enum power_supply_property psp,
263 const union power_supply_propval *val)
265 struct smb136_chip *chip = container_of(psy,
269 dev_info(&chip->client->dev, "%s: smb136_set_property (%d,%d)\n",
270 __func__, psp, val->intval);
273 case POWER_SUPPLY_PROP_STATUS:
274 chip->is_enable = (val->intval == POWER_SUPPLY_STATUS_CHARGING);
275 smb136_charging(chip->client);
277 case POWER_SUPPLY_PROP_CHARGE_TYPE:
278 switch (val->intval) {
281 chip->cable_type = val->intval;
284 dev_err(&chip->client->dev, "cable type NOT supported!\n");
285 chip->cable_type = CABLE_TYPE_NONE;
289 case POWER_SUPPLY_PROP_ONLINE:
290 chip->is_enable = (bool)val->intval;
291 smb136_charging(chip->client);
293 case POWER_SUPPLY_PROP_CURRENT_NOW:
294 if (val->intval <= 450)
295 chip->cable_type = CABLE_TYPE_USB; /* USB */
297 chip->cable_type = CABLE_TYPE_AC; /* TA */
305 #if defined(CONFIG_MACH_Q1_CHN) && defined(CONFIG_SMB136_CHARGER_Q1)
306 static bool is_ovp_status;
309 static irqreturn_t smb136_irq_thread(int irq, void *data)
311 struct smb136_chip *chip = data;
312 #if defined(CONFIG_MACH_Q1_CHN) && defined(CONFIG_SMB136_CHARGER_Q1)
317 dev_info(&chip->client->dev, "%s\n", __func__);
319 smb136_test_read(chip->client);
320 #if defined(CONFIG_MACH_Q1_CHN) && defined(CONFIG_SMB136_CHARGER_Q1)
321 smb136_i2c_read(chip->client, 0x33, &data1);
324 if (is_ovp_status == false) {
325 is_ovp_status = true;
326 if (chip->pdata->ovp_cb)
327 ret = chip->pdata->ovp_cb(true);
328 dev_info(&chip->client->dev, "$s OVP!!\n");
331 if (is_ovp_status == true) {
332 is_ovp_status = false;
333 if (chip->pdata->ovp_cb)
334 ret = chip->pdata->ovp_cb(false);
335 dev_info(&chip->client->dev,
336 "$s ovp status released!!\n");
344 static int smb136_irq_init(struct smb136_chip *chip)
346 struct i2c_client *client = chip->client;
350 ret = request_threaded_irq(client->irq, NULL,
351 #if defined(CONFIG_MACH_Q1_CHN) && defined(CONFIG_SMB136_CHARGER_Q1)
352 smb136_irq_thread, IRQ_TYPE_EDGE_BOTH,
354 smb136_irq_thread, IRQ_TYPE_EDGE_FALLING,
356 "SMB136 charger", chip);
358 dev_err(&client->dev, "failed to reqeust IRQ\n");
362 ret = enable_irq_wake(client->irq);
364 dev_err(&client->dev,
365 "failed to enable wakeup src %d\n", ret);
371 static int smb136_probe(struct i2c_client *client,
372 const struct i2c_device_id *id)
374 struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
375 struct smb136_chip *chip;
380 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE))
383 if (smb136_i2c_read(client, 0x36, &data) < 0) /* check HW */
386 dev_info(&client->dev,
387 "%s : SMB136 Charger Driver Loading\n", __func__);
389 chip = kzalloc(sizeof(struct smb136_chip), GFP_KERNEL);
393 chip->client = client;
394 chip->pdata = client->dev.platform_data;
396 i2c_set_clientdata(client, chip);
399 dev_err(&client->dev,
400 "%s : No platform data supplied\n", __func__);
405 if (chip->pdata->set_charger_name)
406 chip->pdata->set_charger_name();
408 chip->is_enable = false;
409 chip->cable_type = CABLE_TYPE_NONE;
411 chip->charger.name = "smb136-charger";
412 chip->charger.type = POWER_SUPPLY_TYPE_BATTERY;
413 chip->charger.get_property = smb136_get_property;
414 chip->charger.set_property = smb136_set_property;
415 chip->charger.properties = smb136_charger_props;
416 chip->charger.num_properties = ARRAY_SIZE(smb136_charger_props);
418 ret = power_supply_register(&client->dev, &chip->charger);
420 dev_err(&client->dev,
421 "failed: power supply register\n");
426 /* CHG_EN pin control - active low */
427 if (chip->pdata->gpio_chg_en) {
428 s3c_gpio_cfgpin(chip->pdata->gpio_chg_en, S3C_GPIO_OUTPUT);
429 s3c_gpio_setpull(chip->pdata->gpio_chg_en, S3C_GPIO_PULL_NONE);
431 gpio = gpio_request(chip->pdata->gpio_chg_en, "CHG_EN");
433 gpio_direction_output(chip->pdata->gpio_chg_en,
435 gpio_free(chip->pdata->gpio_chg_en);
437 dev_err(&client->dev,
438 "faile to request gpio(CHG_EN)\n");
441 if (chip->pdata->gpio_otg_en) {
442 s3c_gpio_cfgpin(chip->pdata->gpio_otg_en, S3C_GPIO_OUTPUT);
443 s3c_gpio_setpull(chip->pdata->gpio_otg_en, S3C_GPIO_PULL_NONE);
445 gpio = gpio_request(chip->pdata->gpio_otg_en, "OTG_EN");
447 gpio_direction_output(chip->pdata->gpio_otg_en,
449 gpio_free(chip->pdata->gpio_otg_en);
451 dev_err(&client->dev,
452 "faile to request gpio(OTG_EN)\n");
455 if (chip->pdata->gpio_ta_nconnected) {
456 s3c_gpio_cfgpin(chip->pdata->gpio_ta_nconnected,
458 s3c_gpio_setpull(chip->pdata->gpio_ta_nconnected,
462 if (chip->pdata->gpio_chg_ing) {
464 #if defined(CONFIG_MACH_Q1_CHN) && defined(CONFIG_SMB136_CHARGER_Q1)
465 s3c_gpio_cfgpin(chip->pdata->gpio_chg_ing, S3C_GPIO_SFN(0xf));
467 client->irq = gpio_to_irq(chip->pdata->gpio_chg_ing);
468 ret = smb136_irq_init(chip);
472 s3c_gpio_cfgpin(chip->pdata->gpio_chg_ing, S3C_GPIO_INPUT);
473 s3c_gpio_setpull(chip->pdata->gpio_chg_ing, S3C_GPIO_PULL_NONE);
477 #if defined(CONFIG_MACH_Q1_CHN) && defined(CONFIG_SMB136_CHARGER_Q1)
478 is_ovp_status = false;
481 smb136_test_read(client);
490 static int __devexit smb136_remove(struct i2c_client *client)
492 struct smb136_chip *chip = i2c_get_clientdata(client);
498 static const struct i2c_device_id smb136_id[] = {
499 {"smb136-charger", 0},
503 MODULE_DEVICE_TABLE(i2c, smb136_id);
505 static struct i2c_driver smb136_i2c_driver = {
507 .owner = THIS_MODULE,
508 .name = "smb136-charger",
510 .probe = smb136_probe,
511 .remove = __devexit_p(smb136_remove),
513 .id_table = smb136_id,
516 static int __init smb136_init(void)
518 return i2c_add_driver(&smb136_i2c_driver);
521 static void __exit smb136_exit(void)
523 i2c_del_driver(&smb136_i2c_driver);
526 module_init(smb136_init);
527 module_exit(smb136_exit);
529 MODULE_AUTHOR("Ikkeun Kim <iks.kim@samsung.com>");
530 MODULE_DESCRIPTION("smb136 charger driver");
531 MODULE_LICENSE("GPL");