changed Makefile and profiles, added patches for kernel 2.6.24
[openwrt.git] / target / linux / s3c24xx / patches-2.6.24 / 1054-introduce-fiq-use-timer3-as-source.patch.patch
1 From 4ef3bf9d0e7ffd1e70f24e47b7ede98258c8b8f4 Mon Sep 17 00:00:00 2001
2 From: mokopatches <mokopatches@openmoko.org>
3 Date: Sun, 13 Apr 2008 07:23:51 +0100
4 Subject: [PATCH] introduce-fiq-use-timer3-as-source.patch
5
6 This makes the FIQ stuff specific to one of the timers on the
7 s3c244x and adds the platform stuff for fiq in the gta02 init
8
9 Currently one sysfs node is exposed, a count of FIQ events
10
11 cat /sys/devices/platform/sc32440_fiq.0/fiq/count
12
13 From: Andy Green <andy@openmoko.com>
14 Signed-off-by: Andy Green <andy@openmoko.com>
15 ---
16  arch/arm/mach-s3c2440/fiq_c_isr.c            |   56 +++++++++++++++++++++----
17  arch/arm/mach-s3c2440/fiq_c_isr.h            |    2 +
18  arch/arm/mach-s3c2440/mach-gta02.c           |   17 ++++++++
19  include/asm-arm/arch-s3c2410/fiq_ipc_gta02.h |    2 +-
20  4 files changed, 67 insertions(+), 10 deletions(-)
21
22 diff --git a/arch/arm/mach-s3c2440/fiq_c_isr.c b/arch/arm/mach-s3c2440/fiq_c_isr.c
23 index 12f4527..a71a234 100644
24 --- a/arch/arm/mach-s3c2440/fiq_c_isr.c
25 +++ b/arch/arm/mach-s3c2440/fiq_c_isr.c
26 @@ -18,6 +18,9 @@
27  #include <asm/plat-s3c24xx/cpu.h>
28  #include <asm/plat-s3c24xx/irq.h>
29  
30 +#include <asm/arch/pwm.h>
31 +#include <asm/plat-s3c/regs-timer.h>
32 +
33  /*
34   * Major Caveats for using FIQ
35   * ---------------------------
36 @@ -66,6 +69,10 @@ static u8 u8aFiqStack[4096];
37  u32 _fiq_ack_mask; /* used by isr exit define */
38  unsigned long _fiq_count_fiqs; /* used by isr exit define */
39  static int _fiq_irq; /* private ; irq index we were started with, or 0 */
40 +struct s3c2410_pwm pwm_timer_fiq;
41 +int _fiq_timer_index;
42 +u16 _fiq_timer_divisor;
43 +
44  
45  /* this function must live in the monolithic kernel somewhere!  A module is
46   * NOT good enough!
47 @@ -110,23 +117,45 @@ static struct attribute_group s3c2440_fiq_attr_group = {
48   * you still need to clear the source interrupt in S3C2410_INTMSK to get
49   * anything good happening
50   */
51 -static void fiq_init_irq_source(int irq_index_fiq)
52 +static int fiq_init_irq_source(int irq_index_fiq)
53  {
54 +       int rc = 0;
55 +
56         if (!irq_index_fiq) /* no interrupt */
57 -               return;
58 +               goto bail;
59  
60 -       printk(KERN_INFO"Enabling FIQ using int idx %d\n",
61 -              irq_index_fiq - S3C2410_CPUIRQ_OFFSET);
62         local_fiq_disable();
63  
64         _fiq_irq = irq_index_fiq;
65         _fiq_ack_mask = 1 << (irq_index_fiq - S3C2410_CPUIRQ_OFFSET);
66 +       timer_index = (irq_index_fiq - IRQ_TIMER0);
67 +
68 +       /* set up the timer to operate as a pwm device */
69 +
70 +       rc = s3c2410_pwm_init(&pwm_timer_fiq);
71 +       if (rc)
72 +               goto bail;
73 +
74 +       pwm_timer_fiq.timerid = PWM0 + timer_index;
75 +       pwm_timer_fiq.prescaler = (6 - 1) / 2;
76 +       pwm_timer_fiq.divider = S3C2410_TCFG1_MUX3_DIV2;
77 +       /* default rate == ~32us */
78 +       pwm_timer_fiq.counter = pwm_timer_fiq.comparer =
79 +                                       timer_divisor = 64;
80 +
81 +       rc = s3c2410_pwm_enable(&pwm_timer_fiq);
82 +       if (rc)
83 +               goto bail;
84 +
85 +       s3c2410_pwm_start(&pwm_timer_fiq);
86  
87         /* let our selected interrupt be a magic FIQ interrupt */
88         __raw_writel(_fiq_ack_mask, S3C2410_INTMOD);
89  
90         /* it's ready to go as soon as we unmask the source in S3C2410_INTMSK */
91         local_fiq_enable();
92 +bail:
93 +       return rc;
94  }
95  
96  
97 @@ -139,15 +168,13 @@ static void fiq_disable_irq_source(void)
98         _fiq_irq = 0; /* no active source interrupt now either */
99  }
100  
101 -/* this starts FIQ timer events... they continue until the FIQ ISR sees that
102 - * its work is done and it turns off the timer.  After setting up the fiq_ipc
103 - * struct with new work, you call this to start FIQ timer actions up again.
104 - * Only the FIQ ISR decides when it is done and controls turning off the
105 - * timer events.
106 +/*
107 + * fiq_kick() forces a FIQ event to happen shortly after leaving the routine
108   */
109  void fiq_kick(void)
110  {
111         unsigned long flags;
112 +       u32 tcon;
113  
114         /* we have to take care about FIQ because this modification is
115          * non-atomic, FIQ could come in after the read and before the
116 @@ -156,15 +183,24 @@ void fiq_kick(void)
117          */
118         local_save_flags(flags);
119         local_fiq_disable();
120 +       /* allow FIQs to resume */
121         __raw_writel(__raw_readl(S3C2410_INTMSK) &
122                      ~(1 << (_fiq_irq - S3C2410_CPUIRQ_OFFSET)),
123                      S3C2410_INTMSK);
124 +       tcon = __raw_readl(S3C2410_TCON) & ~S3C2410_TCON_T3START;
125 +       /* fake the timer to a count of 1 */
126 +       __raw_writel(1, S3C2410_TCNTB(timer_index));
127 +       __raw_writel(tcon | S3C2410_TCON_T3MANUALUPD, S3C2410_TCON);
128 +       __raw_writel(tcon | S3C2410_TCON_T3MANUALUPD | S3C2410_TCON_T3START,
129 +                    S3C2410_TCON);
130 +       __raw_writel(tcon | S3C2410_TCON_T3START, S3C2410_TCON);
131         local_irq_restore(flags);
132  }
133  EXPORT_SYMBOL_GPL(fiq_kick);
134  
135  
136  
137 +
138  static int __init sc32440_fiq_probe(struct platform_device *pdev)
139  {
140         struct resource *r = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
141 @@ -172,6 +208,8 @@ static int __init sc32440_fiq_probe(struct platform_device *pdev)
142         if (!r)
143                 return -EIO;
144         /* configure for the interrupt we are meant to use */
145 +       printk(KERN_INFO"Enabling FIQ using irq %d\n", r->start);
146 +
147         fiq_init_irq_source(r->start);
148  
149         return sysfs_create_group(&pdev->dev.kobj, &s3c2440_fiq_attr_group);
150 diff --git a/arch/arm/mach-s3c2440/fiq_c_isr.h b/arch/arm/mach-s3c2440/fiq_c_isr.h
151 index f08740e..0c45eb7 100644
152 --- a/arch/arm/mach-s3c2440/fiq_c_isr.h
153 +++ b/arch/arm/mach-s3c2440/fiq_c_isr.h
154 @@ -5,6 +5,8 @@
155  
156  extern unsigned long _fiq_count_fiqs;
157  extern u32 _fiq_ack_mask;
158 +extern int _fiq_timer_index;
159 +extern u16 _fiq_timer_divisor;
160  
161  /* This CANNOT be implemented in a module -- it has to be used in code
162   * included in the monolithic kernel
163 diff --git a/arch/arm/mach-s3c2440/mach-gta02.c b/arch/arm/mach-s3c2440/mach-gta02.c
164 index 0bdd0e0..cb839b2 100644
165 --- a/arch/arm/mach-s3c2440/mach-gta02.c
166 +++ b/arch/arm/mach-s3c2440/mach-gta02.c
167 @@ -57,6 +57,7 @@
168  #include <asm/irq.h>
169  #include <asm/mach-types.h>
170  
171 +#include <asm/arch-s3c2410/regs-irq.h>
172  #include <asm/arch/regs-gpio.h>
173  #include <asm/arch/regs-gpioj.h>
174  #include <asm/arch/fb.h>
175 @@ -336,6 +337,21 @@ struct platform_device gta02_pmu_dev = {
176         },
177  };
178  
179 +/* FIQ */
180 +
181 +static struct resource sc32440_fiq_resources[] = {
182 +       [0] = {
183 +               .flags  = IORESOURCE_IRQ,
184 +               .start  = IRQ_TIMER3,
185 +               .end    = IRQ_TIMER3,
186 +       },
187 +};
188 +
189 +struct platform_device sc32440_fiq_device = {
190 +       .name           = "sc32440_fiq",
191 +       .num_resources  = 1,
192 +       .resource       = sc32440_fiq_resources,
193 +};
194  
195  /* NOR Flash */
196  
197 @@ -403,6 +419,7 @@ static struct platform_device *gta02_devices[] __initdata = {
198         &s3c_device_nand,
199         &s3c_device_ts,
200         &gta02_nor_flash,
201 +       &sc32440_fiq_device,
202  };
203  
204  static struct s3c2410_nand_set gta02_nand_sets[] = {
205 diff --git a/include/asm-arm/arch-s3c2410/fiq_ipc_gta02.h b/include/asm-arm/arch-s3c2410/fiq_ipc_gta02.h
206 index 341f2bb..6cbd8e4 100644
207 --- a/include/asm-arm/arch-s3c2410/fiq_ipc_gta02.h
208 +++ b/include/asm-arm/arch-s3c2410/fiq_ipc_gta02.h
209 @@ -22,7 +22,7 @@ struct fiq_ipc {
210  
211  /* actual definition lives in arch/arm/mach-s3c2440/fiq_c_isr.c */
212  extern struct fiq_ipc fiq_ipc;
213 -
214 +extern unsigned long _fiq_count_fiqs;
215  extern void fiq_kick(void);  /* provoke a FIQ "immediately" */
216  
217  #endif /* _LINUX_FIQ_IPC_H */
218 -- 
219 1.5.6.5
220