Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * linux/arch/arm/mach-h720x/common.c | |
3 | * | |
4 | * Copyright (C) 2003 Thomas Gleixner <tglx@linutronix.de> | |
5 | * 2003 Robert Schwebel <r.schwebel@pengutronix.de> | |
6 | * 2004 Sascha Hauer <s.hauer@pengutronix.de> | |
7 | * | |
8 | * common stuff for Hynix h720x processors | |
9 | * | |
10 | * This program is free software; you can redistribute it and/or modify | |
11 | * it under the terms of the GNU General Public License version 2 as | |
12 | * published by the Free Software Foundation. | |
13 | * | |
14 | */ | |
15 | ||
16 | #include <linux/sched.h> | |
1da177e4 LT |
17 | #include <linux/mman.h> |
18 | #include <linux/init.h> | |
19 | #include <linux/interrupt.h> | |
fced80c7 | 20 | #include <linux/io.h> |
1da177e4 LT |
21 | |
22 | #include <asm/page.h> | |
23 | #include <asm/pgtable.h> | |
24 | #include <asm/dma.h> | |
a09e64fb | 25 | #include <mach/hardware.h> |
1da177e4 LT |
26 | #include <asm/irq.h> |
27 | #include <asm/mach/irq.h> | |
28 | #include <asm/mach/map.h> | |
a09e64fb | 29 | #include <mach/irqs.h> |
1da177e4 LT |
30 | |
31 | #include <asm/mach/dma.h> | |
32 | ||
33 | #if 0 | |
34 | #define IRQDBG(args...) printk(args) | |
35 | #else | |
36 | #define IRQDBG(args...) do {} while(0) | |
37 | #endif | |
38 | ||
39 | void __init arch_dma_init(dma_t *dma) | |
40 | { | |
41 | } | |
42 | ||
43 | /* | |
44 | * Return usecs since last timer reload | |
45 | * (timercount * (usecs perjiffie)) / (ticks per jiffie) | |
46 | */ | |
47 | unsigned long h720x_gettimeoffset(void) | |
48 | { | |
49 | return (CPU_REG (TIMER_VIRT, TM0_COUNT) * tick_usec) / LATCH; | |
50 | } | |
51 | ||
52 | /* | |
53 | * mask Global irq's | |
54 | */ | |
c971ab0d | 55 | static void mask_global_irq(struct irq_data *d) |
1da177e4 | 56 | { |
c971ab0d | 57 | CPU_REG (IRQC_VIRT, IRQC_IER) &= ~(1 << d->irq); |
1da177e4 LT |
58 | } |
59 | ||
60 | /* | |
61 | * unmask Global irq's | |
62 | */ | |
c971ab0d | 63 | static void unmask_global_irq(struct irq_data *d) |
1da177e4 | 64 | { |
c971ab0d | 65 | CPU_REG (IRQC_VIRT, IRQC_IER) |= (1 << d->irq); |
1da177e4 LT |
66 | } |
67 | ||
68 | ||
69 | /* | |
70 | * ack GPIO irq's | |
71 | * Ack only for edge triggered int's valid | |
72 | */ | |
c971ab0d | 73 | static void inline ack_gpio_irq(struct irq_data *d) |
1da177e4 | 74 | { |
c971ab0d LB |
75 | u32 reg_base = GPIO_VIRT(IRQ_TO_REGNO(d->irq)); |
76 | u32 bit = IRQ_TO_BIT(d->irq); | |
1da177e4 LT |
77 | if ( (CPU_REG (reg_base, GPIO_EDGE) & bit)) |
78 | CPU_REG (reg_base, GPIO_CLR) = bit; | |
79 | } | |
80 | ||
81 | /* | |
82 | * mask GPIO irq's | |
83 | */ | |
c971ab0d | 84 | static void inline mask_gpio_irq(struct irq_data *d) |
1da177e4 | 85 | { |
c971ab0d LB |
86 | u32 reg_base = GPIO_VIRT(IRQ_TO_REGNO(d->irq)); |
87 | u32 bit = IRQ_TO_BIT(d->irq); | |
1da177e4 LT |
88 | CPU_REG (reg_base, GPIO_MASK) &= ~bit; |
89 | } | |
90 | ||
91 | /* | |
92 | * unmask GPIO irq's | |
93 | */ | |
c971ab0d | 94 | static void inline unmask_gpio_irq(struct irq_data *d) |
1da177e4 | 95 | { |
c971ab0d LB |
96 | u32 reg_base = GPIO_VIRT(IRQ_TO_REGNO(d->irq)); |
97 | u32 bit = IRQ_TO_BIT(d->irq); | |
1da177e4 LT |
98 | CPU_REG (reg_base, GPIO_MASK) |= bit; |
99 | } | |
100 | ||
101 | static void | |
102 | h720x_gpio_handler(unsigned int mask, unsigned int irq, | |
10dd5ce2 | 103 | struct irq_desc *desc) |
1da177e4 | 104 | { |
8e86f427 | 105 | IRQDBG("%s irq: %d\n", __func__, irq); |
1da177e4 LT |
106 | while (mask) { |
107 | if (mask & 1) { | |
108 | IRQDBG("handling irq %d\n", irq); | |
d8aa0251 | 109 | generic_handle_irq(irq); |
1da177e4 LT |
110 | } |
111 | irq++; | |
1da177e4 LT |
112 | mask >>= 1; |
113 | } | |
114 | } | |
115 | ||
116 | static void | |
10dd5ce2 | 117 | h720x_gpioa_demux_handler(unsigned int irq_unused, struct irq_desc *desc) |
1da177e4 LT |
118 | { |
119 | unsigned int mask, irq; | |
120 | ||
121 | mask = CPU_REG(GPIO_A_VIRT,GPIO_STAT); | |
122 | irq = IRQ_CHAINED_GPIOA(0); | |
8e86f427 | 123 | IRQDBG("%s mask: 0x%08x irq: %d\n", __func__, mask,irq); |
0cd61b68 | 124 | h720x_gpio_handler(mask, irq, desc); |
1da177e4 LT |
125 | } |
126 | ||
127 | static void | |
10dd5ce2 | 128 | h720x_gpiob_demux_handler(unsigned int irq_unused, struct irq_desc *desc) |
1da177e4 LT |
129 | { |
130 | unsigned int mask, irq; | |
131 | mask = CPU_REG(GPIO_B_VIRT,GPIO_STAT); | |
132 | irq = IRQ_CHAINED_GPIOB(0); | |
8e86f427 | 133 | IRQDBG("%s mask: 0x%08x irq: %d\n", __func__, mask,irq); |
0cd61b68 | 134 | h720x_gpio_handler(mask, irq, desc); |
1da177e4 LT |
135 | } |
136 | ||
137 | static void | |
10dd5ce2 | 138 | h720x_gpioc_demux_handler(unsigned int irq_unused, struct irq_desc *desc) |
1da177e4 LT |
139 | { |
140 | unsigned int mask, irq; | |
141 | ||
142 | mask = CPU_REG(GPIO_C_VIRT,GPIO_STAT); | |
143 | irq = IRQ_CHAINED_GPIOC(0); | |
8e86f427 | 144 | IRQDBG("%s mask: 0x%08x irq: %d\n", __func__, mask,irq); |
0cd61b68 | 145 | h720x_gpio_handler(mask, irq, desc); |
1da177e4 LT |
146 | } |
147 | ||
148 | static void | |
10dd5ce2 | 149 | h720x_gpiod_demux_handler(unsigned int irq_unused, struct irq_desc *desc) |
1da177e4 LT |
150 | { |
151 | unsigned int mask, irq; | |
152 | ||
153 | mask = CPU_REG(GPIO_D_VIRT,GPIO_STAT); | |
154 | irq = IRQ_CHAINED_GPIOD(0); | |
8e86f427 | 155 | IRQDBG("%s mask: 0x%08x irq: %d\n", __func__, mask,irq); |
0cd61b68 | 156 | h720x_gpio_handler(mask, irq, desc); |
1da177e4 LT |
157 | } |
158 | ||
159 | #ifdef CONFIG_CPU_H7202 | |
160 | static void | |
10dd5ce2 | 161 | h720x_gpioe_demux_handler(unsigned int irq_unused, struct irq_desc *desc) |
1da177e4 LT |
162 | { |
163 | unsigned int mask, irq; | |
164 | ||
165 | mask = CPU_REG(GPIO_E_VIRT,GPIO_STAT); | |
166 | irq = IRQ_CHAINED_GPIOE(0); | |
8e86f427 | 167 | IRQDBG("%s mask: 0x%08x irq: %d\n", __func__, mask,irq); |
0cd61b68 | 168 | h720x_gpio_handler(mask, irq, desc); |
1da177e4 LT |
169 | } |
170 | #endif | |
171 | ||
10dd5ce2 | 172 | static struct irq_chip h720x_global_chip = { |
c971ab0d LB |
173 | .irq_ack = mask_global_irq, |
174 | .irq_mask = mask_global_irq, | |
175 | .irq_unmask = unmask_global_irq, | |
1da177e4 LT |
176 | }; |
177 | ||
10dd5ce2 | 178 | static struct irq_chip h720x_gpio_chip = { |
c971ab0d LB |
179 | .irq_ack = ack_gpio_irq, |
180 | .irq_mask = mask_gpio_irq, | |
181 | .irq_unmask = unmask_gpio_irq, | |
1da177e4 LT |
182 | }; |
183 | ||
184 | /* | |
185 | * Initialize IRQ's, mask all, enable multiplexed irq's | |
186 | */ | |
187 | void __init h720x_init_irq (void) | |
188 | { | |
189 | int irq; | |
190 | ||
191 | /* Mask global irq's */ | |
192 | CPU_REG (IRQC_VIRT, IRQC_IER) = 0x0; | |
193 | ||
194 | /* Mask all multiplexed irq's */ | |
195 | CPU_REG (GPIO_A_VIRT, GPIO_MASK) = 0x0; | |
196 | CPU_REG (GPIO_B_VIRT, GPIO_MASK) = 0x0; | |
197 | CPU_REG (GPIO_C_VIRT, GPIO_MASK) = 0x0; | |
198 | CPU_REG (GPIO_D_VIRT, GPIO_MASK) = 0x0; | |
199 | ||
200 | /* Initialize global IRQ's, fast path */ | |
201 | for (irq = 0; irq < NR_GLBL_IRQS; irq++) { | |
f38c02f3 TG |
202 | irq_set_chip_and_handler(irq, &h720x_global_chip, |
203 | handle_level_irq); | |
1da177e4 LT |
204 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); |
205 | } | |
206 | ||
207 | /* Initialize multiplexed IRQ's, slow path */ | |
208 | for (irq = IRQ_CHAINED_GPIOA(0) ; irq <= IRQ_CHAINED_GPIOD(31); irq++) { | |
f38c02f3 TG |
209 | irq_set_chip_and_handler(irq, &h720x_gpio_chip, |
210 | handle_edge_irq); | |
1da177e4 LT |
211 | set_irq_flags(irq, IRQF_VALID ); |
212 | } | |
6845664a TG |
213 | irq_set_chained_handler(IRQ_GPIOA, h720x_gpioa_demux_handler); |
214 | irq_set_chained_handler(IRQ_GPIOB, h720x_gpiob_demux_handler); | |
215 | irq_set_chained_handler(IRQ_GPIOC, h720x_gpioc_demux_handler); | |
216 | irq_set_chained_handler(IRQ_GPIOD, h720x_gpiod_demux_handler); | |
1da177e4 LT |
217 | |
218 | #ifdef CONFIG_CPU_H7202 | |
219 | for (irq = IRQ_CHAINED_GPIOE(0) ; irq <= IRQ_CHAINED_GPIOE(31); irq++) { | |
f38c02f3 TG |
220 | irq_set_chip_and_handler(irq, &h720x_gpio_chip, |
221 | handle_edge_irq); | |
1da177e4 LT |
222 | set_irq_flags(irq, IRQF_VALID ); |
223 | } | |
6845664a | 224 | irq_set_chained_handler(IRQ_GPIOE, h720x_gpioe_demux_handler); |
1da177e4 LT |
225 | #endif |
226 | ||
227 | /* Enable multiplexed irq's */ | |
228 | CPU_REG (IRQC_VIRT, IRQC_IER) = IRQ_ENA_MUX; | |
229 | } | |
230 | ||
231 | static struct map_desc h720x_io_desc[] __initdata = { | |
3e9635e4 DS |
232 | { |
233 | .virtual = IO_VIRT, | |
234 | .pfn = __phys_to_pfn(IO_PHYS), | |
235 | .length = IO_SIZE, | |
236 | .type = MT_DEVICE | |
237 | }, | |
1da177e4 LT |
238 | }; |
239 | ||
240 | /* Initialize io tables */ | |
241 | void __init h720x_map_io(void) | |
242 | { | |
243 | iotable_init(h720x_io_desc,ARRAY_SIZE(h720x_io_desc)); | |
244 | } | |
0d68370b RK |
245 | |
246 | void h720x_restart(char mode, const char *cmd) | |
247 | { | |
248 | CPU_REG (PMU_BASE, PMU_STAT) |= PMU_WARMRESET; | |
249 | } | |
50edbf78 NP |
250 | |
251 | static void h720x__idle(void) | |
252 | { | |
253 | CPU_REG (PMU_BASE, PMU_MODE) = PMU_MODE_IDLE; | |
254 | nop(); | |
255 | nop(); | |
256 | CPU_REG (PMU_BASE, PMU_MODE) = PMU_MODE_RUN; | |
257 | nop(); | |
258 | nop(); | |
259 | } | |
260 | ||
261 | static int __init h720x_idle_init(void) | |
262 | { | |
263 | arm_pm_idle = h720x__idle; | |
264 | return 0; | |
265 | } | |
266 | ||
267 | arch_initcall(h720x_idle_init); |