linux/arch/blackfin/mach-bf538/ext-gpio.c
<<
>>
Prefs
   1/*
   2 * GPIOLIB interface for BF538/9 PORT C, D, and E GPIOs
   3 *
   4 * Copyright 2009-2011 Analog Devices Inc.
   5 *
   6 * Licensed under the GPL-2 or later.
   7 */
   8
   9#include <linux/module.h>
  10#include <linux/err.h>
  11#include <asm/blackfin.h>
  12#include <asm/gpio.h>
  13#include <asm/portmux.h>
  14
  15#define DEFINE_REG(reg, off) \
  16static inline u16 read_##reg(void __iomem *port) \
  17        { return bfin_read16(port + off); } \
  18static inline void write_##reg(void __iomem *port, u16 v) \
  19        { bfin_write16(port + off, v); }
  20
  21DEFINE_REG(PORTIO, 0x00)
  22DEFINE_REG(PORTIO_CLEAR, 0x10)
  23DEFINE_REG(PORTIO_SET, 0x20)
  24DEFINE_REG(PORTIO_DIR, 0x40)
  25DEFINE_REG(PORTIO_INEN, 0x50)
  26
  27static void __iomem *gpio_chip_to_mmr(struct gpio_chip *chip)
  28{
  29        switch (chip->base) {
  30        default: /* not really needed, but keeps gcc happy */
  31        case GPIO_PC0: return (void __iomem *)PORTCIO;
  32        case GPIO_PD0: return (void __iomem *)PORTDIO;
  33        case GPIO_PE0: return (void __iomem *)PORTEIO;
  34        }
  35}
  36
  37static int bf538_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
  38{
  39        void __iomem *port = gpio_chip_to_mmr(chip);
  40        return !!(read_PORTIO(port) & (1u << gpio));
  41}
  42
  43static void bf538_gpio_set_value(struct gpio_chip *chip, unsigned gpio, int value)
  44{
  45        void __iomem *port = gpio_chip_to_mmr(chip);
  46        if (value)
  47                write_PORTIO_SET(port, (1u << gpio));
  48        else
  49                write_PORTIO_CLEAR(port, (1u << gpio));
  50}
  51
  52static int bf538_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
  53{
  54        void __iomem *port = gpio_chip_to_mmr(chip);
  55        write_PORTIO_DIR(port, read_PORTIO_DIR(port) & ~(1u << gpio));
  56        write_PORTIO_INEN(port, read_PORTIO_INEN(port) | (1u << gpio));
  57        return 0;
  58}
  59
  60static int bf538_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, int value)
  61{
  62        void __iomem *port = gpio_chip_to_mmr(chip);
  63        write_PORTIO_INEN(port, read_PORTIO_INEN(port) & ~(1u << gpio));
  64        bf538_gpio_set_value(port, gpio, value);
  65        write_PORTIO_DIR(port, read_PORTIO_DIR(port) | (1u << gpio));
  66        return 0;
  67}
  68
  69static int bf538_gpio_request(struct gpio_chip *chip, unsigned gpio)
  70{
  71        return bfin_special_gpio_request(chip->base + gpio, chip->label);
  72}
  73
  74static void bf538_gpio_free(struct gpio_chip *chip, unsigned gpio)
  75{
  76        return bfin_special_gpio_free(chip->base + gpio);
  77}
  78
  79/* We don't set the irq fields as these banks cannot generate interrupts */
  80
  81static struct gpio_chip bf538_portc_chip = {
  82        .label = "GPIO-PC",
  83        .direction_input = bf538_gpio_direction_input,
  84        .get = bf538_gpio_get_value,
  85        .direction_output = bf538_gpio_direction_output,
  86        .set = bf538_gpio_set_value,
  87        .request = bf538_gpio_request,
  88        .free = bf538_gpio_free,
  89        .base = GPIO_PC0,
  90        .ngpio = GPIO_PC9 - GPIO_PC0 + 1,
  91};
  92
  93static struct gpio_chip bf538_portd_chip = {
  94        .label = "GPIO-PD",
  95        .direction_input = bf538_gpio_direction_input,
  96        .get = bf538_gpio_get_value,
  97        .direction_output = bf538_gpio_direction_output,
  98        .set = bf538_gpio_set_value,
  99        .request = bf538_gpio_request,
 100        .free = bf538_gpio_free,
 101        .base = GPIO_PD0,
 102        .ngpio = GPIO_PD13 - GPIO_PD0 + 1,
 103};
 104
 105static struct gpio_chip bf538_porte_chip = {
 106        .label = "GPIO-PE",
 107        .direction_input = bf538_gpio_direction_input,
 108        .get = bf538_gpio_get_value,
 109        .direction_output = bf538_gpio_direction_output,
 110        .set = bf538_gpio_set_value,
 111        .request = bf538_gpio_request,
 112        .free = bf538_gpio_free,
 113        .base = GPIO_PE0,
 114        .ngpio = GPIO_PE15 - GPIO_PE0 + 1,
 115};
 116
 117static int __init bf538_extgpio_setup(void)
 118{
 119        return gpiochip_add(&bf538_portc_chip) |
 120                gpiochip_add(&bf538_portd_chip) |
 121                gpiochip_add(&bf538_porte_chip);
 122}
 123arch_initcall(bf538_extgpio_setup);
 124
 125#ifdef CONFIG_PM
 126static struct {
 127        u16 data, dir, inen;
 128} gpio_bank_saved[3];
 129
 130static void __iomem * const port_bases[3] = {
 131        (void *)PORTCIO,
 132        (void *)PORTDIO,
 133        (void *)PORTEIO,
 134};
 135
 136void bfin_special_gpio_pm_hibernate_suspend(void)
 137{
 138        int i;
 139
 140        for (i = 0; i < ARRAY_SIZE(port_bases); ++i) {
 141                gpio_bank_saved[i].data = read_PORTIO(port_bases[i]);
 142                gpio_bank_saved[i].inen = read_PORTIO_INEN(port_bases[i]);
 143                gpio_bank_saved[i].dir = read_PORTIO_DIR(port_bases[i]);
 144        }
 145}
 146
 147void bfin_special_gpio_pm_hibernate_restore(void)
 148{
 149        int i;
 150
 151        for (i = 0; i < ARRAY_SIZE(port_bases); ++i) {
 152                write_PORTIO_INEN(port_bases[i], gpio_bank_saved[i].inen);
 153                write_PORTIO_SET(port_bases[i],
 154                        gpio_bank_saved[i].data & gpio_bank_saved[i].dir);
 155                write_PORTIO_DIR(port_bases[i], gpio_bank_saved[i].dir);
 156        }
 157}
 158#endif
 159