Path: blob/master/arch/blackfin/mach-bf538/ext-gpio.c
10817 views
/*1* GPIOLIB interface for BF538/9 PORT C, D, and E GPIOs2*3* Copyright 2009 Analog Devices Inc.4*5* Licensed under the GPL-2 or later.6*/78#include <linux/module.h>9#include <linux/err.h>10#include <asm/blackfin.h>11#include <asm/gpio.h>12#include <asm/portmux.h>1314#define DEFINE_REG(reg, off) \15static inline u16 read_##reg(void __iomem *port) \16{ return bfin_read16(port + off); } \17static inline void write_##reg(void __iomem *port, u16 v) \18{ bfin_write16(port + off, v); }1920DEFINE_REG(PORTIO, 0x00)21DEFINE_REG(PORTIO_CLEAR, 0x10)22DEFINE_REG(PORTIO_SET, 0x20)23DEFINE_REG(PORTIO_DIR, 0x40)24DEFINE_REG(PORTIO_INEN, 0x50)2526static void __iomem *gpio_chip_to_mmr(struct gpio_chip *chip)27{28switch (chip->base) {29default: /* not really needed, but keeps gcc happy */30case GPIO_PC0: return (void __iomem *)PORTCIO;31case GPIO_PD0: return (void __iomem *)PORTDIO;32case GPIO_PE0: return (void __iomem *)PORTEIO;33}34}3536static int bf538_gpio_get_value(struct gpio_chip *chip, unsigned gpio)37{38void __iomem *port = gpio_chip_to_mmr(chip);39return !!(read_PORTIO(port) & (1u << gpio));40}4142static void bf538_gpio_set_value(struct gpio_chip *chip, unsigned gpio, int value)43{44void __iomem *port = gpio_chip_to_mmr(chip);45if (value)46write_PORTIO_SET(port, (1u << gpio));47else48write_PORTIO_CLEAR(port, (1u << gpio));49}5051static int bf538_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)52{53void __iomem *port = gpio_chip_to_mmr(chip);54write_PORTIO_DIR(port, read_PORTIO_DIR(port) & ~(1u << gpio));55write_PORTIO_INEN(port, read_PORTIO_INEN(port) | (1u << gpio));56return 0;57}5859static int bf538_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, int value)60{61void __iomem *port = gpio_chip_to_mmr(chip);62write_PORTIO_INEN(port, read_PORTIO_INEN(port) & ~(1u << gpio));63bf538_gpio_set_value(port, gpio, value);64write_PORTIO_DIR(port, read_PORTIO_DIR(port) | (1u << gpio));65return 0;66}6768static int bf538_gpio_request(struct gpio_chip *chip, unsigned gpio)69{70return bfin_special_gpio_request(chip->base + gpio, chip->label);71}7273static void bf538_gpio_free(struct gpio_chip *chip, unsigned gpio)74{75return bfin_special_gpio_free(chip->base + gpio);76}7778/* We don't set the irq fields as these banks cannot generate interrupts */7980static struct gpio_chip bf538_portc_chip = {81.label = "GPIO-PC",82.direction_input = bf538_gpio_direction_input,83.get = bf538_gpio_get_value,84.direction_output = bf538_gpio_direction_output,85.set = bf538_gpio_set_value,86.request = bf538_gpio_request,87.free = bf538_gpio_free,88.base = GPIO_PC0,89.ngpio = GPIO_PC9 - GPIO_PC0 + 1,90};9192static struct gpio_chip bf538_portd_chip = {93.label = "GPIO-PD",94.direction_input = bf538_gpio_direction_input,95.get = bf538_gpio_get_value,96.direction_output = bf538_gpio_direction_output,97.set = bf538_gpio_set_value,98.request = bf538_gpio_request,99.free = bf538_gpio_free,100.base = GPIO_PD0,101.ngpio = GPIO_PD13 - GPIO_PD0 + 1,102};103104static struct gpio_chip bf538_porte_chip = {105.label = "GPIO-PE",106.direction_input = bf538_gpio_direction_input,107.get = bf538_gpio_get_value,108.direction_output = bf538_gpio_direction_output,109.set = bf538_gpio_set_value,110.request = bf538_gpio_request,111.free = bf538_gpio_free,112.base = GPIO_PE0,113.ngpio = GPIO_PE15 - GPIO_PE0 + 1,114};115116static int __init bf538_extgpio_setup(void)117{118return gpiochip_add(&bf538_portc_chip) |119gpiochip_add(&bf538_portd_chip) |120gpiochip_add(&bf538_porte_chip);121}122arch_initcall(bf538_extgpio_setup);123124125