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