bq27541 when system up with no battary,shutdown system
authoreddie <cf@rock-chips.com>
Thu, 1 Sep 2011 02:34:26 +0000 (10:34 +0800)
committereddie <cf@rock-chips.com>
Thu, 1 Sep 2011 02:34:26 +0000 (10:34 +0800)
arch/arm/mach-rk29/board-rk29-newton.c
arch/arm/mach-rk29/include/mach/board.h
drivers/power/bq27541_battery.c [changed mode: 0755->0644]

index 5001fd78c257471b9814319a7f5841616c942c86..943b7a1b1b6be3016e8616e3c60eeac318079faf 100644 (file)
@@ -617,6 +617,9 @@ struct cs42l52_platform_data cs42l52_info = {
 #if defined (CONFIG_BATTERY_BQ27541)
 #define        DC_CHECK_PIN    RK29_PIN4_PA1
 #define        LI_LION_BAT_NUM 1
+#define CHG_OK RK29_PIN4_PA3
+#define BAT_LOW        RK29_PIN4_PA2
+
 static int bq27541_init_dc_check_pin(void){    
        if(gpio_request(DC_CHECK_PIN,"dc_check") != 0){      
                gpio_free(DC_CHECK_PIN);      
@@ -631,6 +634,8 @@ struct bq27541_platform_data bq27541_info = {
        .init_dc_check_pin = bq27541_init_dc_check_pin, 
        .dc_check_pin =  DC_CHECK_PIN,          
        .bat_num = LI_LION_BAT_NUM,
+       .chgok_check_pin =  CHG_OK,
+       .bat_check_pin =  BAT_LOW,
 };
 #endif
 static struct android_pmem_platform_data android_pmem_pdata = {
@@ -2203,24 +2208,9 @@ static struct cpufreq_frequency_table freq_table[] = {
        { .frequency = CPUFREQ_TABLE_END },
 };
 
-#define BAT_LOW        RK29_PIN4_PA2
-#define POWER_ON_PIN   RK29_PIN4_PA4
+
 static void __init machine_rk29_board_init(void)
 {
-       int val =0;
-       gpio_request(BAT_LOW, NULL);
-       gpio_direction_input(BAT_LOW);
-       val = gpio_get_value(BAT_LOW);
-       if (val == 0){
-               printk("no battery, no power up\n");
-               gpio_request(POWER_ON_PIN, "poweronpin");
-               gpio_direction_output(POWER_ON_PIN, GPIO_LOW);
-               while(1){
-                       gpio_set_value(POWER_ON_PIN, GPIO_LOW);
-                       mdelay(100);
-               }
-       }
-       gpio_free(BAT_LOW);
        rk29_board_iomux_init();
 
        board_power_init();
index a9a72b23e842a531e65b32de4f0674e4eca2502e..c97306d4af195d62f8b68147f9eb6f09e80ded60 100644 (file)
@@ -164,7 +164,9 @@ struct bq27510_platform_data {
 
 struct bq27541_platform_data { 
        int (*init_dc_check_pin)(void); 
-       unsigned int dc_check_pin;      
+       unsigned int dc_check_pin;
+       unsigned int bat_check_pin;
+       unsigned int chgok_check_pin;
        unsigned int bat_num;
 };
 
old mode 100755 (executable)
new mode 100644 (file)
index 3b775fe..1ead67d
@@ -25,6 +25,9 @@
 #include <linux/proc_fs.h>
 #include <asm/uaccess.h>
 #include <mach/board.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+
 
 
 #define DRIVER_VERSION                 "1.1.0"
 
 #define BQ27510_SPEED                  100 * 1000
 #define POWER_ON_PIN   RK29_PIN4_PA4
+//#define CHG_OK RK29_PIN4_PA3
 
-#define BAT_LOW        RK29_PIN4_PA2
+//#define BAT_LOW      RK29_PIN4_PA2
 
 
 int  virtual_battery_enable = 0;
 extern int dwc_vbus_status(void);
 static void bq27541_set(void);
 
+
 #if 0
 #define DBG(x...) printk(KERN_INFO x)
 #else
@@ -70,9 +75,12 @@ struct bq27541_device_info {
        struct power_supply     bat;
        struct power_supply     ac;
        struct delayed_work work;
+       struct delayed_work wakeup_work;
        struct i2c_client       *client;
+       int wake_irq;
        unsigned int interval;
        unsigned int dc_check_pin;
+       unsigned int bat_check_pin;
        unsigned int bat_num;
        int power_down;
 };
@@ -156,6 +164,36 @@ static int bq27541_write(struct i2c_client *client, u8 reg, u8 const buf[], unsi
  * Return the battery temperature in tenths of degree Celsius
  * Or < 0 if something fails.
  */
+static irqreturn_t bq27541_bat_wakeup(int irq, void *dev_id)
+{      
+       struct bq27541_device_info *di = (struct bq27541_device_info *)dev_id;
+
+       printk("!!!  bq27541 bat_low irq low vol !!!\n\n\n");
+       disable_irq_wake(di->wake_irq);
+
+       schedule_delayed_work(&di->wakeup_work, msecs_to_jiffies(0));   
+       return IRQ_HANDLED;
+}
+
+static void bq27541_battery_wake_work(struct work_struct *work)
+{
+    int ret;
+    struct bq27541_device_info *di = 
+               (struct bq27541_device_info *)container_of(work, struct bq27541_device_info, wakeup_work.work);
+               
+    rk28_send_wakeup_key();
+    
+    free_irq(di->wake_irq, di);
+       di->wake_irq = gpio_to_irq(di->bat_check_pin);
+       
+       ret = request_irq(di->wake_irq, bq27541_bat_wakeup, IRQF_TRIGGER_FALLING, "bq27541_battery", di);
+       if (ret) {
+               printk("request faild!\n");
+               return;
+       }
+       enable_irq_wake(di->wake_irq);
+}
 
 
 static int bq27541_battery_temperature(struct bq27541_device_info *di)
@@ -187,6 +225,9 @@ static int bq27541_battery_temperature(struct bq27541_device_info *di)
  * Return the battery Voltage in milivolts
  * Or < 0 if something fails.
  */
+
+
+
 static int bq27541_battery_voltage(struct bq27541_device_info *di)
 {
        int ret;
@@ -202,7 +243,6 @@ static int bq27541_battery_voltage(struct bq27541_device_info *di)
        ret = bq27541_read(di->client,BQ27x00_REG_VOLT,buf,2); 
        if (ret<0) {
                dev_err(di->dev, "error reading voltage\n");
-               printk("vol smaller then 3.4V, shutdown");
 //             gpio_set_value(POWER_ON_PIN, GPIO_LOW);
                return ret;
        }
@@ -215,15 +255,16 @@ static int bq27541_battery_voltage(struct bq27541_device_info *di)
                volt = volt * 1000;
        }
                
+
+
        
-       if ((volt <= 3400000)  && (volt > 0)){
-               printk("vol smaller then 3.4V, shutdown");
+       if ((volt <= 3400000)  && (volt > 0) && gpio_get_value(di->dc_check_pin)){
+               printk("vol smaller then 3.4V, report to android!");
                di->power_down = 1;
        }else{
                di->power_down = 0;
        }
 
-
        
        DBG("Enter:%s %d--volt = %d\n",__FUNCTION__,__LINE__,volt);
        return volt;
@@ -468,7 +509,6 @@ static int bq27541_battery_get_property(struct power_supply *psy,
                                        union power_supply_propval *val)
 {
        int ret = 0;
-       int vals=0;
        
        struct bq27541_device_info *di = to_bq27541_device_info(psy);
        DBG("Enter:%s %d psp= %d\n",__FUNCTION__,__LINE__,psp);
@@ -489,10 +529,10 @@ static int bq27541_battery_get_property(struct power_supply *psy,
                val->intval = bq27541_battery_current(di);
                break;
        case POWER_SUPPLY_PROP_CAPACITY:
-               if (!(di->power_down)){      // < 3.4V    power down ,capacity = 0;
-                       val->intval = bq27541_battery_rsoc(di);
-               }else{
+               if (di->power_down == 1){      // < 3.4V    power down ,capacity = 0;
                        val->intval = 0;
+               }else {
+                       val->intval = bq27541_battery_rsoc(di);
                }
                break;
 
@@ -629,8 +669,8 @@ static int bq27541_battery_probe(struct i2c_client *client,
        int retval = 0;
        struct bq27541_platform_data *pdata;
        int val =0;
-       
-
+       char buf[2];
+       int volt;
        DBG("**********  bq27541_battery_probe**************  ");
        pdata = client->dev.platform_data;
        
@@ -649,6 +689,7 @@ static int bq27541_battery_probe(struct i2c_client *client,
        
        di->bat_num = pdata->bat_num;
        di->dc_check_pin = pdata->dc_check_pin;
+       di->bat_check_pin = pdata->bat_check_pin;
        
        if (pdata->init_dc_check_pin)
                pdata->init_dc_check_pin( );
@@ -671,11 +712,95 @@ static int bq27541_battery_probe(struct i2c_client *client,
        INIT_DELAYED_WORK(&di->work, bq27541_battery_work);
        schedule_delayed_work(&di->work, di->interval);
        dev_info(&client->dev, "support ver. %s enabled\n", DRIVER_VERSION);
+
+#if  !defined (CONFIG_NO_BATTERY_IC)
+
+       // no battery  , no power up
+       gpio_request(POWER_ON_PIN, "poweronpin");
+       gpio_request(pdata->bat_check_pin, NULL);
+       gpio_direction_input(pdata->bat_check_pin);
+       gpio_request(pdata->chgok_check_pin, "CHG_OK");
+       gpio_direction_input(pdata->chgok_check_pin);
+
+       val = gpio_get_value(pdata->bat_check_pin);
+       if (val == 1){
+               printk("\n\n!!! bat_low  high !!!\n\n");
+               val = bq27541_read(di->client,BQ27x00_REG_VOLT,buf,2);
+               if (val < 0){
+                       printk("\n\n!!! bq i2c err! no battery,  power down\n!!!\n\n");
+                       gpio_direction_output(POWER_ON_PIN, GPIO_LOW);  
+                       while(1){
+                               gpio_set_value(POWER_ON_PIN, GPIO_LOW);
+                               mdelay(100);
+                       }
+               }
+
+       }else{
+                       
+               printk("\n\n!!! bat_low  low !!!\n\n");
+               val = gpio_get_value(pdata->chgok_check_pin);
+               if (val == 1){
+                       printk("no battery, power down \n");
+                       gpio_direction_output(POWER_ON_PIN, GPIO_LOW);
+                       while(1){
+                               gpio_set_value(POWER_ON_PIN, GPIO_LOW);
+                               mdelay(100);
+                       }
+               }else{
+                       mdelay(1000);
+                       val = gpio_get_value(pdata->chgok_check_pin);
+                       if (val == 1){
+                               printk("no battery, power down \n");
+                               gpio_direction_output(POWER_ON_PIN, GPIO_LOW);                  
+                               while(1){
+                                       gpio_set_value(POWER_ON_PIN, GPIO_LOW);
+                                       mdelay(100);
+                               }
+                       }
+               }
+
+       }
+
+//     gpio_free(POWER_ON_PIN);
+//     gpio_free(pdata->bat_check_pin);
+       gpio_free(pdata->chgok_check_pin);
+
+
+       //smaller  3.4V , no power up
+       if (gpio_get_value(di->dc_check_pin) && (gpio_get_value(pdata->bat_check_pin) == 0)){
+                       printk("no AC && battery low ,so power down \n");
+                       gpio_direction_output(POWER_ON_PIN, GPIO_LOW);                  
+                       while(1){
+                               printk("no AC && battery low ,so power down \n");
+                               gpio_set_value(POWER_ON_PIN, GPIO_LOW);
+                               mdelay(100);
+                       }
+       }       
+
+       
+       // battery low irq
+       di->wake_irq = gpio_to_irq(pdata->bat_check_pin);
+       retval = request_irq(di->wake_irq, bq27541_bat_wakeup, IRQF_TRIGGER_FALLING, "bq27541_battery", di);
+       if (retval) {
+               printk("failed to request bat det irq\n");
+               goto err_batirq_failed;
+       }
+       
+       INIT_DELAYED_WORK(&di->wakeup_work, bq27541_battery_wake_work);
+       enable_irq_wake(di->wake_irq);
+
+
+#endif
+       
        return 0;
 
 batt_failed_4:
        kfree(di);
 batt_failed_2:
+
+err_batirq_failed:
+       gpio_free(pdata->bat_check_pin);
+
        return retval;
 }
 
@@ -718,6 +843,8 @@ static int __init bq27541_battery_init(void)
 }
 
 //module_init(bq27541_battery_init);
+//fs_initcall_sync(bq27541_battery_init);
+
 fs_initcall(bq27541_battery_init);
 //arch_initcall(bq27541_battery_init);