diff options
Diffstat (limited to 'target/linux/s3c24xx/patches/0046-introduce-fiq-use-timer3-as-source.patch.patch')
-rwxr-xr-x | target/linux/s3c24xx/patches/0046-introduce-fiq-use-timer3-as-source.patch.patch | 220 |
1 files changed, 220 insertions, 0 deletions
diff --git a/target/linux/s3c24xx/patches/0046-introduce-fiq-use-timer3-as-source.patch.patch b/target/linux/s3c24xx/patches/0046-introduce-fiq-use-timer3-as-source.patch.patch new file mode 100755 index 0000000000..ea8ae72fb0 --- /dev/null +++ b/target/linux/s3c24xx/patches/0046-introduce-fiq-use-timer3-as-source.patch.patch @@ -0,0 +1,220 @@ +From 26fa0c816d5e1b593128477c7e200fafe3caae18 Mon Sep 17 00:00:00 2001 +From: mokopatches <mokopatches@openmoko.org> +Date: Fri, 25 Jul 2008 22:21:22 +0100 +Subject: [PATCH] introduce-fiq-use-timer3-as-source.patch + +This makes the FIQ stuff specific to one of the timers on the +s3c244x and adds the platform stuff for fiq in the gta02 init + +Currently one sysfs node is exposed, a count of FIQ events + +cat /sys/devices/platform/sc32440_fiq.0/fiq/count + +From: Andy Green <andy@openmoko.com> +Signed-off-by: Andy Green <andy@openmoko.com> +--- + arch/arm/mach-s3c2440/fiq_c_isr.c | 56 +++++++++++++++++++++---- + arch/arm/mach-s3c2440/fiq_c_isr.h | 2 + + arch/arm/mach-s3c2440/mach-gta02.c | 17 ++++++++ + include/asm-arm/arch-s3c2410/fiq_ipc_gta02.h | 2 +- + 4 files changed, 67 insertions(+), 10 deletions(-) + +diff --git a/arch/arm/mach-s3c2440/fiq_c_isr.c b/arch/arm/mach-s3c2440/fiq_c_isr.c +index 12f4527..a71a234 100644 +--- a/arch/arm/mach-s3c2440/fiq_c_isr.c ++++ b/arch/arm/mach-s3c2440/fiq_c_isr.c +@@ -18,6 +18,9 @@ + #include <asm/plat-s3c24xx/cpu.h> + #include <asm/plat-s3c24xx/irq.h> + ++#include <asm/arch/pwm.h> ++#include <asm/plat-s3c/regs-timer.h> ++ + /* + * Major Caveats for using FIQ + * --------------------------- +@@ -66,6 +69,10 @@ static u8 u8aFiqStack[4096]; + u32 _fiq_ack_mask; /* used by isr exit define */ + unsigned long _fiq_count_fiqs; /* used by isr exit define */ + static int _fiq_irq; /* private ; irq index we were started with, or 0 */ ++struct s3c2410_pwm pwm_timer_fiq; ++int _fiq_timer_index; ++u16 _fiq_timer_divisor; ++ + + /* this function must live in the monolithic kernel somewhere! A module is + * NOT good enough! +@@ -110,23 +117,45 @@ static struct attribute_group s3c2440_fiq_attr_group = { + * you still need to clear the source interrupt in S3C2410_INTMSK to get + * anything good happening + */ +-static void fiq_init_irq_source(int irq_index_fiq) ++static int fiq_init_irq_source(int irq_index_fiq) + { ++ int rc = 0; ++ + if (!irq_index_fiq) /* no interrupt */ +- return; ++ goto bail; + +- printk(KERN_INFO"Enabling FIQ using int idx %d\n", +- irq_index_fiq - S3C2410_CPUIRQ_OFFSET); + local_fiq_disable(); + + _fiq_irq = irq_index_fiq; + _fiq_ack_mask = 1 << (irq_index_fiq - S3C2410_CPUIRQ_OFFSET); ++ timer_index = (irq_index_fiq - IRQ_TIMER0); ++ ++ /* set up the timer to operate as a pwm device */ ++ ++ rc = s3c2410_pwm_init(&pwm_timer_fiq); ++ if (rc) ++ goto bail; ++ ++ pwm_timer_fiq.timerid = PWM0 + timer_index; ++ pwm_timer_fiq.prescaler = (6 - 1) / 2; ++ pwm_timer_fiq.divider = S3C2410_TCFG1_MUX3_DIV2; ++ /* default rate == ~32us */ ++ pwm_timer_fiq.counter = pwm_timer_fiq.comparer = ++ timer_divisor = 64; ++ ++ rc = s3c2410_pwm_enable(&pwm_timer_fiq); ++ if (rc) ++ goto bail; ++ ++ s3c2410_pwm_start(&pwm_timer_fiq); + + /* let our selected interrupt be a magic FIQ interrupt */ + __raw_writel(_fiq_ack_mask, S3C2410_INTMOD); + + /* it's ready to go as soon as we unmask the source in S3C2410_INTMSK */ + local_fiq_enable(); ++bail: ++ return rc; + } + + +@@ -139,15 +168,13 @@ static void fiq_disable_irq_source(void) + _fiq_irq = 0; /* no active source interrupt now either */ + } + +-/* this starts FIQ timer events... they continue until the FIQ ISR sees that +- * its work is done and it turns off the timer. After setting up the fiq_ipc +- * struct with new work, you call this to start FIQ timer actions up again. +- * Only the FIQ ISR decides when it is done and controls turning off the +- * timer events. ++/* ++ * fiq_kick() forces a FIQ event to happen shortly after leaving the routine + */ + void fiq_kick(void) + { + unsigned long flags; ++ u32 tcon; + + /* we have to take care about FIQ because this modification is + * non-atomic, FIQ could come in after the read and before the +@@ -156,15 +183,24 @@ void fiq_kick(void) + */ + local_save_flags(flags); + local_fiq_disable(); ++ /* allow FIQs to resume */ + __raw_writel(__raw_readl(S3C2410_INTMSK) & + ~(1 << (_fiq_irq - S3C2410_CPUIRQ_OFFSET)), + S3C2410_INTMSK); ++ tcon = __raw_readl(S3C2410_TCON) & ~S3C2410_TCON_T3START; ++ /* fake the timer to a count of 1 */ ++ __raw_writel(1, S3C2410_TCNTB(timer_index)); ++ __raw_writel(tcon | S3C2410_TCON_T3MANUALUPD, S3C2410_TCON); ++ __raw_writel(tcon | S3C2410_TCON_T3MANUALUPD | S3C2410_TCON_T3START, ++ S3C2410_TCON); ++ __raw_writel(tcon | S3C2410_TCON_T3START, S3C2410_TCON); + local_irq_restore(flags); + } + EXPORT_SYMBOL_GPL(fiq_kick); + + + ++ + static int __init sc32440_fiq_probe(struct platform_device *pdev) + { + struct resource *r = platform_get_resource(pdev, IORESOURCE_IRQ, 0); +@@ -172,6 +208,8 @@ static int __init sc32440_fiq_probe(struct platform_device *pdev) + if (!r) + return -EIO; + /* configure for the interrupt we are meant to use */ ++ printk(KERN_INFO"Enabling FIQ using irq %d\n", r->start); ++ + fiq_init_irq_source(r->start); + + return sysfs_create_group(&pdev->dev.kobj, &s3c2440_fiq_attr_group); +diff --git a/arch/arm/mach-s3c2440/fiq_c_isr.h b/arch/arm/mach-s3c2440/fiq_c_isr.h +index f08740e..0c45eb7 100644 +--- a/arch/arm/mach-s3c2440/fiq_c_isr.h ++++ b/arch/arm/mach-s3c2440/fiq_c_isr.h +@@ -5,6 +5,8 @@ + + extern unsigned long _fiq_count_fiqs; + extern u32 _fiq_ack_mask; ++extern int _fiq_timer_index; ++extern u16 _fiq_timer_divisor; + + /* This CANNOT be implemented in a module -- it has to be used in code + * included in the monolithic kernel +diff --git a/arch/arm/mach-s3c2440/mach-gta02.c b/arch/arm/mach-s3c2440/mach-gta02.c +index 0bdd0e0..cb839b2 100644 +--- a/arch/arm/mach-s3c2440/mach-gta02.c ++++ b/arch/arm/mach-s3c2440/mach-gta02.c +@@ -57,6 +57,7 @@ + #include <asm/irq.h> + #include <asm/mach-types.h> + ++#include <asm/arch-s3c2410/regs-irq.h> + #include <asm/arch/regs-gpio.h> + #include <asm/arch/regs-gpioj.h> + #include <asm/arch/fb.h> +@@ -336,6 +337,21 @@ struct platform_device gta02_pmu_dev = { + }, + }; + ++/* FIQ */ ++ ++static struct resource sc32440_fiq_resources[] = { ++ [0] = { ++ .flags = IORESOURCE_IRQ, ++ .start = IRQ_TIMER3, ++ .end = IRQ_TIMER3, ++ }, ++}; ++ ++struct platform_device sc32440_fiq_device = { ++ .name = "sc32440_fiq", ++ .num_resources = 1, ++ .resource = sc32440_fiq_resources, ++}; + + /* NOR Flash */ + +@@ -403,6 +419,7 @@ static struct platform_device *gta02_devices[] __initdata = { + &s3c_device_nand, + &s3c_device_ts, + >a02_nor_flash, ++ &sc32440_fiq_device, + }; + + static struct s3c2410_nand_set gta02_nand_sets[] = { +diff --git a/include/asm-arm/arch-s3c2410/fiq_ipc_gta02.h b/include/asm-arm/arch-s3c2410/fiq_ipc_gta02.h +index 341f2bb..6cbd8e4 100644 +--- a/include/asm-arm/arch-s3c2410/fiq_ipc_gta02.h ++++ b/include/asm-arm/arch-s3c2410/fiq_ipc_gta02.h +@@ -22,7 +22,7 @@ struct fiq_ipc { + + /* actual definition lives in arch/arm/mach-s3c2440/fiq_c_isr.c */ + extern struct fiq_ipc fiq_ipc; +- ++extern unsigned long _fiq_count_fiqs; + extern void fiq_kick(void); /* provoke a FIQ "immediately" */ + + #endif /* _LINUX_FIQ_IPC_H */ +-- +1.5.6.3 + |