Jelajahi Sumber

n810 battery management: Add calibration data parser

SVN-Revision: 25604
Michael Büsch 15 tahun lalu
induk
melakukan
f277f3bf4f

+ 431 - 40
target/linux/omap24xx/patches-2.6.37/900-n810-battery-management.patch

@@ -10,10 +10,10 @@
  drivers/cbus/tahvo.h             |    6 
  drivers/cbus/tahvo.h             |    6 
  9 files changed, 548 insertions(+), 3 deletions(-)
  9 files changed, 548 insertions(+), 3 deletions(-)
 
 
-Index: linux-2.6.37/drivers/cbus/Kconfig
+Index: linux-2.6.37.1/drivers/cbus/Kconfig
 ===================================================================
 ===================================================================
---- linux-2.6.37.orig/drivers/cbus/Kconfig	2011-02-06 14:05:49.838388760 +0100
-+++ linux-2.6.37/drivers/cbus/Kconfig	2011-02-06 14:05:49.885395646 +0100
+--- linux-2.6.37.1.orig/drivers/cbus/Kconfig	2011-02-19 20:26:01.282338290 +0100
++++ linux-2.6.37.1/drivers/cbus/Kconfig	2011-02-19 20:26:01.526318768 +0100
 @@ -94,4 +94,12 @@
 @@ -94,4 +94,12 @@
  	  to Retu/Vilma. Detection state and events are exposed through
  	  to Retu/Vilma. Detection state and events are exposed through
  	  sysfs.
  	  sysfs.
@@ -27,10 +27,10 @@ Index: linux-2.6.37/drivers/cbus/Kconfig
 +	  If unsure, say N.
 +	  If unsure, say N.
 +
 +
  endmenu
  endmenu
-Index: linux-2.6.37/drivers/cbus/Makefile
+Index: linux-2.6.37.1/drivers/cbus/Makefile
 ===================================================================
 ===================================================================
---- linux-2.6.37.orig/drivers/cbus/Makefile	2011-02-06 14:05:49.829387442 +0100
-+++ linux-2.6.37/drivers/cbus/Makefile	2011-02-06 14:05:49.885395646 +0100
+--- linux-2.6.37.1.orig/drivers/cbus/Makefile	2011-02-19 20:26:01.250340850 +0100
++++ linux-2.6.37.1/drivers/cbus/Makefile	2011-02-19 20:26:01.526318768 +0100
 @@ -12,3 +12,6 @@
 @@ -12,3 +12,6 @@
  obj-$(CONFIG_CBUS_TAHVO_USER)	+= tahvo-user.o
  obj-$(CONFIG_CBUS_TAHVO_USER)	+= tahvo-user.o
  obj-$(CONFIG_CBUS_RETU_USER)	+= retu-user.o
  obj-$(CONFIG_CBUS_RETU_USER)	+= retu-user.o
@@ -38,11 +38,11 @@ Index: linux-2.6.37/drivers/cbus/Makefile
 +n810bm-y			+= n810bm_main.o
 +n810bm-y			+= n810bm_main.o
 +n810bm-y			+= lipocharge.o
 +n810bm-y			+= lipocharge.o
 +obj-$(CONFIG_N810BM)		+= n810bm.o
 +obj-$(CONFIG_N810BM)		+= n810bm.o
-Index: linux-2.6.37/drivers/cbus/n810bm_main.c
+Index: linux-2.6.37.1/drivers/cbus/n810bm_main.c
 ===================================================================
 ===================================================================
 --- /dev/null	1970-01-01 00:00:00.000000000 +0000
 --- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.37/drivers/cbus/n810bm_main.c	2011-02-09 19:05:18.435536304 +0100
-@@ -0,0 +1,1168 @@
++++ linux-2.6.37.1/drivers/cbus/n810bm_main.c	2011-02-20 15:11:55.764356685 +0100
+@@ -0,0 +1,1559 @@
 +/*
 +/*
 + *   Nokia n810 battery management
 + *   Nokia n810 battery management
 + *
 + *
@@ -84,6 +84,8 @@ Index: linux-2.6.37/drivers/cbus/n810bm_main.c
 +
 +
 +#define N810BM_PMM_BLOCK_FILENAME	"n810-cal-bme-pmm.fw"
 +#define N810BM_PMM_BLOCK_FILENAME	"n810-cal-bme-pmm.fw"
 +#define N810BM_PMM_BLOCK_SIZE		0x600
 +#define N810BM_PMM_BLOCK_SIZE		0x600
++#define N810BM_PMM_GROUP_SIZE		0x200
++#define N810BM_PMM_ELEM_SIZE		0x10
 +
 +
 +#define N810BM_CHECK_INTERVAL		(HZ * 2)
 +#define N810BM_CHECK_INTERVAL		(HZ * 2)
 +#define N810BM_MIN_VOLTAGE_THRES	3200 /* Absolute minimum voltage threshold */
 +#define N810BM_MIN_VOLTAGE_THRES	3200 /* Absolute minimum voltage threshold */
