diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /arch/arm/common | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'arch/arm/common')
-rw-r--r-- | arch/arm/common/clkdev.c | 13 | ||||
-rw-r--r-- | arch/arm/common/dmabounce.c | 37 | ||||
-rw-r--r-- | arch/arm/common/it8152.c | 28 | ||||
-rw-r--r-- | arch/arm/common/locomo.c | 372 | ||||
-rw-r--r-- | arch/arm/common/sa1111.c | 112 | ||||
-rw-r--r-- | arch/arm/common/scoop.c | 4 | ||||
-rw-r--r-- | arch/arm/common/vic.c | 265 |
7 files changed, 295 insertions, 536 deletions
diff --git a/arch/arm/common/clkdev.c b/arch/arm/common/clkdev.c index aae5bc01acc8..dba4c1da63ed 100644 --- a/arch/arm/common/clkdev.c +++ b/arch/arm/common/clkdev.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/string.h> | 18 | #include <linux/string.h> |
19 | #include <linux/mutex.h> | 19 | #include <linux/mutex.h> |
20 | #include <linux/clk.h> | 20 | #include <linux/clk.h> |
21 | #include <linux/slab.h> | ||
21 | 22 | ||
22 | #include <asm/clkdev.h> | 23 | #include <asm/clkdev.h> |
23 | #include <mach/clkdev.h> | 24 | #include <mach/clkdev.h> |
@@ -32,7 +33,7 @@ static DEFINE_MUTEX(clocks_mutex); | |||
32 | * If an entry has a device ID, it must match | 33 | * If an entry has a device ID, it must match |
33 | * If an entry has a connection ID, it must match | 34 | * If an entry has a connection ID, it must match |
34 | * Then we take the most specific entry - with the following | 35 | * Then we take the most specific entry - with the following |
35 | * order of precidence: dev+con > dev only > con only. | 36 | * order of precedence: dev+con > dev only > con only. |
36 | */ | 37 | */ |
37 | static struct clk *clk_find(const char *dev_id, const char *con_id) | 38 | static struct clk *clk_find(const char *dev_id, const char *con_id) |
38 | { | 39 | { |
@@ -99,6 +100,16 @@ void clkdev_add(struct clk_lookup *cl) | |||
99 | } | 100 | } |
100 | EXPORT_SYMBOL(clkdev_add); | 101 | EXPORT_SYMBOL(clkdev_add); |
101 | 102 | ||
103 | void __init clkdev_add_table(struct clk_lookup *cl, size_t num) | ||
104 | { | ||
105 | mutex_lock(&clocks_mutex); | ||
106 | while (num--) { | ||
107 | list_add_tail(&cl->node, &clocks); | ||
108 | cl++; | ||
109 | } | ||
110 | mutex_unlock(&clocks_mutex); | ||
111 | } | ||
112 | |||
102 | #define MAX_DEV_ID 20 | 113 | #define MAX_DEV_ID 20 |
103 | #define MAX_CON_ID 16 | 114 | #define MAX_CON_ID 16 |
104 | 115 | ||
diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c index 734ac9135998..cc0a932bbea9 100644 --- a/arch/arm/common/dmabounce.c +++ b/arch/arm/common/dmabounce.c | |||
@@ -277,7 +277,7 @@ static inline dma_addr_t map_single(struct device *dev, void *ptr, size_t size, | |||
277 | * We don't need to sync the DMA buffer since | 277 | * We don't need to sync the DMA buffer since |
278 | * it was allocated via the coherent allocators. | 278 | * it was allocated via the coherent allocators. |
279 | */ | 279 | */ |
280 | dma_cache_maint(ptr, size, dir); | 280 | __dma_single_cpu_to_dev(ptr, size, dir); |
281 | } | 281 | } |
282 | 282 | ||
283 | return dma_addr; | 283 | return dma_addr; |
@@ -308,17 +308,15 @@ static inline void unmap_single(struct device *dev, dma_addr_t dma_addr, | |||
308 | memcpy(ptr, buf->safe, size); | 308 | memcpy(ptr, buf->safe, size); |
309 | 309 | ||
310 | /* | 310 | /* |
311 | * DMA buffers must have the same cache properties | 311 | * Since we may have written to a page cache page, |
312 | * as if they were really used for DMA - which means | 312 | * we need to ensure that the data will be coherent |
313 | * data must be written back to RAM. Note that | 313 | * with user mappings. |
314 | * we don't use dmac_flush_range() here for the | ||
315 | * bidirectional case because we know the cache | ||
316 | * lines will be coherent with the data written. | ||
317 | */ | 314 | */ |
318 | dmac_clean_range(ptr, ptr + size); | 315 | __cpuc_flush_dcache_area(ptr, size); |
319 | outer_clean_range(__pa(ptr), __pa(ptr) + size); | ||
320 | } | 316 | } |
321 | free_safe_buffer(dev->archdata.dmabounce, buf); | 317 | free_safe_buffer(dev->archdata.dmabounce, buf); |
318 | } else { | ||
319 | __dma_single_dev_to_cpu(dma_to_virt(dev, dma_addr), size, dir); | ||
322 | } | 320 | } |
323 | } | 321 | } |
324 | 322 | ||
@@ -342,6 +340,22 @@ dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size, | |||
342 | } | 340 | } |
343 | EXPORT_SYMBOL(dma_map_single); | 341 | EXPORT_SYMBOL(dma_map_single); |
344 | 342 | ||
343 | /* | ||
344 | * see if a mapped address was really a "safe" buffer and if so, copy | ||
345 | * the data from the safe buffer back to the unsafe buffer and free up | ||
346 | * the safe buffer. (basically return things back to the way they | ||
347 | * should be) | ||
348 | */ | ||
349 | void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, | ||
350 | enum dma_data_direction dir) | ||
351 | { | ||
352 | dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n", | ||
353 | __func__, (void *) dma_addr, size, dir); | ||
354 | |||
355 | unmap_single(dev, dma_addr, size, dir); | ||
356 | } | ||
357 | EXPORT_SYMBOL(dma_unmap_single); | ||
358 | |||
345 | dma_addr_t dma_map_page(struct device *dev, struct page *page, | 359 | dma_addr_t dma_map_page(struct device *dev, struct page *page, |
346 | unsigned long offset, size_t size, enum dma_data_direction dir) | 360 | unsigned long offset, size_t size, enum dma_data_direction dir) |
347 | { | 361 | { |
@@ -366,8 +380,7 @@ EXPORT_SYMBOL(dma_map_page); | |||
366 | * the safe buffer. (basically return things back to the way they | 380 | * the safe buffer. (basically return things back to the way they |
367 | * should be) | 381 | * should be) |
368 | */ | 382 | */ |
369 | 383 | void dma_unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size, | |
370 | void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, | ||
371 | enum dma_data_direction dir) | 384 | enum dma_data_direction dir) |
372 | { | 385 | { |
373 | dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n", | 386 | dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n", |
@@ -375,7 +388,7 @@ void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, | |||
375 | 388 | ||
376 | unmap_single(dev, dma_addr, size, dir); | 389 | unmap_single(dev, dma_addr, size, dir); |
377 | } | 390 | } |
378 | EXPORT_SYMBOL(dma_unmap_single); | 391 | EXPORT_SYMBOL(dma_unmap_page); |
379 | 392 | ||
380 | int dmabounce_sync_for_cpu(struct device *dev, dma_addr_t addr, | 393 | int dmabounce_sync_for_cpu(struct device *dev, dma_addr_t addr, |
381 | unsigned long off, size_t sz, enum dma_data_direction dir) | 394 | unsigned long off, size_t sz, enum dma_data_direction dir) |
diff --git a/arch/arm/common/it8152.c b/arch/arm/common/it8152.c index 2793447621c3..7974baacafce 100644 --- a/arch/arm/common/it8152.c +++ b/arch/arm/common/it8152.c | |||
@@ -21,7 +21,6 @@ | |||
21 | #include <linux/ptrace.h> | 21 | #include <linux/ptrace.h> |
22 | #include <linux/interrupt.h> | 22 | #include <linux/interrupt.h> |
23 | #include <linux/mm.h> | 23 | #include <linux/mm.h> |
24 | #include <linux/slab.h> | ||
25 | #include <linux/init.h> | 24 | #include <linux/init.h> |
26 | #include <linux/ioport.h> | 25 | #include <linux/ioport.h> |
27 | #include <linux/irq.h> | 26 | #include <linux/irq.h> |
@@ -272,33 +271,6 @@ int dma_needs_bounce(struct device *dev, dma_addr_t dma_addr, size_t size) | |||
272 | ((dma_addr + size - PHYS_OFFSET) >= SZ_64M); | 271 | ((dma_addr + size - PHYS_OFFSET) >= SZ_64M); |
273 | } | 272 | } |
274 | 273 | ||
275 | /* | ||
276 | * We override these so we properly do dmabounce otherwise drivers | ||
277 | * are able to set the dma_mask to 0xffffffff and we can no longer | ||
278 | * trap bounces. :( | ||
279 | * | ||
280 | * We just return true on everyhing except for < 64MB in which case | ||
281 | * we will fail miseralby and die since we can't handle that case. | ||
282 | */ | ||
283 | int pci_set_dma_mask(struct pci_dev *dev, u64 mask) | ||
284 | { | ||
285 | dev_dbg(&dev->dev, "%s: %llx\n", __func__, mask); | ||
286 | if (mask >= PHYS_OFFSET + SZ_64M - 1) | ||
287 | return 0; | ||
288 | |||
289 | return -EIO; | ||
290 | } | ||
291 | |||
292 | int | ||
293 | pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask) | ||
294 | { | ||
295 | dev_dbg(&dev->dev, "%s: %llx\n", __func__, mask); | ||
296 | if (mask >= PHYS_OFFSET + SZ_64M - 1) | ||
297 | return 0; | ||
298 | |||
299 | return -EIO; | ||
300 | } | ||
301 | |||
302 | int __init it8152_pci_setup(int nr, struct pci_sys_data *sys) | 274 | int __init it8152_pci_setup(int nr, struct pci_sys_data *sys) |
303 | { | 275 | { |
304 | it8152_io.start = IT8152_IO_BASE + 0x12000; | 276 | it8152_io.start = IT8152_IO_BASE + 0x12000; |
diff --git a/arch/arm/common/locomo.c b/arch/arm/common/locomo.c index bd36c778c819..9dff07c80ddb 100644 --- a/arch/arm/common/locomo.c +++ b/arch/arm/common/locomo.c | |||
@@ -32,6 +32,12 @@ | |||
32 | 32 | ||
33 | #include <asm/hardware/locomo.h> | 33 | #include <asm/hardware/locomo.h> |
34 | 34 | ||
35 | /* LoCoMo Interrupts */ | ||
36 | #define IRQ_LOCOMO_KEY (0) | ||
37 | #define IRQ_LOCOMO_GPIO (1) | ||
38 | #define IRQ_LOCOMO_LT (2) | ||
39 | #define IRQ_LOCOMO_SPI (3) | ||
40 | |||
35 | /* M62332 output channel selection */ | 41 | /* M62332 output channel selection */ |
36 | #define M62332_EVR_CH 1 /* M62332 volume channel number */ | 42 | #define M62332_EVR_CH 1 /* M62332 volume channel number */ |
37 | /* 0 : CH.1 , 1 : CH. 2 */ | 43 | /* 0 : CH.1 , 1 : CH. 2 */ |
@@ -58,6 +64,7 @@ struct locomo { | |||
58 | struct device *dev; | 64 | struct device *dev; |
59 | unsigned long phys; | 65 | unsigned long phys; |
60 | unsigned int irq; | 66 | unsigned int irq; |
67 | int irq_base; | ||
61 | spinlock_t lock; | 68 | spinlock_t lock; |
62 | void __iomem *base; | 69 | void __iomem *base; |
63 | #ifdef CONFIG_PM | 70 | #ifdef CONFIG_PM |
@@ -81,9 +88,7 @@ struct locomo_dev_info { | |||
81 | static struct locomo_dev_info locomo_devices[] = { | 88 | static struct locomo_dev_info locomo_devices[] = { |
82 | { | 89 | { |
83 | .devid = LOCOMO_DEVID_KEYBOARD, | 90 | .devid = LOCOMO_DEVID_KEYBOARD, |
84 | .irq = { | 91 | .irq = { IRQ_LOCOMO_KEY }, |
85 | IRQ_LOCOMO_KEY, | ||
86 | }, | ||
87 | .name = "locomo-keyboard", | 92 | .name = "locomo-keyboard", |
88 | .offset = LOCOMO_KEYBOARD, | 93 | .offset = LOCOMO_KEYBOARD, |
89 | .length = 16, | 94 | .length = 16, |
@@ -133,53 +138,20 @@ static struct locomo_dev_info locomo_devices[] = { | |||
133 | }, | 138 | }, |
134 | }; | 139 | }; |
135 | 140 | ||
136 | |||
137 | /** LoCoMo interrupt handling stuff. | ||
138 | * NOTE: LoCoMo has a 1 to many mapping on all of its IRQs. | ||
139 | * that is, there is only one real hardware interrupt | ||
140 | * we determine which interrupt it is by reading some IO memory. | ||
141 | * We have two levels of expansion, first in the handler for the | ||
142 | * hardware interrupt we generate an interrupt | ||
143 | * IRQ_LOCOMO_*_BASE and those handlers generate more interrupts | ||
144 | * | ||
145 | * hardware irq reads LOCOMO_ICR & 0x0f00 | ||
146 | * IRQ_LOCOMO_KEY_BASE | ||
147 | * IRQ_LOCOMO_GPIO_BASE | ||
148 | * IRQ_LOCOMO_LT_BASE | ||
149 | * IRQ_LOCOMO_SPI_BASE | ||
150 | * IRQ_LOCOMO_KEY_BASE reads LOCOMO_KIC & 0x0001 | ||
151 | * IRQ_LOCOMO_KEY | ||
152 | * IRQ_LOCOMO_GPIO_BASE reads LOCOMO_GIR & LOCOMO_GPD & 0xffff | ||
153 | * IRQ_LOCOMO_GPIO[0-15] | ||
154 | * IRQ_LOCOMO_LT_BASE reads LOCOMO_LTINT & 0x0001 | ||
155 | * IRQ_LOCOMO_LT | ||
156 | * IRQ_LOCOMO_SPI_BASE reads LOCOMO_SPIIR & 0x000F | ||
157 | * IRQ_LOCOMO_SPI_RFR | ||
158 | * IRQ_LOCOMO_SPI_RFW | ||
159 | * IRQ_LOCOMO_SPI_OVRN | ||
160 | * IRQ_LOCOMO_SPI_TEND | ||
161 | */ | ||
162 | |||
163 | #define LOCOMO_IRQ_START (IRQ_LOCOMO_KEY_BASE) | ||
164 | #define LOCOMO_IRQ_KEY_START (IRQ_LOCOMO_KEY) | ||
165 | #define LOCOMO_IRQ_GPIO_START (IRQ_LOCOMO_GPIO0) | ||
166 | #define LOCOMO_IRQ_LT_START (IRQ_LOCOMO_LT) | ||
167 | #define LOCOMO_IRQ_SPI_START (IRQ_LOCOMO_SPI_RFR) | ||
168 | |||
169 | static void locomo_handler(unsigned int irq, struct irq_desc *desc) | 141 | static void locomo_handler(unsigned int irq, struct irq_desc *desc) |
170 | { | 142 | { |
143 | struct locomo *lchip = get_irq_chip_data(irq); | ||
171 | int req, i; | 144 | int req, i; |
172 | void __iomem *mapbase = get_irq_chip_data(irq); | ||
173 | 145 | ||
174 | /* Acknowledge the parent IRQ */ | 146 | /* Acknowledge the parent IRQ */ |
175 | desc->chip->ack(irq); | 147 | desc->chip->ack(irq); |
176 | 148 | ||
177 | /* check why this interrupt was generated */ | 149 | /* check why this interrupt was generated */ |
178 | req = locomo_readl(mapbase + LOCOMO_ICR) & 0x0f00; | 150 | req = locomo_readl(lchip->base + LOCOMO_ICR) & 0x0f00; |
179 | 151 | ||
180 | if (req) { | 152 | if (req) { |
181 | /* generate the next interrupt(s) */ | 153 | /* generate the next interrupt(s) */ |
182 | irq = LOCOMO_IRQ_START; | 154 | irq = lchip->irq_base; |
183 | for (i = 0; i <= 3; i++, irq++) { | 155 | for (i = 0; i <= 3; i++, irq++) { |
184 | if (req & (0x0100 << i)) { | 156 | if (req & (0x0100 << i)) { |
185 | generic_handle_irq(irq); | 157 | generic_handle_irq(irq); |
@@ -195,20 +167,20 @@ static void locomo_ack_irq(unsigned int irq) | |||
195 | 167 | ||
196 | static void locomo_mask_irq(unsigned int irq) | 168 | static void locomo_mask_irq(unsigned int irq) |
197 | { | 169 | { |
198 | void __iomem *mapbase = get_irq_chip_data(irq); | 170 | struct locomo *lchip = get_irq_chip_data(irq); |
199 | unsigned int r; | 171 | unsigned int r; |
200 | r = locomo_readl(mapbase + LOCOMO_ICR); | 172 | r = locomo_readl(lchip->base + LOCOMO_ICR); |
201 | r &= ~(0x0010 << (irq - LOCOMO_IRQ_START)); | 173 | r &= ~(0x0010 << (irq - lchip->irq_base)); |
202 | locomo_writel(r, mapbase + LOCOMO_ICR); | 174 | locomo_writel(r, lchip->base + LOCOMO_ICR); |
203 | } | 175 | } |
204 | 176 | ||
205 | static void locomo_unmask_irq(unsigned int irq) | 177 | static void locomo_unmask_irq(unsigned int irq) |
206 | { | 178 | { |
207 | void __iomem *mapbase = get_irq_chip_data(irq); | 179 | struct locomo *lchip = get_irq_chip_data(irq); |
208 | unsigned int r; | 180 | unsigned int r; |
209 | r = locomo_readl(mapbase + LOCOMO_ICR); | 181 | r = locomo_readl(lchip->base + LOCOMO_ICR); |
210 | r |= (0x0010 << (irq - LOCOMO_IRQ_START)); | 182 | r |= (0x0010 << (irq - lchip->irq_base)); |
211 | locomo_writel(r, mapbase + LOCOMO_ICR); | 183 | locomo_writel(r, lchip->base + LOCOMO_ICR); |
212 | } | 184 | } |
213 | 185 | ||
214 | static struct irq_chip locomo_chip = { | 186 | static struct irq_chip locomo_chip = { |
@@ -218,297 +190,22 @@ static struct irq_chip locomo_chip = { | |||
218 | .unmask = locomo_unmask_irq, | 190 | .unmask = locomo_unmask_irq, |
219 | }; | 191 | }; |
220 | 192 | ||
221 | static void locomo_key_handler(unsigned int irq, struct irq_desc *desc) | ||
222 | { | ||
223 | void __iomem *mapbase = get_irq_chip_data(irq); | ||
224 | |||
225 | if (locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC) & 0x0001) { | ||
226 | generic_handle_irq(LOCOMO_IRQ_KEY_START); | ||
227 | } | ||
228 | } | ||
229 | |||
230 | static void locomo_key_ack_irq(unsigned int irq) | ||
231 | { | ||
232 | void __iomem *mapbase = get_irq_chip_data(irq); | ||
233 | unsigned int r; | ||
234 | r = locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC); | ||
235 | r &= ~(0x0100 << (irq - LOCOMO_IRQ_KEY_START)); | ||
236 | locomo_writel(r, mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC); | ||
237 | } | ||
238 | |||
239 | static void locomo_key_mask_irq(unsigned int irq) | ||
240 | { | ||
241 | void __iomem *mapbase = get_irq_chip_data(irq); | ||
242 | unsigned int r; | ||
243 | r = locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC); | ||
244 | r &= ~(0x0010 << (irq - LOCOMO_IRQ_KEY_START)); | ||
245 | locomo_writel(r, mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC); | ||
246 | } | ||
247 | |||
248 | static void locomo_key_unmask_irq(unsigned int irq) | ||
249 | { | ||
250 | void __iomem *mapbase = get_irq_chip_data(irq); | ||
251 | unsigned int r; | ||
252 | r = locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC); | ||
253 | r |= (0x0010 << (irq - LOCOMO_IRQ_KEY_START)); | ||
254 | locomo_writel(r, mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC); | ||
255 | } | ||
256 | |||
257 | static struct irq_chip locomo_key_chip = { | ||
258 | .name = "LOCOMO-key", | ||
259 | .ack = locomo_key_ack_irq, | ||
260 | .mask = locomo_key_mask_irq, | ||
261 | .unmask = locomo_key_unmask_irq, | ||
262 | }; | ||
263 | |||
264 | static void locomo_gpio_handler(unsigned int irq, struct irq_desc *desc) | ||
265 | { | ||
266 | int req, i; | ||
267 | void __iomem *mapbase = get_irq_chip_data(irq); | ||
268 | |||
269 | req = locomo_readl(mapbase + LOCOMO_GIR) & | ||
270 | locomo_readl(mapbase + LOCOMO_GPD) & | ||
271 | 0xffff; | ||
272 | |||
273 | if (req) { | ||
274 | irq = LOCOMO_IRQ_GPIO_START; | ||
275 | for (i = 0; i <= 15; i++, irq++) { | ||
276 | if (req & (0x0001 << i)) { | ||
277 | generic_handle_irq(irq); | ||
278 | } | ||
279 | } | ||
280 | } | ||
281 | } | ||
282 | |||
283 | static void locomo_gpio_ack_irq(unsigned int irq) | ||
284 | { | ||
285 | void __iomem *mapbase = get_irq_chip_data(irq); | ||
286 | unsigned int r; | ||
287 | r = locomo_readl(mapbase + LOCOMO_GWE); | ||
288 | r |= (0x0001 << (irq - LOCOMO_IRQ_GPIO_START)); | ||
289 | locomo_writel(r, mapbase + LOCOMO_GWE); | ||
290 | |||
291 | r = locomo_readl(mapbase + LOCOMO_GIS); | ||
292 | r &= ~(0x0001 << (irq - LOCOMO_IRQ_GPIO_START)); | ||
293 | locomo_writel(r, mapbase + LOCOMO_GIS); | ||
294 | |||
295 | r = locomo_readl(mapbase + LOCOMO_GWE); | ||
296 | r &= ~(0x0001 << (irq - LOCOMO_IRQ_GPIO_START)); | ||
297 | locomo_writel(r, mapbase + LOCOMO_GWE); | ||
298 | } | ||
299 | |||
300 | static void locomo_gpio_mask_irq(unsigned int irq) | ||
301 | { | ||
302 | void __iomem *mapbase = get_irq_chip_data(irq); | ||
303 | unsigned int r; | ||
304 | r = locomo_readl(mapbase + LOCOMO_GIE); | ||
305 | r &= ~(0x0001 << (irq - LOCOMO_IRQ_GPIO_START)); | ||
306 | locomo_writel(r, mapbase + LOCOMO_GIE); | ||
307 | } | ||
308 | |||
309 | static void locomo_gpio_unmask_irq(unsigned int irq) | ||
310 | { | ||
311 | void __iomem *mapbase = get_irq_chip_data(irq); | ||
312 | unsigned int r; | ||
313 | r = locomo_readl(mapbase + LOCOMO_GIE); | ||
314 | r |= (0x0001 << (irq - LOCOMO_IRQ_GPIO_START)); | ||
315 | locomo_writel(r, mapbase + LOCOMO_GIE); | ||
316 | } | ||
317 | |||
318 | static int GPIO_IRQ_rising_edge; | ||
319 | static int GPIO_IRQ_falling_edge; | ||
320 | |||
321 | static int locomo_gpio_type(unsigned int irq, unsigned int type) | ||
322 | { | ||
323 | unsigned int mask; | ||
324 | void __iomem *mapbase = get_irq_chip_data(irq); | ||
325 | |||
326 | mask = 1 << (irq - LOCOMO_IRQ_GPIO_START); | ||
327 | |||
328 | if (type == IRQ_TYPE_PROBE) { | ||
329 | if ((GPIO_IRQ_rising_edge | GPIO_IRQ_falling_edge) & mask) | ||
330 | return 0; | ||
331 | type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING; | ||
332 | } | ||
333 | |||
334 | if (type & IRQ_TYPE_EDGE_RISING) | ||
335 | GPIO_IRQ_rising_edge |= mask; | ||
336 | else | ||
337 | GPIO_IRQ_rising_edge &= ~mask; | ||
338 | if (type & IRQ_TYPE_EDGE_FALLING) | ||
339 | GPIO_IRQ_falling_edge |= mask; | ||
340 | else | ||
341 | GPIO_IRQ_falling_edge &= ~mask; | ||
342 | locomo_writel(GPIO_IRQ_rising_edge, mapbase + LOCOMO_GRIE); | ||
343 | locomo_writel(GPIO_IRQ_falling_edge, mapbase + LOCOMO_GFIE); | ||
344 | |||
345 | return 0; | ||
346 | } | ||
347 | |||
348 | static struct irq_chip locomo_gpio_chip = { | ||
349 | .name = "LOCOMO-gpio", | ||
350 | .ack = locomo_gpio_ack_irq, | ||
351 | .mask = locomo_gpio_mask_irq, | ||
352 | .unmask = locomo_gpio_unmask_irq, | ||
353 | .set_type = locomo_gpio_type, | ||
354 | }; | ||
355 | |||
356 | static void locomo_lt_handler(unsigned int irq, struct irq_desc *desc) | ||
357 | { | ||
358 | void __iomem *mapbase = get_irq_chip_data(irq); | ||
359 | |||
360 | if (locomo_readl(mapbase + LOCOMO_LTINT) & 0x0001) { | ||
361 | generic_handle_irq(LOCOMO_IRQ_LT_START); | ||
362 | } | ||
363 | } | ||
364 | |||
365 | static void locomo_lt_ack_irq(unsigned int irq) | ||
366 | { | ||
367 | void __iomem *mapbase = get_irq_chip_data(irq); | ||
368 | unsigned int r; | ||
369 | r = locomo_readl(mapbase + LOCOMO_LTINT); | ||
370 | r &= ~(0x0100 << (irq - LOCOMO_IRQ_LT_START)); | ||
371 | locomo_writel(r, mapbase + LOCOMO_LTINT); | ||
372 | } | ||
373 | |||
374 | static void locomo_lt_mask_irq(unsigned int irq) | ||
375 | { | ||
376 | void __iomem *mapbase = get_irq_chip_data(irq); | ||
377 | unsigned int r; | ||
378 | r = locomo_readl(mapbase + LOCOMO_LTINT); | ||
379 | r &= ~(0x0010 << (irq - LOCOMO_IRQ_LT_START)); | ||
380 | locomo_writel(r, mapbase + LOCOMO_LTINT); | ||
381 | } | ||
382 | |||
383 | static void locomo_lt_unmask_irq(unsigned int irq) | ||
384 | { | ||
385 | void __iomem *mapbase = get_irq_chip_data(irq); | ||
386 | unsigned int r; | ||
387 | r = locomo_readl(mapbase + LOCOMO_LTINT); | ||
388 | r |= (0x0010 << (irq - LOCOMO_IRQ_LT_START)); | ||
389 | locomo_writel(r, mapbase + LOCOMO_LTINT); | ||
390 | } | ||
391 | |||
392 | static struct irq_chip locomo_lt_chip = { | ||
393 | .name = "LOCOMO-lt", | ||
394 | .ack = locomo_lt_ack_irq, | ||
395 | .mask = locomo_lt_mask_irq, | ||
396 | .unmask = locomo_lt_unmask_irq, | ||
397 | }; | ||
398 | |||
399 | static void locomo_spi_handler(unsigned int irq, struct irq_desc *desc) | ||
400 | { | ||
401 | int req, i; | ||
402 | void __iomem *mapbase = get_irq_chip_data(irq); | ||
403 | |||
404 | req = locomo_readl(mapbase + LOCOMO_SPI + LOCOMO_SPIIR) & 0x000F; | ||
405 | if (req) { | ||
406 | irq = LOCOMO_IRQ_SPI_START; | ||
407 | |||
408 | for (i = 0; i <= 3; i++, irq++) { | ||
409 | if (req & (0x0001 << i)) { | ||
410 | generic_handle_irq(irq); | ||
411 | } | ||
412 | } | ||
413 | } | ||
414 | } | ||
415 | |||
416 | static void locomo_spi_ack_irq(unsigned int irq) | ||
417 | { | ||
418 | void __iomem *mapbase = get_irq_chip_data(irq); | ||
419 | unsigned int r; | ||
420 | r = locomo_readl(mapbase + LOCOMO_SPI + LOCOMO_SPIWE); | ||
421 | r |= (0x0001 << (irq - LOCOMO_IRQ_SPI_START)); | ||
422 | locomo_writel(r, mapbase + LOCOMO_SPI + LOCOMO_SPIWE); | ||
423 | |||
424 | r = locomo_readl(mapbase + LOCOMO_SPI + LOCOMO_SPIIS); | ||
425 | r &= ~(0x0001 << (irq - LOCOMO_IRQ_SPI_START)); | ||
426 | locomo_writel(r, mapbase + LOCOMO_SPI + LOCOMO_SPIIS); | ||
427 | |||
428 | r = locomo_readl(mapbase + LOCOMO_SPI + LOCOMO_SPIWE); | ||
429 | r &= ~(0x0001 << (irq - LOCOMO_IRQ_SPI_START)); | ||
430 | locomo_writel(r, mapbase + LOCOMO_SPI + LOCOMO_SPIWE); | ||
431 | } | ||
432 | |||
433 | static void locomo_spi_mask_irq(unsigned int irq) | ||
434 | { | ||
435 | void __iomem *mapbase = get_irq_chip_data(irq); | ||
436 | unsigned int r; | ||
437 | r = locomo_readl(mapbase + LOCOMO_SPI + LOCOMO_SPIIE); | ||
438 | r &= ~(0x0001 << (irq - LOCOMO_IRQ_SPI_START)); | ||
439 | locomo_writel(r, mapbase + LOCOMO_SPI + LOCOMO_SPIIE); | ||
440 | } | ||
441 | |||
442 | static void locomo_spi_unmask_irq(unsigned int irq) | ||
443 | { | ||
444 | void __iomem *mapbase = get_irq_chip_data(irq); | ||
445 | unsigned int r; | ||
446 | r = locomo_readl(mapbase + LOCOMO_SPI + LOCOMO_SPIIE); | ||
447 | r |= (0x0001 << (irq - LOCOMO_IRQ_SPI_START)); | ||
448 | locomo_writel(r, mapbase + LOCOMO_SPI + LOCOMO_SPIIE); | ||
449 | } | ||
450 | |||
451 | static struct irq_chip locomo_spi_chip = { | ||
452 | .name = "LOCOMO-spi", | ||
453 | .ack = locomo_spi_ack_irq, | ||
454 | .mask = locomo_spi_mask_irq, | ||
455 | .unmask = locomo_spi_unmask_irq, | ||
456 | }; | ||
457 | |||
458 | static void locomo_setup_irq(struct locomo *lchip) | 193 | static void locomo_setup_irq(struct locomo *lchip) |
459 | { | 194 | { |
460 | int irq; | 195 | int irq = lchip->irq_base; |
461 | void __iomem *irqbase = lchip->base; | ||
462 | 196 | ||
463 | /* | 197 | /* |
464 | * Install handler for IRQ_LOCOMO_HW. | 198 | * Install handler for IRQ_LOCOMO_HW. |
465 | */ | 199 | */ |
466 | set_irq_type(lchip->irq, IRQ_TYPE_EDGE_FALLING); | 200 | set_irq_type(lchip->irq, IRQ_TYPE_EDGE_FALLING); |
467 | set_irq_chip_data(lchip->irq, irqbase); | 201 | set_irq_chip_data(lchip->irq, lchip); |
468 | set_irq_chained_handler(lchip->irq, locomo_handler); | 202 | set_irq_chained_handler(lchip->irq, locomo_handler); |
469 | 203 | ||
470 | /* Install handlers for IRQ_LOCOMO_*_BASE */ | 204 | /* Install handlers for IRQ_LOCOMO_* */ |
471 | set_irq_chip(IRQ_LOCOMO_KEY_BASE, &locomo_chip); | 205 | for ( ; irq <= lchip->irq_base + 3; irq++) { |
472 | set_irq_chip_data(IRQ_LOCOMO_KEY_BASE, irqbase); | 206 | set_irq_chip(irq, &locomo_chip); |
473 | set_irq_chained_handler(IRQ_LOCOMO_KEY_BASE, locomo_key_handler); | 207 | set_irq_chip_data(irq, lchip); |
474 | 208 | set_irq_handler(irq, handle_level_irq); | |
475 | set_irq_chip(IRQ_LOCOMO_GPIO_BASE, &locomo_chip); | ||
476 | set_irq_chip_data(IRQ_LOCOMO_GPIO_BASE, irqbase); | ||
477 | set_irq_chained_handler(IRQ_LOCOMO_GPIO_BASE, locomo_gpio_handler); | ||
478 | |||
479 | set_irq_chip(IRQ_LOCOMO_LT_BASE, &locomo_chip); | ||
480 | set_irq_chip_data(IRQ_LOCOMO_LT_BASE, irqbase); | ||
481 | set_irq_chained_handler(IRQ_LOCOMO_LT_BASE, locomo_lt_handler); | ||
482 | |||
483 | set_irq_chip(IRQ_LOCOMO_SPI_BASE, &locomo_chip); | ||
484 | set_irq_chip_data(IRQ_LOCOMO_SPI_BASE, irqbase); | ||
485 | set_irq_chained_handler(IRQ_LOCOMO_SPI_BASE, locomo_spi_handler); | ||
486 | |||
487 | /* install handlers for IRQ_LOCOMO_KEY_BASE generated interrupts */ | ||
488 | set_irq_chip(LOCOMO_IRQ_KEY_START, &locomo_key_chip); | ||
489 | set_irq_chip_data(LOCOMO_IRQ_KEY_START, irqbase); | ||
490 | set_irq_handler(LOCOMO_IRQ_KEY_START, handle_edge_irq); | ||
491 | set_irq_flags(LOCOMO_IRQ_KEY_START, IRQF_VALID | IRQF_PROBE); | ||
492 | |||
493 | /* install handlers for IRQ_LOCOMO_GPIO_BASE generated interrupts */ | ||
494 | for (irq = LOCOMO_IRQ_GPIO_START; irq < LOCOMO_IRQ_GPIO_START + 16; irq++) { | ||
495 | set_irq_chip(irq, &locomo_gpio_chip); | ||
496 | set_irq_chip_data(irq, irqbase); | ||
497 | set_irq_handler(irq, handle_edge_irq); | ||
498 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); | ||
499 | } | ||
500 | |||
501 | /* install handlers for IRQ_LOCOMO_LT_BASE generated interrupts */ | ||
502 | set_irq_chip(LOCOMO_IRQ_LT_START, &locomo_lt_chip); | ||
503 | set_irq_chip_data(LOCOMO_IRQ_LT_START, irqbase); | ||
504 | set_irq_handler(LOCOMO_IRQ_LT_START, handle_edge_irq); | ||
505 | set_irq_flags(LOCOMO_IRQ_LT_START, IRQF_VALID | IRQF_PROBE); | ||
506 | |||
507 | /* install handlers for IRQ_LOCOMO_SPI_BASE generated interrupts */ | ||
508 | for (irq = LOCOMO_IRQ_SPI_START; irq < LOCOMO_IRQ_SPI_START + 4; irq++) { | ||
509 | set_irq_chip(irq, &locomo_spi_chip); | ||
510 | set_irq_chip_data(irq, irqbase); | ||
511 | set_irq_handler(irq, handle_edge_irq); | ||
512 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); | 209 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); |
513 | } | 210 | } |
514 | } | 211 | } |
@@ -555,7 +252,8 @@ locomo_init_one_child(struct locomo *lchip, struct locomo_dev_info *info) | |||
555 | dev->mapbase = 0; | 252 | dev->mapbase = 0; |
556 | dev->length = info->length; | 253 | dev->length = info->length; |
557 | 254 | ||
558 | memmove(dev->irq, info->irq, sizeof(dev->irq)); | 255 | dev->irq[0] = (lchip->irq_base == NO_IRQ) ? |
256 | NO_IRQ : lchip->irq_base + info->irq[0]; | ||
559 | 257 | ||
560 | ret = device_register(&dev->dev); | 258 | ret = device_register(&dev->dev); |
561 | if (ret) { | 259 | if (ret) { |
@@ -592,7 +290,7 @@ static int locomo_suspend(struct platform_device *dev, pm_message_t state) | |||
592 | save->LCM_GPO = locomo_readl(lchip->base + LOCOMO_GPO); /* GPIO */ | 290 | save->LCM_GPO = locomo_readl(lchip->base + LOCOMO_GPO); /* GPIO */ |
593 | locomo_writel(0x00, lchip->base + LOCOMO_GPO); | 291 | locomo_writel(0x00, lchip->base + LOCOMO_GPO); |
594 | save->LCM_SPICT = locomo_readl(lchip->base + LOCOMO_SPI + LOCOMO_SPICT); /* SPI */ | 292 | save->LCM_SPICT = locomo_readl(lchip->base + LOCOMO_SPI + LOCOMO_SPICT); /* SPI */ |
595 | locomo_writel(0x40, lchip->base + LOCOMO_SPICT); | 293 | locomo_writel(0x40, lchip->base + LOCOMO_SPI + LOCOMO_SPICT); |
596 | save->LCM_GPE = locomo_readl(lchip->base + LOCOMO_GPE); /* GPIO */ | 294 | save->LCM_GPE = locomo_readl(lchip->base + LOCOMO_GPE); /* GPIO */ |
597 | locomo_writel(0x00, lchip->base + LOCOMO_GPE); | 295 | locomo_writel(0x00, lchip->base + LOCOMO_GPE); |
598 | save->LCM_ASD = locomo_readl(lchip->base + LOCOMO_ASD); /* ADSTART */ | 296 | save->LCM_ASD = locomo_readl(lchip->base + LOCOMO_ASD); /* ADSTART */ |
@@ -672,6 +370,7 @@ static int locomo_resume(struct platform_device *dev) | |||
672 | static int | 370 | static int |
673 | __locomo_probe(struct device *me, struct resource *mem, int irq) | 371 | __locomo_probe(struct device *me, struct resource *mem, int irq) |
674 | { | 372 | { |
373 | struct locomo_platform_data *pdata = me->platform_data; | ||
675 | struct locomo *lchip; | 374 | struct locomo *lchip; |
676 | unsigned long r; | 375 | unsigned long r; |
677 | int i, ret = -ENODEV; | 376 | int i, ret = -ENODEV; |
@@ -687,6 +386,7 @@ __locomo_probe(struct device *me, struct resource *mem, int irq) | |||
687 | 386 | ||
688 | lchip->phys = mem->start; | 387 | lchip->phys = mem->start; |
689 | lchip->irq = irq; | 388 | lchip->irq = irq; |
389 | lchip->irq_base = (pdata) ? pdata->irq_base : NO_IRQ; | ||
690 | 390 | ||
691 | /* | 391 | /* |
692 | * Map the whole region. This also maps the | 392 | * Map the whole region. This also maps the |
@@ -718,7 +418,7 @@ __locomo_probe(struct device *me, struct resource *mem, int irq) | |||
718 | /* Longtime timer */ | 418 | /* Longtime timer */ |
719 | locomo_writel(0, lchip->base + LOCOMO_LTINT); | 419 | locomo_writel(0, lchip->base + LOCOMO_LTINT); |
720 | /* SPI */ | 420 | /* SPI */ |
721 | locomo_writel(0, lchip->base + LOCOMO_SPIIE); | 421 | locomo_writel(0, lchip->base + LOCOMO_SPI + LOCOMO_SPIIE); |
722 | 422 | ||
723 | locomo_writel(6 + 8 + 320 + 30 - 10, lchip->base + LOCOMO_ASD); | 423 | locomo_writel(6 + 8 + 320 + 30 - 10, lchip->base + LOCOMO_ASD); |
724 | r = locomo_readl(lchip->base + LOCOMO_ASD); | 424 | r = locomo_readl(lchip->base + LOCOMO_ASD); |
@@ -753,7 +453,7 @@ __locomo_probe(struct device *me, struct resource *mem, int irq) | |||
753 | * The interrupt controller must be initialised before any | 453 | * The interrupt controller must be initialised before any |
754 | * other device to ensure that the interrupts are available. | 454 | * other device to ensure that the interrupts are available. |
755 | */ | 455 | */ |
756 | if (lchip->irq != NO_IRQ) | 456 | if (lchip->irq != NO_IRQ && lchip->irq_base != NO_IRQ) |
757 | locomo_setup_irq(lchip); | 457 | locomo_setup_irq(lchip); |
758 | 458 | ||
759 | for (i = 0; i < ARRAY_SIZE(locomo_devices); i++) | 459 | for (i = 0; i < ARRAY_SIZE(locomo_devices); i++) |
@@ -1007,7 +707,7 @@ void locomo_m62332_senddata(struct locomo_dev *ldev, unsigned int dac_data, int | |||
1007 | udelay(DAC_SCL_HIGH_HOLD_TIME); /* 4.7 usec */ | 707 | udelay(DAC_SCL_HIGH_HOLD_TIME); /* 4.7 usec */ |
1008 | if (locomo_readl(mapbase + LOCOMO_DAC) & LOCOMO_DAC_SDAOEB) { /* High is error */ | 708 | if (locomo_readl(mapbase + LOCOMO_DAC) & LOCOMO_DAC_SDAOEB) { /* High is error */ |
1009 | printk(KERN_WARNING "locomo: m62332_senddata Error 1\n"); | 709 | printk(KERN_WARNING "locomo: m62332_senddata Error 1\n"); |
1010 | return; | 710 | goto out; |
1011 | } | 711 | } |
1012 | 712 | ||
1013 | /* Send Sub address (LSB is channel select) */ | 713 | /* Send Sub address (LSB is channel select) */ |
@@ -1035,7 +735,7 @@ void locomo_m62332_senddata(struct locomo_dev *ldev, unsigned int dac_data, int | |||
1035 | udelay(DAC_SCL_HIGH_HOLD_TIME); /* 4.7 usec */ | 735 | udelay(DAC_SCL_HIGH_HOLD_TIME); /* 4.7 usec */ |
1036 | if (locomo_readl(mapbase + LOCOMO_DAC) & LOCOMO_DAC_SDAOEB) { /* High is error */ | 736 | if (locomo_readl(mapbase + LOCOMO_DAC) & LOCOMO_DAC_SDAOEB) { /* High is error */ |
1037 | printk(KERN_WARNING "locomo: m62332_senddata Error 2\n"); | 737 | printk(KERN_WARNING "locomo: m62332_senddata Error 2\n"); |
1038 | return; | 738 | goto out; |
1039 | } | 739 | } |
1040 | 740 | ||
1041 | /* Send DAC data */ | 741 | /* Send DAC data */ |
@@ -1060,9 +760,9 @@ void locomo_m62332_senddata(struct locomo_dev *ldev, unsigned int dac_data, int | |||
1060 | udelay(DAC_SCL_HIGH_HOLD_TIME); /* 4.7 usec */ | 760 | udelay(DAC_SCL_HIGH_HOLD_TIME); /* 4.7 usec */ |
1061 | if (locomo_readl(mapbase + LOCOMO_DAC) & LOCOMO_DAC_SDAOEB) { /* High is error */ | 761 | if (locomo_readl(mapbase + LOCOMO_DAC) & LOCOMO_DAC_SDAOEB) { /* High is error */ |
1062 | printk(KERN_WARNING "locomo: m62332_senddata Error 3\n"); | 762 | printk(KERN_WARNING "locomo: m62332_senddata Error 3\n"); |
1063 | return; | ||
1064 | } | 763 | } |
1065 | 764 | ||
765 | out: | ||
1066 | /* stop */ | 766 | /* stop */ |
1067 | r = locomo_readl(mapbase + LOCOMO_DAC); | 767 | r = locomo_readl(mapbase + LOCOMO_DAC); |
1068 | r &= ~(LOCOMO_DAC_SCLOEB); | 768 | r &= ~(LOCOMO_DAC_SCLOEB); |
diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c index 8ba7044c554d..a52a27c1d9be 100644 --- a/arch/arm/common/sa1111.c +++ b/arch/arm/common/sa1111.c | |||
@@ -35,6 +35,58 @@ | |||
35 | 35 | ||
36 | #include <asm/hardware/sa1111.h> | 36 | #include <asm/hardware/sa1111.h> |
37 | 37 | ||
38 | /* SA1111 IRQs */ | ||
39 | #define IRQ_GPAIN0 (0) | ||
40 | #define IRQ_GPAIN1 (1) | ||
41 | #define IRQ_GPAIN2 (2) | ||
42 | #define IRQ_GPAIN3 (3) | ||
43 | #define IRQ_GPBIN0 (4) | ||
44 | #define IRQ_GPBIN1 (5) | ||
45 | #define IRQ_GPBIN2 (6) | ||
46 | #define IRQ_GPBIN3 (7) | ||
47 | #define IRQ_GPBIN4 (8) | ||
48 | #define IRQ_GPBIN5 (9) | ||
49 | #define IRQ_GPCIN0 (10) | ||
50 | #define IRQ_GPCIN1 (11) | ||
51 | #define IRQ_GPCIN2 (12) | ||
52 | #define IRQ_GPCIN3 (13) | ||
53 | #define IRQ_GPCIN4 (14) | ||
54 | #define IRQ_GPCIN5 (15) | ||
55 | #define IRQ_GPCIN6 (16) | ||
56 | #define IRQ_GPCIN7 (17) | ||
57 | #define IRQ_MSTXINT (18) | ||
58 | #define IRQ_MSRXINT (19) | ||
59 | #define IRQ_MSSTOPERRINT (20) | ||
60 | #define IRQ_TPTXINT (21) | ||
61 | #define IRQ_TPRXINT (22) | ||
62 | #define IRQ_TPSTOPERRINT (23) | ||
63 | #define SSPXMTINT (24) | ||
64 | #define SSPRCVINT (25) | ||
65 | #define SSPROR (26) | ||
66 | #define AUDXMTDMADONEA (32) | ||
67 | #define AUDRCVDMADONEA (33) | ||
68 | #define AUDXMTDMADONEB (34) | ||
69 | #define AUDRCVDMADONEB (35) | ||
70 | #define AUDTFSR (36) | ||
71 | #define AUDRFSR (37) | ||
72 | #define AUDTUR (38) | ||
73 | #define AUDROR (39) | ||
74 | #define AUDDTS (40) | ||
75 | #define AUDRDD (41) | ||
76 | #define AUDSTO (42) | ||
77 | #define IRQ_USBPWR (43) | ||
78 | #define IRQ_HCIM (44) | ||
79 | #define IRQ_HCIBUFFACC (45) | ||
80 | #define IRQ_HCIRMTWKP (46) | ||
81 | #define IRQ_NHCIMFCIR (47) | ||
82 | #define IRQ_USB_PORT_RESUME (48) | ||
83 | #define IRQ_S0_READY_NINT (49) | ||
84 | #define IRQ_S1_READY_NINT (50) | ||
85 | #define IRQ_S0_CD_VALID (51) | ||
86 | #define IRQ_S1_CD_VALID (52) | ||
87 | #define IRQ_S0_BVD1_STSCHG (53) | ||
88 | #define IRQ_S1_BVD1_STSCHG (54) | ||
89 | |||
38 | extern void __init sa1110_mb_enable(void); | 90 | extern void __init sa1110_mb_enable(void); |
39 | 91 | ||
40 | /* | 92 | /* |
@@ -49,6 +101,7 @@ struct sa1111 { | |||
49 | struct clk *clk; | 101 | struct clk *clk; |
50 | unsigned long phys; | 102 | unsigned long phys; |
51 | int irq; | 103 | int irq; |
104 | int irq_base; /* base for cascaded on-chip IRQs */ | ||
52 | spinlock_t lock; | 105 | spinlock_t lock; |
53 | void __iomem *base; | 106 | void __iomem *base; |
54 | #ifdef CONFIG_PM | 107 | #ifdef CONFIG_PM |
@@ -152,36 +205,37 @@ static void | |||
152 | sa1111_irq_handler(unsigned int irq, struct irq_desc *desc) | 205 | sa1111_irq_handler(unsigned int irq, struct irq_desc *desc) |
153 | { | 206 | { |
154 | unsigned int stat0, stat1, i; | 207 | unsigned int stat0, stat1, i; |
155 | void __iomem *base = get_irq_data(irq); | 208 | struct sa1111 *sachip = get_irq_data(irq); |
209 | void __iomem *mapbase = sachip->base + SA1111_INTC; | ||
156 | 210 | ||
157 | stat0 = sa1111_readl(base + SA1111_INTSTATCLR0); | 211 | stat0 = sa1111_readl(mapbase + SA1111_INTSTATCLR0); |
158 | stat1 = sa1111_readl(base + SA1111_INTSTATCLR1); | 212 | stat1 = sa1111_readl(mapbase + SA1111_INTSTATCLR1); |
159 | 213 | ||
160 | sa1111_writel(stat0, base + SA1111_INTSTATCLR0); | 214 | sa1111_writel(stat0, mapbase + SA1111_INTSTATCLR0); |
161 | 215 | ||
162 | desc->chip->ack(irq); | 216 | desc->chip->ack(irq); |
163 | 217 | ||
164 | sa1111_writel(stat1, base + SA1111_INTSTATCLR1); | 218 | sa1111_writel(stat1, mapbase + SA1111_INTSTATCLR1); |
165 | 219 | ||
166 | if (stat0 == 0 && stat1 == 0) { | 220 | if (stat0 == 0 && stat1 == 0) { |
167 | do_bad_IRQ(irq, desc); | 221 | do_bad_IRQ(irq, desc); |
168 | return; | 222 | return; |
169 | } | 223 | } |
170 | 224 | ||
171 | for (i = IRQ_SA1111_START; stat0; i++, stat0 >>= 1) | 225 | for (i = 0; stat0; i++, stat0 >>= 1) |
172 | if (stat0 & 1) | 226 | if (stat0 & 1) |
173 | handle_edge_irq(i, irq_desc + i); | 227 | generic_handle_irq(i + sachip->irq_base); |
174 | 228 | ||
175 | for (i = IRQ_SA1111_START + 32; stat1; i++, stat1 >>= 1) | 229 | for (i = 32; stat1; i++, stat1 >>= 1) |
176 | if (stat1 & 1) | 230 | if (stat1 & 1) |
177 | handle_edge_irq(i, irq_desc + i); | 231 | generic_handle_irq(i + sachip->irq_base); |
178 | 232 | ||
179 | /* For level-based interrupts */ | 233 | /* For level-based interrupts */ |
180 | desc->chip->unmask(irq); | 234 | desc->chip->unmask(irq); |
181 | } | 235 | } |
182 | 236 | ||
183 | #define SA1111_IRQMASK_LO(x) (1 << (x - IRQ_SA1111_START)) | 237 | #define SA1111_IRQMASK_LO(x) (1 << (x - sachip->irq_base)) |
184 | #define SA1111_IRQMASK_HI(x) (1 << (x - IRQ_SA1111_START - 32)) | 238 | #define SA1111_IRQMASK_HI(x) (1 << (x - sachip->irq_base - 32)) |
185 | 239 | ||
186 | static void sa1111_ack_irq(unsigned int irq) | 240 | static void sa1111_ack_irq(unsigned int irq) |
187 | { | 241 | { |
@@ -189,7 +243,8 @@ static void sa1111_ack_irq(unsigned int irq) | |||
189 | 243 | ||
190 | static void sa1111_mask_lowirq(unsigned int irq) | 244 | static void sa1111_mask_lowirq(unsigned int irq) |
191 | { | 245 | { |
192 | void __iomem *mapbase = get_irq_chip_data(irq); | 246 | struct sa1111 *sachip = get_irq_chip_data(irq); |
247 | void __iomem *mapbase = sachip->base + SA1111_INTC; | ||
193 | unsigned long ie0; | 248 | unsigned long ie0; |
194 | 249 | ||
195 | ie0 = sa1111_readl(mapbase + SA1111_INTEN0); | 250 | ie0 = sa1111_readl(mapbase + SA1111_INTEN0); |
@@ -199,7 +254,8 @@ static void sa1111_mask_lowirq(unsigned int irq) | |||
199 | 254 | ||
200 | static void sa1111_unmask_lowirq(unsigned int irq) | 255 | static void sa1111_unmask_lowirq(unsigned int irq) |
201 | { | 256 | { |
202 | void __iomem *mapbase = get_irq_chip_data(irq); | 257 | struct sa1111 *sachip = get_irq_chip_data(irq); |
258 | void __iomem *mapbase = sachip->base + SA1111_INTC; | ||
203 | unsigned long ie0; | 259 | unsigned long ie0; |
204 | 260 | ||
205 | ie0 = sa1111_readl(mapbase + SA1111_INTEN0); | 261 | ie0 = sa1111_readl(mapbase + SA1111_INTEN0); |
@@ -216,8 +272,9 @@ static void sa1111_unmask_lowirq(unsigned int irq) | |||
216 | */ | 272 | */ |
217 | static int sa1111_retrigger_lowirq(unsigned int irq) | 273 | static int sa1111_retrigger_lowirq(unsigned int irq) |
218 | { | 274 | { |
275 | struct sa1111 *sachip = get_irq_chip_data(irq); | ||
276 | void __iomem *mapbase = sachip->base + SA1111_INTC; | ||
219 | unsigned int mask = SA1111_IRQMASK_LO(irq); | 277 | unsigned int mask = SA1111_IRQMASK_LO(irq); |
220 | void __iomem *mapbase = get_irq_chip_data(irq); | ||
221 | unsigned long ip0; | 278 | unsigned long ip0; |
222 | int i; | 279 | int i; |
223 | 280 | ||
@@ -237,8 +294,9 @@ static int sa1111_retrigger_lowirq(unsigned int irq) | |||
237 | 294 | ||
238 | static int sa1111_type_lowirq(unsigned int irq, unsigned int flags) | 295 | static int sa1111_type_lowirq(unsigned int irq, unsigned int flags) |
239 | { | 296 | { |
297 | struct sa1111 *sachip = get_irq_chip_data(irq); | ||
298 | void __iomem *mapbase = sachip->base + SA1111_INTC; | ||
240 | unsigned int mask = SA1111_IRQMASK_LO(irq); | 299 | unsigned int mask = SA1111_IRQMASK_LO(irq); |
241 | void __iomem *mapbase = get_irq_chip_data(irq); | ||
242 | unsigned long ip0; | 300 | unsigned long ip0; |
243 | 301 | ||
244 | if (flags == IRQ_TYPE_PROBE) | 302 | if (flags == IRQ_TYPE_PROBE) |
@@ -260,8 +318,9 @@ static int sa1111_type_lowirq(unsigned int irq, unsigned int flags) | |||
260 | 318 | ||
261 | static int sa1111_wake_lowirq(unsigned int irq, unsigned int on) | 319 | static int sa1111_wake_lowirq(unsigned int irq, unsigned int on) |
262 | { | 320 | { |
321 | struct sa1111 *sachip = get_irq_chip_data(irq); | ||
322 | void __iomem *mapbase = sachip->base + SA1111_INTC; | ||
263 | unsigned int mask = SA1111_IRQMASK_LO(irq); | 323 | unsigned int mask = SA1111_IRQMASK_LO(irq); |
264 | void __iomem *mapbase = get_irq_chip_data(irq); | ||
265 | unsigned long we0; | 324 | unsigned long we0; |
266 | 325 | ||
267 | we0 = sa1111_readl(mapbase + SA1111_WAKEEN0); | 326 | we0 = sa1111_readl(mapbase + SA1111_WAKEEN0); |
@@ -286,7 +345,8 @@ static struct irq_chip sa1111_low_chip = { | |||
286 | 345 | ||
287 | static void sa1111_mask_highirq(unsigned int irq) | 346 | static void sa1111_mask_highirq(unsigned int irq) |
288 | { | 347 | { |
289 | void __iomem *mapbase = get_irq_chip_data(irq); | 348 | struct sa1111 *sachip = get_irq_chip_data(irq); |
349 | void __iomem *mapbase = sachip->base + SA1111_INTC; | ||
290 | unsigned long ie1; | 350 | unsigned long ie1; |
291 | 351 | ||
292 | ie1 = sa1111_readl(mapbase + SA1111_INTEN1); | 352 | ie1 = sa1111_readl(mapbase + SA1111_INTEN1); |
@@ -296,7 +356,8 @@ static void sa1111_mask_highirq(unsigned int irq) | |||
296 | 356 | ||
297 | static void sa1111_unmask_highirq(unsigned int irq) | 357 | static void sa1111_unmask_highirq(unsigned int irq) |
298 | { | 358 | { |
299 | void __iomem *mapbase = get_irq_chip_data(irq); | 359 | struct sa1111 *sachip = get_irq_chip_data(irq); |
360 | void __iomem *mapbase = sachip->base + SA1111_INTC; | ||
300 | unsigned long ie1; | 361 | unsigned long ie1; |
301 | 362 | ||
302 | ie1 = sa1111_readl(mapbase + SA1111_INTEN1); | 363 | ie1 = sa1111_readl(mapbase + SA1111_INTEN1); |
@@ -313,8 +374,9 @@ static void sa1111_unmask_highirq(unsigned int irq) | |||
313 | */ | 374 | */ |
314 | static int sa1111_retrigger_highirq(unsigned int irq) | 375 | static int sa1111_retrigger_highirq(unsigned int irq) |
315 | { | 376 | { |
377 | struct sa1111 *sachip = get_irq_chip_data(irq); | ||
378 | void __iomem *mapbase = sachip->base + SA1111_INTC; | ||
316 | unsigned int mask = SA1111_IRQMASK_HI(irq); | 379 | unsigned int mask = SA1111_IRQMASK_HI(irq); |
317 | void __iomem *mapbase = get_irq_chip_data(irq); | ||
318 | unsigned long ip1; | 380 | unsigned long ip1; |
319 | int i; | 381 | int i; |
320 | 382 | ||
@@ -334,8 +396,9 @@ static int sa1111_retrigger_highirq(unsigned int irq) | |||
334 | 396 | ||
335 | static int sa1111_type_highirq(unsigned int irq, unsigned int flags) | 397 | static int sa1111_type_highirq(unsigned int irq, unsigned int flags) |
336 | { | 398 | { |
399 | struct sa1111 *sachip = get_irq_chip_data(irq); | ||
400 | void __iomem *mapbase = sachip->base + SA1111_INTC; | ||
337 | unsigned int mask = SA1111_IRQMASK_HI(irq); | 401 | unsigned int mask = SA1111_IRQMASK_HI(irq); |
338 | void __iomem *mapbase = get_irq_chip_data(irq); | ||
339 | unsigned long ip1; | 402 | unsigned long ip1; |
340 | 403 | ||
341 | if (flags == IRQ_TYPE_PROBE) | 404 | if (flags == IRQ_TYPE_PROBE) |
@@ -357,8 +420,9 @@ static int sa1111_type_highirq(unsigned int irq, unsigned int flags) | |||
357 | 420 | ||
358 | static int sa1111_wake_highirq(unsigned int irq, unsigned int on) | 421 | static int sa1111_wake_highirq(unsigned int irq, unsigned int on) |
359 | { | 422 | { |
423 | struct sa1111 *sachip = get_irq_chip_data(irq); | ||
424 | void __iomem *mapbase = sachip->base + SA1111_INTC; | ||
360 | unsigned int mask = SA1111_IRQMASK_HI(irq); | 425 | unsigned int mask = SA1111_IRQMASK_HI(irq); |
361 | void __iomem *mapbase = get_irq_chip_data(irq); | ||
362 | unsigned long we1; | 426 | unsigned long we1; |
363 | 427 | ||
364 | we1 = sa1111_readl(mapbase + SA1111_WAKEEN1); | 428 | we1 = sa1111_readl(mapbase + SA1111_WAKEEN1); |
@@ -412,14 +476,14 @@ static void sa1111_setup_irq(struct sa1111 *sachip) | |||
412 | 476 | ||
413 | for (irq = IRQ_GPAIN0; irq <= SSPROR; irq++) { | 477 | for (irq = IRQ_GPAIN0; irq <= SSPROR; irq++) { |
414 | set_irq_chip(irq, &sa1111_low_chip); | 478 | set_irq_chip(irq, &sa1111_low_chip); |
415 | set_irq_chip_data(irq, irqbase); | 479 | set_irq_chip_data(irq, sachip); |
416 | set_irq_handler(irq, handle_edge_irq); | 480 | set_irq_handler(irq, handle_edge_irq); |
417 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); | 481 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); |
418 | } | 482 | } |
419 | 483 | ||
420 | for (irq = AUDXMTDMADONEA; irq <= IRQ_S1_BVD1_STSCHG; irq++) { | 484 | for (irq = AUDXMTDMADONEA; irq <= IRQ_S1_BVD1_STSCHG; irq++) { |
421 | set_irq_chip(irq, &sa1111_high_chip); | 485 | set_irq_chip(irq, &sa1111_high_chip); |
422 | set_irq_chip_data(irq, irqbase); | 486 | set_irq_chip_data(irq, sachip); |
423 | set_irq_handler(irq, handle_edge_irq); | 487 | set_irq_handler(irq, handle_edge_irq); |
424 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); | 488 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); |
425 | } | 489 | } |
@@ -428,7 +492,7 @@ static void sa1111_setup_irq(struct sa1111 *sachip) | |||
428 | * Register SA1111 interrupt | 492 | * Register SA1111 interrupt |
429 | */ | 493 | */ |
430 | set_irq_type(sachip->irq, IRQ_TYPE_EDGE_RISING); | 494 | set_irq_type(sachip->irq, IRQ_TYPE_EDGE_RISING); |
431 | set_irq_data(sachip->irq, irqbase); | 495 | set_irq_data(sachip->irq, sachip); |
432 | set_irq_chained_handler(sachip->irq, sa1111_irq_handler); | 496 | set_irq_chained_handler(sachip->irq, sa1111_irq_handler); |
433 | } | 497 | } |
434 | 498 | ||
diff --git a/arch/arm/common/scoop.c b/arch/arm/common/scoop.c index 7713a08bb10c..9012004321dd 100644 --- a/arch/arm/common/scoop.c +++ b/arch/arm/common/scoop.c | |||
@@ -82,7 +82,7 @@ static int scoop_gpio_get(struct gpio_chip *chip, unsigned offset) | |||
82 | { | 82 | { |
83 | struct scoop_dev *sdev = container_of(chip, struct scoop_dev, gpio); | 83 | struct scoop_dev *sdev = container_of(chip, struct scoop_dev, gpio); |
84 | 84 | ||
85 | /* XXX: I'm usure, but it seems so */ | 85 | /* XXX: I'm unsure, but it seems so */ |
86 | return ioread16(sdev->base + SCOOP_GPRR) & (1 << (offset + 1)); | 86 | return ioread16(sdev->base + SCOOP_GPRR) & (1 << (offset + 1)); |
87 | } | 87 | } |
88 | 88 | ||
@@ -140,6 +140,7 @@ EXPORT_SYMBOL(reset_scoop); | |||
140 | EXPORT_SYMBOL(read_scoop_reg); | 140 | EXPORT_SYMBOL(read_scoop_reg); |
141 | EXPORT_SYMBOL(write_scoop_reg); | 141 | EXPORT_SYMBOL(write_scoop_reg); |
142 | 142 | ||
143 | #ifdef CONFIG_PM | ||
143 | static void check_scoop_reg(struct scoop_dev *sdev) | 144 | static void check_scoop_reg(struct scoop_dev *sdev) |
144 | { | 145 | { |
145 | unsigned short mcr; | 146 | unsigned short mcr; |
@@ -149,7 +150,6 @@ static void check_scoop_reg(struct scoop_dev *sdev) | |||
149 | iowrite16(0x0101, sdev->base + SCOOP_MCR); | 150 | iowrite16(0x0101, sdev->base + SCOOP_MCR); |
150 | } | 151 | } |
151 | 152 | ||
152 | #ifdef CONFIG_PM | ||
153 | static int scoop_suspend(struct platform_device *dev, pm_message_t state) | 153 | static int scoop_suspend(struct platform_device *dev, pm_message_t state) |
154 | { | 154 | { |
155 | struct scoop_dev *sdev = platform_get_drvdata(dev); | 155 | struct scoop_dev *sdev = platform_get_drvdata(dev); |
diff --git a/arch/arm/common/vic.c b/arch/arm/common/vic.c index f232941de8ab..1cf999ade4bc 100644 --- a/arch/arm/common/vic.c +++ b/arch/arm/common/vic.c | |||
@@ -18,6 +18,7 @@ | |||
18 | * along with this program; if not, write to the Free Software | 18 | * along with this program; if not, write to the Free Software |
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
20 | */ | 20 | */ |
21 | |||
21 | #include <linux/init.h> | 22 | #include <linux/init.h> |
22 | #include <linux/list.h> | 23 | #include <linux/list.h> |
23 | #include <linux/io.h> | 24 | #include <linux/io.h> |
@@ -28,48 +29,6 @@ | |||
28 | #include <asm/mach/irq.h> | 29 | #include <asm/mach/irq.h> |
29 | #include <asm/hardware/vic.h> | 30 | #include <asm/hardware/vic.h> |
30 | 31 | ||
31 | static void vic_ack_irq(unsigned int irq) | ||
32 | { | ||
33 | void __iomem *base = get_irq_chip_data(irq); | ||
34 | irq &= 31; | ||
35 | writel(1 << irq, base + VIC_INT_ENABLE_CLEAR); | ||
36 | /* moreover, clear the soft-triggered, in case it was the reason */ | ||
37 | writel(1 << irq, base + VIC_INT_SOFT_CLEAR); | ||
38 | } | ||
39 | |||
40 | static void vic_mask_irq(unsigned int irq) | ||
41 | { | ||
42 | void __iomem *base = get_irq_chip_data(irq); | ||
43 | irq &= 31; | ||
44 | writel(1 << irq, base + VIC_INT_ENABLE_CLEAR); | ||
45 | } | ||
46 | |||
47 | static void vic_unmask_irq(unsigned int irq) | ||
48 | { | ||
49 | void __iomem *base = get_irq_chip_data(irq); | ||
50 | irq &= 31; | ||
51 | writel(1 << irq, base + VIC_INT_ENABLE); | ||
52 | } | ||
53 | |||
54 | /** | ||
55 | * vic_init2 - common initialisation code | ||
56 | * @base: Base of the VIC. | ||
57 | * | ||
58 | * Common initialisation code for registeration | ||
59 | * and resume. | ||
60 | */ | ||
61 | static void vic_init2(void __iomem *base) | ||
62 | { | ||
63 | int i; | ||
64 | |||
65 | for (i = 0; i < 16; i++) { | ||
66 | void __iomem *reg = base + VIC_VECT_CNTL0 + (i * 4); | ||
67 | writel(VIC_VECT_CNTL_ENABLE | i, reg); | ||
68 | } | ||
69 | |||
70 | writel(32, base + VIC_PL190_DEF_VECT_ADDR); | ||
71 | } | ||
72 | |||
73 | #if defined(CONFIG_PM) | 32 | #if defined(CONFIG_PM) |
74 | /** | 33 | /** |
75 | * struct vic_device - VIC PM device | 34 | * struct vic_device - VIC PM device |
@@ -99,13 +58,34 @@ struct vic_device { | |||
99 | /* we cannot allocate memory when VICs are initially registered */ | 58 | /* we cannot allocate memory when VICs are initially registered */ |
100 | static struct vic_device vic_devices[CONFIG_ARM_VIC_NR]; | 59 | static struct vic_device vic_devices[CONFIG_ARM_VIC_NR]; |
101 | 60 | ||
61 | static int vic_id; | ||
62 | |||
102 | static inline struct vic_device *to_vic(struct sys_device *sys) | 63 | static inline struct vic_device *to_vic(struct sys_device *sys) |
103 | { | 64 | { |
104 | return container_of(sys, struct vic_device, sysdev); | 65 | return container_of(sys, struct vic_device, sysdev); |
105 | } | 66 | } |
67 | #endif /* CONFIG_PM */ | ||
106 | 68 | ||
107 | static int vic_id; | 69 | /** |
70 | * vic_init2 - common initialisation code | ||
71 | * @base: Base of the VIC. | ||
72 | * | ||
73 | * Common initialisation code for registeration | ||
74 | * and resume. | ||
75 | */ | ||
76 | static void vic_init2(void __iomem *base) | ||
77 | { | ||
78 | int i; | ||
79 | |||
80 | for (i = 0; i < 16; i++) { | ||
81 | void __iomem *reg = base + VIC_VECT_CNTL0 + (i * 4); | ||
82 | writel(VIC_VECT_CNTL_ENABLE | i, reg); | ||
83 | } | ||
84 | |||
85 | writel(32, base + VIC_PL190_DEF_VECT_ADDR); | ||
86 | } | ||
108 | 87 | ||
88 | #if defined(CONFIG_PM) | ||
109 | static int vic_class_resume(struct sys_device *dev) | 89 | static int vic_class_resume(struct sys_device *dev) |
110 | { | 90 | { |
111 | struct vic_device *vic = to_vic(dev); | 91 | struct vic_device *vic = to_vic(dev); |
@@ -159,31 +139,6 @@ struct sysdev_class vic_class = { | |||
159 | }; | 139 | }; |
160 | 140 | ||
161 | /** | 141 | /** |
162 | * vic_pm_register - Register a VIC for later power management control | ||
163 | * @base: The base address of the VIC. | ||
164 | * @irq: The base IRQ for the VIC. | ||
165 | * @resume_sources: bitmask of interrupts allowed for resume sources. | ||
166 | * | ||
167 | * Register the VIC with the system device tree so that it can be notified | ||
168 | * of suspend and resume requests and ensure that the correct actions are | ||
169 | * taken to re-instate the settings on resume. | ||
170 | */ | ||
171 | static void __init vic_pm_register(void __iomem *base, unsigned int irq, u32 resume_sources) | ||
172 | { | ||
173 | struct vic_device *v; | ||
174 | |||
175 | if (vic_id >= ARRAY_SIZE(vic_devices)) | ||
176 | printk(KERN_ERR "%s: too few VICs, increase CONFIG_ARM_VIC_NR\n", __func__); | ||
177 | else { | ||
178 | v = &vic_devices[vic_id]; | ||
179 | v->base = base; | ||
180 | v->resume_sources = resume_sources; | ||
181 | v->irq = irq; | ||
182 | vic_id++; | ||
183 | } | ||
184 | } | ||
185 | |||
186 | /** | ||
187 | * vic_pm_init - initicall to register VIC pm | 142 | * vic_pm_init - initicall to register VIC pm |
188 | * | 143 | * |
189 | * This is called via late_initcall() to register | 144 | * This is called via late_initcall() to register |
@@ -219,9 +174,60 @@ static int __init vic_pm_init(void) | |||
219 | 174 | ||
220 | return 0; | 175 | return 0; |
221 | } | 176 | } |
222 | |||
223 | late_initcall(vic_pm_init); | 177 | late_initcall(vic_pm_init); |
224 | 178 | ||
179 | /** | ||
180 | * vic_pm_register - Register a VIC for later power management control | ||
181 | * @base: The base address of the VIC. | ||
182 | * @irq: The base IRQ for the VIC. | ||
183 | * @resume_sources: bitmask of interrupts allowed for resume sources. | ||
184 | * | ||
185 | * Register the VIC with the system device tree so that it can be notified | ||
186 | * of suspend and resume requests and ensure that the correct actions are | ||
187 | * taken to re-instate the settings on resume. | ||
188 | */ | ||
189 | static void __init vic_pm_register(void __iomem *base, unsigned int irq, u32 resume_sources) | ||
190 | { | ||
191 | struct vic_device *v; | ||
192 | |||
193 | if (vic_id >= ARRAY_SIZE(vic_devices)) | ||
194 | printk(KERN_ERR "%s: too few VICs, increase CONFIG_ARM_VIC_NR\n", __func__); | ||
195 | else { | ||
196 | v = &vic_devices[vic_id]; | ||
197 | v->base = base; | ||
198 | v->resume_sources = resume_sources; | ||
199 | v->irq = irq; | ||
200 | vic_id++; | ||
201 | } | ||
202 | } | ||
203 | #else | ||
204 | static inline void vic_pm_register(void __iomem *base, unsigned int irq, u32 arg1) { } | ||
205 | #endif /* CONFIG_PM */ | ||
206 | |||
207 | static void vic_ack_irq(unsigned int irq) | ||
208 | { | ||
209 | void __iomem *base = get_irq_chip_data(irq); | ||
210 | irq &= 31; | ||
211 | writel(1 << irq, base + VIC_INT_ENABLE_CLEAR); | ||
212 | /* moreover, clear the soft-triggered, in case it was the reason */ | ||
213 | writel(1 << irq, base + VIC_INT_SOFT_CLEAR); | ||
214 | } | ||
215 | |||
216 | static void vic_mask_irq(unsigned int irq) | ||
217 | { | ||
218 | void __iomem *base = get_irq_chip_data(irq); | ||
219 | irq &= 31; | ||
220 | writel(1 << irq, base + VIC_INT_ENABLE_CLEAR); | ||
221 | } | ||
222 | |||
223 | static void vic_unmask_irq(unsigned int irq) | ||
224 | { | ||
225 | void __iomem *base = get_irq_chip_data(irq); | ||
226 | irq &= 31; | ||
227 | writel(1 << irq, base + VIC_INT_ENABLE); | ||
228 | } | ||
229 | |||
230 | #if defined(CONFIG_PM) | ||
225 | static struct vic_device *vic_from_irq(unsigned int irq) | 231 | static struct vic_device *vic_from_irq(unsigned int irq) |
226 | { | 232 | { |
227 | struct vic_device *v = vic_devices; | 233 | struct vic_device *v = vic_devices; |
@@ -255,10 +261,7 @@ static int vic_set_wake(unsigned int irq, unsigned int on) | |||
255 | 261 | ||
256 | return 0; | 262 | return 0; |
257 | } | 263 | } |
258 | |||
259 | #else | 264 | #else |
260 | static inline void vic_pm_register(void __iomem *base, unsigned int irq, u32 arg1) { } | ||
261 | |||
262 | #define vic_set_wake NULL | 265 | #define vic_set_wake NULL |
263 | #endif /* CONFIG_PM */ | 266 | #endif /* CONFIG_PM */ |
264 | 267 | ||
@@ -270,9 +273,62 @@ static struct irq_chip vic_chip = { | |||
270 | .set_wake = vic_set_wake, | 273 | .set_wake = vic_set_wake, |
271 | }; | 274 | }; |
272 | 275 | ||
273 | /* The PL190 cell from ARM has been modified by ST, so handle both here */ | 276 | /* |
274 | static void vik_init_st(void __iomem *base, unsigned int irq_start, | 277 | * The PL190 cell from ARM has been modified by ST to handle 64 interrupts. |
275 | u32 vic_sources); | 278 | * The original cell has 32 interrupts, while the modified one has 64, |
279 | * replocating two blocks 0x00..0x1f in 0x20..0x3f. In that case | ||
280 | * the probe function is called twice, with base set to offset 000 | ||
281 | * and 020 within the page. We call this "second block". | ||
282 | */ | ||
283 | static void __init vic_init_st(void __iomem *base, unsigned int irq_start, | ||
284 | u32 vic_sources) | ||
285 | { | ||
286 | unsigned int i; | ||
287 | int vic_2nd_block = ((unsigned long)base & ~PAGE_MASK) != 0; | ||
288 | |||
289 | /* Disable all interrupts initially. */ | ||
290 | |||
291 | writel(0, base + VIC_INT_SELECT); | ||
292 | writel(0, base + VIC_INT_ENABLE); | ||
293 | writel(~0, base + VIC_INT_ENABLE_CLEAR); | ||
294 | writel(0, base + VIC_IRQ_STATUS); | ||
295 | writel(0, base + VIC_ITCR); | ||
296 | writel(~0, base + VIC_INT_SOFT_CLEAR); | ||
297 | |||
298 | /* | ||
299 | * Make sure we clear all existing interrupts. The vector registers | ||
300 | * in this cell are after the second block of general registers, | ||
301 | * so we can address them using standard offsets, but only from | ||
302 | * the second base address, which is 0x20 in the page | ||
303 | */ | ||
304 | if (vic_2nd_block) { | ||
305 | writel(0, base + VIC_PL190_VECT_ADDR); | ||
306 | for (i = 0; i < 19; i++) { | ||
307 | unsigned int value; | ||
308 | |||
309 | value = readl(base + VIC_PL190_VECT_ADDR); | ||
310 | writel(value, base + VIC_PL190_VECT_ADDR); | ||
311 | } | ||
312 | /* ST has 16 vectors as well, but we don't enable them by now */ | ||
313 | for (i = 0; i < 16; i++) { | ||
314 | void __iomem *reg = base + VIC_VECT_CNTL0 + (i * 4); | ||
315 | writel(0, reg); | ||
316 | } | ||
317 | |||
318 | writel(32, base + VIC_PL190_DEF_VECT_ADDR); | ||
319 | } | ||
320 | |||
321 | for (i = 0; i < 32; i++) { | ||
322 | if (vic_sources & (1 << i)) { | ||
323 | unsigned int irq = irq_start + i; | ||
324 | |||
325 | set_irq_chip(irq, &vic_chip); | ||
326 | set_irq_chip_data(irq, base); | ||
327 | set_irq_handler(irq, handle_level_irq); | ||
328 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); | ||
329 | } | ||
330 | } | ||
331 | } | ||
276 | 332 | ||
277 | /** | 333 | /** |
278 | * vic_init - initialise a vectored interrupt controller | 334 | * vic_init - initialise a vectored interrupt controller |
@@ -299,7 +355,7 @@ void __init vic_init(void __iomem *base, unsigned int irq_start, | |||
299 | 355 | ||
300 | switch(vendor) { | 356 | switch(vendor) { |
301 | case AMBA_VENDOR_ST: | 357 | case AMBA_VENDOR_ST: |
302 | vik_init_st(base, irq_start, vic_sources); | 358 | vic_init_st(base, irq_start, vic_sources); |
303 | return; | 359 | return; |
304 | default: | 360 | default: |
305 | printk(KERN_WARNING "VIC: unknown vendor, continuing anyways\n"); | 361 | printk(KERN_WARNING "VIC: unknown vendor, continuing anyways\n"); |
@@ -343,60 +399,3 @@ void __init vic_init(void __iomem *base, unsigned int irq_start, | |||
343 | 399 | ||
344 | vic_pm_register(base, irq_start, resume_sources); | 400 | vic_pm_register(base, irq_start, resume_sources); |
345 | } | 401 | } |
346 | |||
347 | /* | ||
348 | * The PL190 cell from ARM has been modified by ST to handle 64 interrupts. | ||
349 | * The original cell has 32 interrupts, while the modified one has 64, | ||
350 | * replocating two blocks 0x00..0x1f in 0x20..0x3f. In that case | ||
351 | * the probe function is called twice, with base set to offset 000 | ||
352 | * and 020 within the page. We call this "second block". | ||
353 | */ | ||
354 | static void __init vik_init_st(void __iomem *base, unsigned int irq_start, | ||
355 | u32 vic_sources) | ||
356 | { | ||
357 | unsigned int i; | ||
358 | int vic_2nd_block = ((unsigned long)base & ~PAGE_MASK) != 0; | ||
359 | |||
360 | /* Disable all interrupts initially. */ | ||
361 | |||
362 | writel(0, base + VIC_INT_SELECT); | ||
363 | writel(0, base + VIC_INT_ENABLE); | ||
364 | writel(~0, base + VIC_INT_ENABLE_CLEAR); | ||
365 | writel(0, base + VIC_IRQ_STATUS); | ||
366 | writel(0, base + VIC_ITCR); | ||
367 | writel(~0, base + VIC_INT_SOFT_CLEAR); | ||
368 | |||
369 | /* | ||
370 | * Make sure we clear all existing interrupts. The vector registers | ||
371 | * in this cell are after the second block of general registers, | ||
372 | * so we can address them using standard offsets, but only from | ||
373 | * the second base address, which is 0x20 in the page | ||
374 | */ | ||
375 | if (vic_2nd_block) { | ||
376 | writel(0, base + VIC_PL190_VECT_ADDR); | ||
377 | for (i = 0; i < 19; i++) { | ||
378 | unsigned int value; | ||
379 | |||
380 | value = readl(base + VIC_PL190_VECT_ADDR); | ||
381 | writel(value, base + VIC_PL190_VECT_ADDR); | ||
382 | } | ||
383 | /* ST has 16 vectors as well, but we don't enable them by now */ | ||
384 | for (i = 0; i < 16; i++) { | ||
385 | void __iomem *reg = base + VIC_VECT_CNTL0 + (i * 4); | ||
386 | writel(0, reg); | ||
387 | } | ||
388 | |||
389 | writel(32, base + VIC_PL190_DEF_VECT_ADDR); | ||
390 | } | ||
391 | |||
392 | for (i = 0; i < 32; i++) { | ||
393 | if (vic_sources & (1 << i)) { | ||
394 | unsigned int irq = irq_start + i; | ||
395 | |||
396 | set_irq_chip(irq, &vic_chip); | ||
397 | set_irq_chip_data(irq, base); | ||
398 | set_irq_handler(irq, handle_level_irq); | ||
399 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); | ||
400 | } | ||
401 | } | ||
402 | } | ||