84e8cc5fe8552e864157dc141a280d4c2e603634
[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 static struct atmel_pio4_port *atmel_pio4_port_base(u32 port)
16 {
17         struct atmel_pio4_port *base = NULL;
18
19         switch (port) {
20         case AT91_PIO_PORTA:
21                 base = (struct atmel_pio4_port *)ATMEL_BASE_PIOA;
22                 break;
23         case AT91_PIO_PORTB:
24                 base = (struct atmel_pio4_port *)ATMEL_BASE_PIOB;
25                 break;
26         case AT91_PIO_PORTC:
27                 base = (struct atmel_pio4_port *)ATMEL_BASE_PIOC;
28                 break;
29         case AT91_PIO_PORTD:
30                 base = (struct atmel_pio4_port *)ATMEL_BASE_PIOD;
31                 break;
32         default:
33                 printf("Error: Atmel PIO4: Failed to get PIO base of port#%d!\n",
34                        port);
35                 break;
36         }
37
38         return base;
39 }
40
41 static int atmel_pio4_config_io_func(u32 port, u32 pin,
42                                      u32 func, u32 use_pullup)
43 {
44         struct atmel_pio4_port *port_base;
45         u32 reg, mask;
46
47         if (pin >= ATMEL_PIO_NPINS_PER_BANK)
48                 return -ENODEV;
49
50         port_base = atmel_pio4_port_base(port);
51         if (!port_base)
52                 return -ENODEV;
53
54         mask = 1 << pin;
55         reg = func;
56         reg |= use_pullup ? ATMEL_PIO_PUEN_MASK : 0;
57
58         writel(mask, &port_base->mskr);
59         writel(reg, &port_base->cfgr);
60
61         return 0;
62 }
63
64 int atmel_pio4_set_gpio(u32 port, u32 pin, u32 use_pullup)
65 {
66         return atmel_pio4_config_io_func(port, pin,
67                                          ATMEL_PIO_CFGR_FUNC_GPIO,
68                                          use_pullup);
69 }
70
71 int atmel_pio4_set_a_periph(u32 port, u32 pin, u32 use_pullup)
72 {
73         return atmel_pio4_config_io_func(port, pin,
74                                          ATMEL_PIO_CFGR_FUNC_PERIPH_A,
75                                          use_pullup);
76 }
77
78 int atmel_pio4_set_b_periph(u32 port, u32 pin, u32 use_pullup)
79 {
80         return atmel_pio4_config_io_func(port, pin,
81                                          ATMEL_PIO_CFGR_FUNC_PERIPH_B,
82                                          use_pullup);
83 }
84
85 int atmel_pio4_set_c_periph(u32 port, u32 pin, u32 use_pullup)
86 {
87         return atmel_pio4_config_io_func(port, pin,
88                                          ATMEL_PIO_CFGR_FUNC_PERIPH_C,
89                                          use_pullup);
90 }
91
92 int atmel_pio4_set_d_periph(u32 port, u32 pin, u32 use_pullup)
93 {
94         return atmel_pio4_config_io_func(port, pin,
95                                          ATMEL_PIO_CFGR_FUNC_PERIPH_D,
96                                          use_pullup);
97 }
98
99 int atmel_pio4_set_e_periph(u32 port, u32 pin, u32 use_pullup)
100 {
101         return atmel_pio4_config_io_func(port, pin,
102                                          ATMEL_PIO_CFGR_FUNC_PERIPH_E,
103                                          use_pullup);
104 }
105
106 int atmel_pio4_set_f_periph(u32 port, u32 pin, u32 use_pullup)
107 {
108         return atmel_pio4_config_io_func(port, pin,
109                                          ATMEL_PIO_CFGR_FUNC_PERIPH_F,
110                                          use_pullup);
111 }
112
113 int atmel_pio4_set_g_periph(u32 port, u32 pin, u32 use_pullup)
114 {
115         return atmel_pio4_config_io_func(port, pin,
116                                          ATMEL_PIO_CFGR_FUNC_PERIPH_G,
117                                          use_pullup);
118 }
119
120 int atmel_pio4_set_pio_output(u32 port, u32 pin, u32 value)
121 {
122         struct atmel_pio4_port *port_base;
123         u32 reg, mask;
124
125         if (pin >= ATMEL_PIO_NPINS_PER_BANK)
126                 return -ENODEV;
127
128         port_base = atmel_pio4_port_base(port);
129         if (!port_base)
130                 return -ENODEV;
131
132         mask = 0x01 << pin;
133         reg = ATMEL_PIO_CFGR_FUNC_GPIO | ATMEL_PIO_DIR_MASK;
134
135         writel(mask, &port_base->mskr);
136         writel(reg, &port_base->cfgr);
137
138         if (value)
139                 writel(mask, &port_base->sodr);
140         else
141                 writel(mask, &port_base->codr);
142
143         return 0;
144 }
145
146 int atmel_pio4_get_pio_input(u32 port, u32 pin)
147 {
148         struct atmel_pio4_port *port_base;
149         u32 reg, mask;
150
151         if (pin >= ATMEL_PIO_NPINS_PER_BANK)
152                 return -ENODEV;
153
154         port_base = atmel_pio4_port_base(port);
155         if (!port_base)
156                 return -ENODEV;
157
158         mask = 0x01 << pin;
159         reg = ATMEL_PIO_CFGR_FUNC_GPIO;
160
161         writel(mask, &port_base->mskr);
162         writel(reg, &port_base->cfgr);
163
164         return (readl(&port_base->pdsr) & mask) ? 1 : 0;
165 }
166
167 #ifdef CONFIG_DM_GPIO
168 static int atmel_pio4_direction_input(struct udevice *dev, unsigned offset)
169 {
170         struct at91_port_platdata *plat = dev_get_platdata(dev);
171         struct atmel_pio4_port *port_base = (atmel_pio4_port *)plat->base_addr;
172         u32 mask = 0x01 << offset;
173         u32 reg = ATMEL_PIO_CFGR_FUNC_GPIO;
174
175         writel(mask, &port_base->mskr);
176         writel(reg, &port_base->cfgr);
177
178         return 0;
179 }
180
181 static int atmel_pio4_direction_output(struct udevice *dev,
182                                        unsigned offset, int value)
183 {
184         struct at91_port_platdata *plat = dev_get_platdata(dev);
185         struct atmel_pio4_port *port_base = (atmel_pio4_port *)plat->base_addr;
186         u32 mask = 0x01 << offset;
187         u32 reg = ATMEL_PIO_CFGR_FUNC_GPIO | ATMEL_PIO_DIR_MASK;
188
189         writel(mask, &port_base->mskr);
190         writel(reg, &port_base->cfgr);
191
192         if (value)
193                 writel(mask, &port_base->sodr);
194         else
195                 writel(mask, &port_base->codr);
196
197         return 0;
198 }
199
200 static int atmel_pio4_get_value(struct udevice *dev, unsigned offset)
201 {
202         struct at91_port_platdata *plat = dev_get_platdata(dev);
203         struct atmel_pio4_port *port_base = (atmel_pio4_port *)plat->base_addr;
204         u32 mask = 0x01 << offset;
205
206         return (readl(&port_base->pdsr) & mask) ? 1 : 0;
207 }
208
209 static int atmel_pio4_set_value(struct udevice *dev,
210                                 unsigned offset, int value)
211 {
212         struct at91_port_platdata *plat = dev_get_platdata(dev);
213         struct atmel_pio4_port *port_base = (atmel_pio4_port *)plat->base_addr;
214         u32 mask = 0x01 << offset;
215
216         if (value)
217                 writel(mask, &port_base->sodr);
218         else
219                 writel(mask, &port_base->codr);
220
221         return 0;
222 }
223
224 static int atmel_pio4_get_function(struct udevice *dev, unsigned offset)
225 {
226         struct at91_port_platdata *plat = dev_get_platdata(dev);
227         struct atmel_pio4_port *port_base = (atmel_pio4_port *)plat->base_addr;
228         u32 mask = 0x01 << offset;
229
230         writel(mask, &port_base->mskr);
231
232         return (readl(&port_base->cfgr) &
233                 ATMEL_PIO_DIR_MASK) ? GPIOF_OUTPUT : GPIOF_INPUT;
234 }
235
236 static const struct dm_gpio_ops atmel_pio4_ops = {
237         .direction_input        = atmel_pio4_direction_input,
238         .direction_output       = atmel_pio4_direction_output,
239         .get_value              = atmel_pio4_get_value,
240         .set_value              = atmel_pio4_set_value,
241         .get_function           = atmel_pio4_get_function,
242 };
243
244 static int atmel_pio4_probe(struct udevice *dev)
245 {
246         struct at91_port_platdata *plat = dev_get_platdata(dev);
247         struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
248
249         uc_priv->bank_name = plat->bank_name;
250         uc_priv->gpio_count = ATMEL_PIO_NPINS_PER_BANK;
251
252         return 0;
253 }
254
255 U_BOOT_DRIVER(gpio_atmel_pio4) = {
256         .name   = "gpio_atmel_pio4",
257         .id     = UCLASS_GPIO,
258         .ops    = &atmel_pio4_ops,
259         .probe  = atmel_pio4_probe,
260 };
261 #endif