• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6/arch/arm/plat-samsung/
1/* linux/arch/arm/plat-s3c/gpio-config.c
2 *
3 * Copyright 2008 Openmoko, Inc.
4 * Copyright 2008-2010 Simtec Electronics
5 *	Ben Dooks <ben@simtec.co.uk>
6 *	http://armlinux.simtec.co.uk/
7 *
8 * S3C series GPIO configuration core
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13*/
14
15#include <linux/kernel.h>
16#include <linux/module.h>
17#include <linux/gpio.h>
18#include <linux/io.h>
19
20#include <plat/gpio-core.h>
21#include <plat/gpio-cfg.h>
22#include <plat/gpio-cfg-helpers.h>
23
24int s3c_gpio_cfgpin(unsigned int pin, unsigned int config)
25{
26	struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
27	unsigned long flags;
28	int offset;
29	int ret;
30
31	if (!chip)
32		return -EINVAL;
33
34	offset = pin - chip->chip.base;
35
36	s3c_gpio_lock(chip, flags);
37	ret = s3c_gpio_do_setcfg(chip, offset, config);
38	s3c_gpio_unlock(chip, flags);
39
40	return ret;
41}
42EXPORT_SYMBOL(s3c_gpio_cfgpin);
43
44unsigned s3c_gpio_getcfg(unsigned int pin)
45{
46	struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
47	unsigned long flags;
48	unsigned ret = 0;
49	int offset;
50
51	if (chip) {
52		offset = pin - chip->chip.base;
53
54		s3c_gpio_lock(chip, flags);
55		ret = s3c_gpio_do_getcfg(chip, offset);
56		s3c_gpio_unlock(chip, flags);
57	}
58
59	return ret;
60}
61EXPORT_SYMBOL(s3c_gpio_getcfg);
62
63
64int s3c_gpio_setpull(unsigned int pin, s3c_gpio_pull_t pull)
65{
66	struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
67	unsigned long flags;
68	int offset, ret;
69
70	if (!chip)
71		return -EINVAL;
72
73	offset = pin - chip->chip.base;
74
75	s3c_gpio_lock(chip, flags);
76	ret = s3c_gpio_do_setpull(chip, offset, pull);
77	s3c_gpio_unlock(chip, flags);
78
79	return ret;
80}
81EXPORT_SYMBOL(s3c_gpio_setpull);
82
83#ifdef CONFIG_S3C_GPIO_CFG_S3C24XX
84int s3c_gpio_setcfg_s3c24xx_a(struct s3c_gpio_chip *chip,
85			      unsigned int off, unsigned int cfg)
86{
87	void __iomem *reg = chip->base;
88	unsigned int shift = off;
89	u32 con;
90
91	if (s3c_gpio_is_cfg_special(cfg)) {
92		cfg &= 0xf;
93
94		/* Map output to 0, and SFN2 to 1 */
95		cfg -= 1;
96		if (cfg > 1)
97			return -EINVAL;
98
99		cfg <<= shift;
100	}
101
102	con = __raw_readl(reg);
103	con &= ~(0x1 << shift);
104	con |= cfg;
105	__raw_writel(con, reg);
106
107	return 0;
108}
109
110unsigned s3c_gpio_getcfg_s3c24xx_a(struct s3c_gpio_chip *chip,
111				   unsigned int off)
112{
113	u32 con;
114
115	con = __raw_readl(chip->base);
116	con >>= off;
117	con &= 1;
118	con++;
119
120	return S3C_GPIO_SFN(con);
121}
122
123int s3c_gpio_setcfg_s3c24xx(struct s3c_gpio_chip *chip,
124			    unsigned int off, unsigned int cfg)
125{
126	void __iomem *reg = chip->base;
127	unsigned int shift = off * 2;
128	u32 con;
129
130	if (s3c_gpio_is_cfg_special(cfg)) {
131		cfg &= 0xf;
132		if (cfg > 3)
133			return -EINVAL;
134
135		cfg <<= shift;
136	}
137
138	con = __raw_readl(reg);
139	con &= ~(0x3 << shift);
140	con |= cfg;
141	__raw_writel(con, reg);
142
143	return 0;
144}
145
146unsigned int s3c_gpio_getcfg_s3c24xx(struct s3c_gpio_chip *chip,
147				     unsigned int off)
148{
149	u32 con;
150
151	con = __raw_readl(chip->base);
152	con >>= off * 2;
153	con &= 3;
154
155	/* this conversion works for IN and OUT as well as special mode */
156	return S3C_GPIO_SPECIAL(con);
157}
158#endif
159
160#ifdef CONFIG_S3C_GPIO_CFG_S3C64XX
161int s3c_gpio_setcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip,
162				 unsigned int off, unsigned int cfg)
163{
164	void __iomem *reg = chip->base;
165	unsigned int shift = (off & 7) * 4;
166	u32 con;
167
168	if (off < 8 && chip->chip.ngpio > 8)
169		reg -= 4;
170
171	if (s3c_gpio_is_cfg_special(cfg)) {
172		cfg &= 0xf;
173		cfg <<= shift;
174	}
175
176	con = __raw_readl(reg);
177	con &= ~(0xf << shift);
178	con |= cfg;
179	__raw_writel(con, reg);
180
181	return 0;
182}
183
184unsigned s3c_gpio_getcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip,
185				      unsigned int off)
186{
187	void __iomem *reg = chip->base;
188	unsigned int shift = (off & 7) * 4;
189	u32 con;
190
191	if (off < 8 && chip->chip.ngpio > 8)
192		reg -= 4;
193
194	con = __raw_readl(reg);
195	con >>= shift;
196	con &= 0xf;
197
198	/* this conversion works for IN and OUT as well as special mode */
199	return S3C_GPIO_SPECIAL(con);
200}
201
202#endif /* CONFIG_S3C_GPIO_CFG_S3C64XX */
203
204#ifdef CONFIG_S3C_GPIO_PULL_UPDOWN
205int s3c_gpio_setpull_updown(struct s3c_gpio_chip *chip,
206			    unsigned int off, s3c_gpio_pull_t pull)
207{
208	void __iomem *reg = chip->base + 0x08;
209	int shift = off * 2;
210	u32 pup;
211
212	pup = __raw_readl(reg);
213	pup &= ~(3 << shift);
214	pup |= pull << shift;
215	__raw_writel(pup, reg);
216
217	return 0;
218}
219
220s3c_gpio_pull_t s3c_gpio_getpull_updown(struct s3c_gpio_chip *chip,
221					unsigned int off)
222{
223	void __iomem *reg = chip->base + 0x08;
224	int shift = off * 2;
225	u32 pup = __raw_readl(reg);
226
227	pup >>= shift;
228	pup &= 0x3;
229	return (__force s3c_gpio_pull_t)pup;
230}
231#endif
232
233#ifdef CONFIG_S3C_GPIO_PULL_UP
234int s3c_gpio_setpull_1up(struct s3c_gpio_chip *chip,
235			 unsigned int off, s3c_gpio_pull_t pull)
236{
237	void __iomem *reg = chip->base + 0x08;
238	u32 pup = __raw_readl(reg);
239
240	pup = __raw_readl(reg);
241
242	if (pup == S3C_GPIO_PULL_UP)
243		pup &= ~(1 << off);
244	else if (pup == S3C_GPIO_PULL_NONE)
245		pup |= (1 << off);
246	else
247		return -EINVAL;
248
249	__raw_writel(pup, reg);
250	return 0;
251}
252
253s3c_gpio_pull_t s3c_gpio_getpull_1up(struct s3c_gpio_chip *chip,
254				     unsigned int off)
255{
256	void __iomem *reg = chip->base + 0x08;
257	u32 pup = __raw_readl(reg);
258
259	pup &= (1 << off);
260	return pup ? S3C_GPIO_PULL_NONE : S3C_GPIO_PULL_UP;
261}
262#endif /* CONFIG_S3C_GPIO_PULL_UP */
263
264#ifdef CONFIG_S5P_GPIO_DRVSTR
265s5p_gpio_drvstr_t s5p_gpio_get_drvstr(unsigned int pin)
266{
267	struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
268	unsigned int off;
269	void __iomem *reg;
270	int shift;
271	u32 drvstr;
272
273	if (!chip)
274		return -EINVAL;
275
276	off = pin - chip->chip.base;
277	shift = off * 2;
278	reg = chip->base + 0x0C;
279
280	drvstr = __raw_readl(reg);
281	drvstr = drvstr >> shift;
282	drvstr &= 0x3;
283
284	return (__force s5p_gpio_drvstr_t)drvstr;
285}
286EXPORT_SYMBOL(s5p_gpio_get_drvstr);
287
288int s5p_gpio_set_drvstr(unsigned int pin, s5p_gpio_drvstr_t drvstr)
289{
290	struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
291	unsigned int off;
292	void __iomem *reg;
293	int shift;
294	u32 tmp;
295
296	if (!chip)
297		return -EINVAL;
298
299	off = pin - chip->chip.base;
300	shift = off * 2;
301	reg = chip->base + 0x0C;
302
303	tmp = __raw_readl(reg);
304	tmp &= ~(0x3 << shift);
305	tmp |= drvstr << shift;
306
307	__raw_writel(tmp, reg);
308
309	return 0;
310}
311EXPORT_SYMBOL(s5p_gpio_set_drvstr);
312#endif	/* CONFIG_S5P_GPIO_DRVSTR */
313