• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #define pr_fmt(x) KBUILD_MODNAME ": " x "\n"
2 
3 #include <linux/kernel.h>
4 #include <linux/module.h>
5 #include <linux/init.h>
6 #include "linux/irq.h"
7 #include <linux/slab.h>
8 #include <linux/interrupt.h>
9 #include <linux/device.h>
10 #include <linux/mutex.h>
11 #include <linux/param.h>
12 #include <linux/jiffies.h>
13 #include <linux/platform_device.h>
14 #include <linux/power_supply.h>
15 #include <linux/fs.h>
16 #include <linux/kernel.h>
17 #include <linux/ktime.h>
18 #include <linux/of.h>
19 #include <linux/timekeeping.h>
20 #include <linux/types.h>
21 #include <linux/string.h>
22 #include <asm/irq.h>
23 #include <linux/cdev.h>
24 #include <linux/delay.h>
25 #include <linux/pm_runtime.h>
26 #include <linux/kthread.h>
27 #include <linux/freezer.h>
28 #include <linux/err.h>
29 #include <sunxi-gpio.h>
30 #include <pinctrl/pinctrl-sunxi.h>
31 #include <linux/of_gpio.h>
32 #include "power/axp2101.h"
33 
34 #include <linux/err.h>
35 //#include "../drivers/gpio/gpiolib.h"
36 #include "axp2202_charger.h"
37 
38 struct axp2202_gpio_power {
39 	char                      *name;
40 	struct device             *dev;
41 	struct regmap             *regmap;
42 	struct power_supply       *gpio_supply;
43 	struct axp_config_info  dts_info;
44 	struct delayed_work        gpio_supply_mon;
45 	struct delayed_work        gpio_chg_state;
46 	struct gpio_config axp_acin_det;
47 	struct gpio_config usbid_drv;
48 	struct gpio_config axp_vbus_det;
49 	int acin_det_gpio_value;
50 };
51 
52 int ac_in_flag;
53 int vbus_in_flag;
54 
55 static enum power_supply_property axp2202_gpio_props[] = {
56 	POWER_SUPPLY_PROP_MODEL_NAME,
57 };
58 
axp2202_gpio_get_property(struct power_supply * psy,enum power_supply_property psp,union power_supply_propval * val)59 static int axp2202_gpio_get_property(struct power_supply *psy,
60 				       enum power_supply_property psp,
61 				       union power_supply_propval *val)
62 {
63 	int ret = 0;
64 
65 	switch (psp) {
66 	case POWER_SUPPLY_PROP_MODEL_NAME:
67 		val->strval = psy->desc->name;
68 		break;
69 	default:
70 		ret = -EINVAL;
71 	}
72 
73 	return ret;
74 }
75 
76 static const struct power_supply_desc axp2202_gpio_desc = {
77 	.name = "axp2202-gpio",
78 	.type = POWER_SUPPLY_TYPE_MAINS,
79 	.get_property = axp2202_gpio_get_property,
80 	.properties = axp2202_gpio_props,
81 	.num_properties = ARRAY_SIZE(axp2202_gpio_props),
82 };
83 
84 
axp2202_irq_handler_gpio_in(void * data)85 int axp2202_irq_handler_gpio_in(void *data)
86 {
87 	struct axp2202_gpio_power *gpio_power = data;
88 
89 	power_supply_changed(gpio_power->gpio_supply);
90 	ac_in_flag = 1;
91 
92 	return 0;
93 }
94 
axp2202_irq_handler_gpio_out(void * data)95 int axp2202_irq_handler_gpio_out(void *data)
96 {
97 	struct axp2202_gpio_power *gpio_power = data;
98 
99 	power_supply_changed(gpio_power->gpio_supply);
100 	ac_in_flag = 0;
101 
102 	return 0;
103 }
104 
axp_acin_gpio_isr(int irq,void * data)105 static irqreturn_t axp_acin_gpio_isr(int irq, void *data)
106 {
107 	struct axp2202_gpio_power *chg_dev = data;
108 	chg_dev->acin_det_gpio_value = __gpio_get_value(
109 			chg_dev->axp_acin_det.gpio);
110 
111 	if (chg_dev->acin_det_gpio_value == 1) {
112 		pr_info("[acin_irq] ac_in_flag = %d\n",
113 			ac_in_flag);
114 		pr_info("acin_det_gpio_value == 1\n\n");
115 		axp2202_irq_handler_gpio_in(chg_dev);
116 	} else {
117 		pr_info("[acout_irq] ac_in_flag = %d\n",
118 			ac_in_flag);
119 		pr_info("nacin_det_gpio_value == 0\n\n");
120 		axp2202_irq_handler_gpio_out(chg_dev);
121 	}
122 
123 	return IRQ_HANDLED;
124 }
125 
axp_vbus_det_isr(int irq,void * data)126 static irqreturn_t axp_vbus_det_isr(int irq, void *data)
127 {
128 	struct axp2202_gpio_power *chg_dev = data;
129 	chg_dev->acin_det_gpio_value = __gpio_get_value(
130 			chg_dev->axp_vbus_det.gpio);
131 
132 	if (chg_dev->acin_det_gpio_value == 1) {
133 		vbus_in_flag = 1;
134 		pr_info("[acin_irq] vbus_dev_flag = %d\n",
135 			vbus_in_flag);
136 		pr_info("vbus_det_gpio_value == 1\n\n");
137 	} else {
138 		vbus_in_flag = 0;
139 		pr_info("[acout_irq] vbus_dev_flag = %d\n",
140 			vbus_in_flag);
141 		pr_info("vbus_det_gpio_value == 0\n\n");
142 	}
143 
144 	return IRQ_HANDLED;
145 }
146 
147 enum axp2202_gpio_virq_index {
148 	AXP2202_VIRQ_GPIO,
149 	AXP2202_VBUS_DET,
150 };
151 
152 static struct axp_interrupts axp_gpio_irq[] = {
153 	[AXP2202_VIRQ_GPIO] = { "pmu_acin_det_gpio", axp_acin_gpio_isr },
154 	[AXP2202_VBUS_DET] = { "pmu_acin_det_gpio", axp_vbus_det_isr },
155 };
156 
axp_acin_gpio_init(struct axp2202_gpio_power * chg_dev)157 static int axp_acin_gpio_init(struct axp2202_gpio_power *chg_dev)
158 {
159 	unsigned long int config_set;
160 	int pull = 0;
161 
162 	int id_irq_num = 0;
163 	unsigned long irq_flags = 0;
164 	int ret = 0;
165 
166 	if (!gpio_is_valid(chg_dev->axp_acin_det.gpio)) {
167 		pr_err("ERR: get pmu_acin_det_gpio is fail\n");
168 		return -EINVAL;
169 	}
170 
171 	if (!gpio_is_valid(chg_dev->usbid_drv.gpio)) {
172 		pr_err("ERR: get pmu_usbid_drv_gpio is fail\n");
173 		return -EINVAL;
174 	}
175 
176 	if (!gpio_is_valid(chg_dev->axp_vbus_det.gpio)) {
177 		pr_err("ERR: get axp_vbus_det_gpio is fail\n");
178 		return -EINVAL;
179 	}
180 
181 	pr_info("axp_acin_gpio_init:%d, usbid_drv:%d, axp_vbus_det:%d\n",
182 			chg_dev->axp_acin_det.gpio, chg_dev->usbid_drv.gpio, chg_dev->axp_vbus_det.gpio);
183 
184 	ret = gpio_request(
185 			chg_dev->axp_acin_det.gpio,
186 			"pmu_acin_det_gpio");
187 
188 	if (ret != 0) {
189 		pr_err("ERR: pmu_acin_det gpio_request failed\n");
190 		return -EINVAL;
191 	}
192 
193 	ret = gpio_request(
194 			chg_dev->usbid_drv.gpio,
195 			"pmu_acin_usbid_drv");
196 
197 	if (ret != 0) {
198 		pr_err("ERR: pmu_usbid_drv gpio_request failed\n");
199 		return -EINVAL;
200 	}
201 
202 	ret = gpio_request(
203 			chg_dev->axp_vbus_det.gpio,
204 			"pmu_vbus_det_gpio");
205 
206 	if (ret != 0) {
207 		pr_err("ERR: pmu_vbus_det_gpio gpio_request failed\n");
208 		return -EINVAL;
209 	}
210 
211 
212 	/* set acin input usbid output */
213 
214 	gpio_direction_input(chg_dev->axp_acin_det.gpio);
215 	gpio_direction_output(chg_dev->usbid_drv.gpio, 1);
216 	gpio_direction_input(chg_dev->axp_vbus_det.gpio);
217 
218 	/* set id gpio pull up */
219 	config_set = SUNXI_PINCFG_PACK(
220 				PIN_CONFIG_BIAS_PULL_UP,
221 				pull);
222 	pinctrl_gpio_set_config(chg_dev->axp_acin_det.gpio,
223 			config_set);
224 
225 	id_irq_num = gpio_to_irq(chg_dev->axp_acin_det.gpio);
226 
227 	if (IS_ERR_VALUE((unsigned long)id_irq_num)) {
228 		pr_err("ERR: map pmu_acin_det gpio to virq failed, err %d\n",
229 			   id_irq_num);
230 		return -EINVAL;
231 	}
232 
233 	axp_gpio_irq[0].irq = id_irq_num;
234 
235 	pr_info("acin_id_irq_num:%d, %d \n", axp_gpio_irq[0].irq, id_irq_num);
236 
237 	irq_flags = IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING |
238 			IRQF_ONESHOT | IRQF_NO_SUSPEND;
239 	ret = request_irq(id_irq_num, axp_gpio_irq[0].isr, irq_flags,
240 			axp_gpio_irq[0].name, chg_dev);
241 
242 
243 	if (IS_ERR_VALUE((unsigned long)ret)) {
244 		pr_err("ERR: request pmu_acin_det virq %d failed, err %d\n",
245 			 id_irq_num, ret);
246 		return -EINVAL;
247 	}
248 
249 	dev_dbg(chg_dev->dev, "Requested %s IRQ %d: %d\n",
250 		axp_gpio_irq[0].name, id_irq_num, ret);
251 
252 	/* set id vbus_det pull up */
253 	config_set = SUNXI_PINCFG_PACK(
254 				PIN_CONFIG_BIAS_PULL_UP,
255 				pull);
256 	pinctrl_gpio_set_config(chg_dev->axp_vbus_det.gpio,
257 			config_set);
258 
259 	id_irq_num = gpio_to_irq(chg_dev->axp_vbus_det.gpio);
260 
261 	if (IS_ERR_VALUE((unsigned long)id_irq_num)) {
262 		pr_err("ERR: map pmu_vbus_det gpio to virq failed, err %d\n",
263 			   id_irq_num);
264 		return -EINVAL;
265 	}
266 
267 	axp_gpio_irq[1].irq = id_irq_num;
268 
269 	pr_info("vbus_det_irq_num:%d, %d \n", axp_gpio_irq[1].irq, id_irq_num);
270 
271 	irq_flags = IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING |
272 			IRQF_ONESHOT | IRQF_NO_SUSPEND;
273 	ret = request_irq(id_irq_num, axp_gpio_irq[1].isr, irq_flags,
274 			axp_gpio_irq[1].name, chg_dev);
275 
276 
277 	if (IS_ERR_VALUE((unsigned long)ret)) {
278 		pr_err("ERR: request pmu_vbus_det virq %d failed, err %d\n",
279 			 id_irq_num, ret);
280 		return -EINVAL;
281 	}
282 
283 	dev_dbg(chg_dev->dev, "Requested %s IRQ %d: %d\n",
284 		axp_gpio_irq[1].name, id_irq_num, ret);
285 
286 	return 0;
287 }
288 
289 
axp2202_gpio_power_monitor(struct work_struct * work)290 static void axp2202_gpio_power_monitor(struct work_struct *work)
291 {
292 	struct axp2202_gpio_power *gpio_power =
293 		container_of(work, typeof(*gpio_power), gpio_supply_mon.work);
294 
295 	unsigned int reg_value;
296 	int gpio_value;
297 
298 	gpio_value = __gpio_get_value(gpio_power->axp_acin_det.gpio);
299 	regmap_read(gpio_power->regmap, AXP2202_CC_STAT0, &reg_value);
300 	reg_value &= AXP2202_OTG_MARK;
301 
302 	if ((reg_value == 0x06) | (reg_value == 0x09) | (reg_value == 0x0c)) {
303 		pr_info("\n\nset_otg_type: %s , %d \n", __func__, __LINE__);
304 		if (!gpio_value) {
305 			regmap_update_bits(gpio_power->regmap, AXP2202_MODULE_EN, AXP2202_CHARGER_ENABLE_MARK, 0);
306 			pr_info("\n\nset_otg_type_disable_charger: %s , %d \n", __func__, __LINE__);
307 		}
308 		gpio_direction_output(gpio_power->usbid_drv.gpio, 0);
309 	} else {
310 		regmap_update_bits(gpio_power->regmap, AXP2202_MODULE_EN, AXP2202_CHARGER_ENABLE_MARK, AXP2202_CHARGER_ENABLE_MARK);
311 		pr_info("\n\nset_no_otg_type_enable_charger: %s , %d \n", __func__, __LINE__);
312 
313 		gpio_direction_output(gpio_power->usbid_drv.gpio, 1);
314 
315 	}
316 
317 	schedule_delayed_work(&gpio_power->gpio_supply_mon, msecs_to_jiffies(500));
318 }
319 
320 
axp2202_gpio_power_init(struct axp2202_gpio_power * gpio_power)321 static void axp2202_gpio_power_init(struct axp2202_gpio_power *gpio_power)
322 {
323 
324 }
325 
326 
axp2202_gpio_dt_parse(struct device_node * node,struct axp_config_info * axp_config)327 int axp2202_gpio_dt_parse(struct device_node *node,
328 			 struct axp_config_info *axp_config)
329 {
330 	axp_config->wakeup_gpio =
331 		of_property_read_bool(node, "wakeup_gpio");
332 
333 	return 0;
334 }
335 
axp2202_gpio_parse_device_tree(struct axp2202_gpio_power * gpio_power)336 static void axp2202_gpio_parse_device_tree(struct axp2202_gpio_power *gpio_power)
337 {
338 	int ret;
339 	struct axp_config_info *cfg;
340 
341 	/* set input current limit */
342 	if (!gpio_power->dev->of_node) {
343 		pr_info("can not find device tree\n");
344 		return;
345 	}
346 
347 	cfg = &gpio_power->dts_info;
348 	ret = axp2202_gpio_dt_parse(gpio_power->dev->of_node, cfg);
349 	if (ret) {
350 		pr_info("can not parse device tree err\n");
351 		return;
352 	}
353 
354 	/*init axp2202 gpio by device tree*/
355 	axp2202_gpio_power_init(gpio_power);
356 }
357 
358 
axp2202_gpio_probe(struct platform_device * pdev)359 static int axp2202_gpio_probe(struct platform_device *pdev)
360 {
361 	int ret = 0;
362 
363 	struct axp2202_gpio_power *gpio_power;
364 
365 	struct device_node *node = pdev->dev.of_node;
366 	struct axp20x_dev *axp_dev = dev_get_drvdata(pdev->dev.parent);
367 	struct power_supply_config psy_cfg = {};
368 
369 	if (!of_device_is_available(node)) {
370 		pr_err("axp2202-gpio device is not configed\n");
371 		return -ENODEV;
372 	}
373 
374 	if (!axp_dev->irq) {
375 		pr_err("can not register axp2202-gpio without irq\n");
376 		return -EINVAL;
377 	}
378 
379 	gpio_power = devm_kzalloc(&pdev->dev, sizeof(*gpio_power), GFP_KERNEL);
380 	if (gpio_power == NULL) {
381 		pr_err("axp2202_gpio_power alloc failed\n");
382 		ret = -ENOMEM;
383 		goto err;
384 	}
385 
386 	gpio_power->name = "axp2202_gpio";
387 	gpio_power->dev = &pdev->dev;
388 	gpio_power->regmap = axp_dev->regmap;
389 
390 	/* parse device tree and set register */
391 	axp2202_gpio_parse_device_tree(gpio_power);
392 
393 	psy_cfg.of_node = pdev->dev.of_node;
394 	psy_cfg.drv_data = gpio_power;
395 
396 	gpio_power->gpio_supply = devm_power_supply_register(gpio_power->dev,
397 			&axp2202_gpio_desc, &psy_cfg);
398 
399 	if (IS_ERR(gpio_power->gpio_supply)) {
400 		pr_err("axp2202 failed to register gpio power\n");
401 		ret = PTR_ERR(gpio_power->gpio_supply);
402 		return ret;
403 	}
404 
405 	gpio_power->axp_acin_det.gpio =
406 		of_get_named_gpio(pdev->dev.of_node,
407 				"pmu_acin_det_gpio", 0);
408 
409 	gpio_power->usbid_drv.gpio =
410 		of_get_named_gpio(pdev->dev.of_node,
411 				"pmu_acin_usbid_drv", 0);
412 
413 	gpio_power->axp_vbus_det.gpio =
414 		of_get_named_gpio(pdev->dev.of_node,
415 				"pmu_vbus_det_gpio", 0);
416 
417 	if (gpio_is_valid(gpio_power->axp_acin_det.gpio)) {
418 		if (gpio_is_valid(gpio_power->usbid_drv.gpio)) {
419 			if (gpio_is_valid(gpio_power->axp_vbus_det.gpio)) {
420 				ret = axp_acin_gpio_init(gpio_power);
421 			if (ret != 0)
422 				pr_err("axp acin init failed\n");
423 			} else {
424 				pr_info("get pmu_vbus_det_gpio is fail\n");
425 			}
426 		} else {
427 			pr_info("get pmu_acin_usbid_drv is fail\n");
428 		}
429 	} else {
430 		pr_info("get pmu_acin_det_gpio is fail\n");
431 	}
432 
433 	platform_set_drvdata(pdev, gpio_power);
434 	printk("axp2202_gpio_probe: %s , %d \n", __func__, __LINE__);
435 
436 	INIT_DELAYED_WORK(&gpio_power->gpio_supply_mon, axp2202_gpio_power_monitor);
437 	schedule_delayed_work(&gpio_power->gpio_supply_mon, msecs_to_jiffies(500));
438 
439 	return ret;
440 
441 err:
442 	pr_err("%s,probe fail, ret = %d\n", __func__, ret);
443 
444 	return ret;
445 }
446 
447 
axp2202_gpio_remove(struct platform_device * pdev)448 static int axp2202_gpio_remove(struct platform_device *pdev)
449 {
450 	struct axp2202_gpio_power *gpio_power = platform_get_drvdata(pdev);
451 
452 	cancel_delayed_work_sync(&gpio_power->gpio_supply_mon);
453 	cancel_delayed_work_sync(&gpio_power->gpio_chg_state);
454 
455 	dev_dbg(&pdev->dev, "==============AXP2202 gpio unegister==============\n");
456 	if (gpio_power->gpio_supply)
457 		power_supply_unregister(gpio_power->gpio_supply);
458 	dev_dbg(&pdev->dev, "axp2202 teardown gpio dev\n");
459 
460 	return 0;
461 }
462 
463 
464 
axp2202_gpio_irq_set(unsigned int irq,bool enable)465 static inline void axp2202_gpio_irq_set(unsigned int irq, bool enable)
466 {
467 	if (enable)
468 		enable_irq(irq);
469 	else
470 		disable_irq(irq);
471 }
472 
axp2202_gpio_virq_dts_set(struct axp2202_gpio_power * gpio_power,bool enable)473 static void axp2202_gpio_virq_dts_set(struct axp2202_gpio_power *gpio_power, bool enable)
474 {
475 	struct axp_config_info *dts_info = &gpio_power->dts_info;
476 
477 	if (!dts_info->wakeup_gpio)
478 		axp2202_gpio_irq_set(axp_gpio_irq[AXP2202_VIRQ_GPIO].irq,
479 				enable);
480 }
481 
axp2202_gpio_suspend(struct platform_device * p,pm_message_t state)482 static int axp2202_gpio_suspend(struct platform_device *p, pm_message_t state)
483 {
484 	struct axp2202_gpio_power *gpio_power = platform_get_drvdata(p);
485 
486 
487 	axp2202_gpio_virq_dts_set(gpio_power, false);
488 	return 0;
489 }
490 
axp2202_gpio_resume(struct platform_device * p)491 static int axp2202_gpio_resume(struct platform_device *p)
492 {
493 	struct axp2202_gpio_power *gpio_power = platform_get_drvdata(p);
494 
495 
496 	axp2202_gpio_virq_dts_set(gpio_power, true);
497 
498 	return 0;
499 }
500 
501 static const struct of_device_id axp2202_gpio_power_match[] = {
502 	{
503 		.compatible = "x-powers,gpio-supply",
504 		.data = (void *)AXP2202_ID,
505 	}, {/* sentinel */}
506 };
507 MODULE_DEVICE_TABLE(of, axp2202_gpio_power_match);
508 
509 static struct platform_driver axp2202_gpio_power_driver = {
510 	.driver = {
511 		.name = "gpio-supply",
512 		.of_match_table = axp2202_gpio_power_match,
513 	},
514 	.probe = axp2202_gpio_probe,
515 	.remove = axp2202_gpio_remove,
516 	.suspend = axp2202_gpio_suspend,
517 	.resume = axp2202_gpio_resume,
518 };
519 
520 module_platform_driver(axp2202_gpio_power_driver);
521 
522 MODULE_AUTHOR("wangxiaoliang <wangxiaoliang@x-powers.com>");
523 MODULE_DESCRIPTION("axp2202 gpio driver");
524 MODULE_LICENSE("GPL");
525 
526