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