From 8d2617b0d21aa6cc637a3a7f1c729fcb60814e6f Mon Sep 17 00:00:00 2001 From: eddie Date: Thu, 1 Sep 2011 10:34:26 +0800 Subject: [PATCH] bq27541 when system up with no battary,shutdown system --- arch/arm/mach-rk29/board-rk29-newton.c | 22 +--- arch/arm/mach-rk29/include/mach/board.h | 4 +- drivers/power/bq27541_battery.c | 149 ++++++++++++++++++++++-- 3 files changed, 147 insertions(+), 28 deletions(-) mode change 100755 => 100644 drivers/power/bq27541_battery.c diff --git a/arch/arm/mach-rk29/board-rk29-newton.c b/arch/arm/mach-rk29/board-rk29-newton.c index 5001fd78c257..943b7a1b1b6b 100644 --- a/arch/arm/mach-rk29/board-rk29-newton.c +++ b/arch/arm/mach-rk29/board-rk29-newton.c @@ -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(); diff --git a/arch/arm/mach-rk29/include/mach/board.h b/arch/arm/mach-rk29/include/mach/board.h index a9a72b23e842..c97306d4af19 100644 --- a/arch/arm/mach-rk29/include/mach/board.h +++ b/arch/arm/mach-rk29/include/mach/board.h @@ -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; }; diff --git a/drivers/power/bq27541_battery.c b/drivers/power/bq27541_battery.c old mode 100755 new mode 100644 index 3b775fecda00..1ead67d8f6bb --- a/drivers/power/bq27541_battery.c +++ b/drivers/power/bq27541_battery.c @@ -25,6 +25,9 @@ #include #include #include +#include +#include + #define DRIVER_VERSION "1.1.0" @@ -46,14 +49,16 @@ #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); -- 2.34.1