blob: a38db9488405165c2756d80ea94dbf7bc4fa1424 [file] [log] [blame]
Vishal Bhoj82c80712015-12-15 21:13:33 +05301/*
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
46struct gpio_device_t {
47 unsigned int base[MAX_GPIO_DEVICES];
48 unsigned int count;
49};
50
51static struct gpio_device_t gpio_dev;
52
53/* return 0 for failure */
54static 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
64int 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
79int 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
94int 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
106int 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
118int 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}