@@ -129,6 +131,38 @@ Index: linux-2.6.37/drivers/cbus/n810bm_main.c
 + */
 + */
 +
 +
 +
 +
++enum n810bm_pmm_adc_id {
++	N810BM_PMM_ADC_0x01	= 0x01,
++	N810BM_PMM_ADC_0x02	= 0x02,
++	N810BM_PMM_ADC_0x03	= 0x03,
++	N810BM_PMM_ADC_0x04	= 0x04,
++	N810BM_PMM_ADC_BATTEMP	= 0x05,
++	N810BM_PMM_ADC_0x06	= 0x06,
++	N810BM_PMM_ADC_0x07	= 0x07,
++	N810BM_PMM_ADC_0x08	= 0x08,
++	N810BM_PMM_ADC_0x0E	= 0x0E,
++	N810BM_PMM_ADC_0x13	= 0x13,
++	N810BM_PMM_ADC_0x14	= 0x14,
++	N810BM_PMM_ADC_0x15	= 0x15,
++	N810BM_PMM_ADC_0x16	= 0x16,
++	N810BM_PMM_ADC_0x17	= 0x17,
++	N810BM_PMM_ADC_0xFE	= 0xFE,
++};
++
++struct n810bm_adc_calib {
++	enum n810bm_pmm_adc_id id;
++	u8 flags;
++	u8 adc_groupnr;
++	u32 field1;
++	u32 field2;
++	u16 field3;
++	u16 field4;
++};
++
++struct n810bm_calib {
++	struct n810bm_adc_calib adc[25];
++};
++
 +enum n810bm_capacity {
 +enum n810bm_capacity {
 +	N810BM_CAP_UNKNOWN	= -1,
 +	N810BM_CAP_UNKNOWN	= -1,
 +	N810BM_CAP_NONE		= 0,
 +	N810BM_CAP_NONE		= 0,
@@ -151,7 +185,7 @@ Index: linux-2.6.37/drivers/cbus/n810bm_main.c
 +	int current_measure_enabled;		/* Current measure enable refcount */
 +	int current_measure_enabled;		/* Current measure enable refcount */
 +
 +
 +	struct platform_device *pdev;
 +	struct platform_device *pdev;
-+	const struct firmware *pmm_block;	/* CAL PMM block */
++	struct n810bm_calib calib;		/* Calibration data */
 +
 +
 +	bool verbose_charge_log;		/* Verbose charge logging */
 +	bool verbose_charge_log;		/* Verbose charge logging */
 +
 +
@@ -313,6 +347,358 @@ Index: linux-2.6.37/drivers/cbus/n810bm_main.c
 +	return value;
 +	return value;
 +}
 +}
 +
 +
