]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/gpio/zynq_gpio.c
tpm: tpm_tis_i2c: Move definitions into the header file
[karo-tx-uboot.git] / drivers / gpio / zynq_gpio.c
1 /*
2  * Xilinx Zynq GPIO device driver
3  *
4  * Copyright (C) 2015 DAVE Embedded Systems <devel@dave.eu>
5  *
6  * Most of code taken from linux kernel driver (linux/drivers/gpio/gpio-zynq.c)
7  * Copyright (C) 2009 - 2014 Xilinx, Inc.
8  *
9  * SPDX-License-Identifier:     GPL-2.0+
10  */
11
12 #include <common.h>
13 #include <asm/gpio.h>
14 #include <asm/io.h>
15 #include <asm/errno.h>
16
17 /**
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
22  *              pin
23  * @bank_pin_num: an output parameter used to return pin number within a bank
24  *                for the given gpio pin
25  *
26  * Returns the bank number and pin offset within the bank.
27  */
28 static inline void zynq_gpio_get_bank_pin(unsigned int pin_num,
29                                           unsigned int *bank_num,
30                                           unsigned int *bank_pin_num)
31 {
32         switch (pin_num) {
33         case ZYNQ_GPIO_BANK0_PIN_MIN ... ZYNQ_GPIO_BANK0_PIN_MAX:
34                 *bank_num = 0;
35                 *bank_pin_num = pin_num;
36                 break;
37         case ZYNQ_GPIO_BANK1_PIN_MIN ... ZYNQ_GPIO_BANK1_PIN_MAX:
38                 *bank_num = 1;
39                 *bank_pin_num = pin_num - ZYNQ_GPIO_BANK1_PIN_MIN;
40                 break;
41         case ZYNQ_GPIO_BANK2_PIN_MIN ... ZYNQ_GPIO_BANK2_PIN_MAX:
42                 *bank_num = 2;
43                 *bank_pin_num = pin_num - ZYNQ_GPIO_BANK2_PIN_MIN;
44                 break;
45         case ZYNQ_GPIO_BANK3_PIN_MIN ... ZYNQ_GPIO_BANK3_PIN_MAX:
46                 *bank_num = 3;
47                 *bank_pin_num = pin_num - ZYNQ_GPIO_BANK3_PIN_MIN;
48                 break;
49         default:
50                 printf("invalid GPIO pin number: %u\n", pin_num);
51                 *bank_num = 0;
52                 *bank_pin_num = 0;
53                 break;
54         }
55 }
56
57 int gpio_is_valid(unsigned gpio)
58 {
59         return (gpio >= 0) && (gpio < ZYNQ_GPIO_NR_GPIOS);
60 }
61
62 static int check_gpio(unsigned gpio)
63 {
64         if (!gpio_is_valid(gpio)) {
65                 printf("ERROR : check_gpio: invalid GPIO %d\n", gpio);
66                 return -1;
67         }
68         return 0;
69 }
70
71 /**
72  * gpio_get_value - Get the state of the specified pin of GPIO device
73  * @gpio:       gpio pin number within the device
74  *
75  * This function reads the state of the specified pin of the GPIO device.
76  *
77  * Return: 0 if the pin is low, 1 if pin is high.
78  */
79 int gpio_get_value(unsigned gpio)
80 {
81         u32 data;
82         unsigned int bank_num, bank_pin_num;
83
84         if (check_gpio(gpio) < 0)
85                 return -1;
86
87         zynq_gpio_get_bank_pin(gpio, &bank_num, &bank_pin_num);
88
89         data = readl(ZYNQ_GPIO_BASE_ADDRESS +
90                              ZYNQ_GPIO_DATA_RO_OFFSET(bank_num));
91
92         return (data >> bank_pin_num) & 1;
93 }
94
95 /**
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
99  *
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.
103  */
104 int gpio_set_value(unsigned gpio, int value)
105 {
106         unsigned int reg_offset, bank_num, bank_pin_num;
107
108         if (check_gpio(gpio) < 0)
109                 return -1;
110
111         zynq_gpio_get_bank_pin(gpio, &bank_num, &bank_pin_num);
112
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);
117         } else {
118                 reg_offset = ZYNQ_GPIO_DATA_LSW_OFFSET(bank_num);
119         }
120
121         /*
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
124          */
125         value = !!value;
126         value = ~(1 << (bank_pin_num + ZYNQ_GPIO_MID_PIN_NUM)) &
127                 ((value << bank_pin_num) | ZYNQ_GPIO_UPPER_MASK);
128
129         writel(value, ZYNQ_GPIO_BASE_ADDRESS + reg_offset);
130
131         return 0;
132 }
133
134 /**
135  * gpio_direction_input - Set the direction of the specified GPIO pin as input
136  * @gpio:       gpio pin number within the device
137  *
138  * This function uses the read-modify-write sequence to set the direction of
139  * the gpio pin as input.
140  *
141  * Return: -1 if invalid gpio specified, 0 if successul
142  */
143 int gpio_direction_input(unsigned gpio)
144 {
145         u32 reg;
146         unsigned int bank_num, bank_pin_num;
147
148         if (check_gpio(gpio) < 0)
149                 return -1;
150
151         zynq_gpio_get_bank_pin(gpio, &bank_num, &bank_pin_num);
152
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))
155                 return -1;
156
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));
161
162         return 0;
163 }
164
165 /**
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
169  *
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.
173  *
174  * Return: 0 always
175  */
176 int gpio_direction_output(unsigned gpio, int value)
177 {
178         u32 reg;
179         unsigned int bank_num, bank_pin_num;
180
181         if (check_gpio(gpio) < 0)
182                 return -1;
183
184         zynq_gpio_get_bank_pin(gpio, &bank_num, &bank_pin_num);
185
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));
190
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));
195
196         /* set the state of the pin */
197         gpio_set_value(gpio, value);
198         return 0;
199 }
200
201 /**
202  * Request a gpio before using it.
203  *
204  * NOTE: Argument 'label' is unused.
205  */
206 int gpio_request(unsigned gpio, const char *label)
207 {
208         if (check_gpio(gpio) < 0)
209                 return -1;
210
211         return 0;
212 }
213
214 /**
215  * Reset and free the gpio after using it.
216  */
217 int gpio_free(unsigned gpio)
218 {
219         return 0;
220 }