]> git.ipfire.org Git - people/ms/u-boot.git/blame - drivers/gpio/zynq_gpio.c
gpio: zynq: Remove non driver model code
[people/ms/u-boot.git] / drivers / gpio / zynq_gpio.c
CommitLineData
d37c6288
AS
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>
68c7026e
SDPP
16#include <dm.h>
17#include <fdtdec.h>
18
19DECLARE_GLOBAL_DATA_PTR;
20
21struct zynq_gpio_privdata {
22 phys_addr_t base;
23};
68c7026e 24
d37c6288
AS
25/**
26 * zynq_gpio_get_bank_pin - Get the bank number and pin number within that bank
27 * for a given pin in the GPIO device
28 * @pin_num: gpio pin number within the device
29 * @bank_num: an output parameter used to return the bank number of the gpio
30 * pin
31 * @bank_pin_num: an output parameter used to return pin number within a bank
32 * for the given gpio pin
33 *
34 * Returns the bank number and pin offset within the bank.
35 */
36static inline void zynq_gpio_get_bank_pin(unsigned int pin_num,
37 unsigned int *bank_num,
38 unsigned int *bank_pin_num)
39{
40 switch (pin_num) {
41 case ZYNQ_GPIO_BANK0_PIN_MIN ... ZYNQ_GPIO_BANK0_PIN_MAX:
42 *bank_num = 0;
43 *bank_pin_num = pin_num;
44 break;
45 case ZYNQ_GPIO_BANK1_PIN_MIN ... ZYNQ_GPIO_BANK1_PIN_MAX:
46 *bank_num = 1;
47 *bank_pin_num = pin_num - ZYNQ_GPIO_BANK1_PIN_MIN;
48 break;
49 case ZYNQ_GPIO_BANK2_PIN_MIN ... ZYNQ_GPIO_BANK2_PIN_MAX:
50 *bank_num = 2;
51 *bank_pin_num = pin_num - ZYNQ_GPIO_BANK2_PIN_MIN;
52 break;
53 case ZYNQ_GPIO_BANK3_PIN_MIN ... ZYNQ_GPIO_BANK3_PIN_MAX:
54 *bank_num = 3;
55 *bank_pin_num = pin_num - ZYNQ_GPIO_BANK3_PIN_MIN;
56 break;
57 default:
58 printf("invalid GPIO pin number: %u\n", pin_num);
59 *bank_num = 0;
60 *bank_pin_num = 0;
61 break;
62 }
63}
64
de77a03b 65static int gpio_is_valid(unsigned gpio)
d37c6288
AS
66{
67 return (gpio >= 0) && (gpio < ZYNQ_GPIO_NR_GPIOS);
68}
69
70static int check_gpio(unsigned gpio)
71{
72 if (!gpio_is_valid(gpio)) {
73 printf("ERROR : check_gpio: invalid GPIO %d\n", gpio);
74 return -1;
75 }
76 return 0;
77}
78
68c7026e
SDPP
79static int zynq_gpio_get_value(struct udevice *dev, unsigned gpio)
80{
81 u32 data;
82 unsigned int bank_num, bank_pin_num;
83 struct zynq_gpio_privdata *priv = dev_get_priv(dev);
84
85 if (check_gpio(gpio) < 0)
86 return -1;
87
88 zynq_gpio_get_bank_pin(gpio, &bank_num, &bank_pin_num);
89
90 data = readl(priv->base +
91 ZYNQ_GPIO_DATA_RO_OFFSET(bank_num));
92
93 return (data >> bank_pin_num) & 1;
94}
95
96static int zynq_gpio_set_value(struct udevice *dev, unsigned gpio, int value)
97{
98 unsigned int reg_offset, bank_num, bank_pin_num;
99 struct zynq_gpio_privdata *priv = dev_get_priv(dev);
100
101 if (check_gpio(gpio) < 0)
102 return -1;
103
104 zynq_gpio_get_bank_pin(gpio, &bank_num, &bank_pin_num);
105
106 if (bank_pin_num >= ZYNQ_GPIO_MID_PIN_NUM) {
107 /* only 16 data bits in bit maskable reg */
108 bank_pin_num -= ZYNQ_GPIO_MID_PIN_NUM;
109 reg_offset = ZYNQ_GPIO_DATA_MSW_OFFSET(bank_num);
110 } else {
111 reg_offset = ZYNQ_GPIO_DATA_LSW_OFFSET(bank_num);
112 }
113
114 /*
115 * get the 32 bit value to be written to the mask/data register where
116 * the upper 16 bits is the mask and lower 16 bits is the data
117 */
118 value = !!value;
119 value = ~(1 << (bank_pin_num + ZYNQ_GPIO_MID_PIN_NUM)) &
120 ((value << bank_pin_num) | ZYNQ_GPIO_UPPER_MASK);
121
122 writel(value, priv->base + reg_offset);
123
124 return 0;
125}
126
127static int zynq_gpio_direction_input(struct udevice *dev, unsigned gpio)
128{
129 u32 reg;
130 unsigned int bank_num, bank_pin_num;
131 struct zynq_gpio_privdata *priv = dev_get_priv(dev);
132
133 if (check_gpio(gpio) < 0)
134 return -1;
135
136 zynq_gpio_get_bank_pin(gpio, &bank_num, &bank_pin_num);
137
138 /* bank 0 pins 7 and 8 are special and cannot be used as inputs */
139 if (bank_num == 0 && (bank_pin_num == 7 || bank_pin_num == 8))
140 return -1;
141
142 /* clear the bit in direction mode reg to set the pin as input */
143 reg = readl(priv->base + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
144 reg &= ~BIT(bank_pin_num);
145 writel(reg, priv->base + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
146
147 return 0;
148}
149
150static int zynq_gpio_direction_output(struct udevice *dev, unsigned gpio,
151 int value)
152{
153 u32 reg;
154 unsigned int bank_num, bank_pin_num;
155 struct zynq_gpio_privdata *priv = dev_get_priv(dev);
156
157 if (check_gpio(gpio) < 0)
158 return -1;
159
160 zynq_gpio_get_bank_pin(gpio, &bank_num, &bank_pin_num);
161
162 /* set the GPIO pin as output */
163 reg = readl(priv->base + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
164 reg |= BIT(bank_pin_num);
165 writel(reg, priv->base + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
166
167 /* configure the output enable reg for the pin */
168 reg = readl(priv->base + ZYNQ_GPIO_OUTEN_OFFSET(bank_num));
169 reg |= BIT(bank_pin_num);
170 writel(reg, priv->base + ZYNQ_GPIO_OUTEN_OFFSET(bank_num));
171
172 /* set the state of the pin */
173 gpio_set_value(gpio, value);
174 return 0;
175}
176
177static const struct dm_gpio_ops gpio_zynq_ops = {
178 .direction_input = zynq_gpio_direction_input,
179 .direction_output = zynq_gpio_direction_output,
180 .get_value = zynq_gpio_get_value,
181 .set_value = zynq_gpio_set_value,
182};
183
184static int zynq_gpio_probe(struct udevice *dev)
185{
186 struct zynq_gpio_privdata *priv = dev_get_priv(dev);
187
188 priv->base = dev_get_addr(dev);
189
190 return 0;
191}
192
193static int zynq_gpio_ofdata_to_platdata(struct udevice *dev)
194{
195 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
196
197 uc_priv->gpio_count = ZYNQ_GPIO_NR_GPIOS;
198
199 return 0;
200}
201
202static const struct udevice_id zynq_gpio_ids[] = {
203 { .compatible = "xlnx,zynq-gpio-1.0" },
204 { }
205};
206
207U_BOOT_DRIVER(gpio_zynq) = {
208 .name = "gpio_zynq",
209 .id = UCLASS_GPIO,
210 .ops = &gpio_zynq_ops,
211 .of_match = zynq_gpio_ids,
212 .ofdata_to_platdata = zynq_gpio_ofdata_to_platdata,
213 .probe = zynq_gpio_probe,
214 .priv_auto_alloc_size = sizeof(struct zynq_gpio_privdata),
215};