++static int pmm_record_get(struct n810bm *bm,
++			  const struct firmware *pmm_block,
++			  void *buffer, size_t length,
++			  unsigned int group, unsigned int element, unsigned int offset)
++{
++	const u8 *pmm_area = pmm_block->data;
++	u8 active_group_mask;
++
++	if (pmm_block->size != N810BM_PMM_BLOCK_SIZE)
++		return -EINVAL;
++	if (group >= N810BM_PMM_BLOCK_SIZE / N810BM_PMM_GROUP_SIZE)
++		return -EINVAL;
++	if (element >= N810BM_PMM_GROUP_SIZE / N810BM_PMM_ELEM_SIZE)
++		return -EINVAL;
++	if (offset >= N810BM_PMM_ELEM_SIZE || length > N810BM_PMM_ELEM_SIZE ||
++	    length + offset > N810BM_PMM_ELEM_SIZE)
++		return -EINVAL;
++
++	active_group_mask = pmm_area[16];
++	if (!(active_group_mask & (1 << group))) {
++		dev_dbg(&bm->pdev->dev, "pwm_record_get: Requested group %u, "
++			"but group is not active", group);
++		return -ENOENT;
++	}
++
++	memcpy(buffer,
++	       pmm_area + group * N810BM_PMM_GROUP_SIZE
++			+ element * N810BM_PMM_ELEM_SIZE
++			+ offset,
++	       length);
++
++	return 0;
++}
++
++/* PMM block group 1 element */
++struct group1_element {
++	u8 id;
++	u8 flags;
++	u8 adc_groupnr;
++	u8 _padding;
++	__le32 field1;
++	__le32 field2;
++} __packed;
++
++static void extract_group1_elem(struct n810bm *bm,
++				const struct firmware *pmm_block,
++				const u8 *pmm_adc_ids, size_t nr_pmm_adc_ids,
++				u32 field1_mask, u32 field2_mask)
++{
++	struct group1_element elem;
++	int err;
++	unsigned int i, element_nr;
++	struct n810bm_adc_calib *adc_calib;
++
++	for (i = 0; i < nr_pmm_adc_ids; i++) {
++		element_nr = pmm_adc_ids[i] + 3;
++
++		err = pmm_record_get(bm, pmm_block, &elem, sizeof(elem),
++				     1, element_nr, 0);
++		if (err)
++			continue;
++		WARN_ON(element_nr - 3 + 1 >= ARRAY_SIZE(bm->calib.adc));
++		adc_calib = &bm->calib.adc[element_nr - 3 + 1];
++
++		if (adc_calib->flags == elem.flags) {
++			WARN_ON(adc_calib->id != elem.id);
++			adc_calib->field1 = le32_to_cpu(elem.field1) & field1_mask;
++			adc_calib->field2 = le32_to_cpu(elem.field2) & field2_mask;
++		}
++	}
++}
++
++static int n810bm_parse_pmm_group1(struct n810bm *bm,
++				   const struct firmware *pmm_block)
++{
++	struct group1_element elem;
++	int err;
++
++	static const u8 pmm_adc_ids_0[] = {
++		N810BM_PMM_ADC_0x01,
++		N810BM_PMM_ADC_0x02,
++		N810BM_PMM_ADC_0x13,
++		N810BM_PMM_ADC_0x0E,
++	};
++	static const u8 pmm_adc_ids_1[] = {
++		N810BM_PMM_ADC_0x04,
++	};
++	static const u8 pmm_adc_ids_2[] = {
++		N810BM_PMM_ADC_BATTEMP,
++	};
++
++	/* Parse element 2 */
++	err = pmm_record_get(bm, pmm_block, &elem, sizeof(elem),
++			     1, 2, 0);
++	if (err) {
++		dev_err(&bm->pdev->dev,
++			"PMM: Failed to get group 1 / element 2");
++		return err;
++	}
++	if (elem.id == N810BM_PMM_ADC_0xFE && elem.flags == 0x05) {
++		bm->calib.adc[0].id = elem.id;
++		bm->calib.adc[0].flags = elem.flags;
++		bm->calib.adc[0].field1 = le32_to_cpu(elem.field1);
++		bm->calib.adc[0].field2 = le32_to_cpu(elem.field2);
++	}
++
++	extract_group1_elem(bm, pmm_block,
++			    pmm_adc_ids_0, ARRAY_SIZE(pmm_adc_ids_0),
++			    0xFFFFFFFF, 0xFFFFFFFF);
++	extract_group1_elem(bm, pmm_block,
++			    pmm_adc_ids_1, ARRAY_SIZE(pmm_adc_ids_1),
++			    0xFFFFFFFF, 0);
++	extract_group1_elem(bm, pmm_block,
++			    pmm_adc_ids_2, ARRAY_SIZE(pmm_adc_ids_2),
++			    0xFFFFFFFF, 0x0000FFFF);
++
++	return 0;
++}
++
++static int n810bm_parse_pmm_group2(struct n810bm *bm,
++				   const struct firmware *pmm_block)
++{
++	dev_err(&bm->pdev->dev, "TODO: CAL BME PMM group 2 parser not implemented, yet");
++	return -EOPNOTSUPP;
++}
++
++static void n810bm_adc_calib_set_defaults(struct n810bm *bm)
++{
++	struct n810bm_adc_calib *adc_calib;
++	const struct n810bm_adc_calib *def;
++	unsigned int i, index;
++
++	static const struct n810bm_adc_calib defaults[] = {
++		/* ADC group-nr 0 */
++		{
++			.id		= N810BM_PMM_ADC_0x06,
++			.flags		= 0x00,
++			.adc_groupnr	= 0,
++		}, {
++			.id		= N810BM_PMM_ADC_0x07,
++			.flags		= 0x00,
++			.adc_groupnr	= 0,
++		}, {
++			.id		= N810BM_PMM_ADC_0x15,
++			.flags		= 0x00,
++			.adc_groupnr	= 0,
++		}, {
++			.id		= N810BM_PMM_ADC_0x08,
++			.flags		= 0x00,
++			.adc_groupnr	= 0,
++		}, {
++			.id		= N810BM_PMM_ADC_0x16,
++			.flags		= 0x00,
++			.adc_groupnr	= 0,
++		}, {
++			.id		= N810BM_PMM_ADC_0x17,
++			.flags		= 0x00,
++			.adc_groupnr	= 0,
++		}, {
++			.id		= N810BM_PMM_ADC_0x03,
++			.flags		= 0x00,
++			.adc_groupnr	= 0,
++		},
++		/* ADC group-nr 1 */
++		{
++			.id		= N810BM_PMM_ADC_0xFE,
++			.flags		= 0x05,
++			.adc_groupnr	= 1,
++			.field1		= (u32)-2,
++			.field2		= 13189,
++		}, {
++			.id		= N810BM_PMM_ADC_0x01,
++			.flags		= 0x01,
++			.adc_groupnr	= 1,
++			.field1		= 2527,
++			.field2		= 21373,
++		}, {
++			.id		= N810BM_PMM_ADC_0x02,
++			.flags		= 0x01,
++			.adc_groupnr	= 1,
++			.field1		= 0,
++			.field2		= 129848,
++		}, {
++			.id		= N810BM_PMM_ADC_0x13,
++			.flags		= 0x01,
++			.adc_groupnr	= 1,
++			.field1		= 0,
++			.field2		= 20000,
++		}, {
++			.id		= N810BM_PMM_ADC_0x0E,
++			.flags		= 0x06,
++			.adc_groupnr	= 1,
++			.field1		= 0,
++			.field2		= 9660,
++		},
++		/* ADC group-nr 2 */
++		{
++			.id		= N810BM_PMM_ADC_0x04,
++			.flags		= 0x02,
++			.adc_groupnr	= 2,
++			.field1		= 1169,
++			.field2		= 0,
++		},
++		/* ADC group-nr 3 */
++		{
++			.id		= N810BM_PMM_ADC_BATTEMP,
++			.flags		= 0x03,
++			.adc_groupnr	= 3,
++			.field1		= 265423000,
++			.field2		= 298,
++		},
++		/* ADC group-nr 4 */
++		{
++			.id		= N810BM_PMM_ADC_0x14,
++			.flags		= 0x04,
++			.adc_groupnr	= 4,
++			.field1		= 19533778,
++			.field2		= 308019670,
++			.field3		= 4700,
++			.field4		= 2500,
++		},
++	};
++
++	/* Clear the array */
++	memset(&bm->calib.adc, 0, sizeof(bm->calib.adc));
++	for (i = 0; i < ARRAY_SIZE(bm->calib.adc); i++)
++		bm->calib.adc[i].flags = 0xFF;
++
++	/* Copy the defaults */
++	for (i = 0; i < ARRAY_SIZE(defaults); i++) {
++		def = &defaults[i];
++
++		index = 0;
++		if (def->id != N810BM_PMM_ADC_0xFE)
++			index = def->id + 1;
++		WARN_ON(index >= ARRAY_SIZE(bm->calib.adc));
++
++		adc_calib = &bm->calib.adc[index];
++		*adc_calib = *def;
++	}
++}
++
++static const struct n810bm_adc_calib * n810bm_get_adc_calib(struct n810bm *bm,
++						enum n810bm_pmm_adc_id id)
++{
++	unsigned int index = 0;
++
++	if (id != N810BM_PMM_ADC_0xFE)
++		index = (unsigned int)id + 1;
++	WARN_ON(index >= ARRAY_SIZE(bm->calib.adc));
++
++	return &bm->calib.adc[index];
++}
++
++static int n810bm_parse_pmm_block(struct n810bm *bm,
++				  const struct firmware *pmm_block)
++{
++	u8 byte;
++	int err;
++	unsigned int i, count;
++	struct n810bm_adc_calib *adc_calib;
++
++	/* Initialize to defaults */
++	n810bm_adc_calib_set_defaults(bm);
++
++	/* Parse the PMM data */
++	err = pmm_record_get(bm, pmm_block, &byte, sizeof(byte),
++			     1, 0, 0); /* group 1 / element 0 */
++	err |= (byte != 0x01);
++	err |= pmm_record_get(bm, pmm_block, &byte, sizeof(byte),
++			      1, 1, 0); /* group 1 / element 1 */
++	err |= (byte != 0x01);
++	if (err)
++		err = n810bm_parse_pmm_group2(bm, pmm_block);
++	else
++		err = n810bm_parse_pmm_group1(bm, pmm_block);
++	if (err)
++		return err;
++
++	/* Sanity checks */
++	for (i = 0, count = 0; i < ARRAY_SIZE(bm->calib.adc); i++) {
++		adc_calib = &bm->calib.adc[i];
++		if (adc_calib->flags == 0xFF)
++			continue;
++		switch (adc_calib->id) {
++		case N810BM_PMM_ADC_0x01:
++			if (adc_calib->field1 < 2400 ||
++			    adc_calib->field1 > 2700)
++				goto value_check_fail;
++			if (adc_calib->field2 < 20000 ||
++			    adc_calib->field2 > 23000)
++				goto value_check_fail;
++			count++;
++			break;
++		case N810BM_PMM_ADC_0x04:
++			if (adc_calib->field1 < 1100 ||
++			    adc_calib->field1 > 1300)
++				goto value_check_fail;
++			count++;
++			break;
++		case N810BM_PMM_ADC_0x0E:
++			if (adc_calib->field2 < 7000 ||
++			    adc_calib->field2 > 12000)
++				goto value_check_fail;
++			count++;
++			break;
++		case N810BM_PMM_ADC_0xFE:
++			if ((s32)adc_calib->field1 > 14 ||
++			    (s32)adc_calib->field1 < -14)
++				goto value_check_fail;
++			if (adc_calib->field2 < 13000 ||
++			    adc_calib->field2 > 13350)
++				goto value_check_fail;
++			count++;
++			break;
++		case N810BM_PMM_ADC_0x02:
++		case N810BM_PMM_ADC_BATTEMP:
++		case N810BM_PMM_ADC_0x13:
++			count++;
++			break;
++		case N810BM_PMM_ADC_0x03:
++		case N810BM_PMM_ADC_0x07:
++		case N810BM_PMM_ADC_0x08:
++		case N810BM_PMM_ADC_0x06:
++		case N810BM_PMM_ADC_0x14:
++		case N810BM_PMM_ADC_0x15:
++		case N810BM_PMM_ADC_0x16:
++		case N810BM_PMM_ADC_0x17:
++			break;
++		}
++		dev_dbg(&bm->pdev->dev,
++			"ADC 0x%02X calib: 0x%02X 0x%02X 0x%08X 0x%08X 0x%04X 0x%04X",
++			adc_calib->id, adc_calib->flags, adc_calib->adc_groupnr,
++			adc_calib->field1, adc_calib->field2,
++			adc_calib->field3, adc_calib->field4);
++	}
++	if (count != 7) {
++		dev_err(&bm->pdev->dev, "PMM sanity check: Did not find "
++			"all required values (count=%u)", count);
++		goto check_fail;
++	}
++
++	return 0;
++
++value_check_fail:
++	dev_err(&bm->pdev->dev, "PMM image sanity check failed "
++		"(id=%02X, field1=%08X, field2=%08X)",
++		adc_calib->id, adc_calib->field1, adc_calib->field2);
++check_fail:
++	return -EILSEQ;
++}
++
 +/* Set the current measure timer that triggers on Tahvo IRQ 7
 +/* Set the current measure timer that triggers on Tahvo IRQ 7
 + * An interval of zero disables the timer. */
 + * An interval of zero disables the timer. */
 +static void n810bm_set_current_measure_timer(struct n810bm *bm,
 +static void n810bm_set_current_measure_timer(struct n810bm *bm,
@@ -1106,7 +1492,6 @@ Index: linux-2.6.37/drivers/cbus/n810bm_main.c
 +	n810bm_cancel_and_flush_work(bm);
 +	n810bm_cancel_and_flush_work(bm);
 +
 +
 +	n810bm_hw_exit(bm);
 +	n810bm_hw_exit(bm);
-+	release_firmware(bm->pmm_block);
 +
 +
 +	bm->initialized = 0;
 +	bm->initialized = 0;
 +}
 +}
