From d25c63532d5940146b9c53fc76a15c3c6b194510 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 5 Oct 2009 16:53:09 +0200 Subject: gta02: Add fiq handler --- arch/arm/mach-s3c2442/Kconfig | 2 + arch/arm/mach-s3c2442/Makefile | 4 +- arch/arm/mach-s3c2442/gta02-fiq.c | 126 +++++++++++++++++++++++++ arch/arm/mach-s3c2442/include/mach/gta02-fiq.h | 9 ++ arch/arm/mach-s3c2442/mach-gta02.c | 12 +-- 5 files changed, 143 insertions(+), 10 deletions(-) create mode 100644 arch/arm/mach-s3c2442/gta02-fiq.c create mode 100644 arch/arm/mach-s3c2442/include/mach/gta02-fiq.h diff --git a/arch/arm/mach-s3c2442/Kconfig b/arch/arm/mach-s3c2442/Kconfig index 550f6492f32..8e37b9f42ab 100644 --- a/arch/arm/mach-s3c2442/Kconfig +++ b/arch/arm/mach-s3c2442/Kconfig @@ -34,6 +34,8 @@ config MACH_NEO1973_GTA02 select MACH_NEO1973 select S3C2410_PWM select S3C_DEV_USB_HOST + 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 2a19113a576..87338d9e139 100644 --- a/arch/arm/mach-s3c2442/Makefile +++ b/arch/arm/mach-s3c2442/Makefile @@ -12,7 +12,7 @@ obj- := obj-$(CONFIG_CPU_S3C2442) += s3c2442.o obj-$(CONFIG_CPU_S3C2442) += clock.o -obj-$(CONFIG_MACH_NEO1973_GTA02) += mach-gta02.o - +obj-$(CONFIG_MACH_NEO1973_GTA02) += mach-gta02.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..78a6501d5be --- /dev/null +++ b/arch/arm/mach-s3c2442/gta02-fiq.c @@ -0,0 +1,126 @@ +#include + +#include +#include +#include +#include +#include +#include +#include + +/* ------------------------------------------------------------------------------- + * 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) + +/* 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 + */ + + 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/mach-gta02.c b/arch/arm/mach-s3c2442/mach-gta02.c index eb4e215f473..d347f3724bb 100644 --- a/arch/arm/mach-s3c2442/mach-gta02.c +++ b/arch/arm/mach-s3c2442/mach-gta02.c @@ -92,7 +92,9 @@ #include #include -static struct pcf50633 *gta02_pcf; +#include + +struct pcf50633 *gta02_pcf; /* * This gets called every 1ms when we paniced. @@ -529,12 +531,6 @@ static struct platform_device gta02_nor_flash = { .num_resources = 1, }; - -struct platform_device s3c24xx_pwm_device = { - .name = "s3c24xx_pwm", - .num_resources = 0, -}; - static struct i2c_board_info gta02_i2c_devs[] __initdata = { { I2C_BOARD_INFO("pcf50633", 0x73), @@ -721,7 +717,7 @@ static struct platform_device *gta02_devices[] __initdata = { &s3c_device_usbgadget, &s3c_device_nand, >a02_nor_flash, - &s3c24xx_pwm_device, + &s3c_device_timer, &s3c_device_iis, &s3c_device_i2c0, }; -- cgit v1.2.3