blob: 656bf4a06c22072f2c228cb69cf174ee7b089b3b [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>
Joe Hershbergerf8928f12011-11-11 15:55:36 -060023#include <asm/gpio.h>
Minkyu Kang1edf0f22010-02-12 18:17:52 +090024
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
Joe Hershbergerf8928f12011-11-11 15:55:36 -0600145struct s5p_gpio_bank *s5p_gpio_get_bank(unsigned gpio)
Łukasz Majewski1e04cae2011-08-22 22:34:58 +0000146{
Łukasz Majewskid6614b72012-09-04 21:47:46 +0000147 int bank;
148 unsigned g = gpio - s5p_gpio_part_max(gpio);
Łukasz Majewski1e04cae2011-08-22 22:34:58 +0000149
Łukasz Majewskid6614b72012-09-04 21:47:46 +0000150 bank = g / GPIO_PER_BANK;
151 bank *= sizeof(struct s5p_gpio_bank);
Joe Hershbergerf8928f12011-11-11 15:55:36 -0600152 return (struct s5p_gpio_bank *) (s5p_gpio_base(gpio) + bank);
Łukasz Majewski1e04cae2011-08-22 22:34:58 +0000153}
154
Joe Hershbergerf8928f12011-11-11 15:55:36 -0600155int s5p_gpio_get_pin(unsigned gpio)
Łukasz Majewski1e04cae2011-08-22 22:34:58 +0000156{
Joe Hershbergerf8928f12011-11-11 15:55:36 -0600157 return gpio % GPIO_PER_BANK;
Łukasz Majewski1e04cae2011-08-22 22:34:58 +0000158}
159
Joe Hershbergerf8928f12011-11-11 15:55:36 -0600160/* Common GPIO API */
161
162int gpio_request(unsigned gpio, const char *label)
Łukasz Majewski1e04cae2011-08-22 22:34:58 +0000163{
164 return 0;
165}
166
Joe Hershbergerf8928f12011-11-11 15:55:36 -0600167int gpio_free(unsigned gpio)
Łukasz Majewski1e04cae2011-08-22 22:34:58 +0000168{
Łukasz Majewski1e04cae2011-08-22 22:34:58 +0000169 return 0;
170}
171
Joe Hershbergerf8928f12011-11-11 15:55:36 -0600172int gpio_direction_input(unsigned gpio)
Łukasz Majewski1e04cae2011-08-22 22:34:58 +0000173{
Joe Hershbergerf8928f12011-11-11 15:55:36 -0600174 s5p_gpio_direction_input(s5p_gpio_get_bank(gpio),
175 s5p_gpio_get_pin(gpio));
Łukasz Majewski1e04cae2011-08-22 22:34:58 +0000176 return 0;
177}
178
Joe Hershbergerf8928f12011-11-11 15:55:36 -0600179int gpio_direction_output(unsigned gpio, int value)
Łukasz Majewski1e04cae2011-08-22 22:34:58 +0000180{
Joe Hershbergerf8928f12011-11-11 15:55:36 -0600181 s5p_gpio_direction_output(s5p_gpio_get_bank(gpio),
182 s5p_gpio_get_pin(gpio), value);
183 return 0;
Łukasz Majewski1e04cae2011-08-22 22:34:58 +0000184}
185
Joe Hershbergerf8928f12011-11-11 15:55:36 -0600186int gpio_get_value(unsigned gpio)
Łukasz Majewski1e04cae2011-08-22 22:34:58 +0000187{
Joe Hershbergerf8928f12011-11-11 15:55:36 -0600188 return (int) s5p_gpio_get_value(s5p_gpio_get_bank(gpio),
189 s5p_gpio_get_pin(gpio));
190}
191
192int gpio_set_value(unsigned gpio, int value)
193{
194 s5p_gpio_set_value(s5p_gpio_get_bank(gpio),
195 s5p_gpio_get_pin(gpio), value);
196
197 return 0;
Łukasz Majewski1e04cae2011-08-22 22:34:58 +0000198}