@@ -1119,16 +1504,20 @@ Index: linux-2.6.37/drivers/cbus/n810bm_main.c
 +	if (!fw) {
 +	if (!fw) {
 +		dev_err(&bm->pdev->dev,
 +		dev_err(&bm->pdev->dev,
 +			"CAL PMM block image file not found");
 +			"CAL PMM block image file not found");
-+		goto error;
++		goto err_release;
 +	}
 +	}
 +	if (fw->size != N810BM_PMM_BLOCK_SIZE ||
 +	if (fw->size != N810BM_PMM_BLOCK_SIZE ||
 +	    memcmp(fw->data, "BME-PMM-BLOCK01", 15) != 0) {
 +	    memcmp(fw->data, "BME-PMM-BLOCK01", 15) != 0) {
 +		dev_err(&bm->pdev->dev,
 +		dev_err(&bm->pdev->dev,
 +			"CAL PMM block image file has an invalid format");
 +			"CAL PMM block image file has an invalid format");
-+		goto error;
++		goto err_release;
 +	}
 +	}
 +
 +
-+	bm->pmm_block = fw;
++	err = n810bm_parse_pmm_block(bm, fw);
++	if (err)
++		goto err_release;
++	release_firmware(fw);
++
 +	err = n810bm_device_init(bm);
 +	err = n810bm_device_init(bm);
 +	if (err) {
 +	if (err) {
 +		dev_err(&bm->pdev->dev,
 +		dev_err(&bm->pdev->dev,
@@ -1137,8 +1526,10 @@ Index: linux-2.6.37/drivers/cbus/n810bm_main.c
 +	}
 +	}
 +
 +
 +	return;
 +	return;
-+error:
++err_release:
 +	release_firmware(fw);
 +	release_firmware(fw);
++error:
++	return;
 +}
 +}
 +
 +
 +static int __devinit n810bm_probe(struct platform_device *pdev)
 +static int __devinit n810bm_probe(struct platform_device *pdev)
