blob: bad0190d5f13b7608826072bd2a295b58c67681b [file] [log] [blame]
developer912c7d22021-03-31 14:53:43 +08001/*
developerfe14b9f2022-09-05 11:18:04 +08002 * Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
developer912c7d22021-03-31 14:53:43 +08003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <assert.h>
8#include <common/debug.h>
9#include <drivers/delay_timer.h>
10#include <drivers/gpio.h>
11#include <lib/mmio.h>
Jianguo Zhangbe99c732022-07-29 13:55:03 +080012#include <lib/mtk_init/mtk_init.h>
developer912c7d22021-03-31 14:53:43 +080013#include <mtgpio.h>
14#include <platform_def.h>
15
16/******************************************************************************
17 *Macro Definition
18 ******************************************************************************/
19#define GPIO_MODE_BITS 4
20#define MAX_GPIO_MODE_PER_REG 8
21#define MAX_GPIO_REG_BITS 32
22#define DIR_BASE (GPIO_BASE + 0x000)
23#define DOUT_BASE (GPIO_BASE + 0x100)
24#define DIN_BASE (GPIO_BASE + 0x200)
25#define MODE_BASE (GPIO_BASE + 0x300)
26#define SET 0x4
27#define CLR 0x8
28
29static void mt_set_gpio_dir_chip(uint32_t pin, int dir)
30{
31 uint32_t pos, bit;
32
33 assert(pin < MAX_GPIO_PIN);
34 assert(dir < MT_GPIO_DIR_MAX);
35
36 pos = pin / MAX_GPIO_REG_BITS;
37 bit = pin % MAX_GPIO_REG_BITS;
38
39 if (dir == MT_GPIO_DIR_IN) {
40 mmio_write_32(DIR_BASE + 0x10U * pos + CLR, 1U << bit);
41 } else {
42 mmio_write_32(DIR_BASE + 0x10U * pos + SET, 1U << bit);
43 }
44}
45
46static int mt_get_gpio_dir_chip(uint32_t pin)
47{
48 uint32_t pos, bit;
49 uint32_t reg;
50
51 assert(pin < MAX_GPIO_PIN);
52
53 pos = pin / MAX_GPIO_REG_BITS;
54 bit = pin % MAX_GPIO_REG_BITS;
55
56 reg = mmio_read_32(DIR_BASE + 0x10U * pos);
57 return (((reg & (1U << bit)) != 0U) ? MT_GPIO_DIR_OUT : MT_GPIO_DIR_IN);
58}
59
60static void mt_set_gpio_out_chip(uint32_t pin, int output)
61{
62 uint32_t pos, bit;
63
64 assert(pin < MAX_GPIO_PIN);
65 assert(output < MT_GPIO_OUT_MAX);
66
67 pos = pin / MAX_GPIO_REG_BITS;
68 bit = pin % MAX_GPIO_REG_BITS;
69
70 if (output == MT_GPIO_OUT_ZERO) {
71 mmio_write_32(DOUT_BASE + 0x10U * pos + CLR, 1U << bit);
72 } else {
73 mmio_write_32(DOUT_BASE + 0x10U * pos + SET, 1U << bit);
74 }
75}
76
77static int mt_get_gpio_in_chip(uint32_t pin)
78{
79 uint32_t pos, bit;
80 uint32_t reg;
81
82 assert(pin < MAX_GPIO_PIN);
83
84 pos = pin / MAX_GPIO_REG_BITS;
85 bit = pin % MAX_GPIO_REG_BITS;
86
87 reg = mmio_read_32(DIN_BASE + 0x10U * pos);
88 return (((reg & (1U << bit)) != 0U) ? 1 : 0);
89}
90
91static void mt_gpio_set_spec_pull_pupd(uint32_t pin, int enable,
92 int select)
93{
94 uintptr_t reg1;
95 uintptr_t reg2;
96 struct mt_pin_info gpio_info;
97
98 gpio_info = mt_pin_infos[pin];
99 uint32_t bit = gpio_info.bit;
100
101 reg1 = mt_gpio_find_reg_addr(pin) + gpio_info.offset;
102 reg2 = reg1 + (gpio_info.base & 0xf0);
103 if (enable == MT_GPIO_PULL_ENABLE) {
104 mmio_write_32(reg2 + SET, (1U << bit));
105 if (select == MT_GPIO_PULL_DOWN) {
106 mmio_write_32(reg1 + SET, (1U << bit));
107 } else {
108 mmio_write_32(reg1 + CLR, (1U << bit));
109 }
110 } else {
111 mmio_write_32(reg2 + CLR, (1U << bit));
112 mmio_write_32((reg2 + 0x010U) + CLR, (1U << bit));
113 }
114}
115
116static void mt_gpio_set_pull_pu_pd(uint32_t pin, int enable,
117 int select)
118{
119 uintptr_t reg1;
120 uintptr_t reg2;
121 struct mt_pin_info gpio_info;
122
123 gpio_info = mt_pin_infos[pin];
124 uint32_t bit = gpio_info.bit;
125
126 reg1 = mt_gpio_find_reg_addr(pin) + gpio_info.offset;
127 reg2 = reg1 - (gpio_info.base & 0xf0);
128
129 if (enable == MT_GPIO_PULL_ENABLE) {
130 if (select == MT_GPIO_PULL_DOWN) {
131 mmio_write_32(reg1 + CLR, (1U << bit));
132 mmio_write_32(reg2 + SET, (1U << bit));
133 } else {
134 mmio_write_32(reg2 + CLR, (1U << bit));
135 mmio_write_32(reg1 + SET, (1U << bit));
136 }
137 } else {
138 mmio_write_32(reg1 + CLR, (1U << bit));
139 mmio_write_32(reg2 + CLR, (1U << bit));
140 }
141}
142
143static void mt_gpio_set_pull_chip(uint32_t pin, int enable,
144 int select)
145{
146 struct mt_pin_info gpio_info;
147
148 gpio_info = mt_pin_infos[pin];
149 if (gpio_info.flag) {
150 mt_gpio_set_spec_pull_pupd(pin, enable, select);
151 } else {
152 mt_gpio_set_pull_pu_pd(pin, enable, select);
153 }
154}
155
156static int mt_gpio_get_spec_pull_pupd(uint32_t pin)
157{
158 uintptr_t reg1;
159 uintptr_t reg2;
160 uint32_t r0;
161 uint32_t r1;
162
163 struct mt_pin_info gpio_info;
164
165 gpio_info = mt_pin_infos[pin];
166 uint32_t bit = gpio_info.bit;
167
168 reg1 = mt_gpio_find_reg_addr(pin) + gpio_info.offset;
169 reg2 = reg1 + (gpio_info.base & 0xf0);
170
171 r0 = (mmio_read_32(reg2) >> bit) & 1U;
172 r1 = (mmio_read_32(reg2 + 0x010) >> bit) & 1U;
173 if (r0 == 0U && r1 == 0U) {
174 return MT_GPIO_PULL_NONE;
175 } else {
176 if (mmio_read_32(reg1) & (1U << bit)) {
177 return MT_GPIO_PULL_DOWN;
178 } else {
179 return MT_GPIO_PULL_UP;
180 }
181 }
182}
183
184static int mt_gpio_get_pull_pu_pd(uint32_t pin)
185{
186 uintptr_t reg1;
187 uintptr_t reg2;
188 uint32_t pu;
189 uint32_t pd;
190
191 struct mt_pin_info gpio_info;
192
193 gpio_info = mt_pin_infos[pin];
194 uint32_t bit = gpio_info.bit;
195
196 reg1 = mt_gpio_find_reg_addr(pin) + gpio_info.offset;
197 reg2 = reg1 - (gpio_info.base & 0xf0);
198 pu = (mmio_read_32(reg1) >> bit) & 1U;
199 pd = (mmio_read_32(reg2) >> bit) & 1U;
200 if (pu == 1U) {
201 return MT_GPIO_PULL_UP;
202 } else if (pd == 1U) {
203 return MT_GPIO_PULL_DOWN;
204 } else {
205 return MT_GPIO_PULL_NONE;
206 }
207}
208
209static int mt_gpio_get_pull_chip(uint32_t pin)
210{
211 struct mt_pin_info gpio_info;
212
213 gpio_info = mt_pin_infos[pin];
214 if (gpio_info.flag) {
215 return mt_gpio_get_spec_pull_pupd(pin);
216 } else {
217 return mt_gpio_get_pull_pu_pd(pin);
218 }
219}
220
221static void mt_set_gpio_pull_select_chip(uint32_t pin, int sel)
222{
223 assert(pin < MAX_GPIO_PIN);
224
225 if (sel == MT_GPIO_PULL_NONE) {
226 mt_gpio_set_pull_chip(pin, MT_GPIO_PULL_DISABLE, MT_GPIO_PULL_DOWN);
227 } else if (sel == MT_GPIO_PULL_UP) {
228 mt_gpio_set_pull_chip(pin, MT_GPIO_PULL_ENABLE, MT_GPIO_PULL_UP);
229 } else if (sel == MT_GPIO_PULL_DOWN) {
230 mt_gpio_set_pull_chip(pin, MT_GPIO_PULL_ENABLE, MT_GPIO_PULL_DOWN);
231 }
232}
233
234/* get pull-up or pull-down, regardless of resistor value */
235static int mt_get_gpio_pull_select_chip(uint32_t pin)
236{
237 assert(pin < MAX_GPIO_PIN);
238
239 return mt_gpio_get_pull_chip(pin);
240}
241
242static void mt_set_gpio_dir(int gpio, int direction)
243{
244 mt_set_gpio_dir_chip((uint32_t)gpio, direction);
245}
246
247static int mt_get_gpio_dir(int gpio)
248{
249 uint32_t pin;
250
251 pin = (uint32_t)gpio;
252 return mt_get_gpio_dir_chip(pin);
253}
254
255static void mt_set_gpio_pull(int gpio, int pull)
256{
257 uint32_t pin;
258
259 pin = (uint32_t)gpio;
260 mt_set_gpio_pull_select_chip(pin, pull);
261}
262
263static int mt_get_gpio_pull(int gpio)
264{
265 uint32_t pin;
266
267 pin = (uint32_t)gpio;
268 return mt_get_gpio_pull_select_chip(pin);
269}
270
271static void mt_set_gpio_out(int gpio, int value)
272{
273 uint32_t pin;
274
275 pin = (uint32_t)gpio;
276 mt_set_gpio_out_chip(pin, value);
277}
278
279static int mt_get_gpio_in(int gpio)
280{
281 uint32_t pin;
282
283 pin = (uint32_t)gpio;
284 return mt_get_gpio_in_chip(pin);
285}
286
287const gpio_ops_t mtgpio_ops = {
288 .get_direction = mt_get_gpio_dir,
289 .set_direction = mt_set_gpio_dir,
290 .get_value = mt_get_gpio_in,
291 .set_value = mt_set_gpio_out,
292 .set_pull = mt_set_gpio_pull,
293 .get_pull = mt_get_gpio_pull,
294};
295
Jianguo Zhangbe99c732022-07-29 13:55:03 +0800296int mt_gpio_init(void)
developer912c7d22021-03-31 14:53:43 +0800297{
298 gpio_init(&mtgpio_ops);
Jianguo Zhangbe99c732022-07-29 13:55:03 +0800299
300 return 0;
developer912c7d22021-03-31 14:53:43 +0800301}
Jianguo Zhangbe99c732022-07-29 13:55:03 +0800302MTK_PLAT_SETUP_0_INIT(mt_gpio_init);