]> git.sur5r.net Git - u-boot/blob - drivers/gpio/atmel_pio4.c
gpio: sunxi: Add compatible string for H5 PIO
[u-boot] / 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 <clk.h>
11 #include <dm.h>
12 #include <fdtdec.h>
13 #include <asm/arch/hardware.h>
14 #include <asm/gpio.h>
15 #include <mach/gpio.h>
16 #include <mach/atmel_pio4.h>
17
18 DECLARE_GLOBAL_DATA_PTR;
19
20 static struct atmel_pio4_port *atmel_pio4_port_base(u32 port)
21 {
22         struct atmel_pio4_port *base = NULL;
23
24         switch (port) {
25         case AT91_PIO_PORTA:
26                 base = (struct atmel_pio4_port *)ATMEL_BASE_PIOA;
27                 break;
28         case AT91_PIO_PORTB:
29                 base = (struct atmel_pio4_port *)ATMEL_BASE_PIOB;
30                 break;
31         case AT91_PIO_PORTC:
32                 base = (struct atmel_pio4_port *)ATMEL_BASE_PIOC;
33                 break;
34         case AT91_PIO_PORTD:
35                 base = (struct atmel_pio4_port *)ATMEL_BASE_PIOD;
36                 break;
37         default:
38                 printf("Error: Atmel PIO4: Failed to get PIO base of port#%d!\n",
39                        port);
40                 break;
41         }
42
43         return base;
44 }
45
46 static int atmel_pio4_config_io_func(u32 port, u32 pin,
47                                      u32 func, u32 use_pullup)
48 {
49         struct atmel_pio4_port *port_base;
50         u32 reg, mask;
51
52         if (pin >= ATMEL_PIO_NPINS_PER_BANK)
53                 return -EINVAL;
54
55         port_base = atmel_pio4_port_base(port);
56         if (!port_base)
57                 return -EINVAL;
58
59         mask = 1 << pin;
60         reg = func;
61         reg |= use_pullup ? ATMEL_PIO_PUEN_MASK : 0;
62
63         writel(mask, &port_base->mskr);
64         writel(reg, &port_base->cfgr);
65
66         return 0;
67 }
68
69 int atmel_pio4_set_gpio(u32 port, u32 pin, u32 use_pullup)
70 {
71         return atmel_pio4_config_io_func(port, pin,
72                                          ATMEL_PIO_CFGR_FUNC_GPIO,
73                                          use_pullup);
74 }
75
76 int atmel_pio4_set_a_periph(u32 port, u32 pin, u32 use_pullup)
77 {
78         return atmel_pio4_config_io_func(port, pin,
79                                          ATMEL_PIO_CFGR_FUNC_PERIPH_A,
80                                          use_pullup);
81 }
82
83 int atmel_pio4_set_b_periph(u32 port, u32 pin, u32 use_pullup)
84 {
85         return atmel_pio4_config_io_func(port, pin,
86                                          ATMEL_PIO_CFGR_FUNC_PERIPH_B,
87                                          use_pullup);
88 }
89
90 int atmel_pio4_set_c_periph(u32 port, u32 pin, u32 use_pullup)
91 {
92         return atmel_pio4_config_io_func(port, pin,
93                                          ATMEL_PIO_CFGR_FUNC_PERIPH_C,
94                                          use_pullup);
95 }
96
97 int atmel_pio4_set_d_periph(u32 port, u32 pin, u32 use_pullup)
98 {
99         return atmel_pio4_config_io_func(port, pin,
100                                          ATMEL_PIO_CFGR_FUNC_PERIPH_D,
101                                          use_pullup);
102 }
103
104 int atmel_pio4_set_e_periph(u32 port, u32 pin, u32 use_pullup)
105 {
106         return atmel_pio4_config_io_func(port, pin,
107                                          ATMEL_PIO_CFGR_FUNC_PERIPH_E,
108                                          use_pullup);
109 }
110
111 int atmel_pio4_set_f_periph(u32 port, u32 pin, u32 use_pullup)
112 {
113         return atmel_pio4_config_io_func(port, pin,
114                                          ATMEL_PIO_CFGR_FUNC_PERIPH_F,
115                                          use_pullup);
116 }
117
118 int atmel_pio4_set_g_periph(u32 port, u32 pin, u32 use_pullup)
119 {
120         return atmel_pio4_config_io_func(port, pin,
121                                          ATMEL_PIO_CFGR_FUNC_PERIPH_G,
122                                          use_pullup);
123 }
124
125 int atmel_pio4_set_pio_output(u32 port, u32 pin, u32 value)
126 {
127         struct atmel_pio4_port *port_base;
128         u32 reg, mask;
129
130         if (pin >= ATMEL_PIO_NPINS_PER_BANK)
131                 return -EINVAL;
132
133         port_base = atmel_pio4_port_base(port);
134         if (!port_base)
135                 return -EINVAL;
136
137         mask = 0x01 << pin;
138         reg = ATMEL_PIO_CFGR_FUNC_GPIO | ATMEL_PIO_DIR_MASK;
139
140         writel(mask, &port_base->mskr);
141         writel(reg, &port_base->cfgr);
142
143         if (value)
144                 writel(mask, &port_base->sodr);
145         else
146                 writel(mask, &port_base->codr);
147
148         return 0;
149 }
150
151 int atmel_pio4_get_pio_input(u32 port, u32 pin)
152 {
153         struct atmel_pio4_port *port_base;
154         u32 reg, mask;
155
156         if (pin >= ATMEL_PIO_NPINS_PER_BANK)
157                 return -EINVAL;
158
159         port_base = atmel_pio4_port_base(port);
160         if (!port_base)
161                 return -EINVAL;
162
163         mask = 0x01 << pin;
164         reg = ATMEL_PIO_CFGR_FUNC_GPIO;
165
166         writel(mask, &port_base->mskr);
167         writel(reg, &port_base->cfgr);
168
169         return (readl(&port_base->pdsr) & mask) ? 1 : 0;
170 }
171
172 #ifdef CONFIG_DM_GPIO
173
174 struct atmel_pioctrl_data {
175         u32 nbanks;
176 };
177
178 struct atmel_pio4_platdata {
179         struct atmel_pio4_port *reg_base;
180 };
181
182 static struct atmel_pio4_port *atmel_pio4_bank_base(struct udevice *dev,
183                                                     u32 bank)
184 {
185         struct atmel_pio4_platdata *plat = dev_get_platdata(dev);
186         struct atmel_pio4_port *port_base =
187                         (struct atmel_pio4_port *)((u32)plat->reg_base +
188                         ATMEL_PIO_BANK_OFFSET * bank);
189
190         return port_base;
191 }
192
193 static int atmel_pio4_direction_input(struct udevice *dev, unsigned offset)
194 {
195         u32 bank = ATMEL_PIO_BANK(offset);
196         u32 line = ATMEL_PIO_LINE(offset);
197         struct atmel_pio4_port *port_base = atmel_pio4_bank_base(dev, bank);
198         u32 mask = BIT(line);
199
200         writel(mask, &port_base->mskr);
201
202         clrbits_le32(&port_base->cfgr,
203                      ATMEL_PIO_CFGR_FUNC_MASK | ATMEL_PIO_DIR_MASK);
204
205         return 0;
206 }
207
208 static int atmel_pio4_direction_output(struct udevice *dev,
209                                        unsigned offset, int value)
210 {
211         u32 bank = ATMEL_PIO_BANK(offset);
212         u32 line = ATMEL_PIO_LINE(offset);
213         struct atmel_pio4_port *port_base = atmel_pio4_bank_base(dev, bank);
214         u32 mask = BIT(line);
215
216         writel(mask, &port_base->mskr);
217
218         clrsetbits_le32(&port_base->cfgr,
219                         ATMEL_PIO_CFGR_FUNC_MASK, ATMEL_PIO_DIR_MASK);
220
221         if (value)
222                 writel(mask, &port_base->sodr);
223         else
224                 writel(mask, &port_base->codr);
225
226         return 0;
227 }
228
229 static int atmel_pio4_get_value(struct udevice *dev, unsigned offset)
230 {
231         u32 bank = ATMEL_PIO_BANK(offset);
232         u32 line = ATMEL_PIO_LINE(offset);
233         struct atmel_pio4_port *port_base = atmel_pio4_bank_base(dev, bank);
234         u32 mask = BIT(line);
235
236         return (readl(&port_base->pdsr) & mask) ? 1 : 0;
237 }
238
239 static int atmel_pio4_set_value(struct udevice *dev,
240                                 unsigned offset, int value)
241 {
242         u32 bank = ATMEL_PIO_BANK(offset);
243         u32 line = ATMEL_PIO_LINE(offset);
244         struct atmel_pio4_port *port_base = atmel_pio4_bank_base(dev, bank);
245         u32 mask = BIT(line);
246
247         if (value)
248                 writel(mask, &port_base->sodr);
249         else
250                 writel(mask, &port_base->codr);
251
252         return 0;
253 }
254
255 static int atmel_pio4_get_function(struct udevice *dev, unsigned offset)
256 {
257         u32 bank = ATMEL_PIO_BANK(offset);
258         u32 line = ATMEL_PIO_LINE(offset);
259         struct atmel_pio4_port *port_base = atmel_pio4_bank_base(dev, bank);
260         u32 mask = BIT(line);
261
262         writel(mask, &port_base->mskr);
263
264         return (readl(&port_base->cfgr) &
265                 ATMEL_PIO_DIR_MASK) ? GPIOF_OUTPUT : GPIOF_INPUT;
266 }
267
268 static const struct dm_gpio_ops atmel_pio4_ops = {
269         .direction_input        = atmel_pio4_direction_input,
270         .direction_output       = atmel_pio4_direction_output,
271         .get_value              = atmel_pio4_get_value,
272         .set_value              = atmel_pio4_set_value,
273         .get_function           = atmel_pio4_get_function,
274 };
275
276 static int atmel_pio4_bind(struct udevice *dev)
277 {
278         return dm_scan_fdt_dev(dev);
279 }
280
281 static int atmel_pio4_probe(struct udevice *dev)
282 {
283         struct atmel_pio4_platdata *plat = dev_get_platdata(dev);
284         struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
285         struct atmel_pioctrl_data *pioctrl_data;
286         struct clk clk;
287         fdt_addr_t addr_base;
288         u32 nbanks;
289         int ret;
290
291         ret = clk_get_by_index(dev, 0, &clk);
292         if (ret)
293                 return ret;
294
295         ret = clk_enable(&clk);
296         if (ret)
297                 return ret;
298
299         clk_free(&clk);
300
301         addr_base = devfdt_get_addr(dev);
302         if (addr_base == FDT_ADDR_T_NONE)
303                 return -EINVAL;
304
305         plat->reg_base = (struct atmel_pio4_port *)addr_base;
306
307         pioctrl_data = (struct atmel_pioctrl_data *)dev_get_driver_data(dev);
308         nbanks = pioctrl_data->nbanks;
309
310         uc_priv->bank_name = fdt_get_name(gd->fdt_blob, dev_of_offset(dev),
311                                           NULL);
312         uc_priv->gpio_count = nbanks * ATMEL_PIO_NPINS_PER_BANK;
313
314         return 0;
315 }
316
317 /*
318  * The number of banks can be different from a SoC to another one.
319  * We can have up to 16 banks.
320  */
321 static const struct atmel_pioctrl_data atmel_sama5d2_pioctrl_data = {
322         .nbanks = 4,
323 };
324
325 static const struct udevice_id atmel_pio4_ids[] = {
326         {
327                 .compatible = "atmel,sama5d2-gpio",
328                 .data = (ulong)&atmel_sama5d2_pioctrl_data,
329         },
330         {}
331 };
332
333 U_BOOT_DRIVER(gpio_atmel_pio4) = {
334         .name   = "gpio_atmel_pio4",
335         .id     = UCLASS_GPIO,
336         .ops    = &atmel_pio4_ops,
337         .probe  = atmel_pio4_probe,
338         .bind   = atmel_pio4_bind,
339         .of_match = atmel_pio4_ids,
340         .platdata_auto_alloc_size = sizeof(struct atmel_pio4_platdata),
341 };
342
343 #endif