@@ -1211,10 +1602,10 @@ Index: linux-2.6.37/drivers/cbus/n810bm_main.c
 +MODULE_FIRMWARE(N810BM_PMM_BLOCK_FILENAME);
 +MODULE_FIRMWARE(N810BM_PMM_BLOCK_FILENAME);
 +MODULE_LICENSE("GPL");
 +MODULE_LICENSE("GPL");
 +MODULE_AUTHOR("Michael Buesch");
 +MODULE_AUTHOR("Michael Buesch");
-Index: linux-2.6.37/drivers/cbus/retu.c
+Index: linux-2.6.37.1/drivers/cbus/retu.c
 ===================================================================
 ===================================================================
---- linux-2.6.37.orig/drivers/cbus/retu.c	2011-02-06 14:05:49.829387442 +0100
-+++ linux-2.6.37/drivers/cbus/retu.c	2011-02-08 17:33:18.981369017 +0100
+--- linux-2.6.37.1.orig/drivers/cbus/retu.c	2011-02-19 20:26:01.251340770 +0100
++++ linux-2.6.37.1/drivers/cbus/retu.c	2011-02-19 20:26:01.529318528 +0100
 @@ -85,10 +85,10 @@
 @@ -85,10 +85,10 @@
   *
   *
   * This function writes a value to the specified register
   * This function writes a value to the specified register
