aboutsummaryrefslogtreecommitdiffstats
path: root/recipes/linux/linux/acern30/n30-batt.patch
diff options
context:
space:
mode:
Diffstat (limited to 'recipes/linux/linux/acern30/n30-batt.patch')
-rw-r--r--recipes/linux/linux/acern30/n30-batt.patch242
1 files changed, 242 insertions, 0 deletions
diff --git a/recipes/linux/linux/acern30/n30-batt.patch b/recipes/linux/linux/acern30/n30-batt.patch
new file mode 100644
index 0000000000..e5eb9e7812
--- /dev/null
+++ b/recipes/linux/linux/acern30/n30-batt.patch
@@ -0,0 +1,242 @@
+A battery controller i2c driver for the n30.
+
+I don't use this driver any more, it was much nicer to use the ARM APM
+emulation to expose this data.
+
+Index: linux-2.6.14/drivers/hwmon/Kconfig
+===================================================================
+--- linux-2.6.14.orig/drivers/hwmon/Kconfig
++++ linux-2.6.14/drivers/hwmon/Kconfig
+@@ -290,6 +290,16 @@
+ This driver can also be built as a module. If so, the module
+ will be called max1619.
+
++config SENSORS_N30_BATT
++ tristate "Acer N30 Battery Controller"
++ depends on HWMON && I2C && MACH_N30
++ help
++ If you say yes here you get support for the battery controller
++ found inside the Acer N30 PDA.
++
++ This driver can also be built as a module. If so, the module
++ will be called n30_batt.
++
+ config SENSORS_PC87360
+ tristate "National Semiconductor PC87360 family"
+ depends on HWMON && I2C && EXPERIMENTAL
+Index: linux-2.6.14/drivers/hwmon/Makefile
+===================================================================
+--- linux-2.6.14.orig/drivers/hwmon/Makefile
++++ linux-2.6.14/drivers/hwmon/Makefile
+@@ -35,6 +35,7 @@
+ obj-$(CONFIG_SENSORS_LM90) += lm90.o
+ obj-$(CONFIG_SENSORS_LM92) += lm92.o
+ obj-$(CONFIG_SENSORS_MAX1619) += max1619.o
++obj-$(CONFIG_SENSORS_N30_BATT) += n30_batt.o
+ obj-$(CONFIG_SENSORS_PC87360) += pc87360.o
+ obj-$(CONFIG_SENSORS_SIS5595) += sis5595.o
+ obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o
+Index: linux-2.6.14/drivers/hwmon/n30_batt.c
+===================================================================
+--- linux-2.6.14.orig/drivers/hwmon/n30_batt.c
++++ linux-2.6.14/drivers/hwmon/n30_batt.c
+@@ -0,0 +1,199 @@
++/*
++ * n30_batt.c - Support for the Acer N30 Battery Controller
++ * Copyright (c) 2005 Christer Weinigel <christer@weinigel.se>
++ *
++ * 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, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++*/
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/slab.h>
++#include <linux/i2c.h>
++#include <linux/hwmon.h>
++#include <asm/mach-types.h>
++#include <asm/apm.h>
++
++static unsigned short normal_i2c[] = { I2C_CLIENT_END, I2C_CLIENT_END };
++static unsigned short probe[] = { I2C_CLIENT_END, I2C_CLIENT_END };
++static unsigned short ignore[] = { I2C_CLIENT_END, I2C_CLIENT_END };
++static unsigned short force[] = { -1, 0x0b, I2C_CLIENT_END, I2C_CLIENT_END };
++static unsigned short *forces[] = { force, NULL };
++
++static struct i2c_client_address_data addr_data = {
++ .normal_i2c = normal_i2c,
++ .probe = probe,
++ .ignore = ignore,
++ .forces = forces,
++};
++
++struct n30_batt_data {
++ struct i2c_client client;
++ struct semaphore update_lock;
++ unsigned long last_updated; /* last update in jiffies */
++ u8 charge;
++};
++
++static struct n30_batt_data *n30_batt_update_device(struct device *dev)
++{
++ struct i2c_client *client = to_i2c_client(dev);
++ struct n30_batt_data *data = i2c_get_clientdata(client);
++
++ down(&data->update_lock);
++
++ if (time_after(jiffies, data->last_updated + 3 * HZ)) {
++ int value;
++
++ value = i2c_smbus_read_byte(client);
++
++ if (value == -1)
++ printk(KERN_WARNING "n30-batt: unable to read charge\n");
++ else
++ data->charge = value;
++ data->last_updated = jiffies;
++ }
++
++ up(&data->update_lock);
++
++ return data;
++}
++
++static ssize_t show_charge(struct device *dev, struct device_attribute *attr, char *buf)
++{
++ struct n30_batt_data *data = n30_batt_update_device(dev);
++ return sprintf(buf, "%d\n", data->charge);
++}
++
++static DEVICE_ATTR(charge, S_IRUGO, show_charge, NULL);
++
++static struct i2c_driver n30_batt_driver;
++
++static struct device *n30_batt_dev;
++
++static int n30_batt_detect(struct i2c_adapter *adapter, int address, int kind)
++{
++ struct i2c_client *new_client;
++ struct n30_batt_data *data;
++ int err = 0;
++ int value;
++
++ printk(KERN_INFO "detect n30 Battery controller\n");
++
++ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
++ goto exit;
++
++ printk(KERN_INFO "kmalloc n30 Battery controller\n");
++
++ if (!(data = kmalloc(sizeof(struct n30_batt_data), GFP_KERNEL))) {
++ err = -ENOMEM;
++ goto exit;
++ }
++ memset(data, 0, sizeof(struct n30_batt_data));
++
++ new_client = &data->client;
++ i2c_set_clientdata(new_client, data);
++ new_client->addr = address;
++ new_client->adapter = adapter;
++ new_client->driver = &n30_batt_driver;
++ new_client->flags = 0;
++ strlcpy(new_client->name, "n30_batt", I2C_NAME_SIZE);
++
++ if ((value = i2c_smbus_read_byte(new_client)) == -1) {
++ printk(KERN_ERR "n30_batt: unable to read charge value\n");
++ err = -ENXIO;
++ goto exit_free;
++ }
++
++ init_MUTEX(&data->update_lock);
++ data->charge = value;
++ data->last_updated = jiffies;
++
++ printk(KERN_DEBUG "n30_batt: battery charge is %d%%\n", data->charge);
++
++ if ((err = i2c_attach_client(new_client)))
++ goto exit_free;
++
++ device_create_file(&new_client->dev, &dev_attr_charge);
++
++ n30_batt_dev = &new_client->dev;
++
++ return 0;
++
++exit_free:
++ kfree(data);
++exit:
++ return err;
++}
++
++static int n30_batt_attach_adapter(struct i2c_adapter *adapter)
++{
++ printk(KERN_INFO "attaching n30 Battery controller\n");
++ return i2c_probe(adapter, &addr_data, n30_batt_detect);
++}
++
++static int n30_batt_detach_client(struct i2c_client *client)
++{
++ n30_batt_dev = NULL;
++ i2c_detach_client(client);
++ kfree(i2c_get_clientdata(client));
++ return 0;
++}
++
++static struct i2c_driver n30_batt_driver = {
++ .owner = THIS_MODULE,
++ .name = "n30_batt",
++ .flags = I2C_DF_NOTIFY,
++ .attach_adapter = n30_batt_attach_adapter,
++ .detach_client = n30_batt_detach_client,
++};
++
++static void n30_get_power_status(struct apm_power_info *info)
++{
++ if (n30_batt_dev) {
++ struct n30_batt_data *data = n30_batt_update_device(n30_batt_dev);
++
++ info->ac_line_status = 0xff;
++ info->battery_status = 0xff;
++ info->battery_flag = 0xff;
++ info->battery_life = data->charge;
++ info->time = -1;
++ info->units = -1;
++ }
++}
++
++static int __init sensors_n30_batt_init(void)
++{
++ printk(KERN_INFO "n30 Battery controller\n");
++
++ if (!machine_is_n30())
++ return -ENODEV;
++ printk(KERN_INFO "adding n30 Battery controller\n");
++
++ apm_get_power_status = n30_get_power_status;
++
++ return i2c_add_driver(&n30_batt_driver);
++}
++
++static void __exit sensors_n30_batt_exit(void)
++{
++ i2c_del_driver(&n30_batt_driver);
++}
++
++MODULE_AUTHOR("Christer Weinigel <christer@weinigel.se>");
++MODULE_DESCRIPTION("Acer n30 Battery Controller");
++MODULE_LICENSE("GPL");
++
++module_init(sensors_n30_batt_init);
++module_exit(sensors_n30_batt_exit);