Kirkwood: add Marvell Kirkwood gpio driver
Signed-off-by: Dieter Kiermaier <dk-arm-linux@gmx.de> Acked-by: Prafulla Wadaskar <prafulla@marvell.com> Tested-by: Heiko Schocher <hs@denx.de>
This commit is contained in:
parent
688b6a0ff2
commit
ec16441085
@ -25,6 +25,7 @@ include $(TOPDIR)/config.mk
|
||||
|
||||
LIB := $(obj)libgpio.a
|
||||
|
||||
COBJS-$(CONFIG_KIRKWOOD_GPIO) += kw_gpio.o
|
||||
COBJS-$(CONFIG_MX31_GPIO) += mx31_gpio.o
|
||||
COBJS-$(CONFIG_PCA953X) += pca953x.o
|
||||
|
||||
|
151
drivers/gpio/kw_gpio.c
Normal file
151
drivers/gpio/kw_gpio.c
Normal file
@ -0,0 +1,151 @@
|
||||
/*
|
||||
* arch/arm/plat-orion/gpio.c
|
||||
*
|
||||
* Marvell Orion SoC GPIO handling.
|
||||
*
|
||||
* This file is licensed under the terms of the GNU General Public
|
||||
* License version 2. This program is licensed "as is" without any
|
||||
* warranty of any kind, whether express or implied.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Based on (mostly copied from) plat-orion based Linux 2.6 kernel driver.
|
||||
* Removed orion_gpiochip struct and kernel level irq handling.
|
||||
*
|
||||
* Dieter Kiermaier dk-arm-linux@gmx.de
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/bitops.h>
|
||||
#include <asm/arch/kirkwood.h>
|
||||
#include <asm/arch/gpio.h>
|
||||
|
||||
static unsigned long gpio_valid_input[BITS_TO_LONGS(GPIO_MAX)];
|
||||
static unsigned long gpio_valid_output[BITS_TO_LONGS(GPIO_MAX)];
|
||||
|
||||
void __set_direction(unsigned pin, int input)
|
||||
{
|
||||
u32 u;
|
||||
|
||||
u = readl(GPIO_IO_CONF(pin));
|
||||
if (input)
|
||||
u |= 1 << (pin & 31);
|
||||
else
|
||||
u &= ~(1 << (pin & 31));
|
||||
writel(u, GPIO_IO_CONF(pin));
|
||||
|
||||
u = readl(GPIO_IO_CONF(pin));
|
||||
}
|
||||
|
||||
void __set_level(unsigned pin, int high)
|
||||
{
|
||||
u32 u;
|
||||
|
||||
u = readl(GPIO_OUT(pin));
|
||||
if (high)
|
||||
u |= 1 << (pin & 31);
|
||||
else
|
||||
u &= ~(1 << (pin & 31));
|
||||
writel(u, GPIO_OUT(pin));
|
||||
}
|
||||
|
||||
void __set_blinking(unsigned pin, int blink)
|
||||
{
|
||||
u32 u;
|
||||
|
||||
u = readl(GPIO_BLINK_EN(pin));
|
||||
if (blink)
|
||||
u |= 1 << (pin & 31);
|
||||
else
|
||||
u &= ~(1 << (pin & 31));
|
||||
writel(u, GPIO_BLINK_EN(pin));
|
||||
}
|
||||
|
||||
int kw_gpio_is_valid(unsigned pin, int mode)
|
||||
{
|
||||
if (pin < GPIO_MAX) {
|
||||
if ((mode & GPIO_INPUT_OK) && !test_bit(pin, gpio_valid_input))
|
||||
goto err_out;
|
||||
|
||||
if ((mode & GPIO_OUTPUT_OK) && !test_bit(pin, gpio_valid_output))
|
||||
goto err_out;
|
||||
return 0;
|
||||
}
|
||||
|
||||
err_out:
|
||||
printf("%s: invalid GPIO %d\n", __func__, pin);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void kw_gpio_set_valid(unsigned pin, int mode)
|
||||
{
|
||||
if (mode == 1)
|
||||
mode = GPIO_INPUT_OK | GPIO_OUTPUT_OK;
|
||||
if (mode & GPIO_INPUT_OK)
|
||||
__set_bit(pin, gpio_valid_input);
|
||||
else
|
||||
__clear_bit(pin, gpio_valid_input);
|
||||
if (mode & GPIO_OUTPUT_OK)
|
||||
__set_bit(pin, gpio_valid_output);
|
||||
else
|
||||
__clear_bit(pin, gpio_valid_output);
|
||||
}
|
||||
/*
|
||||
* GENERIC_GPIO primitives.
|
||||
*/
|
||||
int kw_gpio_direction_input(unsigned pin)
|
||||
{
|
||||
if (!kw_gpio_is_valid(pin, GPIO_INPUT_OK))
|
||||
return 1;
|
||||
|
||||
/* Configure GPIO direction. */
|
||||
__set_direction(pin, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kw_gpio_direction_output(unsigned pin, int value)
|
||||
{
|
||||
if (kw_gpio_is_valid(pin, GPIO_OUTPUT_OK) != 0)
|
||||
{
|
||||
printf("%s: invalid GPIO %d\n", __func__, pin);
|
||||
return 1;
|
||||
}
|
||||
|
||||
__set_blinking(pin, 0);
|
||||
|
||||
/* Configure GPIO output value. */
|
||||
__set_level(pin, value);
|
||||
|
||||
/* Configure GPIO direction. */
|
||||
__set_direction(pin, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kw_gpio_get_value(unsigned pin)
|
||||
{
|
||||
int val;
|
||||
|
||||
if (readl(GPIO_IO_CONF(pin)) & (1 << (pin & 31)))
|
||||
val = readl(GPIO_DATA_IN(pin)) ^ readl(GPIO_IN_POL(pin));
|
||||
else
|
||||
val = readl(GPIO_OUT(pin));
|
||||
|
||||
return (val >> (pin & 31)) & 1;
|
||||
}
|
||||
|
||||
void kw_gpio_set_value(unsigned pin, int value)
|
||||
{
|
||||
/* Configure GPIO output value. */
|
||||
__set_level(pin, value);
|
||||
}
|
||||
|
||||
void kw_gpio_set_blink(unsigned pin, int blink)
|
||||
{
|
||||
/* Set output value to zero. */
|
||||
__set_level(pin, 0);
|
||||
|
||||
/* Set blinking. */
|
||||
__set_blinking(pin, blink);
|
||||
}
|
51
include/asm-arm/arch-kirkwood/gpio.h
Normal file
51
include/asm-arm/arch-kirkwood/gpio.h
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* arch/asm-arm/mach-kirkwood/include/mach/gpio.h
|
||||
*
|
||||
* This file is licensed under the terms of the GNU General Public
|
||||
* License version 2. This program is licensed "as is" without any
|
||||
* warranty of any kind, whether express or implied.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Based on (mostly copied from) plat-orion based Linux 2.6 kernel driver.
|
||||
* Removed kernel level irq handling. Took some macros from kernel to
|
||||
* allow build.
|
||||
*
|
||||
* Dieter Kiermaier dk-arm-linux@gmx.de
|
||||
*/
|
||||
|
||||
#ifndef __KIRKWOOD_GPIO_H
|
||||
#define __KIRKWOOD_GPIO_H
|
||||
|
||||
/* got from kernel include/linux/kernel.h */
|
||||
#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
|
||||
/* got from kernel include/linux/bitops.h */
|
||||
#define BITS_PER_BYTE 8
|
||||
#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
|
||||
|
||||
#define GPIO_MAX 50
|
||||
#define GPIO_OFF(pin) (((pin) >> 5) ? 0x0040 : 0x0000)
|
||||
#define GPIO_OUT(pin) (KW_GPIO0_BASE + GPIO_OFF(pin) + 0x00)
|
||||
#define GPIO_IO_CONF(pin) (KW_GPIO0_BASE + GPIO_OFF(pin) + 0x04)
|
||||
#define GPIO_BLINK_EN(pin) (KW_GPIO0_BASE + GPIO_OFF(pin) + 0x08)
|
||||
#define GPIO_IN_POL(pin) (KW_GPIO0_BASE + GPIO_OFF(pin) + 0x0c)
|
||||
#define GPIO_DATA_IN(pin) (KW_GPIO0_BASE + GPIO_OFF(pin) + 0x10)
|
||||
#define GPIO_EDGE_CAUSE(pin) (KW_GPIO0_BASE + GPIO_OFF(pin) + 0x14)
|
||||
#define GPIO_EDGE_MASK(pin) (KW_GPIO0_BASE + GPIO_OFF(pin) + 0x18)
|
||||
#define GPIO_LEVEL_MASK(pin) (KW_GPIO0_BASE + GPIO_OFF(pin) + 0x1c)
|
||||
|
||||
/*
|
||||
* Kirkwood-specific GPIO API
|
||||
*/
|
||||
int kw_gpio_is_valid(unsigned pin, int mode);
|
||||
int kw_gpio_direction_input(unsigned pin);
|
||||
int kw_gpio_direction_output(unsigned pin, int value);
|
||||
int kw_gpio_get_value(unsigned pin);
|
||||
void kw_gpio_set_value(unsigned pin, int value);
|
||||
void kw_gpio_set_blink(unsigned pin, int blink);
|
||||
void kw_gpio_set_unused(unsigned pin);
|
||||
|
||||
#define GPIO_INPUT_OK (1 << 0)
|
||||
#define GPIO_OUTPUT_OK (1 << 1)
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user