@@ -1236,10 +1627,10 @@ Index: linux-2.6.37/drivers/cbus/retu.c
  
  
  subsys_initcall(retu_init);
  subsys_initcall(retu_init);
  module_exit(retu_exit);
  module_exit(retu_exit);
-Index: linux-2.6.37/drivers/cbus/retu.h
+Index: linux-2.6.37.1/drivers/cbus/retu.h
 ===================================================================
 ===================================================================
---- linux-2.6.37.orig/drivers/cbus/retu.h	2011-02-06 14:05:49.829387442 +0100
-+++ linux-2.6.37/drivers/cbus/retu.h	2011-02-06 14:05:49.886395793 +0100
+--- linux-2.6.37.1.orig/drivers/cbus/retu.h	2011-02-19 20:26:01.252340690 +0100
++++ linux-2.6.37.1/drivers/cbus/retu.h	2011-02-19 20:26:01.530318448 +0100
 @@ -40,6 +40,8 @@
 @@ -40,6 +40,8 @@
  #define RETU_REG_CTRL_CLR	0x0f	/* Regulator clear register */
  #define RETU_REG_CTRL_CLR	0x0f	/* Regulator clear register */
  #define RETU_REG_CTRL_SET	0x10	/* Regulator set register */
  #define RETU_REG_CTRL_SET	0x10	/* Regulator set register */
