blob: e19c769c3321faaa0757a64729226727c859af9c [file] [log] [blame]
Biao Huang8c83c652015-07-31 17:10:55 +08001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright 2015 MediaTek Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
Biao Huang8c83c652015-07-31 17:10:55 +080014 */
15#include <arch/io.h>
16#include <assert.h>
17#include <console/console.h>
18#include <gpio.h>
19#include <types.h>
20#include <soc/addressmap.h>
21#include <soc/gpio.h>
22
23enum {
24 MAX_8173_GPIO = 134,
25 MAX_GPIO_REG_BITS = 16,
26 MAX_GPIO_MODE_PER_REG = 5,
27 GPIO_MODE_BITS = 3,
28};
29
30enum {
31 GPIO_DIRECTION_IN = 0,
32 GPIO_DIRECTION_OUT = 1,
33};
34
35enum {
36 GPIO_MODE = 0,
37};
38
39static void pos_bit_calc(u32 pin, u32 *pos, u32 *bit)
40{
41 *pos = pin / MAX_GPIO_REG_BITS;
42 *bit = pin % MAX_GPIO_REG_BITS;
43}
44
45static void pos_bit_calc_for_mode(u32 pin, u32 *pos, u32 *bit)
46{
47 *pos = pin / MAX_GPIO_MODE_PER_REG;
48 *bit = (pin % MAX_GPIO_MODE_PER_REG) * GPIO_MODE_BITS;
49}
50
51static s32 gpio_set_dir(u32 pin, u32 dir)
52{
53 u32 pos;
54 u32 bit;
55 u16 *reg;
56
57 assert(pin <= MAX_8173_GPIO);
58
59 pos_bit_calc(pin, &pos, &bit);
60
61 if (dir == GPIO_DIRECTION_IN)
62 reg = &mt8173_gpio->dir[pos].rst;
63 else
64 reg = &mt8173_gpio->dir[pos].set;
65
66 write16(reg, 1L << bit);
67
68 return 0;
69}
70
71void gpio_set_pull(gpio_t pin, enum pull_enable enable,
72 enum pull_select select)
73{
74 u32 pos;
75 u32 bit;
76 u16 *en_reg, *sel_reg;
77
78 assert(pin <= MAX_8173_GPIO);
79
80 pos_bit_calc(pin, &pos, &bit);
81
82 if (enable == GPIO_PULL_DISABLE) {
83 en_reg = &mt8173_gpio->pullen[pos].rst;
84 } else {
85 /* These pins' pulls can't be set through GPIO controller. */
86 assert(pin < 22 || pin > 27);
87 assert(pin < 47 || pin > 56);
88 assert(pin < 57 || pin > 68);
89 assert(pin < 73 || pin > 78);
90 assert(pin < 100 || pin > 105);
91 assert(pin < 119 || pin > 124);
92
93 en_reg = &mt8173_gpio->pullen[pos].set;
94 sel_reg = (select == GPIO_PULL_DOWN) ?
95 (&mt8173_gpio->pullsel[pos].rst) :
96 (&mt8173_gpio->pullsel[pos].set);
97 write16(sel_reg, 1L << bit);
98 }
99 write16(en_reg, 1L << bit);
100}
101
102int gpio_get(gpio_t pin)
103{
104 u32 pos;
105 u32 bit;
106 u16 *reg;
107 s32 data;
108
109 assert(pin <= MAX_8173_GPIO);
110
111 pos_bit_calc(pin, &pos, &bit);
112
113 reg = &mt8173_gpio->din[pos].val;
114 data = read32(reg);
115
116 return (data & (1L << bit)) ? 1 : 0;
117}
118
119void gpio_set(gpio_t pin, int output)
120{
121 u32 pos;
122 u32 bit;
123 u16 *reg;
124
125 assert(pin <= MAX_8173_GPIO);
126
127 pos_bit_calc(pin, &pos, &bit);
128
129 if (output == 0)
130 reg = &mt8173_gpio->dout[pos].rst;
131 else
132 reg = &mt8173_gpio->dout[pos].set;
133 write16(reg, 1L << bit);
134}
135
136void gpio_set_mode(gpio_t pin, int mode)
137{
138 u32 pos;
139 u32 bit;
140 u32 mask = (1L << GPIO_MODE_BITS) - 1;
141
142 assert(pin <= MAX_8173_GPIO);
143
144 pos_bit_calc_for_mode(pin, &pos, &bit);
145
146 clrsetbits_le32(&mt8173_gpio->mode[pos].val,
147 mask << bit, mode << bit);
148}
149
150void gpio_input_pulldown(gpio_t gpio)
151{
152 gpio_set_pull(gpio, GPIO_PULL_ENABLE, GPIO_PULL_DOWN);
153 gpio_set_dir(gpio, GPIO_DIRECTION_IN);
154 gpio_set_mode(gpio, GPIO_MODE);
155}
156
157void gpio_input_pullup(gpio_t gpio)
158{
159 gpio_set_pull(gpio, GPIO_PULL_ENABLE, GPIO_PULL_UP);
160 gpio_set_dir(gpio, GPIO_DIRECTION_IN);
161 gpio_set_mode(gpio, GPIO_MODE);
162}
163
164void gpio_input(gpio_t gpio)
165{
166 gpio_set_pull(gpio, GPIO_PULL_DISABLE, GPIO_PULL_DOWN);
167 gpio_set_dir(gpio, GPIO_DIRECTION_IN);
168 gpio_set_mode(gpio, GPIO_MODE);
169}
170
171void gpio_output(gpio_t gpio, int value)
172{
173 gpio_set_pull(gpio, GPIO_PULL_DISABLE, GPIO_PULL_DOWN);
174 gpio_set(gpio, value);
175 gpio_set_dir(gpio, GPIO_DIRECTION_OUT);
176 gpio_set_mode(gpio, GPIO_MODE);
177}