1515 */
1616
1717#include <linux/extcon.h>
18+ #include <linux/interrupt.h>
19+ #include <linux/irq.h>
1820#include <linux/kernel.h>
1921#include <linux/module.h>
22+ #include <linux/of_gpio.h>
2023#include <linux/platform_device.h>
2124#include <linux/power_supply.h>
2225#include <linux/power/rk_usbbc.h>
2326#include <linux/property.h>
27+ #include <linux/rk_keys.h>
2428#include <linux/workqueue.h>
2529
2630enum charger_t {
@@ -29,20 +33,27 @@ enum charger_t {
2933 USB_TYPE_USB_CHARGER ,
3034 USB_TYPE_AC_CHARGER ,
3135 USB_TYPE_CDP_CHARGER ,
36+ DC_TYPE_DC_CHARGER ,
37+ DC_TYPE_NONE_CHARGER ,
3238};
3339
3440struct sy6982c_charger {
3541 struct device * dev ;
3642 struct power_supply * usb_psy ;
3743 struct workqueue_struct * usb_charger_wq ;
3844 struct delayed_work usb_work ;
45+ struct workqueue_struct * dc_charger_wq ;
46+ struct delayed_work dc_work ;
3947 struct delayed_work discnt_work ;
4048 struct notifier_block cable_cg_nb ;
4149 struct notifier_block cable_discnt_nb ;
4250 unsigned int bc_event ;
4351 enum charger_t usb_charger ;
52+ enum charger_t dc_charger ;
4453 bool extcon ;
4554 struct extcon_dev * cable_edev ;
55+ struct gpio_desc * dc_det_pin ;
56+ bool support_dc_det ;
4657};
4758
4859static void sy6982c_cg_bc_evt_worker (struct work_struct * work )
@@ -190,6 +201,8 @@ static int sy6982c_cg_usb_get_property(struct power_supply *psy,
190201 if (cg -> usb_charger != USB_TYPE_UNKNOWN_CHARGER &&
191202 cg -> usb_charger != USB_TYPE_NONE_CHARGER )
192203 online = 1 ;
204+ if (cg -> dc_charger != DC_TYPE_NONE_CHARGER )
205+ online = 1 ;
193206 switch (psp ) {
194207 case POWER_SUPPLY_PROP_ONLINE :
195208 val -> intval = online ;
@@ -234,6 +247,97 @@ static int sy6982c_cg_init_power_supply(struct sy6982c_charger *cg)
234247 return 0 ;
235248}
236249
250+ #ifdef CONFIG_OF
251+ static int sy6982c_charger_parse_dt (struct sy6982c_charger * cg )
252+ {
253+ struct device * dev = cg -> dev ;
254+
255+ cg -> dc_det_pin = devm_gpiod_get_optional (dev , "dc-det" ,
256+ GPIOD_IN );
257+ if (!IS_ERR_OR_NULL (cg -> dc_det_pin )) {
258+ cg -> support_dc_det = true;
259+ } else {
260+ dev_err (dev , "invalid dc det gpio!\n" );
261+ cg -> support_dc_det = false;
262+ }
263+
264+ return 0 ;
265+ }
266+ #else
267+ static int sy6982c_charger_parse_dt (struct sy6982c_charger * cg )
268+ {
269+ return - ENODEV ;
270+ }
271+ #endif
272+
273+ static enum charger_t sy6982c_charger_get_dc_state (struct sy6982c_charger * cg )
274+ {
275+ return (gpiod_get_value (cg -> dc_det_pin )) ?
276+ DC_TYPE_DC_CHARGER : DC_TYPE_NONE_CHARGER ;
277+ }
278+
279+ static void sy6982c_charger_dc_det_worker (struct work_struct * work )
280+ {
281+ enum charger_t charger ;
282+ struct sy6982c_charger * cg = container_of (work ,
283+ struct sy6982c_charger , dc_work .work );
284+
285+ charger = sy6982c_charger_get_dc_state (cg );
286+ if (charger == DC_TYPE_DC_CHARGER )
287+ cg -> dc_charger = charger ;
288+ else
289+ cg -> dc_charger = DC_TYPE_NONE_CHARGER ;
290+
291+ rk_send_wakeup_key ();
292+ }
293+
294+ static irqreturn_t sy6982c_charger_dc_det_isr (int irq , void * charger )
295+ {
296+ struct sy6982c_charger * cg = (struct sy6982c_charger * )charger ;
297+
298+ queue_delayed_work (cg -> dc_charger_wq , & cg -> dc_work ,
299+ msecs_to_jiffies (10 ));
300+
301+ return IRQ_HANDLED ;
302+ }
303+
304+ static int sy6982c_charger_init_dc (struct sy6982c_charger * cg )
305+ {
306+ int ret ;
307+ unsigned long irq_flags ;
308+ unsigned int dc_det_irq ;
309+
310+ if (!cg -> support_dc_det )
311+ return 0 ;
312+
313+ cg -> dc_charger_wq = alloc_ordered_workqueue ("%s" ,
314+ WQ_MEM_RECLAIM | WQ_FREEZABLE ,
315+ "sy6982c-dc-wq" );
316+ if (!cg -> dc_charger_wq )
317+ return - EINVAL ;
318+
319+ INIT_DELAYED_WORK (& cg -> dc_work , sy6982c_charger_dc_det_worker );
320+ cg -> dc_charger = DC_TYPE_NONE_CHARGER ;
321+
322+ if (gpiod_get_value (cg -> dc_det_pin ))
323+ cg -> dc_charger = DC_TYPE_DC_CHARGER ;
324+ else
325+ cg -> dc_charger = DC_TYPE_NONE_CHARGER ;
326+
327+ irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING ,
328+ dc_det_irq = gpiod_to_irq (cg -> dc_det_pin );
329+ ret = devm_request_irq (cg -> dev , dc_det_irq , sy6982c_charger_dc_det_isr ,
330+ irq_flags , "sy6982c_dc_det" , cg );
331+ if (ret != 0 ) {
332+ dev_err (cg -> dev , "sy6982c_dc_det_irq request failed!\n" );
333+ return ret ;
334+ }
335+
336+ enable_irq_wake (dc_det_irq );
337+
338+ return 0 ;
339+ }
340+
237341static int sy6982c_charger_probe (struct platform_device * pdev )
238342{
239343 struct sy6982c_charger * cg ;
@@ -244,6 +348,8 @@ static int sy6982c_charger_probe(struct platform_device *pdev)
244348 return - ENOMEM ;
245349
246350 cg -> dev = & pdev -> dev ;
351+ sy6982c_charger_parse_dt (cg );
352+ sy6982c_charger_init_dc (cg );
247353 cg -> extcon = device_property_read_bool (cg -> dev , "extcon" );
248354 ret = sy6982c_cg_init_usb (cg );
249355 if (ret ) {
@@ -262,12 +368,14 @@ static int sy6982c_charger_probe(struct platform_device *pdev)
262368 return 0 ;
263369}
264370
265- static void sy6982c_charger_remove (struct platform_device * pdev )
371+ static int sy6982c_charger_remove (struct platform_device * pdev )
266372{
267373 struct sy6982c_charger * cg = platform_get_drvdata (pdev );
268374
269375 if (cg -> usb_charger_wq )
270376 destroy_workqueue (cg -> usb_charger_wq );
377+
378+ return 0 ;
271379}
272380
273381static const struct of_device_id sy6982c_charger_match [] = {
0 commit comments