gpio-mxc.c 12.3 KB
Newer Older
1 2 3 4 5
/*
 * MXC GPIO support. (c) 2008 Daniel Mack <daniel@caiaq.de>
 * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
 *
 * Based on code from Freescale,
6
 * Copyright (C) 2004-2010 Freescale Semiconductor, Inc. All Rights Reserved.
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

#include <linux/init.h>
23
#include <linux/interrupt.h>
24 25 26
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/gpio.h>
27 28
#include <linux/platform_device.h>
#include <linux/slab.h>
29
#include <linux/basic_mmio_gpio.h>
30 31
#include <linux/of.h>
#include <linux/of_device.h>
32
#include <linux/module.h>
33
#include <asm-generic/bug.h>
34
#include <asm/mach/irq.h>
35

36 37
#define irq_to_gpio(irq)	((irq) - MXC_GPIO_IRQ_START)

38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
enum mxc_gpio_hwtype {
	IMX1_GPIO,	/* runs on i.mx1 */
	IMX21_GPIO,	/* runs on i.mx21 and i.mx27 */
	IMX31_GPIO,	/* runs on all other i.mx */
};

/* device type dependent stuff */
struct mxc_gpio_hwdata {
	unsigned dr_reg;
	unsigned gdir_reg;
	unsigned psr_reg;
	unsigned icr1_reg;
	unsigned icr2_reg;
	unsigned imr_reg;
	unsigned isr_reg;
	unsigned low_level;
	unsigned high_level;
	unsigned rise_edge;
	unsigned fall_edge;
};

59 60 61 62 63 64
struct mxc_gpio_port {
	struct list_head node;
	void __iomem *base;
	int irq;
	int irq_high;
	int virtual_irq_start;
65
	struct bgpio_chip bgc;
66 67 68
	u32 both_edges;
};

69 70 71 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 120 121 122 123 124 125 126 127 128
static struct mxc_gpio_hwdata imx1_imx21_gpio_hwdata = {
	.dr_reg		= 0x1c,
	.gdir_reg	= 0x00,
	.psr_reg	= 0x24,
	.icr1_reg	= 0x28,
	.icr2_reg	= 0x2c,
	.imr_reg	= 0x30,
	.isr_reg	= 0x34,
	.low_level	= 0x03,
	.high_level	= 0x02,
	.rise_edge	= 0x00,
	.fall_edge	= 0x01,
};

static struct mxc_gpio_hwdata imx31_gpio_hwdata = {
	.dr_reg		= 0x00,
	.gdir_reg	= 0x04,
	.psr_reg	= 0x08,
	.icr1_reg	= 0x0c,
	.icr2_reg	= 0x10,
	.imr_reg	= 0x14,
	.isr_reg	= 0x18,
	.low_level	= 0x00,
	.high_level	= 0x01,
	.rise_edge	= 0x02,
	.fall_edge	= 0x03,
};

static enum mxc_gpio_hwtype mxc_gpio_hwtype;
static struct mxc_gpio_hwdata *mxc_gpio_hwdata;

#define GPIO_DR			(mxc_gpio_hwdata->dr_reg)
#define GPIO_GDIR		(mxc_gpio_hwdata->gdir_reg)
#define GPIO_PSR		(mxc_gpio_hwdata->psr_reg)
#define GPIO_ICR1		(mxc_gpio_hwdata->icr1_reg)
#define GPIO_ICR2		(mxc_gpio_hwdata->icr2_reg)
#define GPIO_IMR		(mxc_gpio_hwdata->imr_reg)
#define GPIO_ISR		(mxc_gpio_hwdata->isr_reg)

#define GPIO_INT_LOW_LEV	(mxc_gpio_hwdata->low_level)
#define GPIO_INT_HIGH_LEV	(mxc_gpio_hwdata->high_level)
#define GPIO_INT_RISE_EDGE	(mxc_gpio_hwdata->rise_edge)
#define GPIO_INT_FALL_EDGE	(mxc_gpio_hwdata->fall_edge)
#define GPIO_INT_NONE		0x4

static struct platform_device_id mxc_gpio_devtype[] = {
	{
		.name = "imx1-gpio",
		.driver_data = IMX1_GPIO,
	}, {
		.name = "imx21-gpio",
		.driver_data = IMX21_GPIO,
	}, {
		.name = "imx31-gpio",
		.driver_data = IMX31_GPIO,
	}, {
		/* sentinel */
	}
};