@@ -1276,10 +1667,10 @@ Index: linux-2.6.37/drivers/cbus/retu.h
  void retu_set_clear_reg_bits(int reg, u16 set, u16 clear);
  void retu_set_clear_reg_bits(int reg, u16 set, u16 clear);
  int retu_read_adc(int channel);
  int retu_read_adc(int channel);
  int retu_request_irq(int id, void *irq_handler, unsigned long arg, char *name);
  int retu_request_irq(int id, void *irq_handler, unsigned long arg, char *name);
-Index: linux-2.6.37/arch/arm/mach-omap2/board-n8x0.c
+Index: linux-2.6.37.1/arch/arm/mach-omap2/board-n8x0.c
 ===================================================================
 ===================================================================
---- linux-2.6.37.orig/arch/arm/mach-omap2/board-n8x0.c	2011-02-06 14:05:49.815385390 +0100
-+++ linux-2.6.37/arch/arm/mach-omap2/board-n8x0.c	2011-02-06 14:05:49.886395793 +0100
+--- linux-2.6.37.1.orig/arch/arm/mach-omap2/board-n8x0.c	2011-02-19 20:26:01.201344770 +0100
++++ linux-2.6.37.1/arch/arm/mach-omap2/board-n8x0.c	2011-02-19 20:26:01.531318368 +0100
 @@ -907,6 +907,17 @@
 @@ -907,6 +907,17 @@
  				    ARRAY_SIZE(n8x0_gpio_switches));
  				    ARRAY_SIZE(n8x0_gpio_switches));
  }
  }
@@ -1307,10 +1698,10 @@ Index: linux-2.6.37/arch/arm/mach-omap2/board-n8x0.c
  }
  }
  
  
  MACHINE_START(NOKIA_N800, "Nokia N800")
  MACHINE_START(NOKIA_N800, "Nokia N800")
-Index: linux-2.6.37/drivers/cbus/lipocharge.c
+Index: linux-2.6.37.1/drivers/cbus/lipocharge.c
 ===================================================================
 ===================================================================
 --- /dev/null	1970-01-01 00:00:00.000000000 +0000
 --- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.37/drivers/cbus/lipocharge.c	2011-02-09 12:42:58.243147563 +0100
++++ linux-2.6.37.1/drivers/cbus/lipocharge.c	2011-02-19 20:26:01.531318368 +0100
 @@ -0,0 +1,183 @@
 @@ -0,0 +1,183 @@
 +/*
 +/*
 + *   Generic LIPO battery charger
 + *   Generic LIPO battery charger
@@ -1495,10 +1886,10 @@ Index: linux-2.6.37/drivers/cbus/lipocharge.c
 +
 +
 +	return 0;
 +	return 0;
 +}
 +}
-Index: linux-2.6.37/drivers/cbus/lipocharge.h
+Index: linux-2.6.37.1/drivers/cbus/lipocharge.h
 ===================================================================
 ===================================================================
 --- /dev/null	1970-01-01 00:00:00.000000000 +0000
 --- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.37/drivers/cbus/lipocharge.h	2011-02-07 20:07:29.669098631 +0100
++++ linux-2.6.37.1/drivers/cbus/lipocharge.h	2011-02-19 20:26:01.531318368 +0100
 @@ -0,0 +1,60 @@
 @@ -0,0 +1,60 @@
 +#ifndef LIPOCHARGE_H_
 +#ifndef LIPOCHARGE_H_
 +#define LIPOCHARGE_H_
 +#define LIPOCHARGE_H_
@@ -1560,10 +1951,10 @@ Index: linux-2.6.37/drivers/cbus/lipocharge.h
 +}
 +}
 +
 +
 +#endif /* LIPOCHARGE_H_ */
 +#endif /* LIPOCHARGE_H_ */
-Index: linux-2.6.37/drivers/cbus/tahvo.h
+Index: linux-2.6.37.1/drivers/cbus/tahvo.h
 ===================================================================
 ===================================================================
---- linux-2.6.37.orig/drivers/cbus/tahvo.h	2011-02-06 14:05:49.830387588 +0100
-+++ linux-2.6.37/drivers/cbus/tahvo.h	2011-02-06 16:22:25.902331536 +0100
+--- linux-2.6.37.1.orig/drivers/cbus/tahvo.h	2011-02-19 20:26:01.256340370 +0100
++++ linux-2.6.37.1/drivers/cbus/tahvo.h	2011-02-19 20:26:01.532318288 +0100
 @@ -30,17 +30,28 @@
 @@ -30,17 +30,28 @@
  #define TAHVO_REG_IDR		0x01	/* Interrupt ID */
  #define TAHVO_REG_IDR		0x01	/* Interrupt ID */
  #define TAHVO_REG_IDSR		0x02	/* Interrupt status */
  #define TAHVO_REG_IDSR		0x02	/* Interrupt status */
