r4044 - in branches/src/target/kernel/2.6.24.x: config patches

werner at sita.openmoko.org werner at sita.openmoko.org
Mon Feb 11 00:37:09 CET 2008


Author: werner
Date: 2008-02-11 00:37:02 +0100 (Mon, 11 Feb 2008)
New Revision: 4044

Added:
   branches/src/target/kernel/2.6.24.x/patches/fiq-hdq.patch
Modified:
   branches/src/target/kernel/2.6.24.x/config/defconfig-2.6.24
   branches/src/target/kernel/2.6.24.x/patches/series
Log:
config/defconfig-2.6.24: added CONFIG_GTA02_HDQ=y

introduce-fiq-hdq.patch (as fiq-hdq.patch)

From: Andy Green <andy at openmoko.com>

This adds a platform driver and device which performs HDQ
battery protocol using a single GPIO pin which is set
through platform data.

HDQ has some hard latency requirements which can't
be met if interrupts are enabled, so normally using
a GPIO for this will require blocking out all other
interrupts and processes for several milliseconds
per register being read or written.

This HDQ protocol engine is a FSM implemented inside the
the FIQ ISR and regulated by timer interrupts happening
at 20us intervals.  The path through the FSM on any
"clock" is very short and should be over with in ~
1us.  Because FIQ has guaranteed latencies of <1us,
it means we can service the HDQ protocol without
blocking interrupts or any other process other than
the caller that is waiting for the result. It's pretty
cool performance from 1 GPIO ;-)

Due to it being hard to do locking from the FIQ ISR
the code simply sleeps 10ms or whatever the scheduler
gives it and checks if the transfer took place yet.

This platform driver doesn't have any knowledge about
the device it is talking to, it just knows it is a
HDQ device.  It exports three functions for read, write
and confirming HDQ is initialized.  It also exports two
/sys nodes that are usable by humans, one dumps the whole
127 register HDQ register space


# cat /sys/devices/platform/gta02-hdq.0/hdq/dump
00 44 55 00 00 00 ba 04 a2 0d 50 00 00 00 00 00
00 00 9a 1a 00 00 ff ff ff ff 29 00 00 00 80 2b
00 00 00 00 00 00 ff ff 00 00 00 00 00 32 af 06
a0 d8 37 4e 00 00 00 00 00 00 00 34 2e 03 b4 e7
00 00 06 00 41 00 4c 02 00 00 00 00 00 00 00 00
83 02 00 00 94 09 59 b9 a5 0d 7f 21 00 00 7a ff
df ff 62 ff a7 04 2e 05 00 00 00 01 00 07 00 00
2a 78 36 67 7b b5 1b a9 af 19 38 89 63 57 42 7c
#

and the other allows to set one register

# echo 2 170 > /sys/devices/platform/gta02-hdq.0/hdq/write

writes 0xAA into register 2.

Signed-off-by: Andy Green <andy at openmoko.com>

---

 arch/arm/mach-s3c2440/mach-gta02.c           |  203 +++++++++++++++++++++
 defconfig-2.6.24                             |    1
 drivers/power/Kconfig                        |    8 +
 drivers/power/Makefile                       |    2
 drivers/power/gta02_hdq.c                    |  250 ++++++++++++++++++++++++++
 include/asm-arm/arch-s3c2410/fiq_ipc_gta02.h |   23 ++
 include/asm-arm/arch-s3c2410/gta02.h         |    1
 7 files changed, 487 insertions(+), 1 deletions(-)
 create mode 100644 drivers/power/gta02_hdq.c



Modified: branches/src/target/kernel/2.6.24.x/config/defconfig-2.6.24
===================================================================
--- branches/src/target/kernel/2.6.24.x/config/defconfig-2.6.24	2008-02-10 22:49:45 UTC (rev 4043)
+++ branches/src/target/kernel/2.6.24.x/config/defconfig-2.6.24	2008-02-10 23:37:02 UTC (rev 4044)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.24
-# Sat Feb  2 15:15:40 2008
+# Sun Feb 10 20:32:17 2008
 #
 CONFIG_ARM=y
 CONFIG_SYS_SUPPORTS_APM_EMULATION=y
