Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.6.
  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
 44int s3c_gpio_cfgpin_range(unsigned int start, unsigned int nr,
 45			  unsigned int cfg)
 46{
 47	int ret;
 48
 49	for (; nr > 0; nr--, start++) {
 50		ret = s3c_gpio_cfgpin(start, cfg);
 51		if (ret != 0)
 52			return ret;
 53	}
 54
 55	return 0;
 56}
 57EXPORT_SYMBOL_GPL(s3c_gpio_cfgpin_range);
 58
 59int s3c_gpio_cfgall_range(unsigned int start, unsigned int nr,
 60			  unsigned int cfg, s3c_gpio_pull_t pull)
 61{
 62	int ret;
 63
 64	for (; nr > 0; nr--, start++) {
 65		s3c_gpio_setpull(start, pull);
 66		ret = s3c_gpio_cfgpin(start, cfg);
 67		if (ret != 0)
 68			return ret;
 69	}
 70
 71	return 0;
 72}
 73EXPORT_SYMBOL_GPL(s3c_gpio_cfgall_range);
 74
 75unsigned s3c_gpio_getcfg(unsigned int pin)
 76{
 77	struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
 78	unsigned long flags;
 79	unsigned ret = 0;
 80	int offset;
 81
 82	if (chip) {
 83		offset = pin - chip->chip.base;
 84
 85		s3c_gpio_lock(chip, flags);
 86		ret = s3c_gpio_do_getcfg(chip, offset);
 87		s3c_gpio_unlock(chip, flags);
 88	}
 89
 90	return ret;
 91}
 92EXPORT_SYMBOL(s3c_gpio_getcfg);
 93
 94
 95int s3c_gpio_setpull(unsigned int pin, s3c_gpio_pull_t pull)
 96{
 97	struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
 98	unsigned long flags;
 99	int offset, ret;
100
101	if (!chip)
102		return -EINVAL;
103
104	offset = pin - chip->chip.base;
105
106	s3c_gpio_lock(chip, flags);
107	ret = s3c_gpio_do_setpull(chip, offset, pull);
108	s3c_gpio_unlock(chip, flags);
109
110	return ret;
111}
112EXPORT_SYMBOL(s3c_gpio_setpull);
113
114s3c_gpio_pull_t s3c_gpio_getpull(unsigned int pin)
115{
116	struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
117	unsigned long flags;
118	int offset;
119	u32 pup = 0;
120
121	if (chip) {
122		offset = pin - chip->chip.base;
123
124		s3c_gpio_lock(chip, flags);
125		pup = s3c_gpio_do_getpull(chip, offset);
126		s3c_gpio_unlock(chip, flags);
127	}
128
129	return (__force s3c_gpio_pull_t)pup;
130}
131EXPORT_SYMBOL(s3c_gpio_getpull);
132
133#ifdef CONFIG_S3C_GPIO_CFG_S3C24XX
134int s3c_gpio_setcfg_s3c24xx_a(struct s3c_gpio_chip *chip,
135			      unsigned int off, unsigned int cfg)
136{
137	void __iomem *reg = chip->base;
138	unsigned int shift = off;
139	u32 con;
140
141	if (s3c_gpio_is_cfg_special(cfg)) {
142		cfg &= 0xf;
143
144		/* Map output to 0, and SFN2 to 1 */
145		cfg -= 1;
146		if (cfg > 1)
147			return -EINVAL;
148
149		cfg <<= shift;
150	}
151
152	con = __raw_readl(reg);
153	con &= ~(0x1 << shift);
154	con |= cfg;
155	__raw_writel(con, reg);
156
157	return 0;
158}
159
160unsigned s3c_gpio_getcfg_s3c24xx_a(struct s3c_gpio_chip *chip,
161				   unsigned int off)
162{
163	u32 con;
164
165	con = __raw_readl(chip->base);
166	con >>= off;
167	con &= 1;
168	con++;
169
170	return S3C_GPIO_SFN(con);
171}
172
173int s3c_gpio_setcfg_s3c24xx(struct s3c_gpio_chip *chip,
174			    unsigned int off, unsigned int cfg)
175{
176	void __iomem *reg = chip->base;
177	unsigned int shift = off * 2;
178	u32 con;
179
180	if (s3c_gpio_is_cfg_special(cfg)) {
181		cfg &= 0xf;
182		if (cfg > 3)
183			return -EINVAL;
184
185		cfg <<= shift;
186	}
187
188	con = __raw_readl(reg);
189	con &= ~(0x3 << shift);
190	con |= cfg;
191	__raw_writel(con, reg);
192
193	return 0;
194}
195
196unsigned int s3c_gpio_getcfg_s3c24xx(struct s3c_gpio_chip *chip,
197				     unsigned int off)
198{
199	u32 con;
200
201	con = __raw_readl(chip->base);
202	con >>= off * 2;
203	con &= 3;
204
205	/* this conversion works for IN and OUT as well as special mode */
206	return S3C_GPIO_SPECIAL(con);
207}
208#endif
209
210#ifdef CONFIG_S3C_GPIO_CFG_S3C64XX
211int s3c_gpio_setcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip,
212				 unsigned int off, unsigned int cfg)
213{
214	void __iomem *reg = chip->base;
215	unsigned int shift = (off & 7) * 4;
216	u32 con;
217
218	if (off < 8 && chip->chip.ngpio > 8)
219		reg -= 4;
220
221	if (s3c_gpio_is_cfg_special(cfg)) {
222		cfg &= 0xf;
223		cfg <<= shift;
224	}
225
226	con = __raw_readl(reg);
227	con &= ~(0xf << shift);
228	con |= cfg;
229	__raw_writel(con, reg);
230
231	return 0;
232}
233
234unsigned s3c_gpio_getcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip,
235				      unsigned int off)
236{
237	void __iomem *reg = chip->base;
238	unsigned int shift = (off & 7) * 4;
239	u32 con;
240
241	if (off < 8 && chip->chip.ngpio > 8)
242		reg -= 4;
243
244	con = __raw_readl(reg);
245	con >>= shift;
246	con &= 0xf;
247
248	/* this conversion works for IN and OUT as well as special mode */
249	return S3C_GPIO_SPECIAL(con);
250}
251
252#endif /* CONFIG_S3C_GPIO_CFG_S3C64XX */
253
254#ifdef CONFIG_S3C_GPIO_PULL_UPDOWN
255int s3c_gpio_setpull_updown(struct s3c_gpio_chip *chip,
256			    unsigned int off, s3c_gpio_pull_t pull)
257{
258	void __iomem *reg = chip->base + 0x08;
259	int shift = off * 2;
260	u32 pup;
261
262	pup = __raw_readl(reg);
263	pup &= ~(3 << shift);
264	pup |= pull << shift;
265	__raw_writel(pup, reg);
266
267	return 0;
268}
269
270s3c_gpio_pull_t s3c_gpio_getpull_updown(struct s3c_gpio_chip *chip,
271					unsigned int off)
272{
273	void __iomem *reg = chip->base + 0x08;
274	int shift = off * 2;
275	u32 pup = __raw_readl(reg);
276
277	pup >>= shift;
278	pup &= 0x3;
279	return (__force s3c_gpio_pull_t)pup;
280}
281
282#ifdef CONFIG_S3C_GPIO_PULL_S3C2443
283int s3c_gpio_setpull_s3c2443(struct s3c_gpio_chip *chip,
284				unsigned int off, s3c_gpio_pull_t pull)
285{
286	switch (pull) {
287	case S3C_GPIO_PULL_NONE:
288		pull = 0x01;
289		break;
290	case S3C_GPIO_PULL_UP:
291		pull = 0x00;
292		break;
293	case S3C_GPIO_PULL_DOWN:
294		pull = 0x02;
295		break;
296	}
297	return s3c_gpio_setpull_updown(chip, off, pull);
298}
299
300s3c_gpio_pull_t s3c_gpio_getpull_s3c2443(struct s3c_gpio_chip *chip,
301					unsigned int off)
302{
303	s3c_gpio_pull_t pull;
304
305	pull = s3c_gpio_getpull_updown(chip, off);
306
307	switch (pull) {
308	case 0x00:
309		pull = S3C_GPIO_PULL_UP;
310		break;
311	case 0x01:
312	case 0x03:
313		pull = S3C_GPIO_PULL_NONE;
314		break;
315	case 0x02:
316		pull = S3C_GPIO_PULL_DOWN;
317		break;
318	}
319
320	return pull;
321}
322#endif
323#endif
324
325#if defined(CONFIG_S3C_GPIO_PULL_UP) || defined(CONFIG_S3C_GPIO_PULL_DOWN)
326static int s3c_gpio_setpull_1(struct s3c_gpio_chip *chip,
327			 unsigned int off, s3c_gpio_pull_t pull,
328			 s3c_gpio_pull_t updown)
329{
330	void __iomem *reg = chip->base + 0x08;
331	u32 pup = __raw_readl(reg);
332
333	if (pull == updown)
334		pup &= ~(1 << off);
335	else if (pull == S3C_GPIO_PULL_NONE)
336		pup |= (1 << off);
337	else
338		return -EINVAL;
339
340	__raw_writel(pup, reg);
341	return 0;
342}
343
344static s3c_gpio_pull_t s3c_gpio_getpull_1(struct s3c_gpio_chip *chip,
345				     unsigned int off, s3c_gpio_pull_t updown)
346{
347	void __iomem *reg = chip->base + 0x08;
348	u32 pup = __raw_readl(reg);
349
350	pup &= (1 << off);
351	return pup ? S3C_GPIO_PULL_NONE : updown;
352}
353#endif /* CONFIG_S3C_GPIO_PULL_UP || CONFIG_S3C_GPIO_PULL_DOWN */
354
355#ifdef CONFIG_S3C_GPIO_PULL_UP
356s3c_gpio_pull_t s3c_gpio_getpull_1up(struct s3c_gpio_chip *chip,
357				     unsigned int off)
358{
359	return s3c_gpio_getpull_1(chip, off, S3C_GPIO_PULL_UP);
360}
361
362int s3c_gpio_setpull_1up(struct s3c_gpio_chip *chip,
363			 unsigned int off, s3c_gpio_pull_t pull)
364{
365	return s3c_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_UP);
366}
367#endif /* CONFIG_S3C_GPIO_PULL_UP */
368
369#ifdef CONFIG_S3C_GPIO_PULL_DOWN
370s3c_gpio_pull_t s3c_gpio_getpull_1down(struct s3c_gpio_chip *chip,
371				     unsigned int off)
372{
373	return s3c_gpio_getpull_1(chip, off, S3C_GPIO_PULL_DOWN);
374}
375
376int s3c_gpio_setpull_1down(struct s3c_gpio_chip *chip,
377			 unsigned int off, s3c_gpio_pull_t pull)
378{
379	return s3c_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_DOWN);
380}
381#endif /* CONFIG_S3C_GPIO_PULL_DOWN */
382
383#ifdef CONFIG_S5P_GPIO_DRVSTR
384s5p_gpio_drvstr_t s5p_gpio_get_drvstr(unsigned int pin)
385{
386	struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
387	unsigned int off;
388	void __iomem *reg;
389	int shift;
390	u32 drvstr;
391
392	if (!chip)
393		return -EINVAL;
394
395	off = pin - chip->chip.base;
396	shift = off * 2;
397	reg = chip->base + 0x0C;
398
399	drvstr = __raw_readl(reg);
400	drvstr = drvstr >> shift;
401	drvstr &= 0x3;
402
403	return (__force s5p_gpio_drvstr_t)drvstr;
404}
405EXPORT_SYMBOL(s5p_gpio_get_drvstr);
406
407int s5p_gpio_set_drvstr(unsigned int pin, s5p_gpio_drvstr_t drvstr)
408{
409	struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
410	unsigned int off;
411	void __iomem *reg;
412	int shift;
413	u32 tmp;
414
415	if (!chip)
416		return -EINVAL;
417
418	off = pin - chip->chip.base;
419	shift = off * 2;
420	reg = chip->base + 0x0C;
421
422	tmp = __raw_readl(reg);
423	tmp &= ~(0x3 << shift);
424	tmp |= drvstr << shift;
425
426	__raw_writel(tmp, reg);
427
428	return 0;
429}
430EXPORT_SYMBOL(s5p_gpio_set_drvstr);
431#endif	/* CONFIG_S5P_GPIO_DRVSTR */