Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.2.
  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 <linux/gpio.h>
 12#include <asm/blackfin.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_data(&bf538_portc_chip, NULL) |
120		gpiochip_add_data(&bf538_portd_chip, NULL) |
121		gpiochip_add_data(&bf538_porte_chip, NULL);
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