/* * s6000 gpio driver * * Copyright (c) 2009 emlix GmbH * Authors: Oskar Schirmer * Johannes Weiner */ #include #include #include #include #include #include #define S6_GPIO_DATA 0x000 #define S6_GPIO_IS 0x404 #define S6_GPIO_IBE 0x408 #define S6_GPIO_IEV 0x40C #define S6_GPIO_IE 0x410 #define S6_GPIO_RIS 0x414 #define S6_GPIO_MIS 0x418 #define S6_GPIO_IC 0x41C #define S6_GPIO_AFSEL 0x420 #define S6_GPIO_DIR 0x800 #define S6_GPIO_BANK(nr) ((nr) * 0x1000) #define S6_GPIO_MASK(nr) (4 << (nr)) #define S6_GPIO_OFFSET(nr) \ (S6_GPIO_BANK((nr) >> 3) + S6_GPIO_MASK((nr) & 7)) static int direction_input(struct gpio_chip *chip, unsigned int off) { writeb(0, S6_REG_GPIO + S6_GPIO_DIR + S6_GPIO_OFFSET(off)); return 0; } static int get(struct gpio_chip *chip, unsigned int off) { return readb(S6_REG_GPIO + S6_GPIO_DATA + S6_GPIO_OFFSET(off)); } static int direction_output(struct gpio_chip *chip, unsigned int off, int val) { unsigned rel = S6_GPIO_OFFSET(off); writeb(~0, S6_REG_GPIO + S6_GPIO_DIR + rel); writeb(val ? ~0 : 0, S6_REG_GPIO + S6_GPIO_DATA + rel); return 0; } static void set(struct gpio_chip *chip, unsigned int off, int val) { writeb(val ? ~0 : 0, S6_REG_GPIO + S6_GPIO_DATA + S6_GPIO_OFFSET(off)); } static struct gpio_chip gpiochip = { .owner = THIS_MODULE, .direction_input = direction_input, .get = get, .direction_output = direction_output, .set = set, .base = 0, .ngpio = 24, .can_sleep = 0, /* no blocking io needed */ .exported = 0, /* no exporting to userspace */ }; static int gpio_init(void) { return gpiochip_add(&gpiochip); } device_initcall(gpio_init);