2 * drivers/mfd/rt5025-misc.c
3 * Driver foo Richtek RT5025 PMIC Misc Part
5 * Copyright (C) 2014 Richtek Technology Corp.
6 * cy_huang <cy_huang@richtek.com>
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.
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>
20 #include <linux/power_supply.h>
22 #include <linux/mfd/rt5025.h>
23 #include <linux/mfd/rt5025-misc.h>
25 static unsigned char misc_init_regval[] = {
36 static struct i2c_client *g_shdn;
37 static bool rt_pm_off;
38 static void rt5025_power_off(void)
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);
44 EXPORT_SYMBOL(rt5025_power_off);
46 int rt5025_cable_exist(void)
49 #ifdef CONFIG_CHARGER_RT5025
50 struct power_supply *psy = power_supply_get_by_name("rt-charger");
51 union power_supply_propval pval;
54 pr_err(" couldn't get charger power supply\n");
56 ret = psy->get_property(psy,
57 POWER_SUPPLY_PROP_CHARGE_NOW, &pval);
61 if (pval.intval > POWER_SUPPLY_TYPE_BATTERY)
68 ret = rt5025_reg_read(g_shdn, RT5025_REG_CHGCTL1);
70 pr_err("couldn't get cable status\n");
73 if (ret & RT5025_CABLEIN_MASK)
78 #endif /* #ifdef CONFIG_CHARGER_RT5025 */
81 EXPORT_SYMBOL(rt5025_cable_exist);
83 static void rt5025_general_irq_handler(void *info, int eventno)
85 struct rt5025_misc_info *mi = info;
87 RTINFO("eventno=%02d\n", eventno);
90 case MISCEVENT_RESETB:
91 dev_warn(mi->dev, "RESETB event trigger\n");
93 case MISCEVENT_KPSHDN:
94 dev_warn(mi->dev, "PwrKey force shdn\n");
97 dev_warn(mi->dev, "syslv event trigger\n");
99 case MISCEVENT_DCDC4LVHV:
100 dev_warn(mi->dev, "DCDC4LVHV event trigger\n");
102 case MISCEVENT_DCDC3LV:
103 dev_warn(mi->dev, "DCDC3LV event trigger\n");
105 case MISCEVENT_DCDC2LV:
106 dev_warn(mi->dev, "DCDC2LV event trigger\n");
108 case MISCEVENT_DCDC1LV:
109 dev_warn(mi->dev, "DCDC2LV event trigger\n");
112 dev_warn(mi->dev, "Over temperature event trigger\n");
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,
137 void rt5025_misc_irq_handler(struct rt5025_misc_info *ci, unsigned int irqevent)
140 unsigned int enable_irq_event = (misc_init_regval[6] << 8) |
142 unsigned int final_irq_event = irqevent&enable_irq_event;
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);
149 EXPORT_SYMBOL(rt5025_misc_irq_handler);
151 static int rt5025_misc_reginit(struct i2c_client *client)
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]);
172 static int rt_parse_dt(struct rt5025_misc_info *mi, struct device *dev)
176 struct device_node *np = dev->of_node;
179 rc = of_property_read_u32(np, "rt,vsyslv", &val);
181 dev_info(dev, "no system lv value, use default value\n");
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;
189 rc = of_property_read_u32(np, "rt,shdnlpress_time", &val);
191 dev_info(dev, "no shdnlpress time, use default value\n");
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;
199 rc = of_property_read_u32(np, "rt,startlpress_time", &val);
201 dev_err(dev, "no start_lpress, use default value\n");
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;
209 if (of_property_read_bool(np, "rt,vsyslv_enshdn"))
210 misc_init_regval[5] |= RT5025_VSYSLVSHDN_MASK;
212 misc_init_regval[5] &= ~RT5025_VSYSLVSHDN_MASK;
215 rt_pm_off = of_property_read_bool(np, "rt,system-power-controller");
216 /* #ifdef CONFIG_OF */
217 rc = rt5025_misc_reginit(mi->i2c);
221 static int rt_parse_pdata(struct rt5025_misc_info *mi, struct device *dev)
223 struct rt5025_misc_data *pdata = dev->platform_data;
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);
245 static int rt5025_misc_probe(struct platform_device *pdev)
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;
253 mi = devm_kzalloc(&pdev->dev, sizeof(*mi), GFP_KERNEL);
258 mi->dev = &pdev->dev;
260 rt_parse_dt(mi, &pdev->dev);
263 dev_err(&pdev->dev, "no initial platform data\n");
267 pdev->dev.platform_data = pdata->misc_pdata;
268 rt_parse_pdata(mi, &pdev->dev);
270 /*for shutdown control*/
273 if (rt_pm_off && !pm_power_off)
274 pm_power_off = rt5025_power_off;
276 platform_set_drvdata(pdev, mi);
277 chip->misc_info = mi;
278 dev_info(&pdev->dev, "driver successfully loaded\n");
284 static int rt5025_misc_remove(struct platform_device *pdev)
286 dev_info(&pdev->dev, "%s\n", __func__);
290 static struct of_device_id rt_match_table[] = {
291 { .compatible = "rt,rt5025-misc",},
295 static struct platform_driver rt5025_misc_driver = {
297 .name = RT5025_DEV_NAME "-misc",
298 .owner = THIS_MODULE,
299 .of_match_table = rt_match_table,
301 .probe = rt5025_misc_probe,
302 .remove = rt5025_misc_remove,
305 static int rt5025_misc_init(void)
307 return platform_driver_register(&rt5025_misc_driver);
309 subsys_initcall(rt5025_misc_init);
311 static void rt5025_misc_exit(void)
313 platform_driver_unregister(&rt5025_misc_driver);
315 module_exit(rt5025_misc_exit);
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);