2 * Xilinx Zynq GPIO device driver
4 * Copyright (C) 2015 DAVE Embedded Systems <devel@dave.eu>
6 * Most of code taken from linux kernel driver (linux/drivers/gpio/gpio-zynq.c)
7 * Copyright (C) 2009 - 2014 Xilinx, Inc.
9 * SPDX-License-Identifier: GPL-2.0+
15 #include <asm/errno.h>
18 * zynq_gpio_get_bank_pin - Get the bank number and pin number within that bank
19 * for a given pin in the GPIO device
20 * @pin_num: gpio pin number within the device
21 * @bank_num: an output parameter used to return the bank number of the gpio
23 * @bank_pin_num: an output parameter used to return pin number within a bank
24 * for the given gpio pin
26 * Returns the bank number and pin offset within the bank.
28 static inline void zynq_gpio_get_bank_pin(unsigned int pin_num,
29 unsigned int *bank_num,
30 unsigned int *bank_pin_num)
33 case ZYNQ_GPIO_BANK0_PIN_MIN ... ZYNQ_GPIO_BANK0_PIN_MAX:
35 *bank_pin_num = pin_num;
37 case ZYNQ_GPIO_BANK1_PIN_MIN ... ZYNQ_GPIO_BANK1_PIN_MAX:
39 *bank_pin_num = pin_num - ZYNQ_GPIO_BANK1_PIN_MIN;
41 case ZYNQ_GPIO_BANK2_PIN_MIN ... ZYNQ_GPIO_BANK2_PIN_MAX:
43 *bank_pin_num = pin_num - ZYNQ_GPIO_BANK2_PIN_MIN;
45 case ZYNQ_GPIO_BANK3_PIN_MIN ... ZYNQ_GPIO_BANK3_PIN_MAX:
47 *bank_pin_num = pin_num - ZYNQ_GPIO_BANK3_PIN_MIN;
50 printf("invalid GPIO pin number: %u\n", pin_num);
57 int gpio_is_valid(unsigned gpio)
59 return (gpio >= 0) && (gpio < ZYNQ_GPIO_NR_GPIOS);
62 static int check_gpio(unsigned gpio)
64 if (!gpio_is_valid(gpio)) {
65 printf("ERROR : check_gpio: invalid GPIO %d\n", gpio);
72 * gpio_get_value - Get the state of the specified pin of GPIO device
73 * @gpio: gpio pin number within the device
75 * This function reads the state of the specified pin of the GPIO device.
77 * Return: 0 if the pin is low, 1 if pin is high.
79 int gpio_get_value(unsigned gpio)
82 unsigned int bank_num, bank_pin_num;
84 if (check_gpio(gpio) < 0)
87 zynq_gpio_get_bank_pin(gpio, &bank_num, &bank_pin_num);
89 data = readl(ZYNQ_GPIO_BASE_ADDRESS +
90 ZYNQ_GPIO_DATA_RO_OFFSET(bank_num));
92 return (data >> bank_pin_num) & 1;
96 * gpio_set_value - Modify the value of the pin with specified value
97 * @gpio: gpio pin number within the device
98 * @value: value used to modify the value of the specified pin
100 * This function calculates the register offset (i.e to lower 16 bits or
101 * upper 16 bits) based on the given pin number and sets the value of a
102 * gpio pin to the specified value. The value is either 0 or non-zero.
104 int gpio_set_value(unsigned gpio, int value)
106 unsigned int reg_offset, bank_num, bank_pin_num;
108 if (check_gpio(gpio) < 0)
111 zynq_gpio_get_bank_pin(gpio, &bank_num, &bank_pin_num);
113 if (bank_pin_num >= ZYNQ_GPIO_MID_PIN_NUM) {
114 /* only 16 data bits in bit maskable reg */
115 bank_pin_num -= ZYNQ_GPIO_MID_PIN_NUM;
116 reg_offset = ZYNQ_GPIO_DATA_MSW_OFFSET(bank_num);
118 reg_offset = ZYNQ_GPIO_DATA_LSW_OFFSET(bank_num);
122 * get the 32 bit value to be written to the mask/data register where
123 * the upper 16 bits is the mask and lower 16 bits is the data
126 value = ~(1 << (bank_pin_num + ZYNQ_GPIO_MID_PIN_NUM)) &
127 ((value << bank_pin_num) | ZYNQ_GPIO_UPPER_MASK);
129 writel(value, ZYNQ_GPIO_BASE_ADDRESS + reg_offset);
135 * gpio_direction_input - Set the direction of the specified GPIO pin as input
136 * @gpio: gpio pin number within the device
138 * This function uses the read-modify-write sequence to set the direction of
139 * the gpio pin as input.
141 * Return: -1 if invalid gpio specified, 0 if successul
143 int gpio_direction_input(unsigned gpio)
146 unsigned int bank_num, bank_pin_num;
148 if (check_gpio(gpio) < 0)
151 zynq_gpio_get_bank_pin(gpio, &bank_num, &bank_pin_num);
153 /* bank 0 pins 7 and 8 are special and cannot be used as inputs */
154 if (bank_num == 0 && (bank_pin_num == 7 || bank_pin_num == 8))
157 /* clear the bit in direction mode reg to set the pin as input */
158 reg = readl(ZYNQ_GPIO_BASE_ADDRESS + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
159 reg &= ~BIT(bank_pin_num);
160 writel(reg, ZYNQ_GPIO_BASE_ADDRESS + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
166 * gpio_direction_output - Set the direction of the specified GPIO pin as output
167 * @gpio: gpio pin number within the device
168 * @value: value to be written to specified pin
170 * This function sets the direction of specified GPIO pin as output, configures
171 * the Output Enable register for the pin and uses zynq_gpio_set to set
172 * the value of the pin to the value specified.
176 int gpio_direction_output(unsigned gpio, int value)
179 unsigned int bank_num, bank_pin_num;
181 if (check_gpio(gpio) < 0)
184 zynq_gpio_get_bank_pin(gpio, &bank_num, &bank_pin_num);
186 /* set the GPIO pin as output */
187 reg = readl(ZYNQ_GPIO_BASE_ADDRESS + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
188 reg |= BIT(bank_pin_num);
189 writel(reg, ZYNQ_GPIO_BASE_ADDRESS + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
191 /* configure the output enable reg for the pin */
192 reg = readl(ZYNQ_GPIO_BASE_ADDRESS + ZYNQ_GPIO_OUTEN_OFFSET(bank_num));
193 reg |= BIT(bank_pin_num);
194 writel(reg, ZYNQ_GPIO_BASE_ADDRESS + ZYNQ_GPIO_OUTEN_OFFSET(bank_num));
196 /* set the state of the pin */
197 gpio_set_value(gpio, value);
202 * Request a gpio before using it.
204 * NOTE: Argument 'label' is unused.
206 int gpio_request(unsigned gpio, const char *label)
208 if (check_gpio(gpio) < 0)
215 * Reset and free the gpio after using it.
217 int gpio_free(unsigned gpio)