blob: 20473b9194279fc145657a899cc9ca3760f3b1c3 [file] [log] [blame]
developer65014b82015-04-13 14:47:57 +08001/*
2 * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice, this
8 * list of conditions and the following disclaimer.
9 *
10 * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 *
14 * Neither the name of ARM nor the names of its contributors may be used
15 * to endorse or promote products derived from this software without specific
16 * prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30#include <debug.h>
31#include <gpio.h>
32#include <mmio.h>
33#include <mt8173_def.h>
34#include <pmic_wrap_init.h>
35
36enum {
37 MAX_GPIO_REG_BITS = 16,
38};
39
40struct mt_gpio_obj {
41 struct gpio_regs *reg;
42};
43
44static struct mt_gpio_obj gpio_dat = {
45 .reg = (struct gpio_regs *)(GPIO_BASE),
46};
47
48static struct mt_gpio_obj *gpio_obj = &gpio_dat;
49
50struct mt_gpioext_obj {
51 struct gpioext_regs *reg;
52};
53
54static struct mt_gpioext_obj gpioext_dat = {
55 .reg = (struct gpioext_regs *)(GPIOEXT_BASE),
56};
57
58static struct mt_gpioext_obj *gpioext_obj = &gpioext_dat;
59
60static inline struct mt_gpio_obj *mt_get_gpio_obj(void)
61{
62 return gpio_obj;
63}
64
65static inline struct mt_gpioext_obj *mt_get_gpioext_obj(void)
66{
67 return gpioext_obj;
68}
69
70enum {
71 GPIO_PRO_DIR = 0,
72 GPIO_PRO_DOUT,
73 GPIO_PRO_DIN,
74 GPIO_PRO_PULLEN,
75 GPIO_PRO_PULLSEL,
76 GPIO_PRO_MODE,
77 GPIO_PRO_MAX,
78};
79
80static inline int32_t gpioext_write(uint16_t *addr, int64_t data)
81{
82 return pwrap_write((uint32_t)(uintptr_t)addr, data);
83}
84
85static inline int32_t gpioext_set_bits(uint32_t bit, uint16_t *reg)
86{
87 return gpioext_write(reg, bit);
88}
89
90static int32_t mt_set_gpio_chip(uint32_t pin, uint32_t property, uint32_t val)
91{
92 uint32_t pos = 0;
93 uint32_t bit = 0;
94 struct mt_gpio_obj *obj = mt_get_gpio_obj();
95 uint16_t *reg;
96 uint32_t data = 0;
97
98 if (!obj)
99 return -ERACCESS;
100
101 if (pin >= GPIO_EXTEND_START)
102 return -ERINVAL;
103
104 if (property >= GPIO_PRO_MAX)
105 return -ERINVAL;
106
107 pos = pin / MAX_GPIO_REG_BITS;
108 bit = pin % MAX_GPIO_REG_BITS;
109 data = 1L << bit;
110
111 switch (property) {
112 case GPIO_PRO_DIR:
113 if (val == GPIO_DIR_IN)
114 reg = &obj->reg->dir[pos].rst;
115 else
116 reg = &obj->reg->dir[pos].set;
117 break;
118 case GPIO_PRO_DOUT:
119 if (val == GPIO_OUT_ZERO)
120 reg = &obj->reg->dout[pos].rst;
121 else
122 reg = &obj->reg->dout[pos].set;
123 break;
124 default:
125 return -ERINVAL;
126 }
127
128 mmio_write_16((uintptr_t)reg, data);
129
130 return RSUCCESS;
131}
132
133static int32_t mt_set_gpio_ext(uint32_t pin, uint32_t property, uint32_t val)
134{
135 uint32_t pos = 0;
136 uint32_t bit = 0;
137 struct mt_gpioext_obj *obj = mt_get_gpioext_obj();
138 uint16_t *reg;
139 uint32_t data = 0;
140 int ret = 0;
141
142 if (!obj)
143 return -ERACCESS;
144
145 if (pin >= MAX_GPIO_PIN)
146 return -ERINVAL;
147
148 if (property >= GPIO_PRO_MAX)
149 return -ERINVAL;
150
151 pin -= GPIO_EXTEND_START;
152 pos = pin / MAX_GPIO_REG_BITS;
153 bit = pin % MAX_GPIO_REG_BITS;
154
155 switch (property) {
156 case GPIO_PRO_DIR:
157 if (val == GPIO_DIR_IN)
158 reg = &obj->reg->dir[pos].rst;
159 else
160 reg = &obj->reg->dir[pos].set;
161 break;
162 case GPIO_PRO_DOUT:
163 if (val == GPIO_OUT_ZERO)
164 reg = &obj->reg->dout[pos].rst;
165 else
166 reg = &obj->reg->dout[pos].set;
167 break;
168 default:
169 return -ERINVAL;
170 }
171 data = (1L << bit);
172 ret = gpioext_set_bits(data, reg);
173
174 return ret ? -ERWRAPPER : RSUCCESS;
175}
176
177static void mt_gpio_pin_decrypt(uint32_t *cipher)
178{
179 if ((*cipher & (0x80000000)) == 0)
180 INFO("Pin %u decrypt warning!\n", *cipher);
181 *cipher &= ~(0x80000000);
182}
183
184int32_t mt_set_gpio_out(uint32_t pin, uint32_t output)
185{
186 uint32_t gp = GPIO_PRO_DOUT;
187
188 mt_gpio_pin_decrypt(&pin);
189
190 return (pin >= GPIO_EXTEND_START) ?
191 mt_set_gpio_ext(pin, gp, output) :
192 mt_set_gpio_chip(pin, gp, output);
193}
194
195void gpio_set(uint32_t gpio, int32_t value)
196{
197 mt_set_gpio_out(gpio, value);
198}