@@ -1594,10 +1985,10 @@ Index: linux-2.6.37/drivers/cbus/tahvo.h
  void tahvo_set_clear_reg_bits(int reg, u16 set, u16 clear);
  void tahvo_set_clear_reg_bits(int reg, u16 set, u16 clear);
  int tahvo_request_irq(int id, void *irq_handler, unsigned long arg, char *name);
  int tahvo_request_irq(int id, void *irq_handler, unsigned long arg, char *name);
  void tahvo_free_irq(int id);
  void tahvo_free_irq(int id);
-Index: linux-2.6.37/drivers/cbus/tahvo.c
+Index: linux-2.6.37.1/drivers/cbus/tahvo.c
 ===================================================================
 ===================================================================
---- linux-2.6.37.orig/drivers/cbus/tahvo.c	2011-02-06 14:05:49.830387588 +0100
-+++ linux-2.6.37/drivers/cbus/tahvo.c	2011-02-06 14:05:49.886395793 +0100
+--- linux-2.6.37.1.orig/drivers/cbus/tahvo.c	2011-02-19 20:26:01.256340370 +0100
++++ linux-2.6.37.1/drivers/cbus/tahvo.c	2011-02-19 20:26:01.532318288 +0100
 @@ -85,10 +85,10 @@
 @@ -85,10 +85,10 @@
   *
   *
   * This function writes a value to the specified register
   * This function writes a value to the specified register
@@ -1611,10 +2002,10 @@ Index: linux-2.6.37/drivers/cbus/tahvo.c
  }
  }
  
  
  /**
  /**
-Index: linux-2.6.37/drivers/cbus/cbus.c
+Index: linux-2.6.37.1/drivers/cbus/cbus.c
 ===================================================================
 ===================================================================
---- linux-2.6.37.orig/drivers/cbus/cbus.c	2011-02-08 17:34:34.988926130 +0100
-+++ linux-2.6.37/drivers/cbus/cbus.c	2011-02-08 17:38:16.980407594 +0100
+--- linux-2.6.37.1.orig/drivers/cbus/cbus.c	2011-02-19 20:26:01.249340930 +0100
++++ linux-2.6.37.1/drivers/cbus/cbus.c	2011-02-19 20:26:01.533318208 +0100
 @@ -31,6 +31,7 @@
 @@ -31,6 +31,7 @@
  #include <linux/gpio.h>
  #include <linux/gpio.h>
  #include <linux/platform_device.h>
  #include <linux/platform_device.h>
@@ -1637,10 +2028,10 @@ Index: linux-2.6.37/drivers/cbus/cbus.c
  MODULE_DESCRIPTION("CBUS serial protocol");
  MODULE_DESCRIPTION("CBUS serial protocol");
  MODULE_LICENSE("GPL");
  MODULE_LICENSE("GPL");
  MODULE_AUTHOR("Juha Yrjölä");
  MODULE_AUTHOR("Juha Yrjölä");
-Index: linux-2.6.37/drivers/cbus/cbus.h
+Index: linux-2.6.37.1/drivers/cbus/cbus.h
 ===================================================================
 ===================================================================
---- linux-2.6.37.orig/drivers/cbus/cbus.h	2011-02-08 17:36:40.172074049 +0100
-+++ linux-2.6.37/drivers/cbus/cbus.h	2011-02-08 17:41:32.680647478 +0100
+--- linux-2.6.37.1.orig/drivers/cbus/cbus.h	2011-02-19 20:26:01.250340850 +0100
++++ linux-2.6.37.1/drivers/cbus/cbus.h	2011-02-19 20:26:01.533318208 +0100
 @@ -33,4 +33,6 @@
 @@ -33,4 +33,6 @@
  extern int cbus_read_reg(struct cbus_host *host, int dev, int reg);
  extern int cbus_read_reg(struct cbus_host *host, int dev, int reg);
  extern int cbus_write_reg(struct cbus_host *host, int dev, int reg, u16 val);
  extern int cbus_write_reg(struct cbus_host *host, int dev, int reg, u16 val);