129 130 131 132 133 134 135
static const struct of_device_id mxc_gpio_dt_ids[] = {
	{ .compatible = "fsl,imx1-gpio", .data = &mxc_gpio_devtype[IMX1_GPIO], },
	{ .compatible = "fsl,imx21-gpio", .data = &mxc_gpio_devtype[IMX21_GPIO], },
	{ .compatible = "fsl,imx31-gpio", .data = &mxc_gpio_devtype[IMX31_GPIO], },
	{ /* sentinel */ }
};

136 137 138 139 140 141
/*
 * MX2 has one interrupt *for all* gpio ports. The list is used
 * to save the references to all ports, so that mx2_gpio_irq_handler
 * can walk through all interrupt status registers.
 */
static LIST_HEAD(mxc_gpio_ports);
142 143 144

/* Note: This driver assumes 32 GPIOs are handled in one register */

145
static int gpio_set_irq_type(struct irq_data *d, u32 type)
146
{
147
	u32 gpio = irq_to_gpio(d->irq);
148 149
	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
	struct mxc_gpio_port *port = gc->private;
150 151 152 153
	u32 bit, val;
	int edge;
	void __iomem *reg = port->base;

154
	port->both_edges &= ~(1 << (gpio & 31));
155
	switch (type) {
156
	case IRQ_TYPE_EDGE_RISING:
157 158
		edge = GPIO_INT_RISE_EDGE;
		break;
159
	case IRQ_TYPE_EDGE_FALLING:
160 161
		edge = GPIO_INT_FALL_EDGE;
		break;
162
	case IRQ_TYPE_EDGE_BOTH:
163
		val = gpio_get_value(gpio);
164 165 166 167 168 169 170 171 172
		if (val) {
			edge = GPIO_INT_LOW_LEV;
			pr_debug("mxc: set GPIO %d to low trigger\n", gpio);
		} else {
			edge = GPIO_INT_HIGH_LEV;
			pr_debug("mxc: set GPIO %d to high trigger\n", gpio);
		}
		port->both_edges |= 1 << (gpio & 31);
		break;
173
	case IRQ_TYPE_LEVEL_LOW:
174 175
		edge = GPIO_INT_LOW_LEV;
		break;
176
	case IRQ_TYPE_LEVEL_HIGH:
177 178
		edge = GPIO_INT_HIGH_LEV;
		break;
179
	default:
180 181 182 183 184
		return -EINVAL;
	}

	reg += GPIO_ICR1 + ((gpio & 0x10) >> 2); /* lower or upper register */
	bit = gpio & 0xf;
185 186
	val = readl(reg) & ~(0x3 << (bit << 1));
	writel(val | (edge << (bit << 1)), reg);
187
	writel(1 << (gpio & 0x1f), port->base + GPIO_ISR);
188 189 190 191

	return 0;
}

192 193 194 195 196 197 198 199
static void mxc_flip_edge(struct mxc_gpio_port *port, u32 gpio)
{
	void __iomem *reg = port->base;
	u32 bit, val;
	int edge;

	reg += GPIO_ICR1 + ((gpio & 0x10) >> 2); /* lower or upper register */
	bit = gpio & 0xf;
200
	val = readl(reg);
201 202
	edge = (val >> (bit << 1)) & 3;
	val &= ~(0x3 << (bit << 1));
203
	if (edge == GPIO_INT_HIGH_LEV) {
204 205
		edge = GPIO_INT_LOW_LEV;
		pr_debug("mxc: switch GPIO %d to low trigger\n", gpio);
206
	} else if (edge == GPIO_INT_LOW_LEV) {
207 208
		edge = GPIO_INT_HIGH_LEV;
		pr_debug("mxc: switch GPIO %d to high trigger\n", gpio);
209
	} else {
210 211 212 213
		pr_err("mxc: invalid configuration for GPIO %d: %x\n",
		       gpio, edge);
		return;
	}
214
	writel(val | (edge << (bit << 1)), reg);
215 216
}

217
/* handle 32 interrupts in one status register */
218 219
static void mxc_gpio_irq_handler(struct mxc_gpio_port *port, u32 irq_stat)
{
220
	u32 gpio_irq_no_base = port->virtual_irq_start;
221

222 223
	while (irq_stat != 0) {
		int irqoffset = fls(irq_stat) - 1;
224

225 226
		if (port->both_edges & (1 << irqoffset))
			mxc_flip_edge(port, irqoffset);
227

228
		generic_handle_irq(gpio_irq_no_base + irqoffset);
229

230
		irq_stat &= ~(1 << irqoffset);
231 232 233
	}
}

