xref: /openbmc/u-boot/drivers/gpio/mxc_gpio.c (revision 52422e37)
1 /*
2  * Copyright (C) 2009
3  * Guennadi Liakhovetski, DENX Software Engineering, <lg@denx.de>
4  *
5  * Copyright (C) 2011
6  * Stefano Babic, DENX Software Engineering, <sbabic@denx.de>
7  *
8  * SPDX-License-Identifier:	GPL-2.0+
9  */
10 #include <common.h>
11 #include <errno.h>
12 #include <dm.h>
13 #include <malloc.h>
14 #include <asm/arch/imx-regs.h>
15 #include <asm/gpio.h>
16 #include <asm/io.h>
17 
18 enum mxc_gpio_direction {
19 	MXC_GPIO_DIRECTION_IN,
20 	MXC_GPIO_DIRECTION_OUT,
21 };
22 
23 #define GPIO_NAME_SIZE			20
24 #define GPIO_PER_BANK			32
25 
26 struct mxc_gpio_plat {
27 	struct gpio_regs *regs;
28 };
29 
30 struct mxc_bank_info {
31 	char label[GPIO_PER_BANK][GPIO_NAME_SIZE];
32 	struct gpio_regs *regs;
33 };
34 
35 #ifndef CONFIG_DM_GPIO
36 #define GPIO_TO_PORT(n)		(n / 32)
37 
38 /* GPIO port description */
39 static unsigned long gpio_ports[] = {
40 	[0] = GPIO1_BASE_ADDR,
41 	[1] = GPIO2_BASE_ADDR,
42 	[2] = GPIO3_BASE_ADDR,
43 #if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX51) || \
44 		defined(CONFIG_MX53) || defined(CONFIG_MX6)
45 	[3] = GPIO4_BASE_ADDR,
46 #endif
47 #if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6)
48 	[4] = GPIO5_BASE_ADDR,
49 	[5] = GPIO6_BASE_ADDR,
50 #endif
51 #if defined(CONFIG_MX53) || defined(CONFIG_MX6)
52 	[6] = GPIO7_BASE_ADDR,
53 #endif
54 };
55 
56 static int mxc_gpio_direction(unsigned int gpio,
57 	enum mxc_gpio_direction direction)
58 {
59 	unsigned int port = GPIO_TO_PORT(gpio);
60 	struct gpio_regs *regs;
61 	u32 l;
62 
63 	if (port >= ARRAY_SIZE(gpio_ports))
64 		return -1;
65 
66 	gpio &= 0x1f;
67 
68 	regs = (struct gpio_regs *)gpio_ports[port];
69 
70 	l = readl(&regs->gpio_dir);
71 
72 	switch (direction) {
73 	case MXC_GPIO_DIRECTION_OUT:
74 		l |= 1 << gpio;
75 		break;
76 	case MXC_GPIO_DIRECTION_IN:
77 		l &= ~(1 << gpio);
78 	}
79 	writel(l, &regs->gpio_dir);
80 
81 	return 0;
82 }
83 
84 int gpio_set_value(unsigned gpio, int value)
85 {
86 	unsigned int port = GPIO_TO_PORT(gpio);
87 	struct gpio_regs *regs;
88 	u32 l;
89 
90 	if (port >= ARRAY_SIZE(gpio_ports))
91 		return -1;
92 
93 	gpio &= 0x1f;
94 
95 	regs = (struct gpio_regs *)gpio_ports[port];
96 
97 	l = readl(&regs->gpio_dr);
98 	if (value)
99 		l |= 1 << gpio;
100 	else
101 		l &= ~(1 << gpio);
102 	writel(l, &regs->gpio_dr);
103 
104 	return 0;
105 }
106 
107 int gpio_get_value(unsigned gpio)
108 {
109 	unsigned int port = GPIO_TO_PORT(gpio);
110 	struct gpio_regs *regs;
111 	u32 val;
112 
113 	if (port >= ARRAY_SIZE(gpio_ports))
114 		return -1;
115 
116 	gpio &= 0x1f;
117 
118 	regs = (struct gpio_regs *)gpio_ports[port];
119 
120 	val = (readl(&regs->gpio_psr) >> gpio) & 0x01;
121 
122 	return val;
123 }
124 
125 int gpio_request(unsigned gpio, const char *label)
126 {
127 	unsigned int port = GPIO_TO_PORT(gpio);
128 	if (port >= ARRAY_SIZE(gpio_ports))
129 		return -1;
130 	return 0;
131 }
132 
133 int gpio_free(unsigned gpio)
134 {
135 	return 0;
136 }
137 
138 int gpio_direction_input(unsigned gpio)
139 {
140 	return mxc_gpio_direction(gpio, MXC_GPIO_DIRECTION_IN);
141 }
142 
143 int gpio_direction_output(unsigned gpio, int value)
144 {
145 	int ret = gpio_set_value(gpio, value);
146 
147 	if (ret < 0)
148 		return ret;
149 
150 	return mxc_gpio_direction(gpio, MXC_GPIO_DIRECTION_OUT);
151 }
152 #endif
153 
154 #ifdef CONFIG_DM_GPIO
155 /**
156  * gpio_is_requested() - check if a GPIO has been requested
157  *
158  * @bank:	Bank to check
159  * @offset:	GPIO offset within bank to check
160  * @return true if marked as requested, false if not
161  */
162 static inline bool gpio_is_requested(struct mxc_bank_info *bank, int offset)
163 {
164 	return *bank->label[offset] != '\0';
165 }
166 
167 static int mxc_gpio_is_output(struct gpio_regs *regs, int offset)
168 {
169 	u32 val;
170 
171 	val = readl(&regs->gpio_dir);
172 
173 	return val & (1 << offset) ? 1 : 0;
174 }
175 
176 static void mxc_gpio_bank_direction(struct gpio_regs *regs, int offset,
177 				    enum mxc_gpio_direction direction)
178 {
179 	u32 l;
180 
181 	l = readl(&regs->gpio_dir);
182 
183 	switch (direction) {
184 	case MXC_GPIO_DIRECTION_OUT:
185 		l |= 1 << offset;
186 		break;
187 	case MXC_GPIO_DIRECTION_IN:
188 		l &= ~(1 << offset);
189 	}
190 	writel(l, &regs->gpio_dir);
191 }
192 
193 static void mxc_gpio_bank_set_value(struct gpio_regs *regs, int offset,
194 				    int value)
195 {
196 	u32 l;
197 
198 	l = readl(&regs->gpio_dr);
199 	if (value)
200 		l |= 1 << offset;
201 	else
202 		l &= ~(1 << offset);
203 	writel(l, &regs->gpio_dr);
204 }
205 
206 static int mxc_gpio_bank_get_value(struct gpio_regs *regs, int offset)
207 {
208 	return (readl(&regs->gpio_psr) >> offset) & 0x01;
209 }
210 
211 static int mxc_gpio_bank_get_output_value(struct gpio_regs *regs, int offset)
212 {
213 	return (readl(&regs->gpio_dr) >> offset) & 0x01;
214 }
215 
216 static int check_requested(struct udevice *dev, unsigned offset,
217 			   const char *func)
218 {
219 	struct mxc_bank_info *bank = dev_get_priv(dev);
220 	struct gpio_dev_priv *uc_priv = dev->uclass_priv;
221 
222 	if (!gpio_is_requested(bank, offset)) {
223 		printf("mxc_gpio: %s: error: gpio %s%d not requested\n",
224 		       func, uc_priv->bank_name, offset);
225 		return -EPERM;
226 	}
227 
228 	return 0;
229 }
230 
231 /* set GPIO pin 'gpio' as an input */
232 static int mxc_gpio_direction_input(struct udevice *dev, unsigned offset)
233 {
234 	struct mxc_bank_info *bank = dev_get_priv(dev);
235 	int ret;
236 
237 	ret = check_requested(dev, offset, __func__);
238 	if (ret)
239 		return ret;
240 
241 	/* Configure GPIO direction as input. */
242 	mxc_gpio_bank_direction(bank->regs, offset, MXC_GPIO_DIRECTION_IN);
243 
244 	return 0;
245 }
246 
247 /* set GPIO pin 'gpio' as an output, with polarity 'value' */
248 static int mxc_gpio_direction_output(struct udevice *dev, unsigned offset,
249 				       int value)
250 {
251 	struct mxc_bank_info *bank = dev_get_priv(dev);
252 	int ret;
253 
254 	ret = check_requested(dev, offset, __func__);
255 	if (ret)
256 		return ret;
257 
258 	/* Configure GPIO output value. */
259 	mxc_gpio_bank_set_value(bank->regs, offset, value);
260 
261 	/* Configure GPIO direction as output. */
262 	mxc_gpio_bank_direction(bank->regs, offset, MXC_GPIO_DIRECTION_OUT);
263 
264 	return 0;
265 }
266 
267 /* read GPIO IN value of pin 'gpio' */
268 static int mxc_gpio_get_value(struct udevice *dev, unsigned offset)
269 {
270 	struct mxc_bank_info *bank = dev_get_priv(dev);
271 	int ret;
272 
273 	ret = check_requested(dev, offset, __func__);
274 	if (ret)
275 		return ret;
276 
277 	return mxc_gpio_bank_get_value(bank->regs, offset);
278 }
279 
280 /* write GPIO OUT value to pin 'gpio' */
281 static int mxc_gpio_set_value(struct udevice *dev, unsigned offset,
282 				 int value)
283 {
284 	struct mxc_bank_info *bank = dev_get_priv(dev);
285 	int ret;
286 
287 	ret = check_requested(dev, offset, __func__);
288 	if (ret)
289 		return ret;
290 
291 	mxc_gpio_bank_set_value(bank->regs, offset, value);
292 
293 	return 0;
294 }
295 
296 static int mxc_gpio_get_state(struct udevice *dev, unsigned int offset,
297 			      char *buf, int bufsize)
298 {
299 	struct gpio_dev_priv *uc_priv = dev->uclass_priv;
300 	struct mxc_bank_info *bank = dev_get_priv(dev);
301 	const char *label;
302 	bool requested;
303 	bool is_output;
304 	int size;
305 
306 	label = bank->label[offset];
307 	is_output = mxc_gpio_is_output(bank->regs, offset);
308 	size = snprintf(buf, bufsize, "%s%d: ",
309 			uc_priv->bank_name ? uc_priv->bank_name : "", offset);
310 	buf += size;
311 	bufsize -= size;
312 	requested = gpio_is_requested(bank, offset);
313 	snprintf(buf, bufsize, "%s: %d [%c]%s%s",
314 		 is_output ? "out" : " in",
315 		 is_output ?
316 			mxc_gpio_bank_get_output_value(bank->regs, offset) :
317 			mxc_gpio_bank_get_value(bank->regs, offset),
318 		 requested ? 'x' : ' ',
319 		 requested ? " " : "",
320 		 label);
321 
322 	return 0;
323 }
324 
325 static int mxc_gpio_request(struct udevice *dev, unsigned offset,
326 			      const char *label)
327 {
328 	struct mxc_bank_info *bank = dev_get_priv(dev);
329 
330 	if (gpio_is_requested(bank, offset))
331 		return -EBUSY;
332 
333 	strncpy(bank->label[offset], label, GPIO_NAME_SIZE);
334 	bank->label[offset][GPIO_NAME_SIZE - 1] = '\0';
335 
336 	return 0;
337 }
338 
339 static int mxc_gpio_free(struct udevice *dev, unsigned offset)
340 {
341 	struct mxc_bank_info *bank = dev_get_priv(dev);
342 	int ret;
343 
344 	ret = check_requested(dev, offset, __func__);
345 	if (ret)
346 		return ret;
347 	bank->label[offset][0] = '\0';
348 
349 	return 0;
350 }
351 
352 static int mxc_gpio_get_function(struct udevice *dev, unsigned offset)
353 {
354 	struct mxc_bank_info *bank = dev_get_priv(dev);
355 
356 	if (!gpio_is_requested(bank, offset))
357 		return GPIOF_UNUSED;
358 
359 	/* GPIOF_FUNC is not implemented yet */
360 	if (mxc_gpio_is_output(bank->regs, offset))
361 		return GPIOF_OUTPUT;
362 	else
363 		return GPIOF_INPUT;
364 }
365 
366 static const struct dm_gpio_ops gpio_mxc_ops = {
367 	.request		= mxc_gpio_request,
368 	.free			= mxc_gpio_free,
369 	.direction_input	= mxc_gpio_direction_input,
370 	.direction_output	= mxc_gpio_direction_output,
371 	.get_value		= mxc_gpio_get_value,
372 	.set_value		= mxc_gpio_set_value,
373 	.get_function		= mxc_gpio_get_function,
374 	.get_state		= mxc_gpio_get_state,
375 };
376 
377 static const struct mxc_gpio_plat mxc_plat[] = {
378 	{ (struct gpio_regs *)GPIO1_BASE_ADDR },
379 	{ (struct gpio_regs *)GPIO2_BASE_ADDR },
380 	{ (struct gpio_regs *)GPIO3_BASE_ADDR },
381 #if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX51) || \
382 		defined(CONFIG_MX53) || defined(CONFIG_MX6)
383 	{ (struct gpio_regs *)GPIO4_BASE_ADDR },
384 #endif
385 #if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6)
386 	{ (struct gpio_regs *)GPIO5_BASE_ADDR },
387 	{ (struct gpio_regs *)GPIO6_BASE_ADDR },
388 #endif
389 #if defined(CONFIG_MX53) || defined(CONFIG_MX6)
390 	{ (struct gpio_regs *)GPIO7_BASE_ADDR },
391 #endif
392 };
393 
394 static int mxc_gpio_probe(struct udevice *dev)
395 {
396 	struct mxc_bank_info *bank = dev_get_priv(dev);
397 	struct mxc_gpio_plat *plat = dev_get_platdata(dev);
398 	struct gpio_dev_priv *uc_priv = dev->uclass_priv;
399 	int banknum;
400 	char name[18], *str;
401 
402 	banknum = plat - mxc_plat;
403 	sprintf(name, "GPIO%d_", banknum + 1);
404 	str = strdup(name);
405 	if (!str)
406 		return -ENOMEM;
407 	uc_priv->bank_name = str;
408 	uc_priv->gpio_count = GPIO_PER_BANK;
409 	bank->regs = plat->regs;
410 
411 	return 0;
412 }
413 
414 U_BOOT_DRIVER(gpio_mxc) = {
415 	.name	= "gpio_mxc",
416 	.id	= UCLASS_GPIO,
417 	.ops	= &gpio_mxc_ops,
418 	.probe	= mxc_gpio_probe,
419 	.priv_auto_alloc_size = sizeof(struct mxc_bank_info),
420 };
421 
422 U_BOOT_DEVICES(mxc_gpios) = {
423 	{ "gpio_mxc", &mxc_plat[0] },
424 	{ "gpio_mxc", &mxc_plat[1] },
425 	{ "gpio_mxc", &mxc_plat[2] },
426 #if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX51) || \
427 		defined(CONFIG_MX53) || defined(CONFIG_MX6)
428 	{ "gpio_mxc", &mxc_plat[3] },
429 #endif
430 #if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6)
431 	{ "gpio_mxc", &mxc_plat[4] },
432 	{ "gpio_mxc", &mxc_plat[5] },
433 #endif
434 #if defined(CONFIG_MX53) || defined(CONFIG_MX6)
435 	{ "gpio_mxc", &mxc_plat[6] },
436 #endif
437 };
438 #endif
439