Revert "Revert "MALI: midgard: support sharing regulator with other devices""
[firefly-linux-kernel-4.4.55.git] / drivers / power / bq24296_charger.c
index b29ca06468051051e1245900f7c944c32948ee57..09a8d7f887350abdcbb5698f4908188984f2f4c7 100755 (executable)
@@ -154,6 +154,7 @@ static int bq24296_init_registers(void)
        int ret = 0;
 
        /* reset the register */
+       /*
        ret = bq24296_update_reg(bq24296_di->client,
                                POWE_ON_CONFIGURATION_REGISTER,
                                REGISTER_RESET_ENABLE << REGISTER_RESET_OFFSET,
@@ -165,7 +166,7 @@ static int bq24296_init_registers(void)
        }
 
        mdelay(5);
-
+*/
        /* Disable the watchdog */
        ret = bq24296_update_reg(bq24296_di->client,
                                TERMINATION_TIMER_CONTROL_REGISTER,
@@ -220,7 +221,6 @@ static int bq24296_get_limit_current(int value)
                data = 6;
        else
                data = 7;
-       data &= 0xff;
        return data;
        
 }
@@ -362,7 +362,7 @@ static int bq24296_charge_mode_config(int on)
        return ret;
 }
 
-extern int dwc_vbus_status(void);
+extern int dwc_otg_check_dpdm(bool wait);
 //extern int get_gadget_connect_flag(void);
 
 static void usb_detect_work_func(struct work_struct *work)
@@ -382,45 +382,66 @@ static void usb_detect_work_func(struct work_struct *work)
                bq24296_chag_down =0;
 
        DBG("%s: retval = %08x bq24296_chag_down = %d\n", __func__,retval,bq24296_chag_down);
-       
+
        mutex_lock(&pi->var_lock);
