gpio-iop.c revision f6ffa5ee039cd0168d82e3edd712ebbb1de93a00
172edd84a6b2db1a21d1ed07929cae560e276a0a6Lennert Buytenhek/*
272edd84a6b2db1a21d1ed07929cae560e276a0a6Lennert Buytenhek * arch/arm/plat-iop/gpio.c
372edd84a6b2db1a21d1ed07929cae560e276a0a6Lennert Buytenhek * GPIO handling for Intel IOP3xx processors.
472edd84a6b2db1a21d1ed07929cae560e276a0a6Lennert Buytenhek *
572edd84a6b2db1a21d1ed07929cae560e276a0a6Lennert Buytenhek * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
672edd84a6b2db1a21d1ed07929cae560e276a0a6Lennert Buytenhek *
772edd84a6b2db1a21d1ed07929cae560e276a0a6Lennert Buytenhek * This program is free software; you can redistribute it and/or modify
872edd84a6b2db1a21d1ed07929cae560e276a0a6Lennert Buytenhek * it under the terms of the GNU General Public License as published by
972edd84a6b2db1a21d1ed07929cae560e276a0a6Lennert Buytenhek * the Free Software Foundation; either version 2 of the License, or (at
1072edd84a6b2db1a21d1ed07929cae560e276a0a6Lennert Buytenhek * your option) any later version.
1172edd84a6b2db1a21d1ed07929cae560e276a0a6Lennert Buytenhek */
1272edd84a6b2db1a21d1ed07929cae560e276a0a6Lennert Buytenhek
1372edd84a6b2db1a21d1ed07929cae560e276a0a6Lennert Buytenhek#include <linux/device.h>
1463f385cd1f649b3f4f2d59fc609e051981215fd7Arnaud Patard#include <linux/init.h>
1563f385cd1f649b3f4f2d59fc609e051981215fd7Arnaud Patard#include <linux/types.h>
1663f385cd1f649b3f4f2d59fc609e051981215fd7Arnaud Patard#include <linux/errno.h>
1763f385cd1f649b3f4f2d59fc609e051981215fd7Arnaud Patard#include <linux/gpio.h>
18dc28094b905a872f8884f1f1c48ca86b3b78583aPaul Gortmaker#include <linux/export.h>
19f6ffa5ee039cd0168d82e3edd712ebbb1de93a00Linus Walleij
20f6ffa5ee039cd0168d82e3edd712ebbb1de93a00Linus Walleij#define IOP3XX_N_GPIOS	8
2172edd84a6b2db1a21d1ed07929cae560e276a0a6Lennert Buytenhek
2272edd84a6b2db1a21d1ed07929cae560e276a0a6Lennert Buytenhekvoid gpio_line_config(int line, int direction)
2372edd84a6b2db1a21d1ed07929cae560e276a0a6Lennert Buytenhek{
2472edd84a6b2db1a21d1ed07929cae560e276a0a6Lennert Buytenhek	unsigned long flags;
2572edd84a6b2db1a21d1ed07929cae560e276a0a6Lennert Buytenhek
2672edd84a6b2db1a21d1ed07929cae560e276a0a6Lennert Buytenhek	local_irq_save(flags);
2772edd84a6b2db1a21d1ed07929cae560e276a0a6Lennert Buytenhek	if (direction == GPIO_IN) {
2872edd84a6b2db1a21d1ed07929cae560e276a0a6Lennert Buytenhek		*IOP3XX_GPOE |= 1 << line;
2972edd84a6b2db1a21d1ed07929cae560e276a0a6Lennert Buytenhek	} else if (direction == GPIO_OUT) {
3072edd84a6b2db1a21d1ed07929cae560e276a0a6Lennert Buytenhek		*IOP3XX_GPOE &= ~(1 << line);
3172edd84a6b2db1a21d1ed07929cae560e276a0a6Lennert Buytenhek	}
3272edd84a6b2db1a21d1ed07929cae560e276a0a6Lennert Buytenhek	local_irq_restore(flags);
3372edd84a6b2db1a21d1ed07929cae560e276a0a6Lennert Buytenhek}
3472edd84a6b2db1a21d1ed07929cae560e276a0a6Lennert BuytenhekEXPORT_SYMBOL(gpio_line_config);
3572edd84a6b2db1a21d1ed07929cae560e276a0a6Lennert Buytenhek
3672edd84a6b2db1a21d1ed07929cae560e276a0a6Lennert Buytenhekint gpio_line_get(int line)
3772edd84a6b2db1a21d1ed07929cae560e276a0a6Lennert Buytenhek{
3872edd84a6b2db1a21d1ed07929cae560e276a0a6Lennert Buytenhek	return !!(*IOP3XX_GPID & (1 << line));
3972edd84a6b2db1a21d1ed07929cae560e276a0a6Lennert Buytenhek}
4072edd84a6b2db1a21d1ed07929cae560e276a0a6Lennert BuytenhekEXPORT_SYMBOL(gpio_line_get);
4172edd84a6b2db1a21d1ed07929cae560e276a0a6Lennert Buytenhek
4272edd84a6b2db1a21d1ed07929cae560e276a0a6Lennert Buytenhekvoid gpio_line_set(int line, int value)
4372edd84a6b2db1a21d1ed07929cae560e276a0a6Lennert Buytenhek{
4472edd84a6b2db1a21d1ed07929cae560e276a0a6Lennert Buytenhek	unsigned long flags;
4572edd84a6b2db1a21d1ed07929cae560e276a0a6Lennert Buytenhek
4672edd84a6b2db1a21d1ed07929cae560e276a0a6Lennert Buytenhek	local_irq_save(flags);
4772edd84a6b2db1a21d1ed07929cae560e276a0a6Lennert Buytenhek	if (value == GPIO_LOW) {
4872edd84a6b2db1a21d1ed07929cae560e276a0a6Lennert Buytenhek		*IOP3XX_GPOD &= ~(1 << line);
4972edd84a6b2db1a21d1ed07929cae560e276a0a6Lennert Buytenhek	} else if (value == GPIO_HIGH) {
5072edd84a6b2db1a21d1ed07929cae560e276a0a6Lennert Buytenhek		*IOP3XX_GPOD |= 1 << line;
5172edd84a6b2db1a21d1ed07929cae560e276a0a6Lennert Buytenhek	}
5272edd84a6b2db1a21d1ed07929cae560e276a0a6Lennert Buytenhek	local_irq_restore(flags);
5372edd84a6b2db1a21d1ed07929cae560e276a0a6Lennert Buytenhek}
5472edd84a6b2db1a21d1ed07929cae560e276a0a6Lennert BuytenhekEXPORT_SYMBOL(gpio_line_set);
5563f385cd1f649b3f4f2d59fc609e051981215fd7Arnaud Patard
5663f385cd1f649b3f4f2d59fc609e051981215fd7Arnaud Patardstatic int iop3xx_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
5763f385cd1f649b3f4f2d59fc609e051981215fd7Arnaud Patard{
5863f385cd1f649b3f4f2d59fc609e051981215fd7Arnaud Patard	gpio_line_config(gpio, GPIO_IN);
5963f385cd1f649b3f4f2d59fc609e051981215fd7Arnaud Patard	return 0;
6063f385cd1f649b3f4f2d59fc609e051981215fd7Arnaud Patard}
6163f385cd1f649b3f4f2d59fc609e051981215fd7Arnaud Patard
6263f385cd1f649b3f4f2d59fc609e051981215fd7Arnaud Patardstatic int iop3xx_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, int level)
6363f385cd1f649b3f4f2d59fc609e051981215fd7Arnaud Patard{
6463f385cd1f649b3f4f2d59fc609e051981215fd7Arnaud Patard	gpio_line_set(gpio, level);
6563f385cd1f649b3f4f2d59fc609e051981215fd7Arnaud Patard	gpio_line_config(gpio, GPIO_OUT);
6663f385cd1f649b3f4f2d59fc609e051981215fd7Arnaud Patard	return 0;
6763f385cd1f649b3f4f2d59fc609e051981215fd7Arnaud Patard}
6863f385cd1f649b3f4f2d59fc609e051981215fd7Arnaud Patard
6963f385cd1f649b3f4f2d59fc609e051981215fd7Arnaud Patardstatic int iop3xx_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
7063f385cd1f649b3f4f2d59fc609e051981215fd7Arnaud Patard{
7163f385cd1f649b3f4f2d59fc609e051981215fd7Arnaud Patard	return gpio_line_get(gpio);
7263f385cd1f649b3f4f2d59fc609e051981215fd7Arnaud Patard}
7363f385cd1f649b3f4f2d59fc609e051981215fd7Arnaud Patard
7463f385cd1f649b3f4f2d59fc609e051981215fd7Arnaud Patardstatic void iop3xx_gpio_set_value(struct gpio_chip *chip, unsigned gpio, int value)
7563f385cd1f649b3f4f2d59fc609e051981215fd7Arnaud Patard{
7663f385cd1f649b3f4f2d59fc609e051981215fd7Arnaud Patard	gpio_line_set(gpio, value);
7763f385cd1f649b3f4f2d59fc609e051981215fd7Arnaud Patard}
7863f385cd1f649b3f4f2d59fc609e051981215fd7Arnaud Patard
7963f385cd1f649b3f4f2d59fc609e051981215fd7Arnaud Patardstatic struct gpio_chip iop3xx_chip = {
8063f385cd1f649b3f4f2d59fc609e051981215fd7Arnaud Patard	.label			= "iop3xx",
8163f385cd1f649b3f4f2d59fc609e051981215fd7Arnaud Patard	.direction_input	= iop3xx_gpio_direction_input,
8263f385cd1f649b3f4f2d59fc609e051981215fd7Arnaud Patard	.get			= iop3xx_gpio_get_value,
8363f385cd1f649b3f4f2d59fc609e051981215fd7Arnaud Patard	.direction_output	= iop3xx_gpio_direction_output,
8463f385cd1f649b3f4f2d59fc609e051981215fd7Arnaud Patard	.set			= iop3xx_gpio_set_value,
8563f385cd1f649b3f4f2d59fc609e051981215fd7Arnaud Patard	.base			= 0,
8663f385cd1f649b3f4f2d59fc609e051981215fd7Arnaud Patard	.ngpio			= IOP3XX_N_GPIOS,
8763f385cd1f649b3f4f2d59fc609e051981215fd7Arnaud Patard};
8863f385cd1f649b3f4f2d59fc609e051981215fd7Arnaud Patard
8963f385cd1f649b3f4f2d59fc609e051981215fd7Arnaud Patardstatic int __init iop3xx_gpio_setup(void)
9063f385cd1f649b3f4f2d59fc609e051981215fd7Arnaud Patard{
9163f385cd1f649b3f4f2d59fc609e051981215fd7Arnaud Patard	return gpiochip_add(&iop3xx_chip);
9263f385cd1f649b3f4f2d59fc609e051981215fd7Arnaud Patard}
9363f385cd1f649b3f4f2d59fc609e051981215fd7Arnaud Patardarch_initcall(iop3xx_gpio_setup);
94