P
Paulius Zaleckas 已提交
234
/* MX1 and MX3 has one interrupt *per* gpio port */
235 236 237
static void mx3_gpio_irq_handler(u32 irq, struct irq_desc *desc)
{
	u32 irq_stat;
T
Thomas Gleixner 已提交
238
	struct mxc_gpio_port *port = irq_get_handler_data(irq);
239 240 241
	struct irq_chip *chip = irq_get_chip(irq);

	chained_irq_enter(chip, desc);
242

243
	irq_stat = readl(port->base + GPIO_ISR) & readl(port->base + GPIO_IMR);
244

245
	mxc_gpio_irq_handler(port, irq_stat);
246 247

	chained_irq_exit(chip, desc);
248 249 250 251 252 253
}

/* MX2 has one interrupt *for all* gpio ports */
static void mx2_gpio_irq_handler(u32 irq, struct irq_desc *desc)
{
	u32 irq_msk, irq_stat;
254
	struct mxc_gpio_port *port;
255 256

	/* walk through all interrupt status registers */
257 258
	list_for_each_entry(port, &mxc_gpio_ports, node) {
		irq_msk = readl(port->base + GPIO_IMR);
259 260 261
		if (!irq_msk)
			continue;

262
		irq_stat = readl(port->base + GPIO_ISR) & irq_msk;
263
		if (irq_stat)
264
			mxc_gpio_irq_handler(port, irq_stat);
265 266 267
	}
}

268 269 270 271 272 273 274 275 276
/*
 * Set interrupt number "irq" in the GPIO as a wake-up source.
 * While system is running, all registered GPIO interrupts need to have
 * wake-up enabled. When system is suspended, only selected GPIO interrupts
 * need to have wake-up enabled.
 * @param  irq          interrupt source number
 * @param  enable       enable as wake-up if equal to non-zero
 * @return       This function returns 0 on success.
 */
277
static int gpio_set_wake_irq(struct irq_data *d, u32 enable)
278
{
279
	u32 gpio = irq_to_gpio(d->irq);
280
	u32 gpio_idx = gpio & 0x1F;
281 282
	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
	struct mxc_gpio_port *port = gc->private;
283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298

	if (enable) {
		if (port->irq_high && (gpio_idx >= 16))
			enable_irq_wake(port->irq_high);
		else
			enable_irq_wake(port->irq);
	} else {
		if (port->irq_high && (gpio_idx >= 16))
			disable_irq_wake(port->irq_high);
		else
			disable_irq_wake(port->irq);
	}

	return 0;
}

299 300 301 302 303 304 305 306 307 308
static void __init mxc_gpio_init_gc(struct mxc_gpio_port *port)
{
	struct irq_chip_generic *gc;
	struct irq_chip_type *ct;

	gc = irq_alloc_generic_chip("gpio-mxc", 1, port->virtual_irq_start,
				    port->base, handle_level_irq);
	gc->private = port;

	ct = gc->chip_types;
309
	ct->chip.irq_ack = irq_gc_ack_set_bit;
310 311 312
	ct->chip.irq_mask = irq_gc_mask_clr_bit;
	ct->chip.irq_unmask = irq_gc_mask_set_bit;
	ct->chip.irq_set_type = gpio_set_irq_type;
313
	ct->chip.irq_set_wake = gpio_set_wake_irq;
314 315 316 317 318 319
	ct->regs.ack = GPIO_ISR;
	ct->regs.mask = GPIO_IMR;

	irq_setup_generic_chip(gc, IRQ_MSK(32), IRQ_GC_INIT_NESTED_LOCK,
			       IRQ_NOREQUEST, 0);
}
320

321 322
static void __devinit mxc_gpio_get_hw(struct platform_device *pdev)
{
323 324 325 326 327 328 329
	const struct of_device_id *of_id =
			of_match_device(mxc_gpio_dt_ids, &pdev->dev);
	enum mxc_gpio_hwtype hwtype;

	if (of_id)
		pdev->id_entry = of_id->data;
	hwtype = pdev->id_entry->driver_data;
330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348

	if (mxc_gpio_hwtype) {
		/*
		 * The driver works with a reasonable presupposition,
		 * that is all gpio ports must be the same type when
		 * running on one soc.
		 */
		BUG_ON(mxc_gpio_hwtype != hwtype);
		return;
	}

	if (hwtype == IMX31_GPIO)
		mxc_gpio_hwdata = &imx31_gpio_hwdata;
	else
		mxc_gpio_hwdata = &imx1_imx21_gpio_hwdata;

	mxc_gpio_hwtype = hwtype;
}

S
Shawn Guo 已提交
349 350 351 352 353 354 355 356 357
static int mxc_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
{
	struct bgpio_chip *bgc = to_bgpio_chip(gc);
	struct mxc_gpio_port *port =
		container_of(bgc, struct mxc_gpio_port, bgc);

	return port->virtual_irq_start + offset;
}

