irq.c 7.3 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13
/*
 * linux/arch/arm/mach-sa1100/irq.c
 *
 * Copyright (C) 1999-2001 Nicolas Pitre
 *
 * Generic IRQ handling for the SA11x0, GPIO 11-27 IRQ demultiplexing.
 *
 * 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>
14 15
#include <linux/interrupt.h>
#include <linux/irq.h>
L
Linus Torvalds 已提交
16 17 18
#include <linux/ioport.h>
#include <linux/sysdev.h>

19
#include <mach/hardware.h>
L
Linus Torvalds 已提交
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
#include <asm/mach/irq.h>

#include "generic.h"


/*
 * SA1100 GPIO edge detection for IRQs:
 * IRQs are generated on Falling-Edge, Rising-Edge, or both.
 * Use this instead of directly setting GRER/GFER.
 */
static int GPIO_IRQ_rising_edge;
static int GPIO_IRQ_falling_edge;
static int GPIO_IRQ_mask = (1 << 11) - 1;

/*
 * To get the GPIO number from an IRQ number
 */
#define GPIO_11_27_IRQ(i)	((i) - 21)
#define GPIO11_27_MASK(irq)	(1 << GPIO_11_27_IRQ(irq))

40
static int sa1100_gpio_type(struct irq_data *d, unsigned int type)
L
Linus Torvalds 已提交
41 42 43
{
	unsigned int mask;

44 45
	if (d->irq <= 10)
		mask = 1 << d->irq;
L
Linus Torvalds 已提交
46
	else
47
		mask = GPIO11_27_MASK(d->irq);
L
Linus Torvalds 已提交
48

49
	if (type == IRQ_TYPE_PROBE) {
L
Linus Torvalds 已提交
50 51
		if ((GPIO_IRQ_rising_edge | GPIO_IRQ_falling_edge) & mask)
			return 0;
52
		type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
L
Linus Torvalds 已提交
53 54
	}

55
	if (type & IRQ_TYPE_EDGE_RISING) {
L
Linus Torvalds 已提交
56 57 58
		GPIO_IRQ_rising_edge |= mask;
	} else
		GPIO_IRQ_rising_edge &= ~mask;
59
	if (type & IRQ_TYPE_EDGE_FALLING) {
L
Linus Torvalds 已提交
60 61 62 63 64 65 66 67 68 69 70 71 72
		GPIO_IRQ_falling_edge |= mask;
	} else
		GPIO_IRQ_falling_edge &= ~mask;

	GRER = GPIO_IRQ_rising_edge & GPIO_IRQ_mask;
	GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask;

	return 0;
}

/*
 * GPIO IRQs must be acknowledged.  This is for IRQs from 0 to 10.
 */
73
static void sa1100_low_gpio_ack(struct irq_data *d)
L
Linus Torvalds 已提交
74
{
75
	GEDR = (1 << d->irq);
L
Linus Torvalds 已提交
76 77
}

78
static void sa1100_low_gpio_mask(struct irq_data *d)
L
Linus Torvalds 已提交
79
{
80
	ICMR &= ~(1 << d->irq);
L
Linus Torvalds 已提交
81 82
}

83
static void sa1100_low_gpio_unmask(struct irq_data *d)
L
Linus Torvalds 已提交
84
{
85
	ICMR |= 1 << d->irq;
L
Linus Torvalds 已提交
86 87
}

88
static int sa1100_low_gpio_wake(struct irq_data *d, unsigned int on)
L
Linus Torvalds 已提交
89 90
{
	if (on)
91
		PWER |= 1 << d->irq;
L
Linus Torvalds 已提交
92
	else
93
		PWER &= ~(1 << d->irq);
L
Linus Torvalds 已提交
94 95 96
	return 0;
}

97 98
static struct irq_chip sa1100_low_gpio_chip = {
	.name		= "GPIO-l",
99 100 101 102 103
	.irq_ack	= sa1100_low_gpio_ack,
	.irq_mask	= sa1100_low_gpio_mask,
	.irq_unmask	= sa1100_low_gpio_unmask,
	.irq_set_type	= sa1100_gpio_type,
	.irq_set_wake	= sa1100_low_gpio_wake,
L
Linus Torvalds 已提交
104 105 106 107 108 109 110 111
};

