d71f5259a34562f0a152cac43f94fe62df14bb63
[oweals/u-boot.git] / drivers / gpio / atmel_pio4.c
1 /*
2  * Atmel PIO4 device driver
3  *
4  * Copyright (C) 2015 Atmel Corporation
5  *               Wenyou.Yang <wenyou.yang@atmel.com>
6  *
7  * SPDX-License-Identifier:     GPL-2.0+
8  */
9 #include <common.h>
10 #include <dm.h>
11 #include <asm/arch/hardware.h>
12 #include <mach/gpio.h>
13 #include <mach/atmel_pio4.h>
14
15 #define ATMEL_PIO4_PINS_PER_BANK        32
16
17 /*
18  * Register Field Definitions
19  */
20 #define ATMEL_PIO4_CFGR_FUNC    (0x7 << 0)
21 #define         ATMEL_PIO4_CFGR_FUNC_GPIO       (0x0 << 0)
22 #define         ATMEL_PIO4_CFGR_FUNC_PERIPH_A   (0x1 << 0)
23 #define         ATMEL_PIO4_CFGR_FUNC_PERIPH_B   (0x2 << 0)
24 #define         ATMEL_PIO4_CFGR_FUNC_PERIPH_C   (0x3 << 0)
25 #define         ATMEL_PIO4_CFGR_FUNC_PERIPH_D   (0x4 << 0)
26 #define         ATMEL_PIO4_CFGR_FUNC_PERIPH_E   (0x5 << 0)
27 #define         ATMEL_PIO4_CFGR_FUNC_PERIPH_F   (0x6 << 0)
28 #define         ATMEL_PIO4_CFGR_FUNC_PERIPH_G   (0x7 << 0)
29 #define ATMEL_PIO4_CFGR_DIR     (0x1 << 8)
30 #define ATMEL_PIO4_CFGR_PUEN    (0x1 << 9)
31 #define ATMEL_PIO4_CFGR_PDEN    (0x1 << 10)
32 #define ATMEL_PIO4_CFGR_IFEN    (0x1 << 12)
33 #define ATMEL_PIO4_CFGR_IFSCEN  (0x1 << 13)
34 #define ATMEL_PIO4_CFGR_OPD     (0x1 << 14)
35 #define ATMEL_PIO4_CFGR_SCHMITT (0x1 << 15)
36 #define ATMEL_PIO4_CFGR_DRVSTR  (0x3 << 16)
37 #define         ATMEL_PIO4_CFGR_DRVSTR_LOW0     (0x0 << 16)
38 #define         ATMEL_PIO4_CFGR_DRVSTR_LOW1     (0x1 << 16)
39 #define         ATMEL_PIO4_CFGR_DRVSTR_MEDIUM   (0x2 << 16)
40 #define         ATMEL_PIO4_CFGR_DRVSTR_HIGH     (0x3 << 16)
41 #define ATMEL_PIO4_CFGR_EVTSEL  (0x7 << 24)
42 #define         ATMEL_PIO4_CFGR_EVTSEL_FALLING  (0x0 << 24)
43 #define         ATMEL_PIO4_CFGR_EVTSEL_RISING   (0x1 << 24)
44 #define         ATMEL_PIO4_CFGR_EVTSEL_BOTH     (0x2 << 24)
45 #define         ATMEL_PIO4_CFGR_EVTSEL_LOW      (0x3 << 24)
46 #define         ATMEL_PIO4_CFGR_EVTSEL_HIGH     (0x4 << 24)
47 #define ATMEL_PIO4_CFGR_PCFS    (0x1 << 29)
48 #define ATMEL_PIO4_CFGR_ICFS    (0x1 << 30)
49
50 static struct atmel_pio4_port *atmel_pio4_port_base(u32 port)
51 {
52         struct atmel_pio4_port *base = NULL;
53
54         switch (port) {
55         case AT91_PIO_PORTA:
56                 base = (struct atmel_pio4_port *)ATMEL_BASE_PIOA;
57                 break;
58         case AT91_PIO_PORTB:
59                 base = (struct atmel_pio4_port *)ATMEL_BASE_PIOB;
60                 break;
61         case AT91_PIO_PORTC:
62                 base = (struct atmel_pio4_port *)ATMEL_BASE_PIOC;
63                 break;
64         case AT91_PIO_PORTD:
65                 base = (struct atmel_pio4_port *)ATMEL_BASE_PIOD;
66                 break;
67         default:
68                 printf("Error: Atmel PIO4: Failed to get PIO base of port#%d!\n",
69                        port);
70                 break;
71         }
72
73         return base;
74 }
75
76 static int atmel_pio4_config_io_func(u32 port, u32 pin,
77                                      u32 func, u32 use_pullup)
78 {
79         struct atmel_pio4_port *port_base;
80         u32 reg, mask;
81
82         if (pin >= ATMEL_PIO4_PINS_PER_BANK)
83                 return -ENODEV;
84
85         port_base = atmel_pio4_port_base(port);
86         if (!port_base)
87                 return -ENODEV;
88
89         mask = 1 << pin;
90         reg = func;
91         reg |= use_pullup ? ATMEL_PIO4_CFGR_PUEN : 0;
92
93         writel(mask, &port_base->mskr);
94         writel(reg, &port_base->cfgr);
95
96         return 0;
97 }
98
99 int atmel_pio4_set_gpio(u32 port, u32 pin, u32 use_pullup)
100 {
101         return atmel_pio4_config_io_func(port, pin,
102                                          ATMEL_PIO4_CFGR_FUNC_GPIO,
103                                          use_pullup);
104 }
105
106 int atmel_pio4_set_a_periph(u32 port, u32 pin, u32 use_pullup)
107 {
108         return atmel_pio4_config_io_func(port, pin,
109                                          ATMEL_PIO4_CFGR_FUNC_PERIPH_A,
110                                          use_pullup);
111 }
112
113 int atmel_pio4_set_b_periph(u32 port, u32 pin, u32 use_pullup)
114 {
115         return atmel_pio4_config_io_func(port, pin,
116                                          ATMEL_PIO4_CFGR_FUNC_PERIPH_B,
117                                          use_pullup);
118 }
119
120 int atmel_pio4_set_c_periph(u32 port, u32 pin, u32 use_pullup)
121 {
122         return atmel_pio4_config_io_func(port, pin,
123                                          ATMEL_PIO4_CFGR_FUNC_PERIPH_C,
124                                          use_pullup);
125 }
126
127 int atmel_pio4_set_d_periph(u32 port, u32 pin, u32 use_pullup)
128 {
129         return atmel_pio4_config_io_func(port, pin,
130                                          ATMEL_PIO4_CFGR_FUNC_PERIPH_D,
131                                          use_pullup);
132 }
133
134 int atmel_pio4_set_e_periph(u32 port, u32 pin, u32 use_pullup)
135 {
136         return atmel_pio4_config_io_func(port, pin,
137                                          ATMEL_PIO4_CFGR_FUNC_PERIPH_E,
138                                          use_pullup);
139 }
140
141 int atmel_pio4_set_f_periph(u32 port, u32 pin, u32 use_pullup)
142 {
143         return atmel_pio4_config_io_func(port, pin,
144                                          ATMEL_PIO4_CFGR_FUNC_PERIPH_F,
145                                          use_pullup);
146 }
147
148 int atmel_pio4_set_g_periph(u32 port, u32 pin, u32 use_pullup)
149 {
150         return atmel_pio4_config_io_func(port, pin,
151                                          ATMEL_PIO4_CFGR_FUNC_PERIPH_G,
152                                          use_pullup);
153 }
154
155 int atmel_pio4_set_pio_output(u32 port, u32 pin, u32 value)
156 {
157         struct atmel_pio4_port *port_base;
158         u32 reg, mask;
159
160         if (pin >= ATMEL_PIO4_PINS_PER_BANK)
161                 return -ENODEV;
162
163         port_base = atmel_pio4_port_base(port);
164         if (!port_base)
165                 return -ENODEV;
166
167         mask = 0x01 << pin;
168         reg = ATMEL_PIO4_CFGR_FUNC_GPIO | ATMEL_PIO4_CFGR_DIR;
169
170         writel(mask, &port_base->mskr);
171         writel(reg, &port_base->cfgr);
172
173         if (value)
174                 writel(mask, &port_base->sodr);
175         else
176                 writel(mask, &port_base->codr);
177
178         return 0;
179 }
180
181 int atmel_pio4_get_pio_input(u32 port, u32 pin)
182 {
183         struct atmel_pio4_port *port_base;
184         u32 reg, mask;
185
186         if (pin >= ATMEL_PIO4_PINS_PER_BANK)
187                 return -ENODEV;
188
189         port_base = atmel_pio4_port_base(port);
190         if (!port_base)
191                 return -ENODEV;
192
193         mask = 0x01 << pin;
194         reg = ATMEL_PIO4_CFGR_FUNC_GPIO;
195
196         writel(mask, &port_base->mskr);
197         writel(reg, &port_base->cfgr);
198
199         return (readl(&port_base->pdsr) & mask) ? 1 : 0;
200 }
201
202 #ifdef CONFIG_DM_GPIO
203 static int atmel_pio4_direction_input(struct udevice *dev, unsigned offset)
204 {
205         struct at91_port_platdata *plat = dev_get_platdata(dev);
206         struct atmel_pio4_port *port_base = (atmel_pio4_port *)plat->base_addr;
207         u32 mask = 0x01 << offset;
208         u32 reg = ATMEL_PIO4_CFGR_FUNC_GPIO;
209
210         writel(mask, &port_base->mskr);
211         writel(reg, &port_base->cfgr);
212
213         return 0;
214 }
215
216 static int atmel_pio4_direction_output(struct udevice *dev,
217                                        unsigned offset, int value)
218 {
219         struct at91_port_platdata *plat = dev_get_platdata(dev);
220         struct atmel_pio4_port *port_base = (atmel_pio4_port *)plat->base_addr;
221         u32 mask = 0x01 << offset;
222         u32 reg = ATMEL_PIO4_CFGR_FUNC_GPIO | ATMEL_PIO4_CFGR_DIR;
223
224         writel(mask, &port_base->mskr);
225         writel(reg, &port_base->cfgr);
226
227         if (value)
228                 writel(mask, &port_base->sodr);
229         else
230                 writel(mask, &port_base->codr);
231
232         return 0;
233 }
234
235 static int atmel_pio4_get_value(struct udevice *dev, unsigned offset)
236 {
237         struct at91_port_platdata *plat = dev_get_platdata(dev);
238         struct atmel_pio4_port *port_base = (atmel_pio4_port *)plat->base_addr;
239         u32 mask = 0x01 << offset;
240
241         return (readl(&port_base->pdsr) & mask) ? 1 : 0;
242 }
243
244 static int atmel_pio4_set_value(struct udevice *dev,
245                                 unsigned offset, int value)
246 {
247         struct at91_port_platdata *plat = dev_get_platdata(dev);
248         struct atmel_pio4_port *port_base = (atmel_pio4_port *)plat->base_addr;
249         u32 mask = 0x01 << offset;
250
251         if (value)
252                 writel(mask, &port_base->sodr);
253         else
254                 writel(mask, &port_base->codr);
255
256         return 0;
257 }
258
259 static int atmel_pio4_get_function(struct udevice *dev, unsigned offset)
260 {
261         struct at91_port_platdata *plat = dev_get_platdata(dev);
262         struct atmel_pio4_port *port_base = (atmel_pio4_port *)plat->base_addr;
263         u32 mask = 0x01 << offset;
264
265         writel(mask, &port_base->mskr);
266
267         return (readl(&port_base->cfgr) &
268                 ATMEL_PIO4_CFGR_DIR) ? GPIOF_OUTPUT : GPIOF_INPUT;
269 }
270
271 static const struct dm_gpio_ops atmel_pio4_ops = {
272         .direction_input        = atmel_pio4_direction_input,
273         .direction_output       = atmel_pio4_direction_output,
274         .get_value              = atmel_pio4_get_value,
275         .set_value              = atmel_pio4_set_value,
276         .get_function           = atmel_pio4_get_function,
277 };
278
279 static int atmel_pio4_probe(struct udevice *dev)
280 {
281         struct at91_port_platdata *plat = dev_get_platdata(dev);
282         struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
283
284         uc_priv->bank_name = plat->bank_name;
285         uc_priv->gpio_count = ATMEL_PIO4_PINS_PER_BANK;
286
287         return 0;
288 }
289
290 U_BOOT_DRIVER(gpio_atmel_pio4) = {
291         .name   = "gpio_atmel_pio4",
292         .id     = UCLASS_GPIO,
293         .ops    = &atmel_pio4_ops,
294         .probe  = atmel_pio4_probe,
295 };
296 #endif