-       DBG("%s: dwc_vbus_status %d\n", __func__, dwc_vbus_status());
-       switch(dwc_vbus_status())
-               {
-                       case 2: // USB Wall charger
+       
+       if (gpio_is_valid(bq24296_pdata->dc_det_pin)){
+                       ret = gpio_request(bq24296_pdata->dc_det_pin, "bq24296_dc_det");
+                       if (ret < 0) {
+                               DBG("Failed to request gpio %d with ret:""%d\n",bq24296_pdata->dc_det_pin, ret);
+                       }
+                       gpio_direction_input(bq24296_pdata->dc_det_pin);
+                       ret = gpio_get_value(bq24296_pdata->dc_det_pin);
+                       if (ret ==0){
                                bq24296_update_input_current_limit(bq24296_di->adp_input_current);
-                               bq24296_set_charge_current(bq24296_di->chg_current);
+                               bq24296_set_charge_current(CHARGE_CURRENT_2048MA);
+                               bq24296_charge_mode_config(0);
+                       }
+                       else {
+                               bq24296_update_input_current_limit(IINLIM_500MA);
+                               bq24296_set_charge_current(CHARGE_CURRENT_512MA);
+                       }
+                       gpio_free(bq24296_pdata->dc_det_pin);
+                       DBG("%s: bq24296_di->dc_det_pin=%x\n", __func__, ret);
+       }
+       else{
+                       DBG("%s: dwc_otg_check_dpdm %d\n", __func__, dwc_otg_check_dpdm(0));
+                       switch(dwc_otg_check_dpdm(0))
+                       {
+                               case 2: // USB Wall charger
+                               bq24296_update_input_current_limit(bq24296_di->usb_input_current);
+                               bq24296_set_charge_current(CHARGE_CURRENT_2048MA);
                                bq24296_charge_mode_config(0);
                                DBG("bq24296: detect usb wall charger\n");
-                       break;
-                       case 1: //normal USB
+                               break;
+                               case 1: //normal USB
                                #if 0
                                if (0 == get_gadget_connect_flag()){  // non-standard AC charger
-                               bq24296_update_input_current_limit(IINLIM_2000MA);
-                               bq24296_set_charge_current(CHARGE_CURRENT_1024MA);
+                               bq24296_update_input_current_limit((bq24296_di->usb_input_current);
+                               bq24296_set_charge_current(CHARGE_CURRENT_2048MA);
                                bq24296_charge_mode_config(0);;
                                }else{
                                #endif
                                // connect to pc        
-                               bq24296_update_input_current_limit(bq24296_di->adp_input_current);
+                               bq24296_update_input_current_limit(bq24296_di->usb_input_current);
                                bq24296_set_charge_current(CHARGE_CURRENT_512MA);
                                bq24296_charge_mode_config(0);
                                DBG("bq24296: detect normal usb charger\n");
-                       //      }
-                       break;
-                       default:
-                               bq24296_update_input_current_limit(bq24296_di->adp_input_current);
-                                bq24296_set_charge_current(CHARGE_CURRENT_512MA);
-                                bq24296_charge_mode_config(0);
+                               //      }
+                               break;
+                               default:
+                               bq24296_update_input_current_limit(IINLIM_500MA);
+                               bq24296_set_charge_current(CHARGE_CURRENT_512MA);
                                DBG("bq24296: detect no usb \n");                       
-                       break;
+                               break;
+                               }
                }
+
        mutex_unlock(&pi->var_lock);
        
        schedule_delayed_work(&pi->usb_detect_work, 1*HZ);
 }
 
-
 static void irq_work_func(struct work_struct *work)
 {
 //     struct bq24296_device_info *info= container_of(work, struct bq24296_device_info, irq_work);
@@ -460,6 +481,11 @@ static struct bq24296_board *bq24296_parse_dt(struct bq24296_device_info *di)
        if (!gpio_is_valid(pdata->chg_irq_pin)) {
                printk("invalid gpio: %d\n",  pdata->chg_irq_pin);
        }
+
+       pdata->dc_det_pin = of_get_named_gpio(bq24296_np,"gpios",1);
+       if (!gpio_is_valid(pdata->dc_det_pin)) {
+               printk("invalid gpio: %d\n",  pdata->dc_det_pin);
+       }
        
        return pdata;
 }
@@ -479,13 +505,25 @@ static struct of_device_id bq24296_battery_of_match[] = {
 MODULE_DEVICE_TABLE(of, bq24296_battery_of_match);
 #endif
 
+static int bq24296_battery_suspend(struct i2c_client *client, pm_message_t mesg)
+{
+       cancel_delayed_work_sync(&bq24296_di->usb_detect_work);
+       return 0;
+}
+
+static int bq24296_battery_resume(struct i2c_client *client)
+{
+       schedule_delayed_work(&bq24296_di->usb_detect_work, msecs_to_jiffies(50));
+       return 0;
+}
+
 static int bq24296_battery_probe(struct i2c_client *client,const struct i2c_device_id *id)
 {
        struct bq24296_device_info *di;
        u8 retval = 0;
        struct bq24296_board *pdev;
        struct device_node *bq24296_node;
-       int ret=0,irq=0;
+       int ret = -EINVAL;
        
         DBG("%s,line=%d\n", __func__,__LINE__);
         
@@ -494,10 +532,10 @@ static int bq24296_battery_probe(struct i2c_client *client,const struct i2c_devi
                printk("could not find bq24296-node\n");
        }
         
-       di = devm_kzalloc( &client->dev,sizeof(*di), GFP_KERNEL);
+       di = devm_kzalloc(&client->dev,sizeof(*di), GFP_KERNEL);
        if (!di) {
                dev_err(&client->dev, "failed to allocate device info data\n");
-               retval = -ENOMEM;
+               ret = -ENOMEM;
                goto batt_failed_2;
        }
        i2c_set_clientdata(client, di);
@@ -529,7 +567,7 @@ static int bq24296_battery_probe(struct i2c_client *client,const struct i2c_devi
        if (ret < 0) {
                dev_err(&di->client->dev, "%s(): Failed in reading register"
                                "0x%02x\n", __func__, VENDOR_STATS_REGISTER);
-               goto batt_failed_4;
+               goto batt_failed_2;
        }
        di->workqueue = create_singlethread_workqueue("bq24296_irq");
        INIT_WORK(&di->irq_work, irq_work_func);
@@ -538,9 +576,10 @@ static int bq24296_battery_probe(struct i2c_client *client,const struct i2c_devi
        schedule_delayed_work(&di->usb_detect_work, 0);
        bq24296_init_registers();
 
+
        if (gpio_is_valid(pdev->chg_irq_pin)){
-               irq = gpio_to_irq(pdev->chg_irq_pin);
-               ret = request_threaded_irq(irq, NULL,chg_irq_func, IRQF_TRIGGER_FALLING| IRQF_ONESHOT, "bq24296_chg_irq", di);
+               pdev->chg_irq = gpio_to_irq(pdev->chg_irq_pin);
+               ret = request_threaded_irq(pdev->chg_irq, NULL, chg_irq_func, IRQF_TRIGGER_FALLING| IRQF_ONESHOT, "bq24296_chg_irq", di);
                if (ret) {
                        ret = -EINVAL;
                        printk("failed to request bq24296_chg_irq\n");
@@ -553,24 +592,23 @@ static int bq24296_battery_probe(struct i2c_client *client,const struct i2c_devi
        DBG("bq24296_battery_probe ok");
        return 0;
 
-batt_failed_4:
-       kfree(di);
-batt_failed_2:
-       
 err_chgirq_failed:
        free_irq(gpio_to_irq(pdev->chg_irq_pin), NULL);
-       return retval;
+batt_failed_2:
+       return ret;
 }
 
 static void bq24296_battery_shutdown(struct i2c_client *client)
 {
-       free_irq(gpio_to_irq(bq24296_pdata->chg_irq_pin), NULL);
-       
+       struct bq24296_device_info *di = i2c_get_clientdata(client);
+
+       if (bq24296_pdata->chg_irq)
+               free_irq(bq24296_pdata->chg_irq, di);
 }
+
 static int bq24296_battery_remove(struct i2c_client *client)
 {
-       struct bq24296_device_info *di = i2c_get_clientdata(client);
-       kfree(di);
+
        return 0;
 }
 
@@ -587,6 +625,8 @@ static struct i2c_driver bq24296_battery_driver = {
        .probe = bq24296_battery_probe,
        .remove = bq24296_battery_remove,
        .shutdown = bq24296_battery_shutdown,
+       .suspend = bq24296_battery_suspend,
+       .resume = bq24296_battery_resume,
        .id_table = bq24296_id,
 };
 
@@ -600,7 +640,7 @@ static int __init bq24296_battery_init(void)
        
        return ret;
 }
-module_init(bq24296_battery_init);
+subsys_initcall(bq24296_battery_init);
 
 static void __exit bq24296_battery_exit(void)
 {