xref: /openbmc/u-boot/drivers/gpio/atmel_pio4.c (revision 5c8fd32b)
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 config)
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 |= config;
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 config)
69 {
70 	return atmel_pio4_config_io_func(port, pin,
71 					 ATMEL_PIO_CFGR_FUNC_GPIO,
72 					 config);
73 }
74 
75 int atmel_pio4_set_a_periph(u32 port, u32 pin, u32 config)
76 {
77 	return atmel_pio4_config_io_func(port, pin,
78 					 ATMEL_PIO_CFGR_FUNC_PERIPH_A,
79 					 config);
80 }
81 
82 int atmel_pio4_set_b_periph(u32 port, u32 pin, u32 config)
83 {
84 	return atmel_pio4_config_io_func(port, pin,
85 					 ATMEL_PIO_CFGR_FUNC_PERIPH_B,
86 					 config);
87 }
88 
89 int atmel_pio4_set_c_periph(u32 port, u32 pin, u32 config)
90 {
91 	return atmel_pio4_config_io_func(port, pin,
92 					 ATMEL_PIO_CFGR_FUNC_PERIPH_C,
93 					 config);
94 }
95 
96 int atmel_pio4_set_d_periph(u32 port, u32 pin, u32 config)
97 {
98 	return atmel_pio4_config_io_func(port, pin,
99 					 ATMEL_PIO_CFGR_FUNC_PERIPH_D,
100 					 config);
101 }
102 
103 int atmel_pio4_set_e_periph(u32 port, u32 pin, u32 config)
104 {
105 	return atmel_pio4_config_io_func(port, pin,
106 					 ATMEL_PIO_CFGR_FUNC_PERIPH_E,
107 					 config);
108 }
109 
110 int atmel_pio4_set_f_periph(u32 port, u32 pin, u32 config)
111 {
112 	return atmel_pio4_config_io_func(port, pin,
113 					 ATMEL_PIO_CFGR_FUNC_PERIPH_F,
114 					 config);
115 }
116 
117 int atmel_pio4_set_g_periph(u32 port, u32 pin, u32 config)
118 {
119 	return atmel_pio4_config_io_func(port, pin,
120 					 ATMEL_PIO_CFGR_FUNC_PERIPH_G,
121 					 config);
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
343