tizen 2.4 release
[profile/mobile/platform/kernel/linux-3.10-sc7730.git] / drivers / power / sprd_charge_ext.c
1 /*
2  * Copyright (C) 2012 Spreadtrum Communications Inc.
3  *
4  * This software is licensed under the terms of the GNU General Public
5  * License version 2, as published by the Free Software Foundation, and
6  * may be copied, distributed, and modified under those terms.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  */
13 #ifdef SPRDBAT_TWO_CHARGE_CHANNEL
14
15 #include <linux/kernel.h>
16 #include <linux/module.h>
17 #include <linux/err.h>
18 #include <linux/platform_device.h>
19 #include <linux/power_supply.h>
20 #include <linux/types.h>
21 #include <linux/pci.h>
22 #include <linux/interrupt.h>
23 #include <asm/io.h>
24 #include <linux/hrtimer.h>
25 #include <linux/spinlock.h>
26 #include <linux/gpio.h>
27 #include <linux/irq.h>
28 #include <linux/wakelock.h>
29 #include <linux/delay.h>
30 #include <mach/hardware.h>
31 #include <mach/adi.h>
32 #include <mach/adc.h>
33 #include <mach/gpio.h>
34 #include <linux/device.h>
35
36 #include <linux/slab.h>
37 #include <linux/jiffies.h>
38 #include "sprd_battery.h"
39 #include <mach/usb.h>
40
41 struct sprdchg_drivier_data_ext {
42     uint32_t gpio_vchg_ovi;
43     uint32_t irq_vchg_ovi;
44     uint32_t gpio_charge_en;
45     uint32_t gpio_charge_done;
46     struct work_struct ovi_irq_work;
47 };
48 static struct sprdchg_drivier_data_ext sprdchg_ext_ic;
49
50 int sprdchg_is_chg_done_ext(void)
51 {
52         return gpio_get_value(sprdchg_ext_ic.gpio_charge_done);
53 }
54
55 void sprdchg_start_charge_ext(void)
56 {
57         gpio_set_value(sprdchg_ext_ic.gpio_charge_en, 0);
58 }
59
60 void sprdchg_stop_charge_ext(void)
61 {
62         gpio_set_value(sprdchg_ext_ic.gpio_charge_en, 1);
63 }
64
65 void sprdchg_open_ovi_fun_ext(void)
66 {
67         irq_set_irq_type(sprdchg_ext_ic.irq_vchg_ovi, IRQ_TYPE_LEVEL_HIGH);
68         enable_irq(sprdchg_ext_ic.irq_vchg_ovi);
69 }
70
71 void sprdchg_close_ovi_fun_ext(void)
72 {
73         disable_irq_nosync(sprdchg_ext_ic.irq_vchg_ovi);
74 }
75
76 static void sprdchg_ovi_irq_works_ext(struct work_struct *work)
77 {
78         int value;
79         value = gpio_get_value(sprdchg_ext_ic.gpio_vchg_ovi);
80         if (value) {
81                 sprdbat_charge_event_ext(SPRDBAT_CHG_EVENT_EXT_OVI);
82         } else {
83                 sprdbat_charge_event_ext(SPRDBAT_CHG_EVENT_EXT_OVI_RESTART);
84         }
85 }
86
87 static __used irqreturn_t sprdchg_vchg_ovi_irq_ext(int irq, void *dev_id)
88 {
89         int value;
90         value = gpio_get_value(sprdchg_ext_ic.gpio_vchg_ovi);
91         if (value) {
92                 printk("sprdchg_vchg_ovi_irq_ext ovi high\n");
93                 irq_set_irq_type(sprdchg_ext_ic.irq_vchg_ovi, IRQ_TYPE_LEVEL_LOW);
94         } else {
95                 printk("sprdchg_vchg_ovi_irq_ext ovi low\n");
96                 irq_set_irq_type(sprdchg_ext_ic.irq_vchg_ovi, IRQ_TYPE_LEVEL_HIGH);
97         }
98         schedule_work(&sprdchg_ext_ic.ovi_irq_work);
99         return IRQ_HANDLED;
100 }
101
102 int sprdchg_charge_init_ext(struct platform_device *pdev)
103 {
104         int ret = -ENODEV;
105         struct resource *res = NULL;
106
107         res = platform_get_resource(pdev, IORESOURCE_IO, 3);
108         sprdchg_ext_ic.gpio_charge_done = res->start;
109         res = platform_get_resource(pdev, IORESOURCE_IO, 4);
110         sprdchg_ext_ic.gpio_charge_en = res->start;
111         res = platform_get_resource(pdev, IORESOURCE_IO, 5);
112         sprdchg_ext_ic.gpio_vchg_ovi = res->start;
113         gpio_request(sprdchg_ext_ic.gpio_vchg_ovi, "vchg_ovi_ext");
114         gpio_direction_input(sprdchg_ext_ic.gpio_vchg_ovi);
115         sprdchg_ext_ic.irq_vchg_ovi = gpio_to_irq(sprdchg_ext_ic.gpio_vchg_ovi);
116         set_irq_flags(sprdchg_ext_ic.irq_vchg_ovi, IRQF_VALID | IRQF_NOAUTOEN);
117         ret = request_irq(sprdchg_ext_ic.irq_vchg_ovi, sprdchg_vchg_ovi_irq_ext,
118                     IRQF_NO_SUSPEND, "sprdbat_vchg_ovi_ext", NULL);
119         INIT_WORK(&sprdchg_ext_ic.ovi_irq_work, sprdchg_ovi_irq_works_ext);
120         gpio_request(sprdchg_ext_ic.gpio_charge_done, "chg_done_ext");
121         gpio_direction_input(sprdchg_ext_ic.gpio_charge_done);
122         gpio_request(sprdchg_ext_ic.gpio_charge_en, "charge_en_ext");
123         gpio_direction_output(sprdchg_ext_ic.gpio_charge_en, 1);
124         sprdchg_stop_charge_ext();
125         return ret;
126 }
127
128 void sprdchg_chg_monitor_cb_ext(void *data)
129 {
130         return;
131 }
132
133 #endif /*  */