358
static int __devinit mxc_gpio_probe(struct platform_device *pdev)
359
{
360
	struct device_node *np = pdev->dev.of_node;
361 362
	struct mxc_gpio_port *port;
	struct resource *iores;
363
	int err;
364

365 366
	mxc_gpio_get_hw(pdev);

367 368 369
	port = kzalloc(sizeof(struct mxc_gpio_port), GFP_KERNEL);
	if (!port)
		return -ENOMEM;
370

371 372 373 374 375
	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!iores) {
		err = -ENODEV;
		goto out_kfree;
	}
376

377 378 379 380 381
	if (!request_mem_region(iores->start, resource_size(iores),
				pdev->name)) {
		err = -EBUSY;
		goto out_kfree;
	}
382

383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399
	port->base = ioremap(iores->start, resource_size(iores));
	if (!port->base) {
		err = -ENOMEM;
		goto out_release_mem;
	}

	port->irq_high = platform_get_irq(pdev, 1);
	port->irq = platform_get_irq(pdev, 0);
	if (port->irq < 0) {
		err = -EINVAL;
		goto out_iounmap;
	}

	/* disable the interrupt and clear the status */
	writel(0, port->base + GPIO_IMR);
	writel(~0, port->base + GPIO_ISR);

400
	if (mxc_gpio_hwtype == IMX21_GPIO) {
401
		/* setup one handler for all GPIO interrupts */
402 403 404 405 406 407 408 409 410 411 412 413 414
		if (pdev->id == 0)
			irq_set_chained_handler(port->irq,
						mx2_gpio_irq_handler);
	} else {
		/* setup one handler for each entry */
		irq_set_chained_handler(port->irq, mx3_gpio_irq_handler);
		irq_set_handler_data(port->irq, port);
		if (port->irq_high > 0) {
			/* setup handler for GPIO 16 to 31 */
			irq_set_chained_handler(port->irq_high,
						mx3_gpio_irq_handler);
			irq_set_handler_data(port->irq_high, port);
		}
415 416
	}

417 418 419
	err = bgpio_init(&port->bgc, &pdev->dev, 4,
			 port->base + GPIO_PSR,
			 port->base + GPIO_DR, NULL,
420
			 port->base + GPIO_GDIR, NULL, 0);
421 422
	if (err)
		goto out_iounmap;
423

S
Shawn Guo 已提交
424
	port->bgc.gc.to_irq = mxc_gpio_to_irq;
425
	port->bgc.gc.base = pdev->id * 32;
426 427
	port->bgc.dir = port->bgc.read_reg(port->bgc.reg_dir);
	port->bgc.data = port->bgc.read_reg(port->bgc.reg_set);
428

429
	err = gpiochip_add(&port->bgc.gc);
430
	if (err)
431
		goto out_bgpio_remove;
432

433 434 435 436 437 438 439 440 441 442
	/*
	 * In dt case, we use gpio number range dynamically
	 * allocated by gpio core.
	 */
	port->virtual_irq_start = MXC_GPIO_IRQ_START + (np ? port->bgc.gc.base :
							     pdev->id * 32);

	/* gpio-mxc can be a generic irq chip */
	mxc_gpio_init_gc(port);

443 444
	list_add_tail(&port->node, &mxc_gpio_ports);

445
	return 0;
446

447 448
out_bgpio_remove:
	bgpio_remove(&port->bgc);
449 450 451 452 453 454 455 456
out_iounmap:
	iounmap(port->base);
out_release_mem:
	release_mem_region(iores->start, resource_size(iores));
out_kfree:
	kfree(port);
	dev_info(&pdev->dev, "%s failed with errno %d\n", __func__, err);
	return err;
457
}
458 459 460 461 462

static struct platform_driver mxc_gpio_driver = {
	.driver		= {
		.name	= "gpio-mxc",
		.owner	= THIS_MODULE,
463
		.of_match_table = mxc_gpio_dt_ids,
464 465
	},
	.probe		= mxc_gpio_probe,
466
	.id_table	= mxc_gpio_devtype,
467 468 469 470 471 472 473 474 475 476 477 478 479
};

static int __init gpio_mxc_init(void)
{
	return platform_driver_register(&mxc_gpio_driver);
}
postcore_initcall(gpio_mxc_init);

MODULE_AUTHOR("Freescale Semiconductor, "
	      "Daniel Mack <danielncaiaq.de>, "
	      "Juergen Beisert <kernel@pengutronix.de>");
MODULE_DESCRIPTION("Freescale MXC GPIO");
MODULE_LICENSE("GPL");