aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/plat-s5p
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-05-23 18:15:27 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-05-23 18:15:27 -0400
commit42cd71bf1e3a081b3150018bbf448cb6c8a844a5 (patch)
tree4a5d2eb0444255e4ad827a76dbd1417dd3876db6 /arch/arm/plat-s5p
parentf5039935ac685b3b9b8c13fbc33cac8643dee32e (diff)
parent9a55d9752d8abfc62f1ab05ccc790d22a0c8e7c0 (diff)
Merge branch 'for-linus' of master.kernel.org:/home/rmk/linux-2.6-arm
* 'for-linus' of master.kernel.org:/home/rmk/linux-2.6-arm: (137 commits) ARM: bcmring: convert to use sp804 clockevents ARM: bcmring: convert to sp804 clocksource ARM: 6912/1: bcmring: Add clkdev table in init_early clockevents: ARM sp804: obtain sp804 timer rate via clks clockevents: ARM sp804: allow clockevent name to be specified clocksource: ARM sp804: obtain sp804 timer rate via clks clocksource: ARM sp804: allow clocksource name to be specified clocksource: convert OMAP1 to 32-bit down counting clocksource clocksource: convert MXS timrotv2 to 32-bit down counting clocksource clocksource: convert SPEAr platforms 16-bit up counting clocksource clocksource: convert Integrator/AP 16-bit down counting clocksource clocksource: convert W90x900 24-bit down counting clocksource clocksource: convert ARM 32-bit down counting clocksources clocksource: convert ARM 32-bit up counting clocksources clocksource: add common mmio clocksource ARM: update sa1100 to reflect PXA updates ARM: omap1: convert to using readl/writel instead of volatile struct ARM: omap1: delete useless interrupt handler ARM: s5p: consolidate selection of timer register ARM: 6939/1: fix missing 'cpu_relax()' declaration ...
Diffstat (limited to 'arch/arm/plat-s5p')
-rw-r--r--arch/arm/plat-s5p/irq-gpioint.c116
-rw-r--r--arch/arm/plat-s5p/irq.c6
-rw-r--r--arch/arm/plat-s5p/s5p-time.c58
3 files changed, 45 insertions, 135 deletions
diff --git a/arch/arm/plat-s5p/irq-gpioint.c b/arch/arm/plat-s5p/irq-gpioint.c
index cd6d67c8382a..135abda31c9a 100644
--- a/arch/arm/plat-s5p/irq-gpioint.c
+++ b/arch/arm/plat-s5p/irq-gpioint.c
@@ -41,72 +41,11 @@ struct s5p_gpioint_bank {
41 41
42LIST_HEAD(banks); 42LIST_HEAD(banks);
43 43
44static int s5p_gpioint_get_offset(struct irq_data *data) 44static int s5p_gpioint_set_type(struct irq_data *d, unsigned int type)
45{ 45{
46 struct s3c_gpio_chip *chip = irq_data_get_irq_handler_data(data); 46 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
47 return data->irq - chip->irq_base; 47 struct irq_chip_type *ct = gc->chip_types;
48} 48 unsigned int shift = (d->irq - gc->irq_base) << 2;
49
50static void s5p_gpioint_ack(struct irq_data *data)
51{
52 struct s3c_gpio_chip *chip = irq_data_get_irq_handler_data(data);
53 int group, offset, pend_offset;
54 unsigned int value;
55
56 group = chip->group;
57 offset = s5p_gpioint_get_offset(data);
58 pend_offset = REG_OFFSET(group);
59
60 value = __raw_readl(GPIO_BASE(chip) + PEND_OFFSET + pend_offset);
61 value |= BIT(offset);
62 __raw_writel(value, GPIO_BASE(chip) + PEND_OFFSET + pend_offset);
63}
64
65static void s5p_gpioint_mask(struct irq_data *data)
66{
67 struct s3c_gpio_chip *chip = irq_data_get_irq_handler_data(data);
68 int group, offset, mask_offset;
69 unsigned int value;
70
71 group = chip->group;
72 offset = s5p_gpioint_get_offset(data);
73 mask_offset = REG_OFFSET(group);
74
75 value = __raw_readl(GPIO_BASE(chip) + MASK_OFFSET + mask_offset);
76 value |= BIT(offset);
77 __raw_writel(value, GPIO_BASE(chip) + MASK_OFFSET + mask_offset);
78}
79
80static void s5p_gpioint_unmask(struct irq_data *data)
81{
82 struct s3c_gpio_chip *chip = irq_data_get_irq_handler_data(data);
83 int group, offset, mask_offset;
84 unsigned int value;
85
86 group = chip->group;
87 offset = s5p_gpioint_get_offset(data);
88 mask_offset = REG_OFFSET(group);
89
90 value = __raw_readl(GPIO_BASE(chip) + MASK_OFFSET + mask_offset);
91 value &= ~BIT(offset);
92 __raw_writel(value, GPIO_BASE(chip) + MASK_OFFSET + mask_offset);
93}
94
95static void s5p_gpioint_mask_ack(struct irq_data *data)
96{
97 s5p_gpioint_mask(data);
98 s5p_gpioint_ack(data);
99}
100
101static int s5p_gpioint_set_type(struct irq_data *data, unsigned int type)
102{
103 struct s3c_gpio_chip *chip = irq_data_get_irq_handler_data(data);
104 int group, offset, con_offset;
105 unsigned int value;
106
107 group = chip->group;
108 offset = s5p_gpioint_get_offset(data);
109 con_offset = REG_OFFSET(group);
110 49
111 switch (type) { 50 switch (type) {
112 case IRQ_TYPE_EDGE_RISING: 51 case IRQ_TYPE_EDGE_RISING:
@@ -130,23 +69,12 @@ static int s5p_gpioint_set_type(struct irq_data *data, unsigned int type)
130 return -EINVAL; 69 return -EINVAL;
131 } 70 }
132 71
133 value = __raw_readl(GPIO_BASE(chip) + CON_OFFSET + con_offset); 72 gc->type_cache &= ~(0x7 << shift);
134 value &= ~(0x7 << (offset * 0x4)); 73 gc->type_cache |= type << shift;
135 value |= (type << (offset * 0x4)); 74 writel(gc->type_cache, gc->reg_base + ct->regs.type);
136 __raw_writel(value, GPIO_BASE(chip) + CON_OFFSET + con_offset);
137
138 return 0; 75 return 0;
139} 76}
140 77
141static struct irq_chip s5p_gpioint = {
142 .name = "s5p_gpioint",
143 .irq_ack = s5p_gpioint_ack,
144 .irq_mask = s5p_gpioint_mask,
145 .irq_mask_ack = s5p_gpioint_mask_ack,
146 .irq_unmask = s5p_gpioint_unmask,
147 .irq_set_type = s5p_gpioint_set_type,
148};
149
150static void s5p_gpioint_handler(unsigned int irq, struct irq_desc *desc) 78static void s5p_gpioint_handler(unsigned int irq, struct irq_desc *desc)
151{ 79{
152 struct s5p_gpioint_bank *bank = irq_get_handler_data(irq); 80 struct s5p_gpioint_bank *bank = irq_get_handler_data(irq);
@@ -179,9 +107,10 @@ static void s5p_gpioint_handler(unsigned int irq, struct irq_desc *desc)
179static __init int s5p_gpioint_add(struct s3c_gpio_chip *chip) 107static __init int s5p_gpioint_add(struct s3c_gpio_chip *chip)
180{ 108{
181 static int used_gpioint_groups = 0; 109 static int used_gpioint_groups = 0;
182 int irq, group = chip->group; 110 int group = chip->group;
183 int i;
184 struct s5p_gpioint_bank *bank = NULL; 111 struct s5p_gpioint_bank *bank = NULL;
112 struct irq_chip_generic *gc;
113 struct irq_chip_type *ct;
185 114
186 if (used_gpioint_groups >= S5P_GPIOINT_GROUP_COUNT) 115 if (used_gpioint_groups >= S5P_GPIOINT_GROUP_COUNT)
187 return -ENOMEM; 116 return -ENOMEM;
@@ -211,19 +140,28 @@ static __init int s5p_gpioint_add(struct s3c_gpio_chip *chip)
211 * chained GPIO irq has been successfully registered, allocate new gpio 140 * chained GPIO irq has been successfully registered, allocate new gpio
212 * int group and assign irq nubmers 141 * int group and assign irq nubmers
213 */ 142 */
214
215 chip->irq_base = S5P_GPIOINT_BASE + 143 chip->irq_base = S5P_GPIOINT_BASE +
216 used_gpioint_groups * S5P_GPIOINT_GROUP_SIZE; 144 used_gpioint_groups * S5P_GPIOINT_GROUP_SIZE;
217 used_gpioint_groups++; 145 used_gpioint_groups++;
218 146
219 bank->chips[group - bank->start] = chip; 147 bank->chips[group - bank->start] = chip;
220 for (i = 0; i < chip->chip.ngpio; i++) { 148
221 irq = chip->irq_base + i; 149 gc = irq_alloc_generic_chip("s5p_gpioint", 1, chip->irq_base,
222 irq_set_chip(irq, &s5p_gpioint); 150 (void __iomem *)GPIO_BASE(chip),
223 irq_set_handler_data(irq, chip); 151 handle_level_irq);
224 irq_set_handler(irq, handle_level_irq); 152 if (!gc)
225 set_irq_flags(irq, IRQF_VALID); 153 return -ENOMEM;
226 } 154 ct = gc->chip_types;
155 ct->chip.irq_ack = irq_gc_ack;
156 ct->chip.irq_mask = irq_gc_mask_set_bit;
157 ct->chip.irq_unmask = irq_gc_mask_clr_bit;
158 ct->chip.irq_set_type = s5p_gpioint_set_type,
159 ct->regs.ack = PEND_OFFSET + REG_OFFSET(chip->group);
160 ct->regs.mask = MASK_OFFSET + REG_OFFSET(chip->group);
161 ct->regs.type = CON_OFFSET + REG_OFFSET(chip->group);
162 irq_setup_generic_chip(gc, IRQ_MSK(chip->chip.ngpio),
163 IRQ_GC_INIT_MASK_CACHE,
164 IRQ_NOREQUEST | IRQ_NOPROBE, 0);
227 return 0; 165 return 0;
228} 166}
229 167
diff --git a/arch/arm/plat-s5p/irq.c b/arch/arm/plat-s5p/irq.c
index 5560b12035d1..a97c08957f49 100644
--- a/arch/arm/plat-s5p/irq.c
+++ b/arch/arm/plat-s5p/irq.c
@@ -64,11 +64,7 @@ void __init s5p_init_irq(u32 *vic, u32 num_vic)
64 vic_init(VA_VIC(irq), VIC_BASE(irq), vic[irq], 0); 64 vic_init(VA_VIC(irq), VIC_BASE(irq), vic[irq], 0);
65#endif 65#endif
66 66
67 s3c_init_vic_timer_irq(IRQ_TIMER0_VIC, IRQ_TIMER0); 67 s3c_init_vic_timer_irq(5, IRQ_TIMER0);
68 s3c_init_vic_timer_irq(IRQ_TIMER1_VIC, IRQ_TIMER1);
69 s3c_init_vic_timer_irq(IRQ_TIMER2_VIC, IRQ_TIMER2);
70 s3c_init_vic_timer_irq(IRQ_TIMER3_VIC, IRQ_TIMER3);
71 s3c_init_vic_timer_irq(IRQ_TIMER4_VIC, IRQ_TIMER4);
72 68
73 s3c_init_uart_irqs(uart_irqs, ARRAY_SIZE(uart_irqs)); 69 s3c_init_uart_irqs(uart_irqs, ARRAY_SIZE(uart_irqs));
74} 70}
diff --git a/arch/arm/plat-s5p/s5p-time.c b/arch/arm/plat-s5p/s5p-time.c
index 8090403eec0f..899a8cc011ff 100644
--- a/arch/arm/plat-s5p/s5p-time.c
+++ b/arch/arm/plat-s5p/s5p-time.c
@@ -290,7 +290,7 @@ static void __init s5p_clockevent_init(void)
290 setup_irq(irq_number, &s5p_clock_event_irq); 290 setup_irq(irq_number, &s5p_clock_event_irq);
291} 291}
292 292
293static cycle_t s5p_timer_read(struct clocksource *cs) 293static void __iomem *s5p_timer_reg(void)
294{ 294{
295 unsigned long offset = 0; 295 unsigned long offset = 0;
296 296
@@ -308,10 +308,17 @@ static cycle_t s5p_timer_read(struct clocksource *cs)
308 308
309 default: 309 default:
310 printk(KERN_ERR "Invalid Timer %d\n", timer_source.source_id); 310 printk(KERN_ERR "Invalid Timer %d\n", timer_source.source_id);
311 return 0; 311 return NULL;
312 } 312 }
313 313
314 return (cycle_t) ~__raw_readl(S3C_TIMERREG(offset)); 314 return S3C_TIMERREG(offset);
315}
316
317static cycle_t s5p_timer_read(struct clocksource *cs)
318{
319 void __iomem *reg = s5p_timer_reg();
320
321 return (cycle_t) (reg ? ~__raw_readl(reg) : 0);
315} 322}
316 323
317/* 324/*
@@ -325,53 +332,22 @@ static DEFINE_CLOCK_DATA(cd);
325 332
326unsigned long long notrace sched_clock(void) 333unsigned long long notrace sched_clock(void)
327{ 334{
328 u32 cyc; 335 void __iomem *reg = s5p_timer_reg();
329 unsigned long offset = 0;
330
331 switch (timer_source.source_id) {
332 case S5P_PWM0:
333 case S5P_PWM1:
334 case S5P_PWM2:
335 case S5P_PWM3:
336 offset = (timer_source.source_id * 0x0c) + 0x14;
337 break;
338
339 case S5P_PWM4:
340 offset = 0x40;
341 break;
342 336
343 default: 337 if (!reg)
344 printk(KERN_ERR "Invalid Timer %d\n", timer_source.source_id);
345 return 0; 338 return 0;
346 }
347 339
348 cyc = ~__raw_readl(S3C_TIMERREG(offset)); 340 return cyc_to_sched_clock(&cd, ~__raw_readl(reg), (u32)~0);
349 return cyc_to_sched_clock(&cd, cyc, (u32)~0);
350} 341}
351 342
352static void notrace s5p_update_sched_clock(void) 343static void notrace s5p_update_sched_clock(void)
353{ 344{
354 u32 cyc; 345 void __iomem *reg = s5p_timer_reg();
355 unsigned long offset = 0;
356 346
357 switch (timer_source.source_id) { 347 if (!reg)
358 case S5P_PWM0: 348 return;
359 case S5P_PWM1:
360 case S5P_PWM2:
361 case S5P_PWM3:
362 offset = (timer_source.source_id * 0x0c) + 0x14;
363 break;
364
365 case S5P_PWM4:
366 offset = 0x40;
367 break;
368
369 default:
370 printk(KERN_ERR "Invalid Timer %d\n", timer_source.source_id);
371 }
372 349
373 cyc = ~__raw_readl(S3C_TIMERREG(offset)); 350 update_sched_clock(&cd, ~__raw_readl(reg), (u32)~0);
374 update_sched_clock(&cd, cyc, (u32)~0);
375} 351}
376 352
377struct clocksource time_clocksource = { 353struct clocksource time_clocksource = {