• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2014-2015, Linaro Ltd and Contributors. All rights reserved.
3  * Copyright (c) 2014-2015, Hisilicon Ltd and Contributors. All rights reserved.
4  *
5  * GPIO driver for PL061
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * Redistributions of source code must retain the above copyright notice, this
11  * list of conditions and the following disclaimer.
12  *
13  * Redistributions in binary form must reproduce the above copyright notice,
14  * this list of conditions and the following disclaimer in the documentation
15  * and/or other materials provided with the distribution.
16  *
17  * Neither the name of ARM nor the names of its contributors may be used
18  * to endorse or promote products derived from this software without specific
19  * prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include <console.h>
35 #include <debug.h>
36 #include <errno.h>
37 #include <gpio.h>
38 #include <mmio.h>
39 
40 #define MAX_GPIO_DEVICES	32
41 #define GPIOS_PER_DEV		8
42 #define GPIO_DIR		0x400
43 
44 #define BIT(nr)			(1UL << (nr))
45 
46 struct gpio_device_t {
47 	unsigned int	base[MAX_GPIO_DEVICES];
48 	unsigned int	count;
49 };
50 
51 static struct gpio_device_t gpio_dev;
52 
53 /* return 0 for failure */
find_gc_base(unsigned int gpio)54 static unsigned int find_gc_base(unsigned int gpio)
55 {
56 	int gc;
57 
58 	gc = gpio / GPIOS_PER_DEV;
59 	if (gc >= gpio_dev.count)
60 		return 0;
61 	return gpio_dev.base[gc];
62 }
63 
gpio_direction_input(unsigned int gpio)64 int gpio_direction_input(unsigned int gpio)
65 {
66 	unsigned int gc_base, offset, data;
67 
68 	gc_base = find_gc_base(gpio);
69 	if (!gc_base)
70 		return -EINVAL;
71 	offset = gpio % GPIOS_PER_DEV;
72 
73 	data = mmio_read_8(gc_base + GPIO_DIR);
74 	data &= ~(1 << offset);
75 	mmio_write_8(gc_base + GPIO_DIR, data);
76 	return 0;
77 }
78 
gpio_direction_output(unsigned int gpio)79 int gpio_direction_output(unsigned int gpio)
80 {
81 	unsigned int gc_base, offset, data;
82 
83 	gc_base = find_gc_base(gpio);
84 	if (!gc_base)
85 		return -EINVAL;
86 	offset = gpio % 8;
87 
88 	data = mmio_read_8(gc_base + GPIO_DIR);
89 	data |= 1 << offset;
90 	mmio_write_8(gc_base + GPIO_DIR, data);
91 	return 0;
92 }
93 
gpio_get_value(unsigned int gpio)94 int gpio_get_value(unsigned int gpio)
95 {
96 	unsigned int gc_base, offset;
97 
98 	gc_base = find_gc_base(gpio);
99 	if (!gc_base)
100 		return -EINVAL;
101 	offset = gpio % 8;
102 
103 	return !!mmio_read_8(gc_base + (BIT(offset + 2)));
104 }
105 
gpio_set_value(unsigned int gpio,unsigned int value)106 int gpio_set_value(unsigned int gpio, unsigned int value)
107 {
108 	unsigned int gc_base, offset;
109 
110 	gc_base = find_gc_base(gpio);
111 	if (!gc_base)
112 		return -EINVAL;
113 	offset = gpio % 8;
114 	mmio_write_8(gc_base + (BIT(offset + 2)), !!value << offset);
115 	return 0;
116 }
117 
gpio_register_device(unsigned int base)118 int gpio_register_device(unsigned int base)
119 {
120 	int i;
121 	if (gpio_dev.count > MAX_GPIO_DEVICES)
122 		return -EINVAL;
123 	for (i = 0; i < gpio_dev.count; i++) {
124 		if (gpio_dev.base[i] == base) {
125 			WARN("%s: duplicated gpio base\n", __func__);
126 			return -EINVAL;
127 		}
128 	}
129 	gpio_dev.base[gpio_dev.count] = base;
130 	gpio_dev.count++;
131 	return 0;
132 }
133