/*
 * IRQ11 (GPIO11 through 27) handler.  We enter here with the
 * irq_controller_lock held, and IRQs disabled.  Decode the IRQ
 * and call the handler.
 */
static void
112
sa1100_high_gpio_handler(unsigned int irq, struct irq_desc *desc)
L
Linus Torvalds 已提交
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
{
	unsigned int mask;

	mask = GEDR & 0xfffff800;
	do {
		/*
		 * clear down all currently active IRQ sources.
		 * We will be processing them all.
		 */
		GEDR = mask;

		irq = IRQ_GPIO11;
		mask >>= 11;
		do {
			if (mask & 1)
128
				generic_handle_irq(irq);
L
Linus Torvalds 已提交
129 130 131 132 133 134 135 136 137 138 139 140 141
			mask >>= 1;
			irq++;
		} while (mask);

		mask = GEDR & 0xfffff800;
	} while (mask);
}

/*
 * Like GPIO0 to 10, GPIO11-27 IRQs need to be handled specially.
 * In addition, the IRQs are all collected up into one bit in the
 * interrupt controller registers.
 */
142
static void sa1100_high_gpio_ack(struct irq_data *d)
L
Linus Torvalds 已提交
143
{
144
	unsigned int mask = GPIO11_27_MASK(d->irq);
L
Linus Torvalds 已提交
145 146 147 148

	GEDR = mask;
}

149
static void sa1100_high_gpio_mask(struct irq_data *d)
L
Linus Torvalds 已提交
150
{
151
	unsigned int mask = GPIO11_27_MASK(d->irq);
L
Linus Torvalds 已提交
152 153 154 155 156 157 158

	GPIO_IRQ_mask &= ~mask;

	GRER &= ~mask;
	GFER &= ~mask;
}

159
static void sa1100_high_gpio_unmask(struct irq_data *d)
L
Linus Torvalds 已提交
160
{
161
	unsigned int mask = GPIO11_27_MASK(d->irq);
L
Linus Torvalds 已提交
162 163 164 165 166 167 168

	GPIO_IRQ_mask |= mask;

	GRER = GPIO_IRQ_rising_edge & GPIO_IRQ_mask;
	GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask;
}

169
static int sa1100_high_gpio_wake(struct irq_data *d, unsigned int on)
L
Linus Torvalds 已提交
170 171
{
	if (on)
172
		PWER |= GPIO11_27_MASK(d->irq);
L
Linus Torvalds 已提交
173
	else
174
		PWER &= ~GPIO11_27_MASK(d->irq);
L
Linus Torvalds 已提交
175 176 177
	return 0;
}

178 179
static struct irq_chip sa1100_high_gpio_chip = {
	.name		= "GPIO-h",
180 181 182 183 184
	.irq_ack	= sa1100_high_gpio_ack,
	.irq_mask	= sa1100_high_gpio_mask,
	.irq_unmask	= sa1100_high_gpio_unmask,
	.irq_set_type	= sa1100_gpio_type,
	.irq_set_wake	= sa1100_high_gpio_wake,
L
Linus Torvalds 已提交
185 186 187 188 189 190
};

/*
 * We don't need to ACK IRQs on the SA1100 unless they're GPIOs
 * this is for internal IRQs i.e. from 11 to 31.
 */
191
static void sa1100_mask_irq(struct irq_data *d)
L
Linus Torvalds 已提交
192
{
193
	ICMR &= ~(1 << d->irq);
L
Linus Torvalds 已提交
194 195
}

196
static void sa1100_unmask_irq(struct irq_data *d)
L
Linus Torvalds 已提交
197
{
198
	ICMR |= (1 << d->irq);
L
Linus Torvalds 已提交
199 200
}

201 202 203
/*
 * Apart form GPIOs, only the RTC alarm can be a wakeup event.
 */
204
static int sa1100_set_wake(struct irq_data *d, unsigned int on)
205
{
206
	if (d->irq == IRQ_RTCAlrm) {
207 208 209 210 211 212 213 214 215
		if (on)
			PWER |= PWER_RTC;
		else
			PWER &= ~PWER_RTC;
		return 0;
	}
	return -EINVAL;
}