@@ -1016,6 +1016,7 @@
 # CONFIG_SPI_TLE62X0 is not set
 # CONFIG_W1 is not set
 # CONFIG_POWER_SUPPLY is not set
+CONFIG_GTA02_HDQ=y
 # CONFIG_HWMON is not set
 CONFIG_WATCHDOG=y
 # CONFIG_WATCHDOG_NOWAYOUT is not set

Added: branches/src/target/kernel/2.6.24.x/patches/fiq-hdq.patch
===================================================================
--- branches/src/target/kernel/2.6.24.x/patches/fiq-hdq.patch	2008-02-10 22:49:45 UTC (rev 4043)
+++ branches/src/target/kernel/2.6.24.x/patches/fiq-hdq.patch	2008-02-10 23:37:02 UTC (rev 4044)
@@ -0,0 +1,570 @@
+Index: linux-2.6.24/arch/arm/mach-s3c2440/mach-gta02.c
+===================================================================
+--- linux-2.6.24.orig/arch/arm/mach-s3c2440/mach-gta02.c
++++ linux-2.6.24/arch/arm/mach-s3c2440/mach-gta02.c
+@@ -96,6 +96,19 @@
+ 
+ #define FIQ_DIVISOR_VIBRATOR DIVISOR_FROM_US(100)
+ 
++#ifdef CONFIG_GTA02_HDQ
++/* HDQ specific */
++#define HDQ_SAMPLE_PERIOD_US 20
++/* private HDQ FSM state -- all other info interesting for caller in fiq_ipc */
++static enum hdq_bitbang_states hdq_state;
++static u8 hdq_ctr;
++static u8 hdq_ctr2;
++static u8 hdq_bit;
++static u8 hdq_shifter;
++static u8 hdq_tx_data_done;
++
++#define FIQ_DIVISOR_HDQ DIVISOR_FROM_US(HDQ_SAMPLE_PERIOD_US)
++#endif
+ /* define FIQ ISR */
+ 
+ FIQ_HANDLER_START()
+@@ -118,9 +131,171 @@
+ 		divisor = FIQ_DIVISOR_VIBRATOR;
+ 	}
+ 
+-	/* TODO: HDQ servicing */
++#ifdef CONFIG_GTA02_HDQ
++	/* HDQ servicing */
++
++	switch (hdq_state) {
++	case HDQB_IDLE:
++		if (fiq_ipc.hdq_request_ctr == fiq_ipc.hdq_transaction_ctr)
++			break;
++		hdq_ctr = 210 / HDQ_SAMPLE_PERIOD_US;
++		s3c2410_gpio_setpin(fiq_ipc.hdq_gpio_pin, 0);
++		s3c2410_gpio_cfgpin(fiq_ipc.hdq_gpio_pin, S3C2410_GPIO_OUTPUT);
++		hdq_tx_data_done = 0;
++		hdq_state = HDQB_TX_BREAK;
++		break;
++
++	case HDQB_TX_BREAK: /* issue low for > 190us */
++		if (--hdq_ctr == 0) {
++			hdq_ctr = 60 / HDQ_SAMPLE_PERIOD_US;
++			hdq_state = HDQB_TX_BREAK_RECOVERY;
++			s3c2410_gpio_setpin(fiq_ipc.hdq_gpio_pin, 1);
++		}
++		break;
++
++	case HDQB_TX_BREAK_RECOVERY: /* issue low for > 40us */
++		if (--hdq_ctr)
++			break;
++		hdq_shifter = fiq_ipc.hdq_ads;
++		hdq_bit = 8; /* 8 bits of ads / rw */
++		hdq_tx_data_done = 0; /* doing ads */
++		/* fallthru on last one */
++	case HDQB_ADS_CALC:
++		if (hdq_shifter & 1)
++			hdq_ctr = 50 / HDQ_SAMPLE_PERIOD_US;
++		else
++			hdq_ctr = 120 / HDQ_SAMPLE_PERIOD_US;
++		/* carefully precompute the other phase length */
++		hdq_ctr2 = (210 - (hdq_ctr * HDQ_SAMPLE_PERIOD_US)) /
++				HDQ_SAMPLE_PERIOD_US;
++		hdq_state = HDQB_ADS_LOW;
++		hdq_shifter >>= 1;
++		hdq_bit--;
++		s3c2410_gpio_setpin(fiq_ipc.hdq_gpio_pin, 0);
++		break;
++
++	case HDQB_ADS_LOW:
++		if (--hdq_ctr)
++			break;
++		s3c2410_gpio_setpin(fiq_ipc.hdq_gpio_pin, 1);
++		hdq_state = HDQB_ADS_HIGH;
++		break;
++
++	case HDQB_ADS_HIGH:
++		if (--hdq_ctr2 > 1) /* account for HDQB_ADS_CALC */
++			break;
++		if (hdq_bit) { /* more bits to do */
++			hdq_state = HDQB_ADS_CALC;
++			break;
++		}
++		/* no more bits, wait it out until hdq_ctr2 exhausted */
++		if (hdq_ctr2)
++			break;
++		/* ok no more bits and very last state */
++		hdq_ctr = 60 / HDQ_SAMPLE_PERIOD_US;
++		/* FIXME 0 = read */
++		if (fiq_ipc.hdq_ads & 0x80) { /* write the byte out */
++			 /* set delay before payload */
++			hdq_ctr = 300 / HDQ_SAMPLE_PERIOD_US;
++ 			/* already high, no need to write */
++			hdq_state = HDQB_WAIT_TX;
++			break;
++		}
++		/* read the next byte */
++		hdq_bit = 8; /* 8 bits of data */
++		hdq_ctr = 3000 / HDQ_SAMPLE_PERIOD_US;
++		hdq_state = HDQB_WAIT_RX;
++		s3c2410_gpio_cfgpin(fiq_ipc.hdq_gpio_pin, S3C2410_GPIO_INPUT);
++		break;
++
++	case HDQB_WAIT_TX: /* issue low for > 40us */
++		if (--hdq_ctr)
++			break;
++		if (!hdq_tx_data_done) { /* was that the data sent? */
++			hdq_tx_data_done++;
++			hdq_shifter = fiq_ipc.hdq_tx_data;
++			hdq_bit = 8; /* 8 bits of data */
++			hdq_state = HDQB_ADS_CALC; /* start sending */
++			break;
++		}
++		fiq_ipc.hdq_error = 0;
++		fiq_ipc.hdq_transaction_ctr++;
++		hdq_state = HDQB_IDLE; /* all tx is done */
++		/* idle in input mode, it's pulled up by 10K */
++		s3c2410_gpio_cfgpin(fiq_ipc.hdq_gpio_pin, S3C2410_GPIO_INPUT);
++		break;
++
++	case HDQB_WAIT_RX: /* wait for battery to talk to us */
++		if (s3c2410_gpio_getpin(fiq_ipc.hdq_gpio_pin) == 0) {
++			/* it talks to us! */
++			hdq_ctr2 = 1;
++			hdq_bit = 8; /* 8 bits of data */
++			/* timeout */
++			hdq_ctr = 300 / HDQ_SAMPLE_PERIOD_US;
++			hdq_state = HDQB_DATA_RX_LOW;
++			break;
++		}
++		if (--hdq_ctr == 0) { /* timed out, error */
++			fiq_ipc.hdq_error = 1;
++			fiq_ipc.hdq_transaction_ctr++;
++			hdq_state = HDQB_IDLE; /* abort */
++		}
++		break;
++
++	/*
++	 * HDQ basically works by measuring the low time of the bit cell
++	 * 32-50us --> '1', 80 - 145us --> '0'
++	 */
++
++	case HDQB_DATA_RX_LOW:
++		if (s3c2410_gpio_getpin(fiq_ipc.hdq_gpio_pin)) {
++			fiq_ipc.hdq_rx_data >>= 1;
++			if (hdq_ctr2 <= (65 / HDQ_SAMPLE_PERIOD_US))
++				fiq_ipc.hdq_rx_data |= 0x80;
++
++			if (--hdq_bit == 0) {
++				fiq_ipc.hdq_error = 0;
++				fiq_ipc.hdq_transaction_ctr++; /* done */
++				hdq_state = HDQB_IDLE;
++			} else
++				hdq_state = HDQB_DATA_RX_HIGH;
++			/* timeout */
++			hdq_ctr = 1000 / HDQ_SAMPLE_PERIOD_US;
++			hdq_ctr2 = 1;
++			break;
++		}
++		hdq_ctr2++;
++		if (--hdq_ctr)
++			break;
++		 /* timed out, error */
++		fiq_ipc.hdq_error = 2;
++		fiq_ipc.hdq_transaction_ctr++;
++		hdq_state = HDQB_IDLE; /* abort */
++		break;
+ 
++	case HDQB_DATA_RX_HIGH:
++		if (!s3c2410_gpio_getpin(fiq_ipc.hdq_gpio_pin)) {
++			/* it talks to us! */
++			hdq_ctr2 = 1;
++			/* timeout */
++			hdq_ctr = 400 / HDQ_SAMPLE_PERIOD_US;
++			hdq_state = HDQB_DATA_RX_LOW;
++			break;
++		}
++		if (--hdq_ctr)
++			break;
++		/* timed out, error */
++		fiq_ipc.hdq_error = 3;
++		fiq_ipc.hdq_transaction_ctr++;
++		/* we're in input mode already */
++		hdq_state = HDQB_IDLE; /* abort */
++		break;
++	}
+ 
++	if (hdq_state != HDQB_IDLE) /* ie, not idle */
++		if (divisor > FIQ_DIVISOR_HDQ)
++			divisor = FIQ_DIVISOR_HDQ; /* keep us going */
++#endif
+ 
+ 	/* disable further timer interrupts if nobody has any work
+ 	 * or adjust rate according to who still has work
+@@ -386,6 +561,23 @@
+ 	.resource	= sc32440_fiq_resources,
+ };
+ 
++#ifdef CONFIG_GTA02_HDQ
++/* HDQ */
++
++static struct resource gta02_hdq_resources[] = {
++	[0] = {
++		.start	= GTA02v5_GPIO_HDQ,
++		.end	= GTA02v5_GPIO_HDQ,
++	},
++};
++
++struct platform_device gta02_hdq_device = {
++	.name 		= "gta02-hdq",
++	.num_resources	= 1,
++	.resource	= gta02_hdq_resources,
++};
++#endif
++
+ /* NOR Flash */
+ 
+ #define GTA02_FLASH_BASE	0x18000000 /* GCS3 */
+@@ -1049,6 +1241,15 @@
+ 
+ 	platform_add_devices(gta02_devices, ARRAY_SIZE(gta02_devices));
+ 
++#ifdef CONFIG_GTA02_HDQ
++	switch (system_rev) {
++	case GTA02v5_SYSTEM_REV:
++		platform_device_register(&gta02_hdq_device);
++		break;
++	default:
++		break;
++	}
++#endif
+ 	s3c2410_pm_init();
+ 
+ 	/* Set LCD_RESET / XRES to high */
+Index: linux-2.6.24/drivers/power/Kconfig
+===================================================================
+--- linux-2.6.24.orig/drivers/power/Kconfig
++++ linux-2.6.24/drivers/power/Kconfig
+@@ -50,3 +50,11 @@
+ 	  Say Y to enable support for the battery on the OLPC laptop.
+ 
+ endif # POWER_SUPPLY
++
++config GTA02_HDQ
++	tristate "Neo Freerunner HDQ"
++	depends on MACH_NEO1973_GTA02 && FIQ && S3C2440_C_FIQ
++	help
++	  Say Y to enable support for communicating with an HDQ battery
++	  on the Neo Freerunner.  You probably want to select
++	  at least BATTERY_BQ27000_HDQ as well
+Index: linux-2.6.24/drivers/power/Makefile
+===================================================================
+--- linux-2.6.24.orig/drivers/power/Makefile
++++ linux-2.6.24/drivers/power/Makefile
+@@ -20,3 +20,5 @@
+ obj-$(CONFIG_BATTERY_DS2760)	+= ds2760_battery.o
+ obj-$(CONFIG_BATTERY_PMU)	+= pmu_battery.o
+ obj-$(CONFIG_BATTERY_OLPC)	+= olpc_battery.o
++
++obj-$(CONFIG_GTA02_HDQ)		+= gta02_hdq.o
+Index: linux-2.6.24/drivers/power/gta02_hdq.c
+===================================================================
+--- /dev/null
++++ linux-2.6.24/drivers/power/gta02_hdq.c
+@@ -0,0 +1,250 @@
++/*
++ * HDQ driver for the FIC Neo1973 GTA02 GSM phone
++ *
++ * (C) 2006-2007 by OpenMoko, Inc.
++ * Author: Andy Green <andy at openmoko.com>
++ * All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/platform_device.h>
++#include <asm/hardware.h>
++#include <asm/mach-types.h>
++#include <asm/arch/gta02.h>
++#include <asm/arch/fiq_ipc_gta02.h>
++
++
++
++#define HDQ_READ 0
++#define HDQ_WRITE 0x80
++
++
++int gta02hdq_initialized(void)
++{
++	return fiq_ipc.hdq_probed;
++}
++EXPORT_SYMBOL_GPL(gta02hdq_initialized);
++
++int gta02hdq_read(int address)
++{
++	int count_sleeps = 5;
++	int ret = -ETIME;
++
++	mutex_lock(&fiq_ipc.hdq_lock);
++
++	fiq_ipc.hdq_ads = address | HDQ_READ;
++	fiq_ipc.hdq_request_ctr++;
++	fiq_kick();
++	/*
++	 * FIQ takes care of it while we block our calling process
++	 * But we're not spinning -- other processes run normally while
++	 * we wait for the result
++	 */
++	while (count_sleeps--) {
++		msleep(10); /* valid transaction always completes in < 10ms */
++
++		if (fiq_ipc.hdq_request_ctr != fiq_ipc.hdq_transaction_ctr)
++			continue;
++
++		if (fiq_ipc.hdq_error)
++			goto done; /* didn't see a response in good time */
++
++		ret = fiq_ipc.hdq_rx_data;
++		goto done;
++	}
++	ret = -EINVAL;
++
++done:
++	mutex_unlock(&fiq_ipc.hdq_lock);
++	return ret;
++}
++EXPORT_SYMBOL_GPL(gta02hdq_read);
++
++int gta02hdq_write(int address, u8 data)
++{
++	int count_sleeps = 5;
++	int ret = -ETIME;
++
++	mutex_lock(&fiq_ipc.hdq_lock);
++
++	fiq_ipc.hdq_ads = address | HDQ_WRITE;
++	fiq_ipc.hdq_tx_data = data;
++	fiq_ipc.hdq_request_ctr++;
++	fiq_kick();
++	/*
++	 * FIQ takes care of it while we block our calling process
++	 * But we're not spinning -- other processes run normally while
++	 * we wait for the result
++	 */
++	while (count_sleeps--) {
++		msleep(10); /* valid transaction always completes in < 10ms */
++
++		if (fiq_ipc.hdq_request_ctr != fiq_ipc.hdq_transaction_ctr)
++			continue; /* something bad with FIQ */
++
++		if (fiq_ipc.hdq_error)
++			goto done; /* didn't see a response in good time */
++	}
++	ret = -EINVAL;
++
++done:
++	mutex_unlock(&fiq_ipc.hdq_lock);
++	return ret;
++}
++EXPORT_SYMBOL_GPL(gta02hdq_write);
++
++/* sysfs */
++
++static ssize_t hdq_sysfs_dump(struct device *dev, struct device_attribute *attr,
++			 char *buf)
++{
++	int n;
++	int v;
++	u8 u8a[128]; /* whole address space for HDQ */
++	char *buf1 = buf;
++
++	/* the dump does not take care about 16 bit regs, because at this
++	 * bus level we don't know about the chip details
++	 */
++	for (n = 0; n < sizeof(u8a); n++) {
++		v = gta02hdq_read(n);
++		if (v < 0)
++			goto bail;
++		u8a[n] = (u8)v;
++	}
++
++	for (n = 0; n < sizeof(u8a); n += 16) {
++		hex_dump_to_buffer(u8a + n, sizeof(u8a), 16, 1, buf1, 4096, 0);
++		buf1 += strlen(buf1);
++		*buf1++ = '\n';
++		*buf1 = '\0';
++	}
++	return (buf1 - buf);
++
++bail:
++	return sprintf(buf, "ERROR %d\n", v);
++}
++
++/* you write by <address> <data>, eg, "34 128" */
++
++#define atoi(str) simple_strtoul(((str != NULL) ? str : ""), NULL, 0)
++
++static ssize_t hdq_sysfs_write(struct device *dev,
++			       struct device_attribute *attr,
++			       const char *buf, size_t count)
++{
++	const char *buf1 = buf + count;
++	int address = atoi(buf);
++
++	while ((buf < buf1) && (*buf != ' '))
++		buf++;
++	if (buf >= buf1)
++		return 0;
++	while ((buf < buf1) && (*buf == ' '))
++		buf++;
++	if (buf >= buf1)
++		return 0;
++
++	gta02hdq_write(address, (u8)atoi(buf));
++
++	return count;
++}
++
++static DEVICE_ATTR(dump, 0400, hdq_sysfs_dump, NULL);
++static DEVICE_ATTR(write, 0600, NULL, hdq_sysfs_write);
++
++static struct attribute *gta02hdq_sysfs_entries[] = {
++	&dev_attr_dump.attr,
++	&dev_attr_write.attr,
++	NULL
++};
++
++static struct attribute_group gta02hdq_attr_group = {
++	.name	= "hdq",
++	.attrs	= gta02hdq_sysfs_entries,
++};
++
++
++#ifdef CONFIG_PM
++static int gta02hdq_suspend(struct platform_device *pdev, pm_message_t state)
++{
++	/* after 18s of this, the battery monitor will also go to sleep */
++	s3c2410_gpio_setpin(fiq_ipc.hdq_gpio_pin, 0);
++	s3c2410_gpio_cfgpin(fiq_ipc.hdq_gpio_pin, S3C2410_GPIO_OUTPUT);
++	return 0;
++}
++
++static int gta02hdq_resume(struct platform_device *pdev)
++{
++	s3c2410_gpio_setpin(fiq_ipc.hdq_gpio_pin, 1);
++	s3c2410_gpio_cfgpin(fiq_ipc.hdq_gpio_pin, S3C2410_GPIO_OUTPUT);
++	return 0;
++}
++#endif
++
++static int __init gta02hdq_probe(struct platform_device *pdev)
++{
++	struct resource *r = platform_get_resource(pdev, 0, 0);
++
++	if (!machine_is_neo1973_gta02())
++		return -EIO;
++
++	if (!r)
++		return -EINVAL;
++
++	platform_set_drvdata(pdev, NULL);
++
++	mutex_init(&fiq_ipc.hdq_lock);
++
++	/* set our HDQ comms pin from the platform data */
++	fiq_ipc.hdq_gpio_pin = r->start;
++
++	s3c2410_gpio_setpin(fiq_ipc.hdq_gpio_pin, 1);
++	s3c2410_gpio_cfgpin(fiq_ipc.hdq_gpio_pin, S3C2410_GPIO_OUTPUT);
++
++	fiq_ipc.hdq_probed = 1; /* we are ready to do stuff now */
++
++	return sysfs_create_group(&pdev->dev.kobj, &gta02hdq_attr_group);
++}
++
++static int gta02hdq_remove(struct platform_device *pdev)
++{
++	sysfs_remove_group(&pdev->dev.kobj, &gta02hdq_attr_group);
++	return 0;
++}
++
++static struct platform_driver gta02hdq_driver = {
++	.probe		= gta02hdq_probe,
++	.remove		= gta02hdq_remove,
++#ifdef CONFIG_PM
++	.suspend	= gta02hdq_suspend,
++	.resume		= gta02hdq_resume,
++#endif
++	.driver		= {
++		.name		= "gta02-hdq",
++	},
++};
++
++static int __init gta02hdq_init(void)
++{
++	return platform_driver_register(&gta02hdq_driver);
++}
++
++static void __exit gta02hdq_exit(void)
++{
++ 	platform_driver_unregister(&gta02hdq_driver);
++}
++
++module_init(gta02hdq_init);
++module_exit(gta02hdq_exit);
++
++MODULE_AUTHOR("Andy Green <andy at openmoko.com>");
++MODULE_DESCRIPTION("FIC Neo1973 GTA02 HDQ driver");
++MODULE_LICENSE("GPL");
+Index: linux-2.6.24/include/asm-arm/arch-s3c2410/fiq_ipc_gta02.h
+===================================================================
+--- linux-2.6.24.orig/include/asm-arm/arch-s3c2410/fiq_ipc_gta02.h
++++ linux-2.6.24/include/asm-arm/arch-s3c2410/fiq_ipc_gta02.h
+@@ -19,12 +19,35 @@
+ #include <asm/arch/pwm.h>
+ #include <asm/plat-s3c/regs-timer.h>
+ 
++enum hdq_bitbang_states {
++	HDQB_IDLE = 0,
++	HDQB_TX_BREAK,
++	HDQB_TX_BREAK_RECOVERY,
++	HDQB_ADS_CALC,
++	HDQB_ADS_LOW,
++	HDQB_ADS_HIGH,
++	HDQB_WAIT_RX,
++	HDQB_DATA_RX_LOW,
++	HDQB_DATA_RX_HIGH,
++	HDQB_WAIT_TX,
++};
+ 
+ struct fiq_ipc {
+ 	/* vibrator */
+ 	unsigned long vib_gpio_pin; /* which pin to meddle with */
+ 	u8 vib_pwm; /* 0 = OFF -- will ensure GPIO deasserted and stop FIQ */
+ 	u8 vib_pwm_latched;
++
++	/* hdq */
++	u8 hdq_probed; /* nonzero after HDQ driver probed */
++	struct mutex hdq_lock; /* if you want to use hdq, you have to take lock */
++	unsigned long hdq_gpio_pin; /* GTA02 = GPD14 which pin to meddle with */
++	u8 hdq_ads; /* b7..b6 = register address, b0 = r/w */
++	u8 hdq_tx_data; /* data to tx for write action */
++	u8 hdq_rx_data; /* data received in read action */
++	u8 hdq_request_ctr; /* incremented by "user" to request a transfer */
++	u8 hdq_transaction_ctr; /* incremented after each transfer */
++	u8 hdq_error; /* 0 = no error */
+ };
+ 
+ /* actual definition lives in arch/arm/mach-s3c2440/fiq_c_isr.c */
+Index: linux-2.6.24/include/asm-arm/arch-s3c2410/gta02.h
+===================================================================
+--- linux-2.6.24.orig/include/asm-arm/arch-s3c2410/gta02.h
++++ linux-2.6.24/include/asm-arm/arch-s3c2410/gta02.h
+@@ -36,6 +36,7 @@
+ 
+ #define GTA02v3_GPIO_nG1_CS	S3C2410_GPD12	/* v3 + v4 only */
+ #define GTA02v3_GPIO_nG2_CS	S3C2410_GPD13	/* v3 + v4 only */
++#define GTA02v5_GPIO_HDQ	S3C2410_GPD14   /* v5 + */
+ 
+ #define GTA02_GPIO_nG1_INT	S3C2410_GPF0
+ #define GTA02_GPIO_IO1		S3C2410_GPF1

Modified: branches/src/target/kernel/2.6.24.x/patches/series
===================================================================
--- branches/src/target/kernel/2.6.24.x/patches/series	2008-02-10 22:49:45 UTC (rev 4043)
+++ branches/src/target/kernel/2.6.24.x/patches/series	2008-02-10 23:37:02 UTC (rev 4044)
@@ -78,6 +78,7 @@
 introduce-fiq-migrate-vibrator-gta02-only.patch
 
 # OE patches
+fiq-hdq.patch
 fix-EVIOCGRAB-semantics.patch
 iis-suspend.patch
 s3c24xx-pcm-suspend.patch





More information about the commitlog mailing list