aboutsummaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-s3c2442/Kconfig3
-rw-r--r--arch/arm/mach-s3c2442/Makefile3
-rw-r--r--arch/arm/mach-s3c2442/gta02-fiq.c135
-rw-r--r--arch/arm/mach-s3c2442/include/mach/gta02-fiq.h9
-rw-r--r--arch/arm/mach-s3c2442/include/mach/gta02.h3
-rw-r--r--arch/arm/mach-s3c2442/mach-gta02.c58
6 files changed, 209 insertions, 2 deletions
diff --git a/arch/arm/mach-s3c2442/Kconfig b/arch/arm/mach-s3c2442/Kconfig
index 2e33904759c..bdb37dd567d 100644
--- a/arch/arm/mach-s3c2442/Kconfig
+++ b/arch/arm/mach-s3c2442/Kconfig
@@ -35,6 +35,9 @@ config MACH_NEO1973_GTA02
select S3C2410_PWM
select S3C_DEV_USB_HOST
select S3C_DEV_NAND
+ select FIQ
+ select S3C_PWM
+ select S3C24XX_GPIO_EXTRA64
help
Say Y here if you are using the Openmoko GTA02 / Freerunner GSM Phone
diff --git a/arch/arm/mach-s3c2442/Makefile b/arch/arm/mach-s3c2442/Makefile
index ebe0579c537..cf39481cb5c 100644
--- a/arch/arm/mach-s3c2442/Makefile
+++ b/arch/arm/mach-s3c2442/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_MACH_NEO1973_GTA02) += mach-gta02.o \
gta02-pm-bt.o \
gta02-pm-gps.o \
gta02-pm-gsm.o \
- gta02-pm-wlan.o
+ gta02-pm-wlan.o \
+ gta02-fiq.o
# Machine support
diff --git a/arch/arm/mach-s3c2442/gta02-fiq.c b/arch/arm/mach-s3c2442/gta02-fiq.c
new file mode 100644
index 00000000000..d91c52341d5
--- /dev/null
+++ b/arch/arm/mach-s3c2442/gta02-fiq.c
@@ -0,0 +1,135 @@
+#include <linux/kernel.h>
+
+#include <asm/fiq.h>
+#include <mach/regs-irq.h>
+#include <plat/regs-timer.h>
+#include <mach/irqs.h>
+#include <linux/io.h>
+#include <linux/pwm.h>
+#include <linux/err.h>
+#include <linux/hdq.h>
+
+/* -------------------------------------------------------------------------------
+ * GTA02 FIQ related
+ *
+ * Calls into vibrator and hdq and based on the return values
+ * determines if we the FIQ source be kept alive
+ */
+
+#define DIVISOR_FROM_US(x) ((x) << 3)
+
+#ifdef CONFIG_HDQ_GPIO_BITBANG
+#define FIQ_DIVISOR_HDQ DIVISOR_FROM_US(HDQ_SAMPLE_PERIOD_US)
+extern int hdq_fiq_handler(void);
+#endif
+
+/* Global data related to our fiq source */
+static uint32_t gta02_fiq_ack_mask;
+static const int gta02_gta02_fiq_timer_id = 2;
+
+struct pwm_device* gta02_fiq_timer;
+
+void gta02_fiq_handler(void)
+{
+ unsigned long intmask;
+ int keep_running = 0;
+ /* disable further timer interrupts if nobody has any work
+ * or adjust rate according to who still has work
+ *
+ * CAUTION: it means forground code must disable FIQ around
+ * its own non-atomic S3C2410_INTMSK changes... not common
+ * thankfully and taken care of by the fiq-basis patch
+ */
+
+#ifdef CONFIG_HDQ_GPIO_BITBANG
+ keep_running = hdq_fiq_handler();
+#endif
+ if (!keep_running) {
+ /* Disable irq */
+ intmask = __raw_readl(S3C2410_INTMSK);
+ intmask |= (gta02_fiq_ack_mask);
+ __raw_writel(intmask, S3C2410_INTMSK);
+ }
+
+ __raw_writel(gta02_fiq_ack_mask, S3C2410_SRCPND);
+}
+
+void gta02_fiq_kick(void)
+{
+ unsigned long flags;
+ unsigned long intmask;
+ /* we have to take care about FIQ because this modification is
+ * non-atomic, FIQ could come in after the read and before the
+ * writeback and its changes to the register would be lost
+ * (platform INTMSK mod code is taken care of already)
+ */
+ local_save_flags(flags);
+ local_fiq_disable();
+
+ /* allow FIQs to resume */
+ intmask = __raw_readl(S3C2410_INTMSK);
+ intmask &= ~(gta02_fiq_ack_mask);
+ __raw_writel(intmask, S3C2410_INTMSK);
+
+ local_irq_restore(flags);
+
+}
+
+int gta02_fiq_enable(void)
+{
+ int ret = 0;
+
+ local_fiq_disable();
+
+ gta02_fiq_timer = pwm_request(gta02_gta02_fiq_timer_id, "fiq timer");
+
+ if (IS_ERR(gta02_fiq_timer)) {
+ ret = PTR_ERR(gta02_fiq_timer);
+ printk("GTA02 FIQ: Could not request fiq timer: %d\n", ret);
+ return ret;
+ }
+
+ gta02_fiq_ack_mask = 1 << (IRQ_TIMER0 + gta02_gta02_fiq_timer_id
+ - S3C2410_CPUIRQ_OFFSET);
+
+
+ ret = pwm_config(gta02_fiq_timer, HDQ_SAMPLE_PERIOD_US * 1000,
+ HDQ_SAMPLE_PERIOD_US * 1000);
+ if (ret) {
+ printk("GTA02 FIQ: Could not configure fiq timer: %d\n", ret);
+ goto err;
+ }
+
+ set_fiq_c_handler(gta02_fiq_handler);
+
+ __raw_writel(gta02_fiq_ack_mask, S3C2410_INTMOD);
+
+ pwm_enable(gta02_fiq_timer);
+
+ local_fiq_enable();
+
+ return 0;
+
+err:
+ pwm_free(gta02_fiq_timer);
+
+ return ret;
+}
+
+void gta02_fiq_disable(void)
+{
+ local_fiq_disable();
+
+ if (!gta02_fiq_timer)
+ return;
+
+ __raw_writel(0, S3C2410_INTMOD);
+ set_fiq_c_handler(NULL);
+
+ pwm_disable(gta02_fiq_timer);
+
+ pwm_free(gta02_fiq_timer);
+
+ gta02_fiq_timer = NULL;
+}
+/* -------------------- /GTA02 FIQ Handler ------------------------------------- */
diff --git a/arch/arm/mach-s3c2442/include/mach/gta02-fiq.h b/arch/arm/mach-s3c2442/include/mach/gta02-fiq.h
new file mode 100644
index 00000000000..90de3530595
--- /dev/null
+++ b/arch/arm/mach-s3c2442/include/mach/gta02-fiq.h
@@ -0,0 +1,9 @@
+#ifndef __GTA02_FIQ_H
+#define __GTA02_FIQ_H
+
+extern void gta02_fiq_handler(void);
+extern void gta02_fiq_kick(void);
+extern int gta02_fiq_enable(void);
+extern void gta02_fiq_disable(void);
+
+#endif
diff --git a/arch/arm/mach-s3c2442/include/mach/gta02.h b/arch/arm/mach-s3c2442/include/mach/gta02.h
index 11624c0b926..b67e5ec2919 100644
--- a/arch/arm/mach-s3c2442/include/mach/gta02.h
+++ b/arch/arm/mach-s3c2442/include/mach/gta02.h
@@ -80,6 +80,9 @@
#define GTA02_PCB_ID2_0 S3C2410_GPD(3)
#define GTA02_PCB_ID2_1 S3C2410_GPD(4)
+#define GTA02_GPIO_GLAMO_BASE S3C_GPIO_END
+#define GTA02_GPIO_GLAMO(x) (GTA02_GPIO_GLAMO_BASE + (x))
+
int gta02_get_pcb_revision(void);
extern struct pcf50633 *gta02_pcf;
diff --git a/arch/arm/mach-s3c2442/mach-gta02.c b/arch/arm/mach-s3c2442/mach-gta02.c
index ff801779075..6afd4bd2c68 100644
--- a/arch/arm/mach-s3c2442/mach-gta02.c
+++ b/arch/arm/mach-s3c2442/mach-gta02.c
@@ -109,6 +109,15 @@
#include <linux/platform_battery.h>
+#include <mach/ts.h>
+#include <linux/input/touchscreen/ts_filter_chain.h>
+#ifdef CONFIG_TOUCHSCREEN_FILTER
+#include <linux/input/touchscreen/ts_filter_linear.h>
+#include <linux/input/touchscreen/ts_filter_mean.h>
+#include <linux/input/touchscreen/ts_filter_median.h>
+#include <linux/input/touchscreen/ts_filter_group.h>
+#endif
+
struct pcf50633 *gta02_pcf;
/*
@@ -982,6 +991,51 @@ static struct platform_device gta02_pwm_leds_device = {
}
};
+/* Touchscreen configuration. */
+
+#ifdef CONFIG_TOUCHSCREEN_FILTER
+const static struct ts_filter_group_configuration gta02_ts_group = {
+ .length = 12,
+ .close_enough = 10,
+ .threshold = 6, /* At least half of the points in a group. */
+ .attempts = 10,
+};
+
+const static struct ts_filter_median_configuration gta02_ts_median = {
+ .extent = 20,
+ .decimation_below = 3,
+ .decimation_threshold = 8 * 3,
+ .decimation_above = 4,
+};
+
+const static struct ts_filter_mean_configuration gta02_ts_mean = {
+ .length = 4,
+};
+
+const static struct ts_filter_linear_configuration gta02_ts_linear = {
+ .constants = {1, 0, 0, 0, 1, 0, 1}, /* Don't modify coords. */
+ .coord0 = 0,
+ .coord1 = 1,
+};
+#endif
+
+const static struct ts_filter_chain_configuration gta02_filter_configuration[] =
+{
+#ifdef CONFIG_TOUCHSCREEN_FILTER
+ {&ts_filter_group_api, &gta02_ts_group.config},
+ {&ts_filter_median_api, &gta02_ts_median.config},
+ {&ts_filter_mean_api, &gta02_ts_mean.config},
+ {&ts_filter_linear_api, &gta02_ts_linear.config},
+#endif
+ {NULL, NULL},
+};
+
+const static struct s3c2410_ts_mach_info gta02_ts_cfg = {
+ .delay = 10000,
+ .presc = 0xff, /* slow as we can go */
+ .filter_config = gta02_filter_configuration,
+};
+
struct hdq_platform_data gta02_hdq_platform_data = {
.attach_child_devices = gta02_hdq_attach_child_devices,
.gpio_dir_out = gta02_hdq_gpio_direction_out,
@@ -1001,7 +1055,7 @@ struct platform_device gta02_hdq_device = {
.resource = gta02_hdq_resources,
.dev = {
.platform_data = &gta02_hdq_platform_data,
- .parent = &s3c_device_timer[0].dev,
+ .parent = &s3c_device_timer[2].dev,
},
};
@@ -1040,6 +1094,7 @@ static struct platform_device *gta02_devices[] __initdata = {
/* These guys DO need to be children of PMU. */
static struct platform_device *gta02_devices_pmu_children[] = {
+ &s3c_device_ts,
&gta02_glamo_dev,
&s3c_device_timer[2],
&gta02_hdq_device,
@@ -1184,6 +1239,7 @@ static void __init gta02_machine_init(void)
s3c24xx_udc_set_platdata(&gta02_udc_cfg);
s3c_i2c0_set_platdata(NULL);
+ set_s3c2410ts_info(&gta02_ts_cfg);
i2c_register_board_info(0, gta02_i2c_devs, ARRAY_SIZE(gta02_i2c_devs));
spi_register_board_info(gta02_spi_board_info,