diff options
Diffstat (limited to 'arch/arm/mach-pxa/pcm990-baseboard.c')
-rw-r--r-- | arch/arm/mach-pxa/pcm990-baseboard.c | 83 |
1 files changed, 50 insertions, 33 deletions
diff --git a/arch/arm/mach-pxa/pcm990-baseboard.c b/arch/arm/mach-pxa/pcm990-baseboard.c index abab4e2b122c..cb723e84bc27 100644 --- a/arch/arm/mach-pxa/pcm990-baseboard.c +++ b/arch/arm/mach-pxa/pcm990-baseboard.c | |||
@@ -65,6 +65,18 @@ static unsigned long pcm990_pin_config[] __initdata = { | |||
65 | GPIO31_AC97_SYNC, | 65 | GPIO31_AC97_SYNC, |
66 | }; | 66 | }; |
67 | 67 | ||
68 | static void __iomem *pcm990_cpld_base; | ||
69 | |||
70 | static u8 pcm990_cpld_readb(unsigned int reg) | ||
71 | { | ||
72 | return readb(pcm990_cpld_base + reg); | ||
73 | } | ||
74 | |||
75 | static void pcm990_cpld_writeb(u8 value, unsigned int reg) | ||
76 | { | ||
77 | writeb(value, pcm990_cpld_base + reg); | ||
78 | } | ||
79 | |||
68 | /* | 80 | /* |
69 | * pcm990_lcd_power - control power supply to the LCD | 81 | * pcm990_lcd_power - control power supply to the LCD |
70 | * @on: 0 = switch off, 1 = switch on | 82 | * @on: 0 = switch off, 1 = switch on |
@@ -78,13 +90,13 @@ static void pcm990_lcd_power(int on, struct fb_var_screeninfo *var) | |||
78 | /* enable LCD-Latches | 90 | /* enable LCD-Latches |
79 | * power on LCD | 91 | * power on LCD |
80 | */ | 92 | */ |
81 | __PCM990_CTRL_REG(PCM990_CTRL_PHYS + PCM990_CTRL_REG3) = | 93 | pcm990_cpld_writeb(PCM990_CTRL_LCDPWR + PCM990_CTRL_LCDON, |
82 | PCM990_CTRL_LCDPWR + PCM990_CTRL_LCDON; | 94 | PCM990_CTRL_REG3); |
83 | } else { | 95 | } else { |
84 | /* disable LCD-Latches | 96 | /* disable LCD-Latches |
85 | * power off LCD | 97 | * power off LCD |
86 | */ | 98 | */ |
87 | __PCM990_CTRL_REG(PCM990_CTRL_PHYS + PCM990_CTRL_REG3) = 0x00; | 99 | pcm990_cpld_writeb(0, PCM990_CTRL_REG3); |
88 | } | 100 | } |
89 | } | 101 | } |
90 | #endif | 102 | #endif |
@@ -243,15 +255,26 @@ static unsigned long pcm990_irq_enabled; | |||
243 | static void pcm990_mask_ack_irq(struct irq_data *d) | 255 | static void pcm990_mask_ack_irq(struct irq_data *d) |
244 | { | 256 | { |
245 | int pcm990_irq = (d->irq - PCM027_IRQ(0)); | 257 | int pcm990_irq = (d->irq - PCM027_IRQ(0)); |
246 | PCM990_INTMSKENA = (pcm990_irq_enabled &= ~(1 << pcm990_irq)); | 258 | |
259 | pcm990_irq_enabled &= ~(1 << pcm990_irq); | ||
260 | |||
261 | pcm990_cpld_writeb(pcm990_irq_enabled, PCM990_CTRL_INTMSKENA); | ||
247 | } | 262 | } |
248 | 263 | ||
249 | static void pcm990_unmask_irq(struct irq_data *d) | 264 | static void pcm990_unmask_irq(struct irq_data *d) |
250 | { | 265 | { |
251 | int pcm990_irq = (d->irq - PCM027_IRQ(0)); | 266 | int pcm990_irq = (d->irq - PCM027_IRQ(0)); |
267 | u8 val; | ||
268 | |||
252 | /* the irq can be acknowledged only if deasserted, so it's done here */ | 269 | /* the irq can be acknowledged only if deasserted, so it's done here */ |
253 | PCM990_INTSETCLR |= 1 << pcm990_irq; | 270 | |
254 | PCM990_INTMSKENA = (pcm990_irq_enabled |= (1 << pcm990_irq)); | 271 | pcm990_irq_enabled |= (1 << pcm990_irq); |
272 | |||
273 | val = pcm990_cpld_readb(PCM990_CTRL_INTSETCLR); | ||
274 | val |= 1 << pcm990_irq; | ||
275 | pcm990_cpld_writeb(val, PCM990_CTRL_INTSETCLR); | ||
276 | |||
277 | pcm990_cpld_writeb(pcm990_irq_enabled, PCM990_CTRL_INTMSKENA); | ||
255 | } | 278 | } |
256 | 279 | ||
257 | static struct irq_chip pcm990_irq_chip = { | 280 | static struct irq_chip pcm990_irq_chip = { |
@@ -261,7 +284,10 @@ static struct irq_chip pcm990_irq_chip = { | |||
261 | 284 | ||
262 | static void pcm990_irq_handler(unsigned int irq, struct irq_desc *desc) | 285 | static void pcm990_irq_handler(unsigned int irq, struct irq_desc *desc) |
263 | { | 286 | { |
264 | unsigned long pending = (~PCM990_INTSETCLR) & pcm990_irq_enabled; | 287 | unsigned long pending; |
288 | |||
289 | pending = ~pcm990_cpld_readb(PCM990_CTRL_INTSETCLR); | ||
290 | pending &= pcm990_irq_enabled; | ||
265 | 291 | ||
266 | do { | 292 | do { |
267 | /* clear our parent IRQ */ | 293 | /* clear our parent IRQ */ |
@@ -270,7 +296,8 @@ static void pcm990_irq_handler(unsigned int irq, struct irq_desc *desc) | |||
270 | irq = PCM027_IRQ(0) + __ffs(pending); | 296 | irq = PCM027_IRQ(0) + __ffs(pending); |
271 | generic_handle_irq(irq); | 297 | generic_handle_irq(irq); |
272 | } | 298 | } |
273 | pending = (~PCM990_INTSETCLR) & pcm990_irq_enabled; | 299 | pending = ~pcm990_cpld_readb(PCM990_CTRL_INTSETCLR); |
300 | pending &= pcm990_irq_enabled; | ||
274 | } while (pending); | 301 | } while (pending); |
275 | } | 302 | } |
276 | 303 | ||
@@ -285,8 +312,9 @@ static void __init pcm990_init_irq(void) | |||
285 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); | 312 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); |
286 | } | 313 | } |
287 | 314 | ||
288 | PCM990_INTMSKENA = 0x00; /* disable all Interrupts */ | 315 | /* disable all Interrupts */ |
289 | PCM990_INTSETCLR = 0xFF; | 316 | pcm990_cpld_writeb(0x0, PCM990_CTRL_INTMSKENA); |
317 | pcm990_cpld_writeb(0xff, PCM990_CTRL_INTSETCLR); | ||
290 | 318 | ||
291 | irq_set_chained_handler(PCM990_CTRL_INT_IRQ, pcm990_irq_handler); | 319 | irq_set_chained_handler(PCM990_CTRL_INT_IRQ, pcm990_irq_handler); |
292 | irq_set_irq_type(PCM990_CTRL_INT_IRQ, PCM990_CTRL_INT_IRQ_EDGE); | 320 | irq_set_irq_type(PCM990_CTRL_INT_IRQ, PCM990_CTRL_INT_IRQ_EDGE); |
@@ -309,13 +337,16 @@ static int pcm990_mci_init(struct device *dev, irq_handler_t mci_detect_int, | |||
309 | static void pcm990_mci_setpower(struct device *dev, unsigned int vdd) | 337 | static void pcm990_mci_setpower(struct device *dev, unsigned int vdd) |
310 | { | 338 | { |
311 | struct pxamci_platform_data *p_d = dev->platform_data; | 339 | struct pxamci_platform_data *p_d = dev->platform_data; |
340 | u8 val; | ||
341 | |||
342 | val = pcm990_cpld_readb(PCM990_CTRL_REG5); | ||
312 | 343 | ||
313 | if ((1 << vdd) & p_d->ocr_mask) | 344 | if ((1 << vdd) & p_d->ocr_mask) |
314 | __PCM990_CTRL_REG(PCM990_CTRL_PHYS + PCM990_CTRL_REG5) = | 345 | val |= PCM990_CTRL_MMC2PWR; |
315 | PCM990_CTRL_MMC2PWR; | ||
316 | else | 346 | else |
317 | __PCM990_CTRL_REG(PCM990_CTRL_PHYS + PCM990_CTRL_REG5) = | 347 | val &= ~PCM990_CTRL_MMC2PWR; |
318 | ~PCM990_CTRL_MMC2PWR; | 348 | |
349 | pcm990_cpld_writeb(PCM990_CTRL_MMC2PWR, PCM990_CTRL_REG5); | ||
319 | } | 350 | } |
320 | 351 | ||
321 | static void pcm990_mci_exit(struct device *dev, void *data) | 352 | static void pcm990_mci_exit(struct device *dev, void *data) |
@@ -481,23 +512,6 @@ static struct platform_device pcm990_camera[] = { | |||
481 | #endif /* CONFIG_VIDEO_PXA27x ||CONFIG_VIDEO_PXA27x_MODULE */ | 512 | #endif /* CONFIG_VIDEO_PXA27x ||CONFIG_VIDEO_PXA27x_MODULE */ |
482 | 513 | ||
483 | /* | 514 | /* |
484 | * enable generic access to the base board control CPLDs U6 and U7 | ||
485 | */ | ||
486 | static struct map_desc pcm990_io_desc[] __initdata = { | ||
487 | { | ||
488 | .virtual = PCM990_CTRL_BASE, | ||
489 | .pfn = __phys_to_pfn(PCM990_CTRL_PHYS), | ||
490 | .length = PCM990_CTRL_SIZE, | ||
491 | .type = MT_DEVICE /* CPLD */ | ||
492 | }, { | ||
493 | .virtual = PCM990_CF_PLD_BASE, | ||
494 | .pfn = __phys_to_pfn(PCM990_CF_PLD_PHYS), | ||
495 | .length = PCM990_CF_PLD_SIZE, | ||
496 | .type = MT_DEVICE /* CPLD */ | ||
497 | } | ||
498 | }; | ||
499 | |||
500 | /* | ||
501 | * system init for baseboard usage. Will be called by pcm027 init. | 515 | * system init for baseboard usage. Will be called by pcm027 init. |
502 | * | 516 | * |
503 | * Add platform devices present on this baseboard and init | 517 | * Add platform devices present on this baseboard and init |
@@ -507,8 +521,11 @@ void __init pcm990_baseboard_init(void) | |||
507 | { | 521 | { |
508 | pxa2xx_mfp_config(ARRAY_AND_SIZE(pcm990_pin_config)); | 522 | pxa2xx_mfp_config(ARRAY_AND_SIZE(pcm990_pin_config)); |
509 | 523 | ||
510 | /* register CPLD access */ | 524 | pcm990_cpld_base = ioremap(PCM990_CTRL_PHYS, PCM990_CTRL_SIZE); |
511 | iotable_init(ARRAY_AND_SIZE(pcm990_io_desc)); | 525 | if (!pcm990_cpld_base) { |
526 | pr_err("pcm990: failed to ioremap cpld\n"); | ||
527 | return; | ||
528 | } | ||
512 | 529 | ||
513 | /* register CPLD's IRQ controller */ | 530 | /* register CPLD's IRQ controller */ |
514 | pcm990_init_irq(); | 531 | pcm990_init_irq(); |