11/*
22 * bq2415x charger driver
33 *
4- * Copyright (C) 2011-2012 Pali Rohár <[email protected] > 4+ * Copyright (C) 2011-2013 Pali Rohár <[email protected] > 55 *
66 * This program is free software; you can redistribute it and/or modify
77 * it under the terms of the GNU General Public License as published by
@@ -170,6 +170,8 @@ struct bq2415x_device {
170170 struct bq2415x_platform_data init_data ;
171171 struct power_supply charger ;
172172 struct delayed_work work ;
173+ struct power_supply * notify_psy ;
174+ struct notifier_block nb ;
173175 enum bq2415x_mode reported_mode ;/* mode reported by hook function */
174176 enum bq2415x_mode mode ; /* current configured mode */
175177 enum bq2415x_chip chip ;
@@ -795,24 +797,53 @@ static int bq2415x_set_mode(struct bq2415x_device *bq, enum bq2415x_mode mode)
795797
796798}
797799
798- /* hook function called by other driver which set reported mode */
799- static void bq2415x_hook_function ( enum bq2415x_mode mode , void * data )
800+ static int bq2415x_notifier_call ( struct notifier_block * nb ,
801+ unsigned long val , void * v )
800802{
801- struct bq2415x_device * bq = data ;
803+ struct bq2415x_device * bq =
804+ container_of (nb , struct bq2415x_device , nb );
805+ struct power_supply * psy = v ;
806+ enum bq2415x_mode mode ;
807+ union power_supply_propval prop ;
808+ int ret ;
809+ int mA ;
802810
803- if (!bq )
804- return ;
811+ if (val != PSY_EVENT_PROP_CHANGED )
812+ return NOTIFY_OK ;
813+
814+ if (psy != bq -> notify_psy )
815+ return NOTIFY_OK ;
816+
817+ dev_dbg (bq -> dev , "notifier call was called\n" );
818+
819+ ret = psy -> get_property (psy , POWER_SUPPLY_PROP_CURRENT_MAX , & prop );
820+ if (ret != 0 )
821+ return NOTIFY_OK ;
822+
823+ mA = prop .intval ;
824+
825+ if (mA == 0 )
826+ mode = BQ2415X_MODE_OFF ;
827+ else if (mA < 500 )
828+ mode = BQ2415X_MODE_NONE ;
829+ else if (mA < 1800 )
830+ mode = BQ2415X_MODE_HOST_CHARGER ;
831+ else
832+ mode = BQ2415X_MODE_DEDICATED_CHARGER ;
833+
834+ if (bq -> reported_mode == mode )
835+ return NOTIFY_OK ;
805836
806- dev_dbg (bq -> dev , "hook function was called\n" );
807837 bq -> reported_mode = mode ;
808838
809839 /* if automode is not enabled do not tell about reported_mode */
810840 if (bq -> automode < 1 )
811- return ;
841+ return NOTIFY_OK ;
812842
813843 sysfs_notify (& bq -> charger .dev -> kobj , NULL , "reported_mode" );
814844 bq2415x_set_mode (bq , bq -> reported_mode );
815845
846+ return NOTIFY_OK ;
816847}
817848
818849/**** timer functions ****/
@@ -1512,9 +1543,11 @@ static int bq2415x_probe(struct i2c_client *client,
15121543 int num ;
15131544 char * name ;
15141545 struct bq2415x_device * bq ;
1546+ struct device_node * np = client -> dev .of_node ;
1547+ struct bq2415x_platform_data * pdata = client -> dev .platform_data ;
15151548
1516- if (!client -> dev . platform_data ) {
1517- dev_err (& client -> dev , "platform data not set \n" );
1549+ if (!np && ! pdata ) {
1550+ dev_err (& client -> dev , "platform data missing \n" );
15181551 return - ENODEV ;
15191552 }
15201553
@@ -1539,6 +1572,17 @@ static int bq2415x_probe(struct i2c_client *client,
15391572 goto error_2 ;
15401573 }
15411574
1575+ if (np ) {
1576+ bq -> notify_psy = power_supply_get_by_phandle (np , "ti,usb-charger-detection" );
1577+
1578+ if (!bq -> notify_psy )
1579+ return - EPROBE_DEFER ;
1580+ }
1581+ else if (pdata -> notify_device )
1582+ bq -> notify_psy = power_supply_get_by_name (pdata -> notify_device );
1583+ else
1584+ bq -> notify_psy = NULL ;
1585+
15421586 i2c_set_clientdata (client , bq );
15431587
15441588 bq -> id = num ;
@@ -1550,8 +1594,34 @@ static int bq2415x_probe(struct i2c_client *client,
15501594 bq -> autotimer = 0 ;
15511595 bq -> automode = 0 ;
15521596
1553- memcpy (& bq -> init_data , client -> dev .platform_data ,
1554- sizeof (bq -> init_data ));
1597+ if (np ) {
1598+ ret = of_property_read_u32 (np , "ti,current-limit" ,
1599+ & bq -> init_data .current_limit );
1600+ if (ret )
1601+ return ret ;
1602+ ret = of_property_read_u32 (np , "ti,weak-battery-voltage" ,
1603+ & bq -> init_data .weak_battery_voltage );
1604+ if (ret )
1605+ return ret ;
1606+ ret = of_property_read_u32 (np , "ti,battery-regulation-voltage" ,
1607+ & bq -> init_data .battery_regulation_voltage );
1608+ if (ret )
1609+ return ret ;
1610+ ret = of_property_read_u32 (np , "ti,charge-current" ,
1611+ & bq -> init_data .charge_current );
1612+ if (ret )
1613+ return ret ;
1614+ ret = of_property_read_u32 (np , "ti,termination-current" ,
1615+ & bq -> init_data .termination_current );
1616+ if (ret )
1617+ return ret ;
1618+ ret = of_property_read_u32 (np , "ti,resistor-sense" ,
1619+ & bq -> init_data .resistor_sense );
1620+ if (ret )
1621+ return ret ;
1622+ } else {
1623+ memcpy (& bq -> init_data , pdata , sizeof (bq -> init_data ));
1624+ }
15551625
15561626 bq2415x_reset_chip (bq );
15571627
@@ -1573,16 +1643,20 @@ static int bq2415x_probe(struct i2c_client *client,
15731643 goto error_4 ;
15741644 }
15751645
1576- if (bq -> init_data .set_mode_hook ) {
1577- if (bq -> init_data .set_mode_hook (
1578- bq2415x_hook_function , bq )) {
1579- bq -> automode = 1 ;
1580- bq2415x_set_mode (bq , bq -> reported_mode );
1581- dev_info (bq -> dev , "automode enabled\n" );
1582- } else {
1583- bq -> automode = -1 ;
1584- dev_info (bq -> dev , "automode failed\n" );
1646+ if (bq -> notify_psy ) {
1647+ bq -> nb .notifier_call = bq2415x_notifier_call ;
1648+ ret = power_supply_reg_notifier (& bq -> nb );
1649+ if (ret ) {
1650+ dev_err (bq -> dev , "failed to reg notifier: %d\n" , ret );
1651+ goto error_5 ;
15851652 }
1653+
1654+ /* Query for initial reported_mode and set it */
1655+ bq2415x_notifier_call (& bq -> nb , PSY_EVENT_PROP_CHANGED , bq -> notify_psy );
1656+ bq2415x_set_mode (bq , bq -> reported_mode );
1657+
1658+ bq -> automode = 1 ;
1659+ dev_info (bq -> dev , "automode enabled\n" );
15861660 } else {
15871661 bq -> automode = -1 ;
15881662 dev_info (bq -> dev , "automode not supported\n" );
@@ -1594,6 +1668,7 @@ static int bq2415x_probe(struct i2c_client *client,
15941668 dev_info (bq -> dev , "driver registered\n" );
15951669 return 0 ;
15961670
1671+ error_5 :
15971672error_4 :
15981673 bq2415x_sysfs_exit (bq );
15991674error_3 :
@@ -1614,8 +1689,8 @@ static int bq2415x_remove(struct i2c_client *client)
16141689{
16151690 struct bq2415x_device * bq = i2c_get_clientdata (client );
16161691
1617- if (bq -> init_data . set_mode_hook )
1618- bq -> init_data . set_mode_hook ( NULL , NULL );
1692+ if (bq -> notify_psy )
1693+ power_supply_unreg_notifier ( & bq -> nb );
16191694
16201695 bq2415x_sysfs_exit (bq );
16211696 bq2415x_power_supply_exit (bq );
0 commit comments