diff options
author | Ben Dooks <ben-linux@fluff.org> | 2008-10-21 09:06:57 -0400 |
---|---|---|
committer | Ben Dooks <ben-linux@fluff.org> | 2008-12-15 16:52:51 -0500 |
commit | f982dc5321848ca6150a7a2c2bb3e28bddcf5ebe (patch) | |
tree | a854a69febfa17e3503da09d3c8d58384c678c82 /arch | |
parent | e550ae741663e4708dcdad3fc392db156189c77c (diff) |
[ARM] S3C64XX: Map timer memory and interrupts
Add the physical to virtual memory mapping and the
necessary interrupt demuxing for the PWM timer blocks.
Signed-off-by: Ben Dooks <ben-linux@fluff.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/plat-s3c/include/plat/regs-timer.h | 3 | ||||
-rw-r--r-- | arch/arm/plat-s3c64xx/cpu.c | 6 | ||||
-rw-r--r-- | arch/arm/plat-s3c64xx/include/plat/irqs.h | 20 | ||||
-rw-r--r-- | arch/arm/plat-s3c64xx/irq.c | 87 |
4 files changed, 107 insertions, 9 deletions
diff --git a/arch/arm/plat-s3c/include/plat/regs-timer.h b/arch/arm/plat-s3c/include/plat/regs-timer.h index cc0eedd53e38..086ce2685836 100644 --- a/arch/arm/plat-s3c/include/plat/regs-timer.h +++ b/arch/arm/plat-s3c/include/plat/regs-timer.h | |||
@@ -10,7 +10,6 @@ | |||
10 | * S3C2410 Timer configuration | 10 | * S3C2410 Timer configuration |
11 | */ | 11 | */ |
12 | 12 | ||
13 | |||
14 | #ifndef __ASM_ARCH_REGS_TIMER_H | 13 | #ifndef __ASM_ARCH_REGS_TIMER_H |
15 | #define __ASM_ARCH_REGS_TIMER_H | 14 | #define __ASM_ARCH_REGS_TIMER_H |
16 | 15 | ||
@@ -21,6 +20,8 @@ | |||
21 | #define S3C2410_TCFG1 S3C_TIMERREG(0x04) | 20 | #define S3C2410_TCFG1 S3C_TIMERREG(0x04) |
22 | #define S3C2410_TCON S3C_TIMERREG(0x08) | 21 | #define S3C2410_TCON S3C_TIMERREG(0x08) |
23 | 22 | ||
23 | #define S3C64XX_TINT_CSTAT S3C_TIMERREG(0x44) | ||
24 | |||
24 | #define S3C2410_TCFG_PRESCALER0_MASK (255<<0) | 25 | #define S3C2410_TCFG_PRESCALER0_MASK (255<<0) |
25 | #define S3C2410_TCFG_PRESCALER1_MASK (255<<8) | 26 | #define S3C2410_TCFG_PRESCALER1_MASK (255<<8) |
26 | #define S3C2410_TCFG_PRESCALER1_SHIFT (8) | 27 | #define S3C2410_TCFG_PRESCALER1_SHIFT (8) |
diff --git a/arch/arm/plat-s3c64xx/cpu.c b/arch/arm/plat-s3c64xx/cpu.c index dc7bf112ec05..2559d6afc317 100644 --- a/arch/arm/plat-s3c64xx/cpu.c +++ b/arch/arm/plat-s3c64xx/cpu.c | |||
@@ -87,12 +87,16 @@ static struct map_desc s3c_iodesc[] __initdata = { | |||
87 | .pfn = __phys_to_pfn(S3C64XX_PA_VIC1), | 87 | .pfn = __phys_to_pfn(S3C64XX_PA_VIC1), |
88 | .length = SZ_16K, | 88 | .length = SZ_16K, |
89 | .type = MT_DEVICE, | 89 | .type = MT_DEVICE, |
90 | }, { | ||
91 | .virtual = S3C_VA_TIMER, | ||
92 | .pfn = __phys_to_pfn(S3C_PA_TIMER), | ||
93 | .length = SZ_16K, | ||
94 | .type = MT_DEVICE, | ||
90 | }, | 95 | }, |
91 | }; | 96 | }; |
92 | 97 | ||
93 | /* read cpu identification code */ | 98 | /* read cpu identification code */ |
94 | 99 | ||
95 | |||
96 | void __init s3c64xx_init_io(struct map_desc *mach_desc, int size) | 100 | void __init s3c64xx_init_io(struct map_desc *mach_desc, int size) |
97 | { | 101 | { |
98 | unsigned long idcode; | 102 | unsigned long idcode; |
diff --git a/arch/arm/plat-s3c64xx/include/plat/irqs.h b/arch/arm/plat-s3c64xx/include/plat/irqs.h index 3564dfbec85a..8bdfb27425e6 100644 --- a/arch/arm/plat-s3c64xx/include/plat/irqs.h +++ b/arch/arm/plat-s3c64xx/include/plat/irqs.h | |||
@@ -89,12 +89,12 @@ | |||
89 | #define IRQ_ARM_DMA S3C64XX_IRQ_VIC0(20) | 89 | #define IRQ_ARM_DMA S3C64XX_IRQ_VIC0(20) |
90 | #define IRQ_ARM_DMAS S3C64XX_IRQ_VIC0(21) | 90 | #define IRQ_ARM_DMAS S3C64XX_IRQ_VIC0(21) |
91 | #define IRQ_KEYPAD S3C64XX_IRQ_VIC0(22) | 91 | #define IRQ_KEYPAD S3C64XX_IRQ_VIC0(22) |
92 | #define IRQ_TIMER0 S3C64XX_IRQ_VIC0(23) | 92 | #define IRQ_TIMER0_VIC S3C64XX_IRQ_VIC0(23) |
93 | #define IRQ_TIMER1 S3C64XX_IRQ_VIC0(24) | 93 | #define IRQ_TIMER1_VIC S3C64XX_IRQ_VIC0(24) |
94 | #define IRQ_TIMER2 S3C64XX_IRQ_VIC0(25) | 94 | #define IRQ_TIMER2_VIC S3C64XX_IRQ_VIC0(25) |
95 | #define IRQ_WDT S3C64XX_IRQ_VIC0(26) | 95 | #define IRQ_WDT S3C64XX_IRQ_VIC0(26) |
96 | #define IRQ_TIMER3 S3C64XX_IRQ_VIC0(27) | 96 | #define IRQ_TIMER3_VIC S3C64XX_IRQ_VIC0(27) |
97 | #define IRQ_TIMER4 S3C64XX_IRQ_VIC0(28) | 97 | #define IRQ_TIMER4_VIC S3C64XX_IRQ_VIC0(28) |
98 | #define IRQ_LCD_FIFO S3C64XX_IRQ_VIC0(29) | 98 | #define IRQ_LCD_FIFO S3C64XX_IRQ_VIC0(29) |
99 | #define IRQ_LCD_VSYNC S3C64XX_IRQ_VIC0(30) | 99 | #define IRQ_LCD_VSYNC S3C64XX_IRQ_VIC0(30) |
100 | #define IRQ_LCD_SYSTEM S3C64XX_IRQ_VIC0(31) | 100 | #define IRQ_LCD_SYSTEM S3C64XX_IRQ_VIC0(31) |
@@ -136,11 +136,19 @@ | |||
136 | #define IRQ_TC IRQ_PENDN | 136 | #define IRQ_TC IRQ_PENDN |
137 | #define IRQ_ADC S3C64XX_IRQ_VIC1(31) | 137 | #define IRQ_ADC S3C64XX_IRQ_VIC1(31) |
138 | 138 | ||
139 | #define S3C64XX_TIMER_IRQ(x) S3C_IRQ(64 + (x)) | ||
140 | |||
141 | #define IRQ_TIMER0 S3C64XX_TIMER_IRQ(0) | ||
142 | #define IRQ_TIMER1 S3C64XX_TIMER_IRQ(1) | ||
143 | #define IRQ_TIMER2 S3C64XX_TIMER_IRQ(2) | ||
144 | #define IRQ_TIMER3 S3C64XX_TIMER_IRQ(3) | ||
145 | #define IRQ_TIMER4 S3C64XX_TIMER_IRQ(4) | ||
146 | |||
139 | /* Since the IRQ_EINT(x) are a linear mapping on current s3c64xx series | 147 | /* Since the IRQ_EINT(x) are a linear mapping on current s3c64xx series |
140 | * we just defined them as an IRQ_EINT(x) macro from S3C_IRQ_EINT_BASE | 148 | * we just defined them as an IRQ_EINT(x) macro from S3C_IRQ_EINT_BASE |
141 | * which we place after the pair of VICs. */ | 149 | * which we place after the pair of VICs. */ |
142 | 150 | ||
143 | #define S3C_IRQ_EINT_BASE S3C_IRQ(64) | 151 | #define S3C_IRQ_EINT_BASE S3C_IRQ(64+5) |
144 | 152 | ||
145 | #define S3C_EINT(x) ((x) + S3C_IRQ_EINT_BASE) | 153 | #define S3C_EINT(x) ((x) + S3C_IRQ_EINT_BASE) |
146 | 154 | ||
diff --git a/arch/arm/plat-s3c64xx/irq.c b/arch/arm/plat-s3c64xx/irq.c index 308dc4198a17..1e6fa5c828c9 100644 --- a/arch/arm/plat-s3c64xx/irq.c +++ b/arch/arm/plat-s3c64xx/irq.c | |||
@@ -14,21 +14,106 @@ | |||
14 | 14 | ||
15 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
16 | #include <linux/interrupt.h> | 16 | #include <linux/interrupt.h> |
17 | #include <linux/irq.h> | ||
17 | #include <linux/io.h> | 18 | #include <linux/io.h> |
18 | 19 | ||
19 | #include <asm/hardware/vic.h> | 20 | #include <asm/hardware/vic.h> |
20 | #include <asm/irq.h> | ||
21 | 21 | ||
22 | #include <mach/map.h> | 22 | #include <mach/map.h> |
23 | #include <plat/regs-timer.h> | ||
23 | #include <plat/cpu.h> | 24 | #include <plat/cpu.h> |
24 | 25 | ||
26 | /* Timer interrupt handling */ | ||
27 | |||
28 | static void s3c_irq_demux_timer(unsigned int base_irq, unsigned int sub_irq) | ||
29 | { | ||
30 | generic_handle_irq(sub_irq); | ||
31 | } | ||
32 | |||
33 | static void s3c_irq_demux_timer0(unsigned int irq, struct irq_desc *desc) | ||
34 | { | ||
35 | s3c_irq_demux_timer(irq, IRQ_TIMER0); | ||
36 | } | ||
37 | |||
38 | static void s3c_irq_demux_timer1(unsigned int irq, struct irq_desc *desc) | ||
39 | { | ||
40 | s3c_irq_demux_timer(irq, IRQ_TIMER1); | ||
41 | } | ||
42 | |||
43 | static void s3c_irq_demux_timer2(unsigned int irq, struct irq_desc *desc) | ||
44 | { | ||
45 | s3c_irq_demux_timer(irq, IRQ_TIMER2); | ||
46 | } | ||
47 | |||
48 | static void s3c_irq_demux_timer3(unsigned int irq, struct irq_desc *desc) | ||
49 | { | ||
50 | s3c_irq_demux_timer(irq, IRQ_TIMER3); | ||
51 | } | ||
52 | |||
53 | static void s3c_irq_demux_timer4(unsigned int irq, struct irq_desc *desc) | ||
54 | { | ||
55 | s3c_irq_demux_timer(irq, IRQ_TIMER4); | ||
56 | } | ||
57 | |||
58 | /* We assume the IRQ_TIMER0..IRQ_TIMER4 range is continuous. */ | ||
59 | |||
60 | static void s3c_irq_timer_mask(unsigned int irq) | ||
61 | { | ||
62 | u32 reg = __raw_readl(S3C64XX_TINT_CSTAT); | ||
63 | |||
64 | reg &= 0x1f; /* mask out pending interrupts */ | ||
65 | reg &= ~(1 << (irq - IRQ_TIMER0)); | ||
66 | __raw_writel(reg, S3C64XX_TINT_CSTAT); | ||
67 | } | ||
68 | |||
69 | static void s3c_irq_timer_unmask(unsigned int irq) | ||
70 | { | ||
71 | u32 reg = __raw_readl(S3C64XX_TINT_CSTAT); | ||
72 | |||
73 | reg &= 0x1f; /* mask out pending interrupts */ | ||
74 | reg |= 1 << (irq - IRQ_TIMER0); | ||
75 | __raw_writel(reg, S3C64XX_TINT_CSTAT); | ||
76 | } | ||
77 | |||
78 | static void s3c_irq_timer_ack(unsigned int irq) | ||
79 | { | ||
80 | u32 reg = __raw_readl(S3C64XX_TINT_CSTAT); | ||
81 | |||
82 | reg &= 0x1f; | ||
83 | reg |= (1 << 5) << (irq - IRQ_TIMER0); | ||
84 | __raw_writel(reg, S3C64XX_TINT_CSTAT); | ||
85 | } | ||
86 | |||
87 | static struct irq_chip s3c_irq_timer = { | ||
88 | .name = "s3c-timer", | ||
89 | .mask = s3c_irq_timer_mask, | ||
90 | .unmask = s3c_irq_timer_unmask, | ||
91 | .ack = s3c_irq_timer_ack, | ||
92 | }; | ||
93 | |||
25 | void __init s3c64xx_init_irq(u32 vic0_valid, u32 vic1_valid) | 94 | void __init s3c64xx_init_irq(u32 vic0_valid, u32 vic1_valid) |
26 | { | 95 | { |
96 | int irq; | ||
97 | |||
27 | printk(KERN_INFO "%s: initialising interrupts\n", __func__); | 98 | printk(KERN_INFO "%s: initialising interrupts\n", __func__); |
28 | 99 | ||
29 | /* initialise the pair of VICs */ | 100 | /* initialise the pair of VICs */ |
30 | vic_init(S3C_VA_VIC0, S3C_VIC0_BASE, vic0_valid); | 101 | vic_init(S3C_VA_VIC0, S3C_VIC0_BASE, vic0_valid); |
31 | vic_init(S3C_VA_VIC1, S3C_VIC1_BASE, vic1_valid); | 102 | vic_init(S3C_VA_VIC1, S3C_VIC1_BASE, vic1_valid); |
103 | |||
104 | /* add the timer sub-irqs */ | ||
105 | |||
106 | set_irq_chained_handler(IRQ_TIMER0_VIC, s3c_irq_demux_timer0); | ||
107 | set_irq_chained_handler(IRQ_TIMER1_VIC, s3c_irq_demux_timer1); | ||
108 | set_irq_chained_handler(IRQ_TIMER2_VIC, s3c_irq_demux_timer2); | ||
109 | set_irq_chained_handler(IRQ_TIMER3_VIC, s3c_irq_demux_timer3); | ||
110 | set_irq_chained_handler(IRQ_TIMER4_VIC, s3c_irq_demux_timer4); | ||
111 | |||
112 | for (irq = IRQ_TIMER0; irq <= IRQ_TIMER4; irq++) { | ||
113 | set_irq_chip(irq, &s3c_irq_timer); | ||
114 | set_irq_handler(irq, handle_level_irq); | ||
115 | set_irq_flags(irq, IRQF_VALID); | ||
116 | } | ||
32 | } | 117 | } |
33 | 118 | ||
34 | 119 | ||