216 217
static struct irq_chip sa1100_normal_chip = {
	.name		= "SC",
218 219 220 221
	.irq_ack	= sa1100_mask_irq,
	.irq_mask	= sa1100_mask_irq,
	.irq_unmask	= sa1100_unmask_irq,
	.irq_set_wake	= sa1100_set_wake,
L
Linus Torvalds 已提交
222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283
};

static struct resource irq_resource = {
	.name	= "irqs",
	.start	= 0x90050000,
	.end	= 0x9005ffff,
};

static struct sa1100irq_state {
	unsigned int	saved;
	unsigned int	icmr;
	unsigned int	iclr;
	unsigned int	iccr;
} sa1100irq_state;

static int sa1100irq_suspend(struct sys_device *dev, pm_message_t state)
{
	struct sa1100irq_state *st = &sa1100irq_state;

	st->saved = 1;
	st->icmr = ICMR;
	st->iclr = ICLR;
	st->iccr = ICCR;

	/*
	 * Disable all GPIO-based interrupts.
	 */
	ICMR &= ~(IC_GPIO11_27|IC_GPIO10|IC_GPIO9|IC_GPIO8|IC_GPIO7|
		  IC_GPIO6|IC_GPIO5|IC_GPIO4|IC_GPIO3|IC_GPIO2|
		  IC_GPIO1|IC_GPIO0);

	/*
	 * Set the appropriate edges for wakeup.
	 */
	GRER = PWER & GPIO_IRQ_rising_edge;
	GFER = PWER & GPIO_IRQ_falling_edge;
	
	/*
	 * Clear any pending GPIO interrupts.
	 */
	GEDR = GEDR;

	return 0;
}

static int sa1100irq_resume(struct sys_device *dev)
{
	struct sa1100irq_state *st = &sa1100irq_state;

	if (st->saved) {
		ICCR = st->iccr;
		ICLR = st->iclr;

		GRER = GPIO_IRQ_rising_edge & GPIO_IRQ_mask;
		GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask;

		ICMR = st->icmr;
	}
	return 0;
}

static struct sysdev_class sa1100irq_sysclass = {
284
	.name		= "sa11x0-irq",
L
Linus Torvalds 已提交
285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326
	.suspend	= sa1100irq_suspend,
	.resume		= sa1100irq_resume,
};

static struct sys_device sa1100irq_device = {
	.id		= 0,
	.cls		= &sa1100irq_sysclass,
};

static int __init sa1100irq_init_devicefs(void)
{
	sysdev_class_register(&sa1100irq_sysclass);
	return sysdev_register(&sa1100irq_device);
}

device_initcall(sa1100irq_init_devicefs);

void __init sa1100_init_irq(void)
{
	unsigned int irq;

	request_resource(&iomem_resource, &irq_resource);

	/* disable all IRQs */
	ICMR = 0;

	/* all IRQs are IRQ, not FIQ */
	ICLR = 0;

	/* clear all GPIO edge detects */
	GFER = 0;
	GRER = 0;
	GEDR = -1;

	/*
	 * Whatever the doc says, this has to be set for the wait-on-irq
	 * instruction to work... on a SA1100 rev 9 at least.
	 */
	ICCR = 1;

	for (irq = 0; irq <= 10; irq++) {
		set_irq_chip(irq, &sa1100_low_gpio_chip);
327
		set_irq_handler(irq, handle_edge_irq);
L
Linus Torvalds 已提交
328 329 330 331 332
		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
	}

	for (irq = 12; irq <= 31; irq++) {
		set_irq_chip(irq, &sa1100_normal_chip);
333
		set_irq_handler(irq, handle_level_irq);
L
Linus Torvalds 已提交
334 335 336 337 338
		set_irq_flags(irq, IRQF_VALID);
	}

	for (irq = 32; irq <= 48; irq++) {
		set_irq_chip(irq, &sa1100_high_gpio_chip);
339
		set_irq_handler(irq, handle_edge_irq);
L
Linus Torvalds 已提交
340 341 342 343 344 345 346 347
		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
	}

	/*
	 * Install handler for GPIO 11-27 edge detect interrupts
	 */
	set_irq_chip(IRQ_GPIO11_27, &sa1100_normal_chip);
	set_irq_chained_handler(IRQ_GPIO11_27, sa1100_high_gpio_handler);
348 349

	sa1100_init_gpio();
L
Linus Torvalds 已提交
350
}