2 arch/arm/mach-omap2/board-n8x0.c | 13 +
3 drivers/cbus/Kconfig | 12 +
4 drivers/cbus/Makefile | 3
5 drivers/cbus/lipocharge.c | 63 ++++++
6 drivers/cbus/lipocharge.h | 50 ++++
7 drivers/cbus/n810bm_main.c | 397 +++++++++++++++++++++++++++++++++++++++
8 drivers/cbus/retu.c | 4
9 drivers/cbus/retu.h | 3
10 drivers/cbus/tahvo.h | 6
11 9 files changed, 548 insertions(+), 3 deletions(-)
13 Index: linux-2.6.37/drivers/cbus/Kconfig
14 ===================================================================
15 --- linux-2.6.37.orig/drivers/cbus/Kconfig 2011-01-28 22:33:39.703215389 +0100
16 +++ linux-2.6.37/drivers/cbus/Kconfig 2011-01-28 23:41:57.094298060 +0100
18 to Retu/Vilma. Detection state and events are exposed through
22 + depends on CBUS_RETU && CBUS_TAHVO
23 + tristate "Nokia n810 battery management"
25 + Nokia n810 device battery management.
30 Index: linux-2.6.37/drivers/cbus/Makefile
31 ===================================================================
32 --- linux-2.6.37.orig/drivers/cbus/Makefile 2011-01-28 22:33:39.694216931 +0100
33 +++ linux-2.6.37/drivers/cbus/Makefile 2011-01-28 22:33:39.754206648 +0100
35 obj-$(CONFIG_CBUS_TAHVO_USER) += tahvo-user.o
36 obj-$(CONFIG_CBUS_RETU_USER) += retu-user.o
37 obj-$(CONFIG_CBUS_RETU_HEADSET) += retu-headset.o
38 +n810bm-y += n810bm_main.o
39 +n810bm-y += lipocharge.o
40 +obj-$(CONFIG_N810BM) += n810bm.o
41 Index: linux-2.6.37/drivers/cbus/n810bm_main.c
42 ===================================================================
43 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
44 +++ linux-2.6.37/drivers/cbus/n810bm_main.c 2011-01-28 23:41:23.510064352 +0100
47 + * Nokia n810 battery management
49 + * WARNING: This driver is based on unconfirmed documentation.
50 + * It is possibly dangerous to use this software.
51 + * Use this software at your own risk!
53 + * Copyright (c) 2010-2011 Michael Buesch <mb@bu3sch.de>
55 + * This program is free software; you can redistribute it and/or
56 + * modify it under the terms of the GNU General Public License
57 + * as published by the Free Software Foundation; either version 2
58 + * of the License, or (at your option) any later version.
60 + * This program is distributed in the hope that it will be useful,
61 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
62 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
63 + * GNU General Public License for more details.
66 +#include <linux/module.h>
67 +#include <linux/device.h>
68 +#include <linux/platform_device.h>
69 +#include <linux/slab.h>
70 +#include <linux/spinlock.h>
71 +#include <linux/timer.h>
72 +#include <linux/reboot.h>
76 +#include "lipocharge.h"
79 +#define N810BM_CHECK_INTERVAL (HZ * 5)
80 +#define N810BM_MIN_VOLTAGE_THRES 3300 /* Absolute minimum voltage threshold */
84 + * The battery size indicator ADC measures the resistance between
85 + * the battery BSI pin and ground. This is used to detect the battery
86 + * capacity, as the BSI resistor is related to capacity.
88 + * Manually measured lookup table.
89 + * Hard to measure, thus not very accurate.
91 + * Resistance | ADC value
92 + * ========================
100 + * Manually measured lookup table.
101 + * Hard to measure, thus not very accurate.
103 + * Voltage | ADC value
104 + * =====================
123 +enum n810bm_capacity {
124 + N810BM_CAP_UNKNOWN = 0,
125 + N810BM_CAP_1500MAH = 1500, /* 1500 mAh battery */
129 + struct platform_device *pdev;
131 + enum n810bm_capacity capacity;
132 + struct timer_list check_timer;
134 + struct lipocharge *charger;
140 +static NORET_TYPE void n810bm_emergency(struct n810bm *bm, const char *message) ATTRIB_NORET;
141 +static void n810bm_emergency(struct n810bm *bm, const char *message)
143 + printk(KERN_EMERG "n810 battery management fatal fault: %s\n", message);
144 + /* Force a hard shutdown. */
145 + machine_power_off();
146 + panic("n810bm: Failed to halt machine in emergency state\n");
150 +static u16 retu_read(struct n810bm *bm, unsigned int reg)
153 + unsigned long flags;
155 + spin_lock_irqsave(&retu_lock, flags);
156 + ret = retu_read_reg(reg);
157 + spin_unlock_irqrestore(&retu_lock, flags);
158 + if (ret < 0 || ret > 0xFFFF)
159 + n810bm_emergency(bm, "retu_read");
165 +static void retu_maskset(struct n810bm *bm, unsigned int reg, u16 mask, u16 set)
168 + unsigned long flags;
171 + spin_lock_irqsave(&retu_lock, flags);
173 + ret = retu_read_reg(reg);
174 + if (ret < 0 || ret > 0xFFFF)
181 + ret = retu_write_reg(reg, value);
184 + spin_unlock_irqrestore(&retu_lock, flags);
189 + spin_unlock_irqrestore(&retu_lock, flags);
190 + n810bm_emergency(bm, "retu_maskset");
193 +static inline void retu_write(struct n810bm *bm, unsigned int reg, u16 value)
195 + return retu_maskset(bm, reg, 0xFFFF, value);
198 +static int retu_adc_average(struct n810bm *bm, unsigned int chan,
199 + unsigned int nr_passes)
201 + unsigned int i, value = 0;
204 + if (WARN_ON(!nr_passes))
206 + for (i = 0; i < nr_passes; i++) {
207 + ret = retu_read_adc(chan);
212 + value /= nr_passes;
217 +static int adc_sanity_check(struct n810bm *bm, unsigned int channel)
221 + value = retu_read_adc(channel);
223 + dev_err(&bm->pdev->dev, "Failed to read GND ADC channel %u",
227 + dev_info(&bm->pdev->dev,
228 + "GND ADC channel %u sanity check got value: %d",
231 + n810bm_emergency(bm, "GND ADC sanity check failed");
238 +static int n810bm_check_adc_sanity(struct n810bm *bm)
242 + /* Discard one conversion */
243 + retu_write(bm, RETU_REG_ADCSCR, 0);
244 + retu_read_adc(RETU_ADC_GND2);
246 + err = adc_sanity_check(bm, RETU_ADC_GND2);
253 +/* Measure the battery voltage. Returns the value in mV (or negative value on error). */
254 +static int n810bm_measure_batt_voltage(struct n810bm *bm)
258 + const unsigned int scale = 1000;
260 + adc = retu_adc_average(bm, RETU_ADC_BATTVOLT, 5);
265 + mv = 2800 + ((adc - 0x37) * (((4200 - 2800) * scale) / (0x236 - 0x37))) / scale;
270 +/* Measure the charger voltage. Returns the value in mV (or negative value on error). */
271 +static int n810bm_measure_charger_voltage(struct n810bm *bm)
276 + adc = retu_adc_average(bm, RETU_ADC_CHGVOLT, 5);
279 + //TODO convert to mV
285 +/* Measure backup battery voltage. Returns the value in mV (or negative value on error). */
286 +static int n810bm_measure_backup_batt_voltage(struct n810bm *bm)
291 + adc = retu_adc_average(bm, RETU_ADC_BKUPVOLT, 3);
294 + //TODO convert to mV
300 +/* Measure the battery temperature. Returns the value in K (or negative value on error). */
301 +static int n810bm_measure_batt_temp(struct n810bm *bm)
306 + adc = retu_adc_average(bm, RETU_ADC_BATTEMP, 3);
309 + //TODO convert to K
315 +/* Read the battery capacity via BSI pin. */
316 +static enum n810bm_capacity n810bm_read_batt_capacity(struct n810bm *bm)
319 + const unsigned int hyst = 20;
321 + adc = retu_adc_average(bm, RETU_ADC_BSI, 5);
323 + dev_err(&bm->pdev->dev, "Failed to read BSI ADC");
324 + return N810BM_CAP_UNKNOWN;
327 + if (adc >= 0x3B5 - hyst && adc <= 0x3B5 + hyst)
328 + return N810BM_CAP_1500MAH;
330 + dev_err(&bm->pdev->dev, "Capacity indicator 0x%X unknown", adc);
332 + return N810BM_CAP_UNKNOWN;
335 +/* Convert a battery voltage (in mV) to percentage. */
336 +static unsigned int n810bm_mvolt2percent(unsigned int mv)
338 + const unsigned int minv = 3700;
339 + const unsigned int maxv = 4150;
340 + unsigned int percent;
342 + mv = clamp(mv, minv, maxv);
343 + percent = (mv - minv) * 100 / (maxv - minv);
348 +static void n810bm_check_timer(unsigned long data)
350 + struct n810bm *bm = (struct n810bm *)data;
351 + unsigned long flags;
354 + spin_lock_irqsave(&bm->lock, flags);
356 + mv = n810bm_measure_batt_voltage(bm);
358 + n810bm_emergency(bm, "check timer: Failed to measure");
359 + if (mv < N810BM_MIN_VOLTAGE_THRES)
360 + n810bm_emergency(bm, "check timer: Minimum voltage threshold reached");
362 + mod_timer(&bm->check_timer, round_jiffies(jiffies + N810BM_CHECK_INTERVAL));
363 + spin_unlock_irqrestore(&bm->lock, flags);
368 +static void n810bm_adc_irq_handler(unsigned long data)
370 +// struct n810bm *bm = (struct n810bm *)data;
372 + retu_ack_irq(RETU_INT_ADCS);
374 +printk("n810bm: ADC timer triggered\n");
377 +static ssize_t n810bm_attr_charge_show(struct device *dev,
378 + struct device_attribute *attr,
381 + struct platform_device *pdev = to_platform_device(dev);
382 + struct n810bm *bm = platform_get_drvdata(pdev);
387 + spin_lock_irq(&bm->lock);
388 + millivolt = n810bm_measure_batt_voltage(bm);
389 + if (millivolt >= 0) {
390 + count = snprintf(buf, PAGE_SIZE, "%u\n",
391 + n810bm_mvolt2percent(millivolt));
394 + spin_unlock_irq(&bm->lock);
396 + return err ? err : count;
398 +static DEVICE_ATTR(batt_charge, 0444, n810bm_attr_charge_show, NULL);
400 +static ssize_t n810bm_attr_capacity_show(struct device *dev,
401 + struct device_attribute *attr,
404 + struct platform_device *pdev = to_platform_device(dev);
405 + struct n810bm *bm = platform_get_drvdata(pdev);
408 + spin_lock_irq(&bm->lock);
409 + count = snprintf(buf, PAGE_SIZE, "%u\n",
410 + (unsigned int)bm->capacity);
411 + spin_unlock_irq(&bm->lock);
415 +static DEVICE_ATTR(batt_capacity, 0444, n810bm_attr_capacity_show, NULL);
417 +static ssize_t n810bm_attr_battemp_show(struct device *dev,
418 + struct device_attribute *attr,
421 + struct platform_device *pdev = to_platform_device(dev);
422 + struct n810bm *bm = platform_get_drvdata(pdev);
424 + int k, err = -ENODEV;
426 + spin_lock_irq(&bm->lock);
427 + k = n810bm_measure_batt_temp(bm);
429 + count = snprintf(buf, PAGE_SIZE, "%d\n", k);
432 + spin_unlock_irq(&bm->lock);
434 + return err ? err : count;
436 +static DEVICE_ATTR(batt_temp, 0444, n810bm_attr_battemp_show, NULL);
438 +static ssize_t n810bm_attr_charger_voltage(struct device *dev,
439 + struct device_attribute *attr,
442 + struct platform_device *pdev = to_platform_device(dev);
443 + struct n810bm *bm = platform_get_drvdata(pdev);
445 + int mv, err = -ENODEV;
447 + spin_lock_irq(&bm->lock);
448 + mv = n810bm_measure_charger_voltage(bm);
450 + count = snprintf(buf, PAGE_SIZE, "%d\n", mv);
453 + spin_unlock_irq(&bm->lock);
455 + return err ? err : count;
457 +static DEVICE_ATTR(charger_voltage, 0444, n810bm_attr_charger_voltage, NULL);
459 +static ssize_t n810bm_attr_backup_batt_voltage(struct device *dev,
460 + struct device_attribute *attr,
463 + struct platform_device *pdev = to_platform_device(dev);
464 + struct n810bm *bm = platform_get_drvdata(pdev);
466 + int mv, err = -ENODEV;
468 + spin_lock_irq(&bm->lock);
469 + mv = n810bm_measure_backup_batt_voltage(bm);
471 + count = snprintf(buf, PAGE_SIZE, "%d\n", mv);
474 + spin_unlock_irq(&bm->lock);
476 + return err ? err : count;
478 +static DEVICE_ATTR(backup_batt_voltage, 0444, n810bm_attr_backup_batt_voltage, NULL);
480 +static void n810bm_hw_exit(struct n810bm *bm)
482 + retu_write(bm, RETU_REG_ADCSCR, 0);
485 +static int n810bm_hw_init(struct n810bm *bm)
489 + err = n810bm_check_adc_sanity(bm);
492 + bm->capacity = n810bm_read_batt_capacity(bm);
493 + if (bm->capacity == N810BM_CAP_UNKNOWN) {
494 + dev_err(&bm->pdev->dev, "Unknown battery detected");
498 + dev_info(&bm->pdev->dev, "Detected %u mAh battery\n",
499 + (unsigned int)bm->capacity);
507 +static int __devinit n810bm_probe(struct platform_device *pdev)
512 + bm = kzalloc(sizeof(*bm), GFP_KERNEL);
516 + platform_set_drvdata(pdev, bm);
517 + spin_lock_init(&bm->lock);
518 + setup_timer(&bm->check_timer, n810bm_check_timer, (unsigned long)bm);
520 + err = n810bm_hw_init(bm);
523 + err = device_create_file(&pdev->dev, &dev_attr_batt_charge);
526 + err = device_create_file(&pdev->dev, &dev_attr_batt_capacity);
528 + goto err_rem_charge;
529 + err = device_create_file(&pdev->dev, &dev_attr_batt_temp);
532 + err = device_create_file(&pdev->dev, &dev_attr_charger_voltage);
535 + err = device_create_file(&pdev->dev, &dev_attr_backup_batt_voltage);
538 + err = retu_request_irq(RETU_INT_ADCS, n810bm_adc_irq_handler,
539 + (unsigned long)bm, "n810bm");
543 + mod_timer(&bm->check_timer, round_jiffies(jiffies + N810BM_CHECK_INTERVAL));
545 + dev_info(&pdev->dev, "Battery management initialized");
550 + device_remove_file(&pdev->dev, &dev_attr_backup_batt_voltage);
552 + device_remove_file(&pdev->dev, &dev_attr_charger_voltage);
554 + device_remove_file(&pdev->dev, &dev_attr_batt_temp);
556 + device_remove_file(&pdev->dev, &dev_attr_batt_capacity);
558 + device_remove_file(&pdev->dev, &dev_attr_batt_charge);
560 + n810bm_hw_exit(bm);
563 + platform_set_drvdata(pdev, NULL);
567 +static int __devexit n810bm_remove(struct platform_device *pdev)
569 + struct n810bm *bm = platform_get_drvdata(pdev);
571 + retu_free_irq(RETU_INT_ADCS);
572 + del_timer_sync(&bm->check_timer);
573 + device_remove_file(&pdev->dev, &dev_attr_backup_batt_voltage);
574 + device_remove_file(&pdev->dev, &dev_attr_charger_voltage);
575 + device_remove_file(&pdev->dev, &dev_attr_batt_temp);
576 + device_remove_file(&pdev->dev, &dev_attr_batt_capacity);
577 + device_remove_file(&pdev->dev, &dev_attr_batt_charge);
578 + n810bm_hw_exit(bm);
581 + platform_set_drvdata(pdev, NULL);
586 +static struct platform_driver n810bm_driver = {
587 + .remove = __devexit_p(n810bm_remove),
593 +static int __init n810bm_modinit(void)
595 + return platform_driver_probe(&n810bm_driver, n810bm_probe);
597 +module_init(n810bm_modinit);
599 +static void __exit n810bm_modexit(void)
601 + platform_driver_unregister(&n810bm_driver);
603 +module_exit(n810bm_modexit);
605 +MODULE_DESCRIPTION("Nokia n810 battery management");
606 +MODULE_LICENSE("GPL");
607 +MODULE_AUTHOR("Michael Buesch");
608 Index: linux-2.6.37/drivers/cbus/retu.c
609 ===================================================================
610 --- linux-2.6.37.orig/drivers/cbus/retu.c 2011-01-28 22:33:39.695216760 +0100
611 +++ linux-2.6.37/drivers/cbus/retu.c 2011-01-28 22:33:39.754206648 +0100
614 * This function writes a value to the specified register
616 -void retu_write_reg(int reg, u16 val)
617 +int retu_write_reg(int reg, u16 val)
619 BUG_ON(!retu_initialized);
620 - cbus_write_reg(cbus_host, RETU_ID, reg, val);
621 + return cbus_write_reg(cbus_host, RETU_ID, reg, val);
624 void retu_set_clear_reg_bits(int reg, u16 set, u16 clear)
625 Index: linux-2.6.37/drivers/cbus/retu.h
626 ===================================================================
627 --- linux-2.6.37.orig/drivers/cbus/retu.h 2011-01-28 22:33:39.695216760 +0100
628 +++ linux-2.6.37/drivers/cbus/retu.h 2011-01-28 22:40:55.380584650 +0100
630 #define RETU_REG_CC2 0x0e /* Common control register 2 */
631 #define RETU_REG_CTRL_CLR 0x0f /* Regulator clear register */
632 #define RETU_REG_CTRL_SET 0x10 /* Regulator set register */
633 +#define RETU_REG_UNK1 0x14 /* 0x1000 is set when charger is plugged in */
634 #define RETU_REG_STATUS 0x16 /* Status register */
635 #define RETU_REG_WATCHDOG 0x17 /* Watchdog register */
636 #define RETU_REG_AUDTXR 0x18 /* Audio Codec Tx register */
639 #define MAX_RETU_IRQ_HANDLERS 16
642 +#define RETU_ADC_GND 0x00 /* Ground */
643 +#define RETU_ADC_BSI 0x01 /* Battery Size Indicator */
644 +#define RETU_ADC_BATTEMP 0x02 /* Battery temperature */
645 +#define RETU_ADC_CHGVOLT 0x03 /* Charger voltage */
646 +#define RETU_ADC_HEADSET 0x04 /* Headset detection */
647 +#define RETU_ADC_HOOKDET 0x05 /* Hook detection */
648 +#define RETU_ADC_RFGP 0x06 /* RF GP */
649 +#define RETU_ADC_WBTX 0x07 /* Wideband Tx detection */
650 +#define RETU_ADC_BATTVOLT 0x08 /* Battery voltage measurement */
651 +#define RETU_ADC_GND2 0x09 /* Ground */
652 +#define RETU_ADC_LIGHTSENS 0x0A /* Light sensor */
653 +#define RETU_ADC_LIGHTTEMP 0x0B /* Light sensor temperature */
654 +#define RETU_ADC_BKUPVOLT 0x0C /* Backup battery voltage */
655 +#define RETU_ADC_TEMP 0x0D /* RETU temperature */
658 int retu_read_reg(int reg);
659 -void retu_write_reg(int reg, u16 val);
660 +int retu_write_reg(int reg, u16 val);
661 void retu_set_clear_reg_bits(int reg, u16 set, u16 clear);
662 int retu_read_adc(int channel);
663 int retu_request_irq(int id, void *irq_handler, unsigned long arg, char *name);
664 Index: linux-2.6.37/arch/arm/mach-omap2/board-n8x0.c
665 ===================================================================
666 --- linux-2.6.37.orig/arch/arm/mach-omap2/board-n8x0.c 2011-01-28 22:33:39.679219500 +0100
667 +++ linux-2.6.37/arch/arm/mach-omap2/board-n8x0.c 2011-01-28 22:33:39.754206648 +0100
669 ARRAY_SIZE(n8x0_gpio_switches));
672 +static struct platform_device n810_bm_device = {
677 +static void __init n810_bm_init(void)
679 + if (platform_device_register(&n810_bm_device))
683 static void __init n8x0_init_machine(void)
685 omap2420_mux_init(board_mux, OMAP_PACKAGE_ZAC);
694 MACHINE_START(NOKIA_N800, "Nokia N800")
695 Index: linux-2.6.37/drivers/cbus/lipocharge.c
696 ===================================================================
697 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
698 +++ linux-2.6.37/drivers/cbus/lipocharge.c 2011-01-28 22:33:39.755206476 +0100
701 + * Generic LIPO battery charger
703 + * Copyright (c) 2010 Michael Buesch <mb@bu3sch.de>
705 + * This program is free software; you can redistribute it and/or
706 + * modify it under the terms of the GNU General Public License
707 + * as published by the Free Software Foundation; either version 2
708 + * of the License, or (at your option) any later version.
710 + * This program is distributed in the hope that it will be useful,
711 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
712 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
713 + * GNU General Public License for more details.
716 +#include "lipocharge.h"
718 +#include <linux/slab.h>
721 +static void lipocharge_timer(unsigned long data)
723 + struct lipocharge *c = (struct lipocharge *)data;
725 + spin_lock(&c->lock);
727 + spin_unlock(&c->lock);
730 +struct lipocharge * lipocharge_alloc(gfp_t gfp)
732 + struct lipocharge *c;
734 + c = kzalloc(sizeof(*c), gfp);
737 + spin_lock_init(&c->lock);
738 + setup_timer(&c->timer, lipocharge_timer, (unsigned long)c);
743 +void lipocharge_free(struct lipocharge *c)
748 +int lipocharge_start(struct lipocharge *c)
750 + if (!c->set_current || !c->get_voltage ||
751 + !c->finished || !c->emergency)
753 + if (!c->top_voltage || c->top_voltage > 4200)
758 +void lipocharge_stop(struct lipocharge *c)
760 + del_timer_sync(&c->timer);
763 Index: linux-2.6.37/drivers/cbus/lipocharge.h
764 ===================================================================
765 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
766 +++ linux-2.6.37/drivers/cbus/lipocharge.h 2011-01-28 22:33:39.755206476 +0100
768 +#ifndef LIPOCHARGE_H_
769 +#define LIPOCHARGE_H_
771 +#include <linux/timer.h>
772 +#include <linux/spinlock.h>
775 +#define LIPORATE(a,b) (((a) * 1000) + (b))
776 +#define LIPORATE_1C LIPORATE(1,0) /* 1C */
777 +#define LIPORATE_p8C LIPORATE(0,8) /* 0.8C */
779 +/** struct lipocharge - A generic LIPO charger
781 + * @capacity: Battery capacity in mAh.
782 + * @rate: Charge rate.
783 + * @top_voltage: Fully charged voltage, in mV.
785 + * @set_current: Set the charge current, in mA.
786 + * @get_voltage: Get the battery voltage, in mV.
788 + * @emergency: Something went wrong. Force shutdown.
790 + * @priv: opaque pointer.
794 + unsigned int capacity;
796 + unsigned int top_voltage;
798 + int (*set_current)(struct lipocharge *c, unsigned int ma);
799 + int (*get_voltage)(struct lipocharge *c, unsigned int *mv);
801 + void (*finished)(struct lipocharge *c);
802 + void (*emergency)(struct lipocharge *c);
808 + struct timer_list timer;
811 +struct lipocharge * lipocharge_alloc(gfp_t gfp);
812 +void lipocharge_free(struct lipocharge *c);
814 +int lipocharge_start(struct lipocharge *c);
815 +void lipocharge_stop(struct lipocharge *c);
817 +#endif /* LIPOCHARGE_H_ */
818 Index: linux-2.6.37/drivers/cbus/tahvo.h
819 ===================================================================
820 --- linux-2.6.37.orig/drivers/cbus/tahvo.h 2011-01-28 22:33:39.696216589 +0100
821 +++ linux-2.6.37/drivers/cbus/tahvo.h 2011-01-28 22:33:39.755206476 +0100
823 #define TAHVO_REG_IDR 0x01 /* Interrupt ID */
824 #define TAHVO_REG_IDSR 0x02 /* Interrupt status */
825 #define TAHVO_REG_IMR 0x03 /* Interrupt mask */
826 +#define TAHVO_REG_CHGCURR 0x04 /* Charge current control (8-bit) */
827 #define TAHVO_REG_LEDPWMR 0x05 /* LED PWM */
828 #define TAHVO_REG_USBR 0x06 /* USB control */
829 +#define TAHVO_REG_CHGCTL 0x08 /* Charge control register */
830 +#define TAHVO_REG_CHGCTL_EN 0x0001 /* Global charge enable */
831 +#define TAHVO_REG_CHGCTL2 0x0c /* Charge control register 2 */
832 +#define TAHVO_REG_BATCURR 0x0d /* Battery (dis)charge current (signed 16-bit) */
834 #define TAHVO_REG_MAX 0x0d
836 /* Interrupt sources */