diff options
author | Kevin | 2014-11-15 11:48:36 +0800 |
---|---|---|
committer | Kevin | 2014-11-15 11:48:36 +0800 |
commit | d04075478d378d9e15f3e1abfd14b0bd124077d4 (patch) | |
tree | 733dd964582f388b9e3e367c249946cd32a2851f /board/wmt/wmt_battery/wmt_battery.c | |
download | FOSSEE-netbook-uboot-source-d04075478d378d9e15f3e1abfd14b0bd124077d4.tar.gz FOSSEE-netbook-uboot-source-d04075478d378d9e15f3e1abfd14b0bd124077d4.tar.bz2 FOSSEE-netbook-uboot-source-d04075478d378d9e15f3e1abfd14b0bd124077d4.zip |
init commit via android 4.4 uboot
Diffstat (limited to 'board/wmt/wmt_battery/wmt_battery.c')
-rwxr-xr-x | board/wmt/wmt_battery/wmt_battery.c | 434 |
1 files changed, 434 insertions, 0 deletions
diff --git a/board/wmt/wmt_battery/wmt_battery.c b/board/wmt/wmt_battery/wmt_battery.c new file mode 100755 index 0000000..dac30ee --- /dev/null +++ b/board/wmt/wmt_battery/wmt_battery.c @@ -0,0 +1,434 @@ +/* + * Copyright (c) 2014 WonderMedia Technologies, Inc. + * + * This program is free software: you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software Foundation, + * either version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU General Public License for more details. + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + * + * WonderMedia Technologies, Inc. + * 10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. + */ + +#include <common.h> +#include <command.h> +#include <asm/errno.h> + +#include "../include/wmt_iomux.h" +#include "wmt_battery.h" + +#define return_val_if_failed(val, expr) \ +do { \ + if (!(expr)) { \ + printf(" %s, %d, Warnning: " #expr " failed.\n", \ + __FUNCTION__, __LINE__); \ + return val; \ + } \ +} while(0) + +struct battery_param { + struct battery_dev *bat_dev; +}; + +struct charger_param { + struct charger_dev *chg_dev; +}; + +static struct battery_param battery_param; +static struct charger_param charger_param; + +static int full_by_hw = 0; + +static struct battery_dev *battery_devices[] = { + &vt1603_battery_dev, + &ug31xx_battery_dev, + &ug3102_battery_dev, + &sp2541_battery_dev, + &bq_battery_dev, + NULL, +}; + +static struct charger_dev *charger_devices[] = { + &mp2625_charger_dev, + &g2214_charger_dev, + NULL, +}; + +static int parse_charger_param(struct charger_param *cp) +{ + static const char uboot_env[] = "wmt.charger.param"; + struct charger_dev **dev = &charger_devices[0]; + char *env; + + if (!(env = getenv((char *)uboot_env))) { + printf("please setenv %s\n", uboot_env); + return -EINVAL; + } + + while (*dev) { + if ((*dev)->name && + !strncmp((*dev)->name, env, strlen((*dev)->name))) + break; + ++dev; + } + + if (!(*dev)) + return -EINVAL; + + cp->chg_dev = *dev; + printf("Charger matched: %s\n", cp->chg_dev->name); + return 0; +} + +static int parse_battery_param(struct battery_param *bp) +{ + static const char uboot_env[] = "wmt.battery.param"; + struct battery_dev **dev = &battery_devices[0]; + char *env; + + if (!(env = getenv((char *)uboot_env))) { + printf("please setenv %s\n", uboot_env); + return -EINVAL; + } + + while (*dev) { + if ((*dev)->name && + !strncmp((*dev)->name, env, strlen((*dev)->name))) + break; + ++dev; + } + + if (!(*dev)) + return -EINVAL; + + bp->bat_dev = *dev; + printf("Battery matched: %s\n", bp->bat_dev->name); + return 0; +} + +static int parse_battery_full_param(void) +{ + static const char uboot_env[] = "wmt.bat.hwfull"; + char *env; + + if (!(env = getenv((char *)uboot_env))) { + full_by_hw = 0; + return -EINVAL; + } + + full_by_hw = simple_strtol(env, NULL, 10); + printf("full_by_hw %d\n", full_by_hw); + return 0; +} + +static struct { + int charging; + int full; + int led_power; + int led_gpio_level; +} charger_led; + +static int parse_charger_led(void) +{ + enum { + idx_id, + idx_v1, + idx_v2, + idx_max, + }; + long ps[idx_max]; + char *p, *endp; + int i = 0; + + // initialize as invalid gpio + charger_led.charging = -1; + charger_led.full = -1; + charger_led.led_power = -1; + + p = getenv("wmt.charger.led"); + if (!p) + return -EINVAL; + + while (i < idx_max) { + ps[i++] = simple_strtol(p, &endp, 10); + if (*endp == '\0') + break; + p = endp + 1; + if (*p == '\0') + break; + } + + if (i != 3) + return -EINVAL; + + switch (ps[idx_id]) { + case 0: + charger_led.led_power = ps[idx_v1]; + charger_led.led_gpio_level = ps[idx_v2]; + printf("charger led power: %d (%d)\n", + charger_led.led_power, charger_led.led_gpio_level); + break; + case 1: + charger_led.charging = ps[idx_v1]; + charger_led.full = ps[idx_v2]; + printf("charger led pin: charging %d, full %d\n", + charger_led.charging, charger_led.full); + break; + default: + printf("no valid charger led found\n"); + return -EINVAL; + } + + return 0; +} + +int wmt_power_supply_init(void) +{ + struct charger_param *cp = &charger_param; + struct battery_param *bp = &battery_param; + static int inited = 0; + + if (inited) + return 0; + ++inited; + + if (parse_charger_param(cp)) { + pr_err("charger not found\n"); + return -ENODEV; + } + if (cp->chg_dev->init()) { + pr_err("%s init failed\n", cp->chg_dev->name); + return -EIO; + } + + if (parse_battery_param(bp)) { + pr_err("cattery not found\n"); + return -ENODEV; + } + if (bp->bat_dev->init()) { + pr_err("%s init failed\n", bp->bat_dev->name); + return -EIO; + } + + parse_charger_led(); + parse_battery_full_param(); + + return 0; +} + +int pmic_init(void) +{ + if (is_g2214_avail() != -1) + g2214_pmic_init(); + return 0; +} + +static inline void led_enable(int gpio, int enable) +{ + if (gpio_is_valid(gpio)) { + if (enable) + gpio_direction_output(gpio, 1); + else { + gpio_direction_output(gpio, 0); + + /* walkaround for hardware bug. + * set gpio to input to let led off. + */ + gpio_direction_input(gpio); + } + } +} + +static inline void led_power_enable(int enable) +{ + int gpio = charger_led.led_power; + + if (gpio_is_valid(gpio)) { + if (enable) + gpio_direction_output(gpio, charger_led.led_gpio_level); + else + gpio_direction_output(gpio, !charger_led.led_gpio_level); + } +} + +int wmt_charger_event_callback(enum event_type event) +{ + struct charger_dev *dev = charger_param.chg_dev; + + return_val_if_failed(-1, dev != NULL); + return_val_if_failed(-1, dev->event_proc); + + printf(" ## %s, %d\n", __func__, event); + + switch (event) { + case POWER_EVENT_DCDET_ADAPTER: + case POWER_EVENT_CHARGING: + led_power_enable(1); + if (wmt_battery_is_charging_full()) { + led_enable(charger_led.charging, 0); + led_enable(charger_led.full, 1); + } else { + led_enable(charger_led.charging, 1); + led_enable(charger_led.full, 0); + } + break; + case POWER_EVENT_DCDET_USBPC: + if (wmt_charger_pc_charging()) { + led_power_enable(1); + if (wmt_battery_is_charging_full()) { + led_enable(charger_led.charging, 0); + led_enable(charger_led.full, 1); + } else + led_enable(charger_led.charging, 1); + } else { + led_power_enable(0); + led_enable(charger_led.charging, 0); + } + led_enable(charger_led.full, 0); + break; + case POWER_EVENT_DCDET_PLUGOUT: + case POWER_EVENT_DISCHARGING: + led_power_enable(0); + led_enable(charger_led.charging, 0); + led_enable(charger_led.full, 0); + break; + case POWER_EVENT_CHARGING_FULL: + led_power_enable(1); + led_enable(charger_led.charging, 0); + led_enable(charger_led.full, 1); + break; + default: + break; + } + + return dev->event_proc(event); +} + +int wmt_charger_cable_type(void) +{ + struct charger_dev *dev = charger_param.chg_dev; + + return_val_if_failed(-1, dev != NULL); + return_val_if_failed(-1, dev->cable_type); + + return dev->cable_type(); +} + +int wmt_charger_pc_charging(void) +{ + struct charger_dev *dev = charger_param.chg_dev; + + return_val_if_failed(-1, dev != NULL); + + return (dev->pc_charging) ? dev->pc_charging() : 0; +} + +int wmt_battery_get_capacity(void) +{ + struct battery_dev *dev = battery_param.bat_dev; + static unsigned int ref_full = 0; + int capacity; + + return_val_if_failed(-1, dev != NULL); + return_val_if_failed(-1, dev->get_capacity); + + capacity = dev->get_capacity(); + + if (!wmt_battery_is_gauge()) { + + if (full_by_hw) { + if (wmt_battery_is_charging_full()) + return capacity; + else if (capacity == 100) + return 99; + } + + if (capacity == 100 && !wmt_battery_is_charging_full()) { + if (ref_full < 30 * 60) { + capacity = 99; + ref_full++; + } else + printf("ref full %d, 30 minutes, report full\n", ref_full); + } else + ref_full = 0; + + printf("-> %d, ref full %d\n", capacity, ref_full); + } + + return capacity; +} + +int wmt_battery_get_voltage(void) +{ + struct battery_dev *dev = battery_param.bat_dev; + + return_val_if_failed(-1, dev != NULL); + return_val_if_failed(-1, dev->get_voltage); + + return dev->get_voltage(); +} + +int wmt_battery_get_current(void) +{ + struct battery_dev *dev = battery_param.bat_dev; + + return_val_if_failed(-1, dev != NULL); + return_val_if_failed(-1, dev->get_current); + + return dev->get_current(); +} + +int wmt_battery_is_lowlevel(void) +{ + struct battery_dev *dev = battery_param.bat_dev; + + return_val_if_failed(-1, dev != NULL); + return_val_if_failed(-1, dev->check_batlow); + + return dev->check_batlow(); +} + +int wmt_battery_is_charging_full(void) +{ + struct charger_dev *dev = charger_param.chg_dev; + + return_val_if_failed(-1, dev != NULL); + return_val_if_failed(-1, dev->check_full); + + if (!wmt_is_dc_plugin()) + return -1; + + return dev->check_full(); +} + +int wmt_battery_is_gauge(void) +{ + struct battery_dev *dev = battery_param.bat_dev; + + return_val_if_failed(-1, dev != NULL); + + return dev->is_gauge; +} + +static int do_batt(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + wmt_power_supply_init(); + + printf(" voltage %d mV\n", wmt_battery_get_voltage()); + printf(" capacity %d\n", wmt_battery_get_capacity()); + printf(" dinc %d\n", wmt_is_dc_plugin()); + + return 0; +} + +U_BOOT_CMD( + batt, 1, 1, do_batt, + "batt - print Board Info structure\n", + NULL +); + |