blob: 1edf9a26a2f660dcbcdd0f6d3555b9b08ffcdc60 [file] [log] [blame]
Minkyu Kang1edf0f22010-02-12 18:17:52 +09001/*
2 * (C) Copyright 2009 Samsung Electronics
3 * Minkyu Kang <mk7.kang@samsung.com>
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of
8 * the License, or (at your option) any later version.
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.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
18 * MA 02111-1307 USA
19 */
20
21#include <common.h>
22#include <asm/io.h>
23#include <asm/arch/gpio.h>
24
25#define CON_MASK(x) (0xf << ((x) << 2))
26#define CON_SFR(x, v) ((v) << ((x) << 2))
27
28#define DAT_MASK(x) (0x1 << (x))
29#define DAT_SET(x) (0x1 << (x))
30
31#define PULL_MASK(x) (0x3 << ((x) << 1))
32#define PULL_MODE(x, v) ((v) << ((x) << 1))
33
34#define DRV_MASK(x) (0x3 << ((x) << 1))
35#define DRV_SET(x, m) ((m) << ((x) << 1))
36#define RATE_MASK(x) (0x1 << (x + 16))
37#define RATE_SET(x) (0x1 << (x + 16))
38
Łukasz Majewski4d954cc2011-07-15 00:16:22 +000039void s5p_gpio_cfg_pin(struct s5p_gpio_bank *bank, int gpio, int cfg)
Minkyu Kang1edf0f22010-02-12 18:17:52 +090040{
41 unsigned int value;
42
43 value = readl(&bank->con);
44 value &= ~CON_MASK(gpio);
45 value |= CON_SFR(gpio, cfg);
46 writel(value, &bank->con);
47}
48
Łukasz Majewski4d954cc2011-07-15 00:16:22 +000049void s5p_gpio_direction_output(struct s5p_gpio_bank *bank, int gpio, int en)
Minkyu Kang1edf0f22010-02-12 18:17:52 +090050{
51 unsigned int value;
52
Łukasz Majewski4d954cc2011-07-15 00:16:22 +000053 s5p_gpio_cfg_pin(bank, gpio, GPIO_OUTPUT);
Minkyu Kang1edf0f22010-02-12 18:17:52 +090054
55 value = readl(&bank->dat);
56 value &= ~DAT_MASK(gpio);
57 if (en)
58 value |= DAT_SET(gpio);
59 writel(value, &bank->dat);
60}
61
Łukasz Majewski4d954cc2011-07-15 00:16:22 +000062void s5p_gpio_direction_input(struct s5p_gpio_bank *bank, int gpio)
Minkyu Kang1edf0f22010-02-12 18:17:52 +090063{
Łukasz Majewski4d954cc2011-07-15 00:16:22 +000064 s5p_gpio_cfg_pin(bank, gpio, GPIO_INPUT);
Minkyu Kang1edf0f22010-02-12 18:17:52 +090065}
66
Łukasz Majewski4d954cc2011-07-15 00:16:22 +000067void s5p_gpio_set_value(struct s5p_gpio_bank *bank, int gpio, int en)
Minkyu Kang1edf0f22010-02-12 18:17:52 +090068{
69 unsigned int value;
70
71 value = readl(&bank->dat);
72 value &= ~DAT_MASK(gpio);
73 if (en)
74 value |= DAT_SET(gpio);
75 writel(value, &bank->dat);
76}
77
Łukasz Majewski4d954cc2011-07-15 00:16:22 +000078unsigned int s5p_gpio_get_value(struct s5p_gpio_bank *bank, int gpio)
Minkyu Kang1edf0f22010-02-12 18:17:52 +090079{
80 unsigned int value;
81
82 value = readl(&bank->dat);
83 return !!(value & DAT_MASK(gpio));
84}
85
Łukasz Majewski4d954cc2011-07-15 00:16:22 +000086void s5p_gpio_set_pull(struct s5p_gpio_bank *bank, int gpio, int mode)
Minkyu Kang1edf0f22010-02-12 18:17:52 +090087{
88 unsigned int value;
89
90 value = readl(&bank->pull);
91 value &= ~PULL_MASK(gpio);
92
93 switch (mode) {
94 case GPIO_PULL_DOWN:
95 case GPIO_PULL_UP:
96 value |= PULL_MODE(gpio, mode);
97 break;
98 default:
Minkyu Kangced528f2010-05-28 12:34:29 +090099 break;
Minkyu Kang1edf0f22010-02-12 18:17:52 +0900100 }
101
102 writel(value, &bank->pull);
103}
104
Łukasz Majewski4d954cc2011-07-15 00:16:22 +0000105void s5p_gpio_set_drv(struct s5p_gpio_bank *bank, int gpio, int mode)
Minkyu Kang1edf0f22010-02-12 18:17:52 +0900106{
107 unsigned int value;
108
109 value = readl(&bank->drv);
110 value &= ~DRV_MASK(gpio);
111
112 switch (mode) {
113 case GPIO_DRV_1X:
114 case GPIO_DRV_2X:
115 case GPIO_DRV_3X:
116 case GPIO_DRV_4X:
117 value |= DRV_SET(gpio, mode);
118 break;
119 default:
120 return;
121 }
122
123 writel(value, &bank->drv);
124}
125
Łukasz Majewski4d954cc2011-07-15 00:16:22 +0000126void s5p_gpio_set_rate(struct s5p_gpio_bank *bank, int gpio, int mode)
Minkyu Kang1edf0f22010-02-12 18:17:52 +0900127{
128 unsigned int value;
129
130 value = readl(&bank->drv);
131 value &= ~RATE_MASK(gpio);
132
133 switch (mode) {
134 case GPIO_DRV_FAST:
135 case GPIO_DRV_SLOW:
136 value |= RATE_SET(gpio);
137 break;
138 default:
139 return;
140 }
141
142 writel(value, &bank->drv);
143}
Łukasz Majewski1e04cae2011-08-22 22:34:58 +0000144
145struct s5p_gpio_bank *s5p_gpio_get_bank(int nr)
146{
147 int bank = nr / GPIO_PER_BANK;
148 bank *= sizeof(struct s5p_gpio_bank);
149
150 return (struct s5p_gpio_bank *) (s5p_gpio_base(nr) + bank);
151}
152
153int s5p_gpio_get_pin(int nr)
154{
155 return nr % GPIO_PER_BANK;
156}
157
158int gpio_request(int gpio, const char *label)
159{
160 return 0;
161}
162
163int gpio_direction_input(int nr)
164{
165 s5p_gpio_direction_input(s5p_gpio_get_bank(nr),
166 s5p_gpio_get_pin(nr));
167 return 0;
168}
169
170int gpio_direction_output(int nr, int value)
171{
172 s5p_gpio_direction_output(s5p_gpio_get_bank(nr),
173 s5p_gpio_get_pin(nr), value);
174 return 0;
175}
176
177int gpio_get_value(int nr)
178{
179 return (int) s5p_gpio_get_value(s5p_gpio_get_bank(nr),
180 s5p_gpio_get_pin(nr));
181}
182
183void gpio_set_value(int nr, int value)
184{
185 s5p_gpio_set_value(s5p_gpio_get_bank(nr),
186 s5p_gpio_get_pin(nr), value);
187}