kernel-power v49 -> kernel-bfs
[kernel-bfs] / kernel-bfs-2.6.28 / debian / patches / bq27x00-reg.diff
diff --git a/kernel-bfs-2.6.28/debian/patches/bq27x00-reg.diff b/kernel-bfs-2.6.28/debian/patches/bq27x00-reg.diff
new file mode 100644 (file)
index 0000000..11a9950
--- /dev/null
@@ -0,0 +1,205 @@
+diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c
+index 46db966..6a6224e 100644
+--- a/drivers/power/bq27x00_battery.c
++++ b/drivers/power/bq27x00_battery.c
+@@ -29,12 +29,15 @@
+ #include <linux/jiffies.h>
+ #include <linux/workqueue.h>
+ #include <linux/delay.h>
++#include <linux/fs.h>
++#include <linux/miscdevice.h>
+ #include <linux/platform_device.h>
+ #include <linux/power_supply.h>
+ #include <linux/idr.h>
+ #include <linux/i2c.h>
+ #include <linux/slab.h>
+ #include <asm/unaligned.h>
++#include <asm/uaccess.h>
+ #include <linux/power/bq27x00_battery.h>
+@@ -89,8 +92,34 @@ struct bq27x00_reg_cache {
+       int flags;
+ };
++#define BQ27X00_READ_REG _IO(MISC_MAJOR, 0)
++
++/**
++ * struct bq27x00_reg_parms - User data for ioctl call BQ27X00_READ_REG
++ * @reg: Battery register
++ * @single: 1 if register is 8bit, 0 if 16bit
++ * @ret: value of register reg
++ *    Ioctl call BQ27X00_READ_REG can be used to read battery register.
++ *    If bq27x00_battery is loaded, it is not possible to use i2c-get
++ *    to get status of battery registers, so this ioctl can be used.
++ */
++struct bq27x00_reg_parms {
++      int reg;
++      int single;
++      int ret;
++};
++
++struct bq27x00_reg_device {
++      struct miscdevice miscdev;
++      struct bq27x00_device_info *di;
++      struct bq27x00_reg_device *next, *prev;
++};
++
++static struct bq27x00_reg_device *bq27x00_reg_devices = NULL;
++
+ struct bq27x00_device_info {
+       struct device           *dev;
++      struct bq27x00_reg_device *regdev;
+       int                     id;
+       enum bq27x00_chip       chip;
+@@ -141,6 +153,109 @@ static inline int bq27x00_read(struct bq27x00_device_info *di, u8 reg,
+       return di->bus.read(di, reg, single);
+ }
++/* Code for register device access */
++
++static long bq27x00_battery_reg_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
++{
++      int ret;
++      int minor = iminor(filp->f_dentry->d_inode);
++      struct bq27x00_reg_parms param;
++      struct bq27x00_reg_device *regdev = bq27x00_reg_devices;
++
++      while (regdev) {
++              if (regdev->miscdev.minor == minor)
++                      break;
++              regdev = regdev->next;
++      }
++
++      if (!regdev)
++              return -ENXIO;
++
++      if (cmd != BQ27X00_READ_REG)
++              return -EINVAL;
++
++      ret = copy_from_user(&param, (void __user *)arg, sizeof(param));
++      if (ret != 0)
++              return -EACCES;
++
++      param.ret = bq27x00_read(regdev->di, param.reg, param.single);
++
++      ret = copy_to_user((void __user *)arg, &param, sizeof(param));
++      if (ret != 0)
++              return -EACCES;
++
++      return 0;
++}
++
++static int bq27x00_battery_reg_open(struct inode *inode, struct file *file)
++{
++      if (!try_module_get(THIS_MODULE))
++              return -EPERM;
++
++      return 0;
++}
++
++static int bq27x00_battery_reg_release(struct inode *inode, struct file *file)
++{
++      module_put(THIS_MODULE);
++      return 0;
++}
++
++static struct file_operations bq27x00_reg_fileops = {
++      .owner = THIS_MODULE,
++      .unlocked_ioctl = bq27x00_battery_reg_ioctl,
++      .open = bq27x00_battery_reg_open,
++      .release = bq27x00_battery_reg_release,
++};
++
++static int bq27x00_battery_reg_init(struct bq27x00_device_info *di)
++{
++      struct bq27x00_reg_device *regdev;
++      int ret;
++
++      regdev = kzalloc(sizeof *regdev, GFP_KERNEL);
++      if (!regdev)
++              return -ENOMEM;
++
++      regdev->miscdev.minor = MISC_DYNAMIC_MINOR;
++      regdev->miscdev.name = di->bat.name;
++      regdev->miscdev.fops = &bq27x00_reg_fileops;
++      regdev->di = di;
++
++      ret = misc_register(&regdev->miscdev);
++      if (ret != 0) {
++              kfree(regdev);
++              return ret;
++      }
++
++      di->regdev = regdev;
++
++      if (bq27x00_reg_devices)
++              bq27x00_reg_devices->prev = regdev;
++
++      regdev->prev = NULL;
++      regdev->next = bq27x00_reg_devices;
++      bq27x00_reg_devices = regdev;
++
++      return 0;
++}
++
++static void bq27x00_battery_reg_exit(struct bq27x00_device_info *di)
++{
++      misc_deregister(&di->regdev->miscdev);
++
++      if (di->regdev->next)
++              di->regdev->next->prev = di->regdev->prev;
++
++      if (di->regdev->prev)
++              di->regdev->prev->next = di->regdev->next;
++
++      if (di->regdev == bq27x00_reg_devices)
++              bq27x00_reg_devices = NULL;
++
++      kfree(di->regdev);
++}
++
+ /*
+  * Return the battery Relative State-of-Charge
+  * Or < 0 if something fails.
+@@ -839,6 +839,9 @@ static int bq27x00_battery_probe(struct
+       i2c_set_clientdata(client, di);
++      if (bq27x00_battery_reg_init(di))
++              di->regdev = NULL;
++
+       return 0;
+ batt_failed_3:
+@@ -859,6 +862,9 @@ static int bq27x00_battery_remove(struct
+       bq27x00_powersupply_unregister(di);
++      if (di->regdev)
++              bq27x00_battery_reg_exit(di);
++
+       kfree(di->bat.name);
+       mutex_lock(&battery_mutex);
+@@ -829,6 +944,9 @@ static int __devinit bq27000_battery_probe(struct platform_device *pdev)
+       if (ret)
+               goto err_free;
++      if (bq27x00_battery_reg_init(di))
++              di->regdev = NULL;
++
+       return 0;
+ err_free:
+@@ -844,6 +962,9 @@ static int __devexit bq27000_battery_remove(struct platform_device *pdev)
+       bq27x00_powersupply_unregister(di);
++      if (di->regdev)
++              bq27x00_battery_reg_exit(di);
++
+       platform_set_drvdata(pdev, NULL);
+       kfree(di);