Re: [PATCH v7 4/8] Loongson: YeeLoong: add battery driver

Wu Zhangjin <[email protected]>
Newsgroups gmane.linux.kernel,gmane.linux.ports.mips.general,gmane.linux.laptop
Organization DSLab, Lanzhou University, China
Message-ID <[email protected]>
Hi, Pavel

Seems you have reviewed this patch, can I get your Acked-by:?

Thanks!
	Wu Zhangjin

On Fri, 2009-12-04 at 21:34 +0800, Wu Zhangjin wrote:
> From: Wu Zhangjin <[email protected]>
> 
> This patch adds APM emulated Battery Driver, it provides standard
> interface(/proc/apm) for user-space applications(e.g. kpowersave,
> gnome-power-manager) to manage the battery.
> 
> Signed-off-by: Wu Zhangjin <[email protected]>
> ---
>  drivers/platform/mips/Kconfig           |    2 +
>  drivers/platform/mips/yeeloong_laptop.c |  104 +++++++++++++++++++++++++++++++
>  2 files changed, 106 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/platform/mips/Kconfig b/drivers/platform/mips/Kconfig
> index f7a3705..0c6b5ad 100644
> --- a/drivers/platform/mips/Kconfig
> +++ b/drivers/platform/mips/Kconfig
> @@ -18,6 +18,8 @@ config LEMOTE_YEELOONG2F
>  	tristate "Lemote YeeLoong Laptop"
>  	depends on LEMOTE_MACH2F
>  	select BACKLIGHT_CLASS_DEVICE
> +	select SYS_SUPPORTS_APM_EMULATION
> +	select APM_EMULATION
>  	default m
>  	help
>  	  YeeLoong netbook is a mini laptop made by Lemote, which is basically
> diff --git a/drivers/platform/mips/yeeloong_laptop.c b/drivers/platform/mips/yeeloong_laptop.c
> index fbc4ebb..729e368 100644
> --- a/drivers/platform/mips/yeeloong_laptop.c
> +++ b/drivers/platform/mips/yeeloong_laptop.c
> @@ -13,6 +13,7 @@
>  #include <linux/platform_device.h>
>  #include <linux/backlight.h>	/* for backlight subdriver */
>  #include <linux/fb.h>
> +#include <linux/apm-emulation.h>/* for battery subdriver */
>  
>  #include <ec_kb3310b.h>
>  
> @@ -83,6 +84,106 @@ static void yeeloong_backlight_exit(void)
>  	}
>  }
>  
> +/* battery subdriver */
> +
> +static void get_fixed_battery_info(void)
> +{
> +	int design_cap, full_charged_cap, design_vol, vendor, cell_count;
> +
> +	design_cap = (ec_read(REG_BAT_DESIGN_CAP_HIGH) << 8)
> +	    | ec_read(REG_BAT_DESIGN_CAP_LOW);
> +	full_charged_cap = (ec_read(REG_BAT_FULLCHG_CAP_HIGH) << 8)
> +	    | ec_read(REG_BAT_FULLCHG_CAP_LOW);
> +	design_vol = (ec_read(REG_BAT_DESIGN_VOL_HIGH) << 8)
> +	    | ec_read(REG_BAT_DESIGN_VOL_LOW);
> +	vendor = ec_read(REG_BAT_VENDOR);
> +	cell_count = ec_read(REG_BAT_CELL_COUNT);
> +
> +	if (vendor != 0) {
> +		pr_info("battery vendor(%s), cells count(%d), "
> +		       "with designed capacity(%d),designed voltage(%d),"
> +		       " full charged capacity(%d)\n",
> +		       (vendor ==
> +			FLAG_BAT_VENDOR_SANYO) ? "SANYO" : "SIMPLO",
> +		       (cell_count == FLAG_BAT_CELL_3S1P) ? 3 : 6,
> +		       design_cap, design_vol,
> +		       full_charged_cap);
> +	}
> +}
> +
> +#define APM_CRITICAL		5
> +
> +static void get_power_status(struct apm_power_info *info)
> +{
> +	unsigned char bat_status;
> +
> +	info->battery_status = APM_BATTERY_STATUS_UNKNOWN;
> +	info->battery_flag = APM_BATTERY_FLAG_UNKNOWN;
> +	info->units = APM_UNITS_MINS;
> +
> +	info->battery_life = (ec_read(REG_BAT_RELATIVE_CAP_HIGH) << 8) |
> +		(ec_read(REG_BAT_RELATIVE_CAP_LOW));
> +
> +	info->ac_line_status = (ec_read(REG_BAT_POWER) & BIT_BAT_POWER_ACIN) ?
> +		APM_AC_ONLINE : APM_AC_OFFLINE;
> +
> +	bat_status = ec_read(REG_BAT_STATUS);
> +
> +	if (!(bat_status & BIT_BAT_STATUS_IN)) {
> +		/* no battery inserted */
> +		info->battery_status = APM_BATTERY_STATUS_NOT_PRESENT;
> +		info->battery_flag = APM_BATTERY_FLAG_NOT_PRESENT;
> +		info->time = 0x00;
> +		return;
> +	}
> +
> +	/* adapter inserted */
> +	if (info->ac_line_status == APM_AC_ONLINE) {
> +		if (!(bat_status & BIT_BAT_STATUS_FULL)) {
> +			/* battery is not fully charged */
> +			info->battery_status = APM_BATTERY_STATUS_CHARGING;
> +			info->battery_flag = APM_BATTERY_FLAG_CHARGING;
> +		} else {
> +			/* battery is fully charged */
> +			info->battery_status = APM_BATTERY_STATUS_HIGH;
> +			info->battery_flag = APM_BATTERY_FLAG_HIGH;
> +			info->battery_life = 100;
> +		}
> +	} else {
> +		/* battery is too low */
> +		if (bat_status & BIT_BAT_STATUS_LOW) {
> +			info->battery_status = APM_BATTERY_STATUS_LOW;
> +			info->battery_flag = APM_BATTERY_FLAG_LOW;
> +			if (info->battery_life <= APM_CRITICAL) {
> +				/* we should power off the system now */
> +				info->battery_status =
> +					APM_BATTERY_STATUS_CRITICAL;
> +				info->battery_flag = APM_BATTERY_FLAG_CRITICAL;
> +			}
> +		} else {
> +			/* assume the battery is high enough. */
> +			info->battery_status = APM_BATTERY_STATUS_HIGH;
> +			info->battery_flag = APM_BATTERY_FLAG_HIGH;
> +		}
> +	}
> +	info->time = ((info->battery_life - 3) * 54 + 142) / 60;
> +}
> +
> +static int yeeloong_battery_init(void)
> +{
> +	get_fixed_battery_info();
> +
> +	apm_get_power_status = get_power_status;
> +
> +	return 0;
> +}
> +
> +static void yeeloong_battery_exit(void)
> +{
> +	if (apm_get_power_status == get_power_status)
> +		apm_get_power_status = NULL;
> +}
> +
>  static struct platform_device_id platform_device_ids[] = {
>  	{
>  		.name = "yeeloong_laptop",
> @@ -120,11 +221,14 @@ static int __init yeeloong_init(void)
>  		return ret;
>  	}
>  
> +	yeeloong_battery_init();
> +
>  	return 0;
>  }
>  
>  static void __exit yeeloong_exit(void)
>  {
> +	yeeloong_battery_exit();
>  	yeeloong_backlight_exit();
>  	platform_driver_unregister(&platform_driver);
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.