mfd: fusb302: change to host when connect type-c to standard-a cable
[firefly-linux-kernel-4.4.55.git] / drivers / mfd / rt5025-misc.c
1 /*
2  *  drivers/mfd/rt5025-misc.c
3  *  Driver foo Richtek RT5025 PMIC Misc Part
4  *
5  *  Copyright (C) 2014 Richtek Technology Corp.
6  *  cy_huang <cy_huang@richtek.com>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  */
13
14 #include <linux/module.h>
15 #include <linux/kernel.h>
16 #include <linux/err.h>
17 #include <linux/i2c.h>
18 #include <linux/platform_device.h>
19 #include <linux/of.h>
20 #include <linux/power_supply.h>
21
22 #include <linux/mfd/rt5025.h>
23 #include <linux/mfd/rt5025-misc.h>
24
25 static unsigned char misc_init_regval[] = {
26         0x2A,   /* reg 0x15 */
27         0x00,   /* reg 0x16 */
28         0x60,   /* reg 0x17 */
29         0x16,   /* reg 0x19 */
30         0x60,   /* reg 0x1A */
31         0x0C,   /* reg 0x1B */
32         0xF3,   /* reg 0x36 */
33         0x90,   /* reg 0x38 */
34 };
35
36 static struct i2c_client *g_shdn;
37 static bool rt_pm_off;
38 static void rt5025_power_off(void)
39 {
40         rt5025_reg_write(g_shdn, RT5025_REG_CHANNELH, 0x00);
41         rt5025_reg_write(g_shdn, RT5025_REG_CHANNELL, 0x80);
42         rt5025_set_bits(g_shdn, RT5025_REG_MISC3, RT5025_SHDNCTRL_MASK);
43 }
44 EXPORT_SYMBOL(rt5025_power_off);
45
46 int rt5025_cable_exist(void)
47 {
48         int ret = 0;
49         #ifdef CONFIG_CHARGER_RT5025
50         struct power_supply *psy = power_supply_get_by_name("rt-charger");
51         union power_supply_propval pval;
52
53         if (!psy) {
54                 pr_err(" couldn't get charger power supply\n");
55         } else {
56                 ret = psy->get_property(psy,
57                         POWER_SUPPLY_PROP_CHARGE_NOW, &pval);
58                 if (ret < 0) {
59                         ret = 0;
60                 } else {
61                         if (pval.intval > POWER_SUPPLY_TYPE_BATTERY)
62                                 ret = 1;
63                         else
64                                 ret = 0;
65                 }
66         }
67         #else
68         ret = rt5025_reg_read(g_shdn, RT5025_REG_CHGCTL1);
69         if (ret < 0) {
70                 pr_err("couldn't get cable status\n");
71                 ret = 0;
72         } else {
73                 if (ret & RT5025_CABLEIN_MASK)
74                         ret = 1;
75                 else
76                         ret = 0;
77         }
78         #endif /* #ifdef CONFIG_CHARGER_RT5025 */
79         return ret;
80 }
81 EXPORT_SYMBOL(rt5025_cable_exist);
82
83 static void rt5025_general_irq_handler(void *info, int eventno)
84 {
85         struct rt5025_misc_info *mi = info;
86
87         RTINFO("eventno=%02d\n", eventno);
88
89         switch (eventno) {
90         case MISCEVENT_RESETB:
91                 dev_warn(mi->dev, "RESETB event trigger\n");
92                 break;
93         case MISCEVENT_KPSHDN:
94                 dev_warn(mi->dev, "PwrKey force shdn\n");
95                 break;
96         case MISCEVENT_SYSLV:
97                 dev_warn(mi->dev, "syslv event trigger\n");
98                 break;
99         case MISCEVENT_DCDC4LVHV:
100                 dev_warn(mi->dev, "DCDC4LVHV event trigger\n");
101                 break;
102         case MISCEVENT_DCDC3LV:
103                 dev_warn(mi->dev, "DCDC3LV event trigger\n");
104                 break;
105         case MISCEVENT_DCDC2LV:
106                 dev_warn(mi->dev, "DCDC2LV event trigger\n");
107                 break;
108         case MISCEVENT_DCDC1LV:
109                 dev_warn(mi->dev, "DCDC2LV event trigger\n");
110                 break;
111         case MISCEVENT_OT:
112                 dev_warn(mi->dev, "Over temperature event trigger\n");
113                 break;
114         default:
115                 break;
116         }
117 }
118
119 static rt_irq_handler rt_miscirq_handler[MISCEVENT_MAX] = {
120         [MISCEVENT_GPIO0_IE] = rt5025_general_irq_handler,
121         [MISCEVENT_GPIO1_IE] = rt5025_general_irq_handler,
122         [MISCEVENT_GPIO2_IE] = rt5025_general_irq_handler,
123         [MISCEVENT_RESETB] = rt5025_general_irq_handler,
124         [MISCEVENT_PWRONF] = rt5025_general_irq_handler,
125         [MISCEVENT_PWRONR] = rt5025_general_irq_handler,
126         [MISCEVENT_KPSHDN] = rt5025_general_irq_handler,
127         [MISCEVENT_SYSLV] = rt5025_general_irq_handler,
128         [MISCEVENT_DCDC4LVHV] = rt5025_general_irq_handler,
129         [MISCEVENT_PWRONLP_IRQ] = rt5025_general_irq_handler,
130         [MISCEVENT_PWRONSP_IRQ] = rt5025_general_irq_handler,
131         [MISCEVENT_DCDC3LV] = rt5025_general_irq_handler,
132         [MISCEVENT_DCDC2LV] = rt5025_general_irq_handler,
133         [MISCEVENT_DCDC1LV] = rt5025_general_irq_handler,
134         [MISCEVENT_OT] = rt5025_general_irq_handler,
135 };
136
137 void rt5025_misc_irq_handler(struct rt5025_misc_info *ci, unsigned int irqevent)
138 {
139         int i;
140         unsigned int enable_irq_event = (misc_init_regval[6] << 8) |
141                 misc_init_regval[7];
142         unsigned int final_irq_event = irqevent&enable_irq_event;
143
144         for (i = 0; i < MISCEVENT_MAX; i++) {
145                 if ((final_irq_event&(1 << i)) && rt_miscirq_handler[i])
146                         rt_miscirq_handler[i](ci, i);
147         }
148 }
149 EXPORT_SYMBOL(rt5025_misc_irq_handler);
150
151 static int  rt5025_misc_reginit(struct i2c_client *client)
152 {
153         rt5025_reg_write(client, RT5025_REG_MISC1, misc_init_regval[0]);
154         rt5025_reg_write(client, RT5025_REG_ONEVENT, misc_init_regval[1]);
155         rt5025_assign_bits(client, RT5025_REG_DCDCONOFF,
156                 RT5025_VSYSOFF_MASK, misc_init_regval[2]);
157         rt5025_reg_write(client, RT5025_REG_MISC2, misc_init_regval[3]);
158         rt5025_reg_write(client, RT5025_REG_MISC3, misc_init_regval[4]);
159         rt5025_reg_write(client, RT5025_REG_MISC4, misc_init_regval[5]);
160         /*set all to be masked*/
161         rt5025_reg_write(client, RT5025_REG_IRQEN4, 0x00);
162         rt5025_reg_write(client, RT5025_REG_IRQEN5, 0x00);
163         /*clear the old irq status*/
164         rt5025_reg_read(client, RT5025_REG_IRQSTAT4);
165         rt5025_reg_read(client, RT5025_REG_IRQSTAT5);
166         /*set enable irqs as we want*/
167         rt5025_reg_write(client, RT5025_REG_IRQEN4, misc_init_regval[6]);
168         rt5025_reg_write(client, RT5025_REG_IRQEN5, misc_init_regval[7]);
169         return 0;
170 }
171
172 static int rt_parse_dt(struct rt5025_misc_info *mi, struct device *dev)
173 {
174         int rc;
175         #ifdef CONFIG_OF
176         struct device_node *np = dev->of_node;
177         unsigned int val;
178
179         rc = of_property_read_u32(np, "rt,vsyslv", &val);
180         if (rc < 0) {
181                 dev_info(dev, "no system lv value, use default value\n");
182         } else {
183                 if (val > RT5025_VOFF_MAX)
184                         val = RT5025_VOFF_MAX;
185                 misc_init_regval[2] &= ~RT5025_VSYSOFF_MASK;
186                 misc_init_regval[2] |= val << RT5025_VSYSOFF_SHFT;
187         }
188
189         rc = of_property_read_u32(np, "rt,shdnlpress_time", &val);
190         if (rc < 0) {
191                 dev_info(dev, "no shdnlpress time, use default value\n");
192         } else {
193                 if (val > RT5025_SHDNPRESS_MAX)
194                         val = RT5025_SHDNPRESS_MAX;
195                 misc_init_regval[3] &= ~RT5025_SHDNLPRESS_MASK;
196                 misc_init_regval[3] |= val << RT5025_SHDNLPRESS_SHFT;
197         }
198
199         rc = of_property_read_u32(np, "rt,startlpress_time", &val);
200         if (rc < 0) {
201                 dev_err(dev, "no start_lpress, use default value\n");
202         } else {
203                 if (val > RT5025_STARTIME_MAX)
204                         val = RT5025_STARTIME_MAX;
205                 misc_init_regval[3] &= ~RT5025_STARTLPRESS_MASK;
206                 misc_init_regval[3] |= val << RT5025_STARTLPRESS_SHFT;
207         }
208
209         if (of_property_read_bool(np, "rt,vsyslv_enshdn"))
210                 misc_init_regval[5] |= RT5025_VSYSLVSHDN_MASK;
211         else
212                 misc_init_regval[5] &= ~RT5025_VSYSLVSHDN_MASK;
213         #endif
214
215         rt_pm_off = of_property_read_bool(np, "rt,system-power-controller");
216         /* #ifdef CONFIG_OF */
217         rc = rt5025_misc_reginit(mi->i2c);
218         return rc;
219 }
220
221 static int rt_parse_pdata(struct rt5025_misc_info *mi, struct device *dev)
222 {
223         struct rt5025_misc_data  *pdata = dev->platform_data;
224         int rc = 0;
225
226         /*system low voltage*/
227         misc_init_regval[2] &= ~RT5025_VSYSOFF_MASK;
228         misc_init_regval[2] |= (pdata->vsyslv << RT5025_VSYSOFF_SHFT);
229         /*shutdown long press time*/
230         misc_init_regval[3] &= ~RT5025_SHDNLPRESS_MASK;
231         misc_init_regval[3] |= (pdata->shdnlpress_time <<
232                 RT5025_SHDNLPRESS_SHFT);
233         /*start long press time*/
234         misc_init_regval[3] &= ~RT5025_STARTLPRESS_MASK;
235         misc_init_regval[3] |= (pdata->startlpress_time <<
236                 RT5025_STARTLPRESS_SHFT);
237         /*systemlv enable shutdown*/
238         misc_init_regval[5] &= ~RT5025_VSYSLVSHDN_MASK;
239         misc_init_regval[5] |= (pdata->vsyslv_enshdn <<
240                 RT5025_VSYSLVSHDN_SHFT);
241         rc = rt5025_misc_reginit(mi->i2c);
242         return rc;
243 }
244
245 static int rt5025_misc_probe(struct platform_device *pdev)
246 {
247         struct rt5025_chip *chip = dev_get_drvdata(pdev->dev.parent);
248         struct rt5025_platform_data *pdata = (pdev->dev.parent)->platform_data;
249         struct rt5025_misc_info *mi;
250         bool use_dt = pdev->dev.of_node;
251         int ret = 0;
252
253         mi = devm_kzalloc(&pdev->dev, sizeof(*mi), GFP_KERNEL);
254         if (!mi)
255                 return -ENOMEM;
256
257         mi->i2c = chip->i2c;
258         mi->dev = &pdev->dev;
259         if (use_dt) {
260                 rt_parse_dt(mi, &pdev->dev);
261         } else {
262                 if (!pdata) {
263                         dev_err(&pdev->dev, "no initial platform data\n");
264                         ret = -EINVAL;
265                         goto err_init;
266                 }
267                 pdev->dev.platform_data = pdata->misc_pdata;
268                 rt_parse_pdata(mi, &pdev->dev);
269         }
270         /*for shutdown control*/
271         g_shdn = chip->i2c;
272
273         if (rt_pm_off && !pm_power_off)
274                 pm_power_off = rt5025_power_off;
275
276         platform_set_drvdata(pdev, mi);
277         chip->misc_info = mi;
278         dev_info(&pdev->dev, "driver successfully loaded\n");
279         return 0;
280 err_init:
281         return ret;
282 }
283
284 static int rt5025_misc_remove(struct platform_device *pdev)
285 {
286         dev_info(&pdev->dev, "%s\n", __func__);
287         return 0;
288 }
289
290 static struct of_device_id rt_match_table[] = {
291         { .compatible = "rt,rt5025-misc",},
292         {},
293 };
294
295 static struct platform_driver rt5025_misc_driver = {
296         .driver = {
297                 .name = RT5025_DEV_NAME "-misc",
298                 .owner = THIS_MODULE,
299                 .of_match_table = rt_match_table,
300         },
301         .probe = rt5025_misc_probe,
302         .remove = rt5025_misc_remove,
303 };
304
305 static int rt5025_misc_init(void)
306 {
307         return platform_driver_register(&rt5025_misc_driver);
308 }
309 subsys_initcall(rt5025_misc_init);
310
311 static void rt5025_misc_exit(void)
312 {
313         platform_driver_unregister(&rt5025_misc_driver);
314 }
315 module_exit(rt5025_misc_exit);
316
317 MODULE_LICENSE("GPL");
318 MODULE_AUTHOR("CY Huang <cy_huang@richtek.com");
319 MODULE_DESCRIPTION("Misc driver for RT5025");
320 MODULE_ALIAS("platform:" RT5025_DEV_NAME "-misc");
321 MODULE_VERSION(RT5025_DRV_VER);