summaryrefslogtreecommitdiffstats
path: root/lemote/gnewsense/2.6.32/2.6.32-yeeloong-battery.patch
diff options
context:
space:
mode:
Diffstat (limited to 'lemote/gnewsense/2.6.32/2.6.32-yeeloong-battery.patch')
-rw-r--r--lemote/gnewsense/2.6.32/2.6.32-yeeloong-battery.patch401
1 files changed, 401 insertions, 0 deletions
diff --git a/lemote/gnewsense/2.6.32/2.6.32-yeeloong-battery.patch b/lemote/gnewsense/2.6.32/2.6.32-yeeloong-battery.patch
new file mode 100644
index 000000000..176e34466
--- /dev/null
+++ b/lemote/gnewsense/2.6.32/2.6.32-yeeloong-battery.patch
@@ -0,0 +1,401 @@
+This is taken from the 2.6.31.6 Lemote patchset. yeeloong_battery.c
+used to be in drivers/platform/loongson, now moved to
+arch/mips/loongson/lemote-2f. Changed to include ec_kb3310b.h instead
+of ec/kb3310b.h, and adjusted calls to
+yeeloong_sci_{,un}install_handler, formerly *_event_handler. -lxoliva
+
+
+Index: arch/mips/loongson/lemote-2f/Makefile
+===================================================================
+--- arch/mips/loongson/lemote-2f/Makefile.orig 2009-12-12 20:51:06.000000000 -0200
++++ arch/mips/loongson/lemote-2f/Makefile 2009-12-12 20:51:07.000000000 -0200
+@@ -14,4 +14,4 @@ obj-$(CONFIG_LOONGSON_SUSPEND) += pm.o
+ # Platform Drivers
+ #
+ obj-$(CONFIG_LEMOTE_LYNLOONG2F_PDEV) += lynloong_pc.o
+-obj-$(CONFIG_LEMOTE_YEELOONG2F_PDEV) += yeeloong_laptop.o
++obj-$(CONFIG_LEMOTE_YEELOONG2F_PDEV) += yeeloong_laptop.o yeeloong_battery.o
+Index: arch/mips/loongson/lemote-2f/yeeloong_battery.c
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ arch/mips/loongson/lemote-2f/yeeloong_battery.c 2009-12-12 20:57:41.000000000 -0200
+@@ -0,0 +1,379 @@
++/*
++ * EC(Embedded Controller) KB3310B battery management driver on Linux
++ *
++ * Copyright (C) 2008 Lemote Inc.
++ * Author: liujl <liujl@lemote.com>
++ *
++ * NOTE: The SDA0/SCL0 in KB3310B are used to communicate with the battery
++ * IC, Here we use DS2786 IC to handle the battery management. All the
++ * resources for handle battery management in KB3310B are:
++ * 1, one SMBus interface with port 0
++ * 2, gpio40 output for charge enable
++ */
++
++#include <linux/module.h>
++#include <linux/poll.h>
++#include <linux/proc_fs.h>
++#include <linux/miscdevice.h>
++#include <linux/capability.h>
++#include <linux/sched.h>
++#include <linux/device.h>
++#include <linux/kernel.h>
++#include <linux/list.h>
++#include <linux/init.h>
++#include <linux/completion.h>
++#include <linux/delay.h>
++#include <linux/timer.h>
++
++#include <asm/delay.h>
++
++#include "ec_kb3310b.h"
++
++#ifndef APM_32_BIT_SUPPORT
++#define APM_32_BIT_SUPPORT 0x0002
++#endif
++
++/* The EC Battery device, here is his minor number. */
++#define ECBAT_MINOR_DEV MISC_DYNAMIC_MINOR
++
++/*
++ * apm threshold : percent unit.
++ */
++#define BAT_MAX_THRESHOLD 99
++#define BAT_MIN_THRESHOLD 5
++
++/*
++ * This structure gets filled in by the machine specific 'get_power_status'
++ * implementation. Any fields which are not set default to a safe value.
++ */
++struct apm_pwr_info {
++ unsigned char ac_line_status;
++#define APM_AC_OFFLINE 0
++#define APM_AC_ONLINE 1
++#define APM_AC_BACKUP 2
++#define APM_AC_UNKNOWN 0xff
++
++ unsigned char battery_status;
++#define APM_BATTERY_STATUS_HIGH 0
++#define APM_BATTERY_STATUS_LOW 1
++#define APM_BATTERY_STATUS_CRITICAL 2
++#define APM_BATTERY_STATUS_CHARGING 3
++#define APM_BATTERY_STATUS_NOT_PRESENT 4
++#define APM_BATTERY_STATUS_UNKNOWN 0xff
++
++ unsigned char battery_flag;
++#define APM_BATTERY_FLAG_HIGH (1 << 0)
++#define APM_BATTERY_FLAG_LOW (1 << 1)
++#define APM_BATTERY_FLAG_CRITICAL (1 << 2)
++#define APM_BATTERY_FLAG_CHARGING (1 << 3)
++#define APM_BATTERY_FLAG_NOT_PRESENT (1 << 7)
++#define APM_BATTERY_FLAG_UNKNOWN 0xff
++
++ int battery_life;
++ int time;
++ int units;
++#define APM_UNITS_MINS 0
++#define APM_UNITS_SECS 1
++#define APM_UNITS_UNKNOWN -1
++
++ /* battery designed capacity */
++ unsigned int bat_design_cap;
++ /* battery designed voltage */
++ unsigned int bat_design_vol;
++ /* battery capacity after full charged */
++ unsigned int bat_full_charged_cap;
++ /* battery vendor number */
++ unsigned char bat_vendor;
++ /* battery cell count */
++ unsigned char bat_cell_count;
++
++ /* battery dynamic charge/discharge voltage */
++ unsigned int bat_voltage;
++ /* battery dynamic charge/discharge current */
++ int bat_current;
++ /* battery current temperature */
++ unsigned int bat_temperature;
++};
++
++static DEFINE_MUTEX(bat_info_lock);
++struct bat_info {
++ unsigned int ac_in;
++ unsigned int bat_in;
++ unsigned int bat_flag;
++ /* we use capacity for caculating the life and time */
++ unsigned int curr_bat_cap;
++
++ /* battery designed capacity */
++ unsigned int bat_design_cap;
++ /* battery designed voltage */
++ unsigned int bat_design_vol;
++ /* battery capacity after full charged */
++ unsigned int bat_full_charged_cap;
++ /* battery vendor number */
++ unsigned char bat_vendor;
++ /* battery cell count */
++ unsigned char bat_cell_count;
++
++ /* battery dynamic charge/discharge voltage */
++ unsigned int bat_voltage;
++ /* battery dynamic charge/discharge current */
++ int bat_current;
++ /* battery current temperature */
++ unsigned int bat_temperature;
++} bat_info = {
++ .ac_in = APM_AC_UNKNOWN,
++ .bat_in = APM_BATTERY_STATUS_UNKNOWN,
++ .curr_bat_cap = 0,
++ /* fixed value */
++ .bat_design_cap = 0,
++ .bat_full_charged_cap = 0,
++ .bat_design_vol = 0,
++ .bat_vendor = 0,
++ .bat_cell_count = 0,
++ /* rest variable */
++ .bat_voltage = 0,
++ .bat_current = 0,
++ .bat_temperature = 0
++};
++
++/*
++ * 1.4 :
++ * 1, 89inch basic work version.
++ * 2, you should set xorg.conf ServerFlag of "NoPM" to true
++ * 1.5 :
++ * 1, bat_flag is added to struct bat_info.
++ * 2, BAT_MIN_THRESHOLD is changed to 5%.
++ */
++static const char driver_version[] = "1.38"; /* no spaces */
++
++static struct miscdevice apm_device = {
++ .minor = ECBAT_MINOR_DEV,
++ .name = "apm_bios",
++ .fops = NULL
++};
++
++static void get_battery_fixed_info(void)
++{
++ bat_info.bat_design_cap = (ec_read(REG_BAT_DESIGN_CAP_HIGH) << 8)
++ | ec_read(REG_BAT_DESIGN_CAP_LOW);
++ bat_info.bat_full_charged_cap = (ec_read(REG_BAT_FULLCHG_CAP_HIGH) << 8)
++ | ec_read(REG_BAT_FULLCHG_CAP_LOW);
++ bat_info.bat_design_vol = (ec_read(REG_BAT_DESIGN_VOL_HIGH) << 8)
++ | ec_read(REG_BAT_DESIGN_VOL_LOW);
++ bat_info.bat_vendor = ec_read(REG_BAT_VENDOR);
++ bat_info.bat_cell_count = ec_read(REG_BAT_CELL_COUNT);
++ if (bat_info.bat_vendor != 0) {
++ printk(KERN_INFO
++ "battery vendor(%s), cells count(%d), "
++ "with designed capacity(%d),designed voltage(%d),"
++ " full charged capacity(%d)\n",
++ (bat_info.bat_vendor ==
++ FLAG_BAT_VENDOR_SANYO) ? "SANYO" : "SIMPLO",
++ (bat_info.bat_cell_count == FLAG_BAT_CELL_3S1P) ? 3 : 6,
++ bat_info.bat_design_cap, bat_info.bat_design_vol,
++ bat_info.bat_full_charged_cap);
++ }
++}
++
++static void get_battery_variable_info(void)
++{
++ unsigned char bat_charge;
++ unsigned char power_flag;
++ unsigned char bat_status;
++ unsigned char charge_status;
++
++ mutex_lock(&bat_info_lock);
++
++ bat_charge = ec_read(REG_BAT_CHARGE);
++ power_flag = ec_read(REG_BAT_POWER);
++ bat_status = ec_read(REG_BAT_STATUS);
++ charge_status = ec_read(REG_BAT_CHARGE_STATUS);
++ bat_info.bat_voltage =
++ (ec_read(REG_BAT_VOLTAGE_HIGH) << 8) |
++ (ec_read(REG_BAT_VOLTAGE_LOW));
++ bat_info.bat_current =
++ (ec_read(REG_BAT_CURRENT_HIGH) << 8) |
++ (ec_read(REG_BAT_CURRENT_LOW));
++ bat_info.bat_temperature =
++ (ec_read(REG_BAT_TEMPERATURE_HIGH) << 8) |
++ (ec_read(REG_BAT_TEMPERATURE_LOW));
++ bat_info.curr_bat_cap =
++ (ec_read(REG_BAT_RELATIVE_CAP_HIGH) << 8) |
++ (ec_read(REG_BAT_RELATIVE_CAP_LOW));
++
++ bat_info.ac_in =
++ (power_flag & BIT_BAT_POWER_ACIN) ? APM_AC_ONLINE :
++ APM_AC_OFFLINE;
++ if (!(bat_status & BIT_BAT_STATUS_IN)) {
++ /* there is no battery inserted */
++ bat_info.bat_in = APM_BATTERY_STATUS_NOT_PRESENT;
++ bat_info.bat_flag = APM_BATTERY_FLAG_NOT_PRESENT;
++ } else {
++ /* there is adapter inserted */
++ if (bat_info.ac_in == APM_AC_ONLINE) {
++ /* if the battery is not fully charged */
++ if (!(bat_status & BIT_BAT_STATUS_FULL)) {
++ bat_info.bat_in =
++ APM_BATTERY_STATUS_CHARGING;
++ bat_info.bat_flag =
++ APM_BATTERY_FLAG_CHARGING;
++ } else {
++ /* if the battery is fully charged */
++ bat_info.bat_in =
++ APM_BATTERY_STATUS_HIGH;
++ bat_info.bat_flag =
++ APM_BATTERY_FLAG_HIGH;
++ bat_info.curr_bat_cap = 100;
++ }
++ } else {
++ /* if the battery is too low */
++ if (bat_status & BIT_BAT_STATUS_LOW) {
++ bat_info.bat_in =
++ APM_BATTERY_STATUS_LOW;
++ bat_info.bat_flag =
++ APM_BATTERY_FLAG_LOW;
++ if (bat_info.curr_bat_cap <=
++ BAT_MIN_THRESHOLD) {
++ bat_info.bat_in =
++ APM_BATTERY_STATUS_CRITICAL;
++ bat_info.bat_flag =
++ APM_BATTERY_FLAG_CRITICAL;
++ }
++ /* we should power off the system now */
++ } else {
++ /* assume the battery is high enough. */
++ bat_info.bat_in =
++ APM_BATTERY_STATUS_HIGH;
++ bat_info.bat_flag =
++ APM_BATTERY_FLAG_HIGH;
++ }
++ }
++ }
++
++ mutex_unlock(&bat_info_lock);
++}
++
++#ifdef CONFIG_PROC_FS
++static int bat_proc_read(char *page, char **start, off_t off, int count,
++ int *eof, void *data);
++static struct proc_dir_entry *bat_proc_entry;
++
++static int bat_proc_read(char *page, char **start, off_t off, int count,
++ int *eof, void *data)
++{
++ struct apm_pwr_info info;
++ char *units;
++ int ret;
++
++ /* get variable battery infomation */
++ get_battery_variable_info();
++
++ mutex_lock(&bat_info_lock);
++ info.battery_life = bat_info.curr_bat_cap;
++ info.ac_line_status = bat_info.ac_in;
++ info.battery_status = bat_info.bat_in;
++ info.battery_flag = bat_info.bat_flag;
++ info.bat_voltage = bat_info.bat_voltage;
++ if (bat_info.bat_current & 0x8000)
++ info.bat_current = 0xffff - bat_info.bat_current;
++ else
++ info.bat_current = bat_info.bat_current;
++ info.bat_temperature = bat_info.bat_temperature;
++
++ /* this should be charged according to the capacity-time flow. */
++ if (info.battery_status != APM_BATTERY_STATUS_NOT_PRESENT)
++ info.time = ((bat_info.curr_bat_cap - 3) * 54 + 142) / 60;
++ else
++ info.time = 0x00;
++ info.units = APM_UNITS_MINS;
++
++ mutex_unlock(&bat_info_lock);
++ switch (info.units) {
++ default:
++ units = "?";
++ break;
++ case 0:
++ units = "min";
++ break;
++ case 1:
++ units = "sec";
++ break;
++ }
++
++ ret =
++ sprintf(page,
++ "%s 1.2 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s %dmV %dmA %d\n",
++ driver_version, APM_32_BIT_SUPPORT, info.ac_line_status,
++ info.battery_status, info.battery_flag, info.battery_life,
++ info.time, units, info.bat_voltage, info.bat_current,
++ info.bat_temperature);
++
++ ret -= off;
++ if (ret < off + count)
++ *eof = 1;
++ *start = page + off;
++ if (ret > count)
++ ret = count;
++ if (ret < 0)
++ ret = 0;
++
++ return ret;
++}
++#endif
++
++static int ac_bat_action(int status)
++{
++ get_battery_variable_info();
++
++ return status;
++}
++
++static int __init apm_init(void)
++{
++ int ret;
++
++ printk(KERN_INFO
++ "APM of battery on KB3310B Embedded Controller init.\n");
++
++ /* get fixed battery infomation */
++ get_battery_fixed_info();
++ /* install battery event handler */
++ yeeloong_install_sci_handler(EVENT_AC_BAT, ac_bat_action);
++
++#ifdef CONFIG_PROC_FS
++ bat_proc_entry = NULL;
++ bat_proc_entry = create_proc_entry("apm", S_IWUSR | S_IRUGO, NULL);
++ if (bat_proc_entry == NULL) {
++ printk(KERN_ERR "EC BAT : register /proc/apm failed.\n");
++ return -EINVAL;
++ }
++ bat_proc_entry->read_proc = bat_proc_read;
++ bat_proc_entry->write_proc = NULL;
++ bat_proc_entry->data = NULL;
++#endif
++
++ ret = misc_register(&apm_device);
++ if (ret != 0) {
++ remove_proc_entry("apm", NULL);
++ printk(KERN_ERR "ecbat : misc register error.\n");
++ }
++ return ret;
++}
++
++static void __exit apm_exit(void)
++{
++ /* uninstall battery event handler */
++ yeeloong_uninstall_sci_handler(EVENT_AC_BAT, ac_bat_action);
++
++ misc_deregister(&apm_device);
++#ifdef CONFIG_PROC_FS
++ remove_proc_entry("apm", NULL);
++#endif
++}
++
++module_init(apm_init);
++module_exit(apm_exit);
++
++MODULE_AUTHOR("liujl <liujl@lemote.com>");
++MODULE_DESCRIPTION("Advanced Power Management For Kb3310");
++MODULE_LICENSE("GPL");
OpenPOWER on IntegriCloud