irq-lpd7a40x.c 3.2 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/* arch/arm/mach-lh7a40x/irq-lpd7a40x.c
 *
 *  Copyright (C) 2004 Coastal Environmental Systems
 *  Copyright (C) 2004 Logic Product Development
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU General Public License
 *  version 2 as published by the Free Software Foundation.
 *
 */

#include <linux/init.h>
#include <linux/module.h>
#include <linux/interrupt.h>

16
#include <mach/hardware.h>
L
Linus Torvalds 已提交
17 18
#include <asm/irq.h>
#include <asm/mach/irq.h>
19
#include <mach/irqs.h>
L
Linus Torvalds 已提交
20

R
Russell King 已提交
21
#include "common.h"
L
Linus Torvalds 已提交
22

23
static void lh7a40x_ack_cpld_irq(struct irq_data *d)
L
Linus Torvalds 已提交
24 25 26 27
{
	/* CPLD doesn't have ack capability */
}

28
static void lh7a40x_mask_cpld_irq(struct irq_data *d)
L
Linus Torvalds 已提交
29
{
30
	switch (d->irq) {
L
Linus Torvalds 已提交
31 32 33 34 35 36 37 38 39
	case IRQ_LPD7A40X_ETH_INT:
		CPLD_INTERRUPTS = CPLD_INTERRUPTS | 0x4;
		break;
	case IRQ_LPD7A400_TS:
		CPLD_INTERRUPTS = CPLD_INTERRUPTS | 0x8;
		break;
	}
}

40
static void lh7a40x_unmask_cpld_irq(struct irq_data *d)
L
Linus Torvalds 已提交
41
{
42
	switch (d->irq) {
L
Linus Torvalds 已提交
43 44 45 46 47 48 49 50 51
	case IRQ_LPD7A40X_ETH_INT:
		CPLD_INTERRUPTS = CPLD_INTERRUPTS & ~ 0x4;
		break;
	case IRQ_LPD7A400_TS:
		CPLD_INTERRUPTS = CPLD_INTERRUPTS & ~ 0x8;
		break;
	}
}

52
static struct irq_chip lh7a40x_cpld_chip = {
53 54 55 56
	.name		= "CPLD",
	.irq_ack	= lh7a40x_ack_cpld_irq,
	.irq_mask	= lh7a40x_mask_cpld_irq,
	.irq_unmask	= lh7a40x_unmask_cpld_irq,
L
Linus Torvalds 已提交
57 58
};

59
static void lh7a40x_cpld_handler (unsigned int irq, struct irq_desc *desc)
L
Linus Torvalds 已提交
60 61 62
{
	unsigned int mask = CPLD_INTERRUPTS;

63
	desc->irq_data.chip->ack (irq);
L
Linus Torvalds 已提交
64 65

	if ((mask & 0x1) == 0)	/* WLAN */
66
		generic_handle_irq(IRQ_LPD7A40X_ETH_INT);
L
Linus Torvalds 已提交
67 68

	if ((mask & 0x2) == 0)	/* Touch */
69
		generic_handle_irq(IRQ_LPD7A400_TS);
L
Linus Torvalds 已提交
70

71
	desc->irq_data.chip->unmask (irq); /* Level-triggered need this */
L
Linus Torvalds 已提交
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
}


  /* IRQ initialization */

void __init lh7a40x_init_board_irq (void)
{
	int irq;

		/* Rev A (v2.8): PF0, PF1, PF2, and PF3 are available IRQs.
		                 PF7 supports the CPLD.
		   Rev B (v3.4): PF0, PF1, and PF2 are available IRQs.
		                 PF3 supports the CPLD.
		   (Some) LPD7A404 prerelease boards report a version
		   number of 0x16, but we force an override since the
		   hardware is of the newer variety.
		*/

	unsigned char cpld_version = CPLD_REVISION;
	int pinCPLD;

#if defined CONFIG_MACH_LPD7A404
	cpld_version = 0x34;	/* Override, for now */
#endif
	pinCPLD = (cpld_version == 0x28) ? 7 : 3;

		/* First, configure user controlled GPIOF interrupts  */

	GPIO_PFDD	&= ~0x0f; /* PF0-3 are inputs */
	GPIO_INTTYPE1	&= ~0x0f; /* PF0-3 are level triggered */
	GPIO_INTTYPE2	&= ~0x0f; /* PF0-3 are active low */
	barrier ();
	GPIO_GPIOFINTEN |=  0x0f; /* Enable PF0, PF1, PF2, and PF3 IRQs */

		/* Then, configure CPLD interrupt */

	CPLD_INTERRUPTS	=   0x0c; /* Disable all CPLD interrupts */
	GPIO_PFDD	&= ~(1 << pinCPLD); /* Make input */
	GPIO_INTTYPE1	|=  (1 << pinCPLD); /* Edge triggered */
	GPIO_INTTYPE2	&= ~(1 << pinCPLD); /* Active low */
	barrier ();
	GPIO_GPIOFINTEN |=  (1 << pinCPLD); /* Enable */

		/* Cascade CPLD interrupts */

	for (irq = IRQ_BOARD_START;
	     irq < IRQ_BOARD_START + NR_IRQ_BOARD; ++irq) {
		set_irq_chip (irq, &lh7a40x_cpld_chip);
120
		set_irq_handler (irq, handle_edge_irq);
L
Linus Torvalds 已提交
121 122 123 124 125 126 127 128
		set_irq_flags (irq, IRQF_VALID);
	}

	set_irq_chained_handler ((cpld_version == 0x28)
				 ? IRQ_CPLD_V28
				 : IRQ_CPLD_V34,
				 lh7a40x_cpld_handler);
}