2 * smb347 battery driver
4 * This package is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
8 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
9 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
10 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13 #include <linux/module.h>
14 #include <linux/param.h>
15 #include <linux/jiffies.h>
16 #include <linux/workqueue.h>
17 #include <linux/delay.h>
18 #include <linux/platform_device.h>
19 #include <linux/power_supply.h>
20 #include <linux/idr.h>
21 #include <linux/i2c.h>
22 #include <linux/slab.h>
23 #include <asm/unaligned.h>
24 #include <mach/gpio.h>
25 #include <linux/proc_fs.h>
26 #include <asm/uaccess.h>
27 #include <mach/board.h>
28 #include <mach/iomux.h>
29 #include <linux/power/smb347-charger.h>
31 #include <linux/interrupt.h>
32 #include "../usb/dwc_otg/dwc_otg_driver.h"
35 #define xhc_printk(format, ...) printk(format, ## __VA_ARGS__)
37 #define xhc_printk(format, ...)
40 #define SMB347_STATUS_D 0x3d
41 #define SMB347_SPEED (300 * 1000)
42 #define MAX_REG_INDEX 0x3f
44 struct workqueue_struct *wq;
46 struct i2c_client *client;
47 struct delayed_work work;
48 struct smb347_info *info;
49 struct work_struct full_power_work_struct;
54 /* Input current limit in mA */
55 static const unsigned int icl_tbl[] = {
68 extern dwc_otg_device_t* g_otgdev;
69 struct smb347_device * g_smb347_dev;
70 static void smb347_init(struct i2c_client *client);
72 static int smb347_read(struct i2c_client *client, const char reg, char *buf, int len)
75 ret = i2c_master_reg8_recv(client, reg, buf, len, SMB347_SPEED);
79 static int smb347_write(struct i2c_client *client,const char reg, char *buf, int len)
82 ret = i2c_master_reg8_send(client, reg, buf, len, SMB347_SPEED);
86 static int dump_smb347_reg(struct smb347_device *dev)
93 xhc_printk("dev is null");
96 for(reg = 0; reg <= MAX_REG_INDEX; reg++)
98 ret = i2c_master_reg8_recv(dev->client, reg, &buf, 1, SMB347_SPEED);
102 printk("read smb137 reg error:%d\n",ret);
106 printk("reg 0x%x:0x%x\n",reg,buf);
114 static ssize_t smb_debug_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t _count)
119 struct smb347_device *smb347_dev = dev_get_drvdata(dev);
120 if (sscanf(buf, "%x", &temp) != 1)
124 smb347_write(smb347_dev->client, reg, &val,1);
129 static ssize_t smb_debug_show(struct device *dev, struct device_attribute *attr,
132 struct smb347_device *smb347_dev = dev_get_drvdata(dev);
133 dump_smb347_reg(smb347_dev);
137 static struct device_attribute smb_debug =
138 __ATTR(smb_debug, S_IRUGO | S_IWUSR, smb_debug_show, smb_debug_store);
140 int smb347_is_chg_ok(void)
145 smb347_read(g_smb347_dev->client, 0x37, ®, 1);
152 EXPORT_SYMBOL(smb347_is_chg_ok);
154 int smb347_is_charging(void)
156 int status = 0;//POWER_SUPPLY_STATUS_UNKNOWN;
159 smb347_read(g_smb347_dev->client, SMB347_STATUS_D, &data, 1);
166 EXPORT_SYMBOL(smb347_is_charging);
168 void smb347_set_something(void)
172 smb347_init(g_smb347_dev->client);
176 EXPORT_SYMBOL(smb347_set_something);
178 void smb347_set_charging(void)
183 smb347_write(g_smb347_dev->client, 0x03, &val, 1);
185 smb347_read(g_smb347_dev->client, 0x04, &val, 1);
187 smb347_write(g_smb347_dev->client, 0x04, &val, 1);
192 EXPORT_SYMBOL(smb347_set_charging);
194 void smb347_set_discharging(void)
199 smb347_write(g_smb347_dev->client, 0x03, &val, 1);
201 smb347_read(g_smb347_dev->client, 0x04, &val, 1);
203 smb347_write(g_smb347_dev->client, 0x04, &val, 1);
208 EXPORT_SYMBOL(smb347_set_discharging);
210 /* Convert current to register value using lookup table */
211 static int current_to_hw(const unsigned int *tbl, size_t size, unsigned int val)
214 for (i = 0; i < size; i++) {
220 return i > 0 ? i - 1 : -EINVAL;
223 static int smb347_set_current_limits(struct smb347_device *smb_dev)
226 if (smb_dev->info->max_current) {
227 xhc_printk("xhc_test_smb_dev->info->max_current = %d\n", smb_dev->info->max_current);
228 ret = current_to_hw (icl_tbl, ARRAY_SIZE(icl_tbl),
229 smb_dev->info->max_current);
233 ret = (ret << 4) + ret;
234 ret = 0x77; //Hardcode 2000mA 2012-11-06
235 xhc_printk("ret = %x\n", ret);
236 ret = smb347_write(smb_dev->client, 0x01, &ret, 1);
237 xhc_printk("ret = %x\n", ret);
245 static void suspend_smb347(struct smb347_device *smb347_dev)
249 smb347_write(smb347_dev->client,0x30,®,1);
250 smb347_read(smb347_dev->client, 0x02, ®, 1);
252 smb347_write(smb347_dev->client,0x02,®,1);
253 xhc_printk("%s\n", __func__);
256 static void active_smb347(struct smb347_device *smb347_dev)
260 smb347_write(smb347_dev->client,0x30,®,1);
261 smb347_read(smb347_dev->client, 0x02, ®, 1);
263 smb347_write(smb347_dev->client,0x02,®,1);
264 xhc_printk("%s\n", __func__);
267 static int smb347_set_otg_control(struct smb347_device *smb_dev)
271 if (smb_dev->info->otg_power_form_smb == 1) {
272 ret = smb347_read(smb_dev->client, 0x09, ®, 1);
274 xhc_printk("error,ret = %x\n", ret);
280 ret = smb347_write(smb_dev->client,0x09,®,1);
282 xhc_printk("error,ret = %x\n", ret);
286 smb347_write(smb_dev->client,0x0a,®,1);
288 xhc_printk("error,ret = %x\n", ret);
296 static void smb347_init(struct i2c_client *client)
300 smb347_write(client, 0x30, ®, 1);
303 smb347_write(client, 0x00, ®, 1);
306 smb347_write(client, 0x01, ®, 1);
309 smb347_write(client, 0x03, ®, 1);
311 smb347_read(client, 0x05, ®, 1);
313 smb347_write(client, 0x05, ®, 1);
315 /* close interrupt */
316 smb347_read(client, 0x38, ®, 1);
317 smb347_read(client, 0x3a, ®, 1);
319 smb347_write(client, 0x0c, ®, 1);
320 smb347_write(client, 0x0d, ®, 1);
322 /* set dc charge when bosh inser dc and usb */
323 smb347_read(client, 0x02, ®, 1);
325 smb347_write(client, 0x02, ®, 1);
328 smb347_set_otg_control(g_smb347_dev);
329 smb347_set_current_limits(g_smb347_dev);
331 dump_smb347_reg(g_smb347_dev);
334 static void smb347_set_current_work(struct work_struct *work)
336 struct smb347_device *smb347_dev = container_of(to_delayed_work(work), struct smb347_device, work);
338 if (g_otgdev->core_if->op_state == A_HOST && smb347_dev->usb_host_in == 0) {
340 xhc_printk("otg_dev->core_if->op_state = %d\n", g_otgdev->core_if->op_state);
341 if (g_smb347_dev->info->otg_power_form_smb == 1) {
344 smb347_write(smb347_dev->client,0x0a,®,1);
346 suspend_smb347(smb347_dev);
348 smb347_dev->usb_host_in = 1;
349 } else if (g_otgdev->core_if->op_state != A_HOST && smb347_dev->usb_host_in == 1) {
351 xhc_printk("otg_dev->core_if->op_state = %d\n", g_otgdev->core_if->op_state);
352 if (g_smb347_dev->info->otg_power_form_smb == 1) {
354 smb347_write(smb347_dev->client,0x0a,®,1);
356 active_smb347(smb347_dev);
358 smb347_dev->usb_host_in = 0;
360 schedule_delayed_work(&smb347_dev->work, 100);
363 static int smb347_battery_probe(struct i2c_client *client,
364 const struct i2c_device_id *id)
367 struct smb347_device *smb347_dev;
368 struct smb347_info *info = client->dev.platform_data;;
370 xhc_printk("__xhc__%s, line = %d\n", __func__, __LINE__);
371 smb347_dev = kzalloc(sizeof(struct smb347_device), GFP_KERNEL);
372 smb347_dev->usb_host_in = 0;
374 dev_err(&client->dev, "failed to allocate device info data\n");
379 xhc_printk("__xhc__%s, line = %d\n", __func__, __LINE__);
380 i2c_set_clientdata(client, smb347_dev);
381 dev_set_drvdata(&client->dev,smb347_dev);
382 smb347_dev->client = client;
383 smb347_dev->info = info;
384 g_smb347_dev = smb347_dev;
385 wq = create_singlethread_workqueue("smb347_det");
387 if(info->chg_susp_pin) {
388 rk30_mux_api_set(GPIO4D1_SMCDATA9_TRACEDATA9_NAME, 0);
389 ret = gpio_request(info->chg_susp_pin, "chg susp pin");
391 gpio_free(info->chg_susp_pin);
392 xhc_printk("smb347 gpio_request chg_susp_pin error\n");
395 gpio_direction_output(info->chg_susp_pin, 0);
396 gpio_set_value(info->chg_susp_pin, GPIO_HIGH);
399 if(info->chg_ctl_pin) {
400 ret = gpio_request(info->chg_ctl_pin, "chg ctl pin");
402 gpio_free(info->chg_ctl_pin);
403 xhc_printk("smb347 gpio_request chg_ctl_pin error\n");
406 xhc_printk("__xhc__%s, line = %d\n", __func__, __LINE__);
407 gpio_direction_output(info->chg_ctl_pin, 0);
408 // gpio_set_value(info->chg_ctl_pin, GPIO_HIGH);
413 rk30_mux_api_set(GPIO4D5_SMCDATA13_TRACEDATA13_NAME, 0);
414 ret = gpio_request(info->chg_en_pin, "chg en pin");
416 gpio_free(info->chg_en_pin);
417 xhc_printk("smb347 gpio_request chg_en_pin error\n");
420 gpio_direction_output(info->chg_en_pin, 0);
421 gpio_set_value(info->chg_en_pin, GPIO_LOW);
426 INIT_DELAYED_WORK(&smb347_dev->work,smb347_set_current_work);
427 schedule_delayed_work(&smb347_dev->work, msecs_to_jiffies(3*1000));
429 ret = device_create_file(&client->dev,&smb_debug);
431 dev_err(&client->dev, "failed to create sysfs file\n");
438 static int smb347_battery_remove(struct i2c_client *client)
443 static int smb347_battery_suspend(struct i2c_client *client, pm_message_t mesg)
445 xhc_printk("__xhc__%s,", __func__);
449 static int smb347_battery_resume(struct i2c_client *client)
451 xhc_printk("__xhc__%s,", __func__);
454 static void smb347_battery_shutdown(struct i2c_client *client)
457 smb347_write(client,0x09,®,1);
458 xhc_printk("%s,----xhc----\n", __func__);
460 static const struct i2c_device_id smb347_id[] = {
465 static struct i2c_driver smb347_battery_driver = {
466 .probe = smb347_battery_probe,
467 .remove = smb347_battery_remove,
468 .suspend = smb347_battery_suspend,
469 .resume = smb347_battery_resume,
470 .shutdown = smb347_battery_shutdown,
472 .id_table = smb347_id,
478 static int __init smb347_battery_init(void)
482 ret = i2c_add_driver(&smb347_battery_driver);
484 xhc_printk(KERN_ERR "Unable to register smb347 driver\n");
489 static void __exit smb347_battery_exit(void)
491 if (g_smb347_dev->info->otg_power_form_smb != 1) {
492 active_smb347(g_smb347_dev);
494 i2c_del_driver(&smb347_battery_driver);
497 //subsys_initcall_sync(smb347_battery_init);
498 subsys_initcall(smb347_battery_init);
499 module_exit(smb347_battery_exit);
502 delay 500ms to fix the problam
503 that sometime limit 500ma when startup when insert the hc charger
505 static int __init delay_for_smb347(void)
507 xhc_printk("function: %s\n", __func__);
511 core_initcall(delay_for_smb347);
513 MODULE_AUTHOR("xhc@rock-chips.com");
514 MODULE_DESCRIPTION("smb347 battery monitor driver");
515 MODULE_LICENSE("GPL");