Blame view

drivers/gpio/gpio-ks8695.c 7.37 KB
8a87a996e   Andrew Victor   [ARM] 4377/1: KS8...
1
2
3
4
  /*
   * arch/arm/mach-ks8695/gpio.c
   *
   * Copyright (C) 2006 Andrew Victor
72880ad86   Daniel Silverstone   [ARM] KS8695: Fix...
5
6
   * Updated to GPIOLIB, Copyright 2008 Simtec Electronics
   *                     Daniel Silverstone <dsilvers@simtec.co.uk>
8a87a996e   Andrew Victor   [ARM] 4377/1: KS8...
7
8
9
10
11
12
13
14
15
16
17
18
19
20
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License version 2 as
   * published by the Free Software Foundation.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   */
2f8163baa   Russell King   ARM: gpio: conver...
21
  #include <linux/gpio.h>
8a87a996e   Andrew Victor   [ARM] 4377/1: KS8...
22
23
24
  #include <linux/kernel.h>
  #include <linux/mm.h>
  #include <linux/init.h>
20118ff97   Andrew Victor   [ARM] 4603/1: KS8...
25
26
  #include <linux/debugfs.h>
  #include <linux/seq_file.h>
8a87a996e   Andrew Victor   [ARM] 4377/1: KS8...
27
  #include <linux/module.h>
fced80c73   Russell King   [ARM] Convert asm...
28
  #include <linux/io.h>
8a87a996e   Andrew Victor   [ARM] 4377/1: KS8...
29

a09e64fbc   Russell King   [ARM] Move includ...
30
  #include <mach/hardware.h>
8a87a996e   Andrew Victor   [ARM] 4377/1: KS8...
31
  #include <asm/mach/irq.h>
a09e64fbc   Russell King   [ARM] Move includ...
32
  #include <mach/regs-gpio.h>
e24e4498c   Linus Walleij   ARM: 7036/1: mach...
33
  #include <mach/gpio-ks8695.h>
8a87a996e   Andrew Victor   [ARM] 4377/1: KS8...
34
35
36
37
38
  
  /*
   * Configure a GPIO line for either GPIO function, or its internal
   * function (Interrupt, Timer, etc).
   */
72880ad86   Daniel Silverstone   [ARM] KS8695: Fix...
39
  static void ks8695_gpio_mode(unsigned int pin, short gpio)
8a87a996e   Andrew Victor   [ARM] 4377/1: KS8...
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
  {
  	unsigned int enable[] = { IOPC_IOEINT0EN, IOPC_IOEINT1EN, IOPC_IOEINT2EN, IOPC_IOEINT3EN, IOPC_IOTIM0EN, IOPC_IOTIM1EN };
  	unsigned long x, flags;
  
  	if (pin > KS8695_GPIO_5)	/* only GPIO 0..5 have internal functions */
  		return;
  
  	local_irq_save(flags);
  
  	x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPC);
  	if (gpio)			/* GPIO: set bit to 0 */
  		x &= ~enable[pin];
  	else				/* Internal function: set bit to 1 */
  		x |= enable[pin];
  	__raw_writel(x, KS8695_GPIO_VA + KS8695_IOPC);
  
  	local_irq_restore(flags);
  }
  
  
  static unsigned short gpio_irq[] = { KS8695_IRQ_EXTERN0, KS8695_IRQ_EXTERN1, KS8695_IRQ_EXTERN2, KS8695_IRQ_EXTERN3 };
  
  /*
   * Configure GPIO pin as external interrupt source.
   */
72880ad86   Daniel Silverstone   [ARM] KS8695: Fix...
65
  int ks8695_gpio_interrupt(unsigned int pin, unsigned int type)
8a87a996e   Andrew Victor   [ARM] 4377/1: KS8...
66
67
68
69
70
71
72
73
74
75
  {
  	unsigned long x, flags;
  
  	if (pin > KS8695_GPIO_3)	/* only GPIO 0..3 can generate IRQ */
  		return -EINVAL;
  
  	local_irq_save(flags);
  
  	/* set pin as input */
  	x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
8d163b3fa   Andrew Victor   [ARM] 5296/1: [KS...
76
  	x &= ~IOPM(pin);
8a87a996e   Andrew Victor   [ARM] 4377/1: KS8...
77
78
79
80
81
  	__raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM);
  
  	local_irq_restore(flags);
  
  	/* Set IRQ triggering type */
6845664a6   Thomas Gleixner   arm: Cleanup the ...
82
  	irq_set_irq_type(gpio_irq[pin], type);
8a87a996e   Andrew Victor   [ARM] 4377/1: KS8...
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
  
  	/* enable interrupt mode */
  	ks8695_gpio_mode(pin, 0);
  
  	return 0;
  }
  EXPORT_SYMBOL(ks8695_gpio_interrupt);
  
  
  
  /* .... Generic GPIO interface .............................................. */
  
  /*
   * Configure the GPIO line as an input.
   */
72880ad86   Daniel Silverstone   [ARM] KS8695: Fix...
98
  static int ks8695_gpio_direction_input(struct gpio_chip *gc, unsigned int pin)
8a87a996e   Andrew Victor   [ARM] 4377/1: KS8...
99
100
101
102
103
104
105
106
107
108
109
110
111
  {
  	unsigned long x, flags;
  
  	if (pin > KS8695_GPIO_15)
  		return -EINVAL;
  
  	/* set pin to GPIO mode */
  	ks8695_gpio_mode(pin, 1);
  
  	local_irq_save(flags);
  
  	/* set pin as input */
  	x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
8d163b3fa   Andrew Victor   [ARM] 5296/1: [KS...
112
  	x &= ~IOPM(pin);
8a87a996e   Andrew Victor   [ARM] 4377/1: KS8...
113
114
115
116
117
118
  	__raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM);
  
  	local_irq_restore(flags);
  
  	return 0;
  }
8a87a996e   Andrew Victor   [ARM] 4377/1: KS8...
119
120
121
122
123
  
  
  /*
   * Configure the GPIO line as an output, with default state.
   */
72880ad86   Daniel Silverstone   [ARM] KS8695: Fix...
124
125
  static int ks8695_gpio_direction_output(struct gpio_chip *gc,
  					unsigned int pin, int state)
8a87a996e   Andrew Victor   [ARM] 4377/1: KS8...
126
127
128
129
130
131
132
133
134
135
136
137
138
139
  {
  	unsigned long x, flags;
  
  	if (pin > KS8695_GPIO_15)
  		return -EINVAL;
  
  	/* set pin to GPIO mode */
  	ks8695_gpio_mode(pin, 1);
  
  	local_irq_save(flags);
  
  	/* set line state */
  	x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
  	if (state)
8d163b3fa   Andrew Victor   [ARM] 5296/1: [KS...
140
  		x |= IOPD(pin);
8a87a996e   Andrew Victor   [ARM] 4377/1: KS8...
141
  	else
8d163b3fa   Andrew Victor   [ARM] 5296/1: [KS...
142
  		x &= ~IOPD(pin);
8a87a996e   Andrew Victor   [ARM] 4377/1: KS8...
143
144
145
146
  	__raw_writel(x, KS8695_GPIO_VA + KS8695_IOPD);
  
  	/* set pin as output */
  	x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
8d163b3fa   Andrew Victor   [ARM] 5296/1: [KS...
147
  	x |= IOPM(pin);
8a87a996e   Andrew Victor   [ARM] 4377/1: KS8...
148
149
150
151
152
153
  	__raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM);
  
  	local_irq_restore(flags);
  
  	return 0;
  }
8a87a996e   Andrew Victor   [ARM] 4377/1: KS8...
154
155
156
157
158
  
  
  /*
   * Set the state of an output GPIO line.
   */
72880ad86   Daniel Silverstone   [ARM] KS8695: Fix...
159
160
  static void ks8695_gpio_set_value(struct gpio_chip *gc,
  				  unsigned int pin, int state)
8a87a996e   Andrew Victor   [ARM] 4377/1: KS8...
161
162
163
164
165
166
167
168
169
170
171
  {
  	unsigned long x, flags;
  
  	if (pin > KS8695_GPIO_15)
  		return;
  
  	local_irq_save(flags);
  
  	/* set output line state */
  	x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
  	if (state)
8d163b3fa   Andrew Victor   [ARM] 5296/1: [KS...
172
  		x |= IOPD(pin);
8a87a996e   Andrew Victor   [ARM] 4377/1: KS8...
173
  	else
8d163b3fa   Andrew Victor   [ARM] 5296/1: [KS...
174
  		x &= ~IOPD(pin);
8a87a996e   Andrew Victor   [ARM] 4377/1: KS8...
175
176
177
178
  	__raw_writel(x, KS8695_GPIO_VA + KS8695_IOPD);
  
  	local_irq_restore(flags);
  }
8a87a996e   Andrew Victor   [ARM] 4377/1: KS8...
179
180
181
182
183
  
  
  /*
   * Read the state of a GPIO line.
   */
72880ad86   Daniel Silverstone   [ARM] KS8695: Fix...
184
  static int ks8695_gpio_get_value(struct gpio_chip *gc, unsigned int pin)
8a87a996e   Andrew Victor   [ARM] 4377/1: KS8...
185
186
187
188
189
190
191
  {
  	unsigned long x;
  
  	if (pin > KS8695_GPIO_15)
  		return -EINVAL;
  
  	x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
8d163b3fa   Andrew Victor   [ARM] 5296/1: [KS...
192
  	return (x & IOPD(pin)) != 0;
8a87a996e   Andrew Victor   [ARM] 4377/1: KS8...
193
  }
8a87a996e   Andrew Victor   [ARM] 4377/1: KS8...
194
195
196
197
198
  
  
  /*
   * Map GPIO line to IRQ number.
   */
7ef71320e   Ben Dooks   [ARM] KS8695: Add...
199
  static int ks8695_gpio_to_irq(struct gpio_chip *gc, unsigned int pin)
8a87a996e   Andrew Victor   [ARM] 4377/1: KS8...
200
201
202
203
204
205
  {
  	if (pin > KS8695_GPIO_3)	/* only GPIO 0..3 can generate IRQ */
  		return -EINVAL;
  
  	return gpio_irq[pin];
  }
8a87a996e   Andrew Victor   [ARM] 4377/1: KS8...
206
207
208
209
210
211
212
213
214
215
216
217
  
  /*
   * Map IRQ number to GPIO line.
   */
  int irq_to_gpio(unsigned int irq)
  {
  	if ((irq < KS8695_IRQ_EXTERN0) || (irq > KS8695_IRQ_EXTERN3))
  		return -EINVAL;
  
  	return (irq - KS8695_IRQ_EXTERN0);
  }
  EXPORT_SYMBOL(irq_to_gpio);
20118ff97   Andrew Victor   [ARM] 4603/1: KS8...
218

72880ad86   Daniel Silverstone   [ARM] KS8695: Fix...
219
220
221
222
223
224
225
226
  /* GPIOLIB interface */
  
  static struct gpio_chip ks8695_gpio_chip = {
  	.label			= "KS8695",
  	.direction_input	= ks8695_gpio_direction_input,
  	.direction_output	= ks8695_gpio_direction_output,
  	.get			= ks8695_gpio_get_value,
  	.set			= ks8695_gpio_set_value,
7ef71320e   Ben Dooks   [ARM] KS8695: Add...
227
  	.to_irq			= ks8695_gpio_to_irq,
72880ad86   Daniel Silverstone   [ARM] KS8695: Fix...
228
229
230
231
232
233
234
235
236
237
238
239
  	.base			= 0,
  	.ngpio			= 16,
  	.can_sleep		= 0,
  };
  
  /* Register the GPIOs */
  void ks8695_register_gpios(void)
  {
  	if (gpiochip_add(&ks8695_gpio_chip))
  		printk(KERN_ERR "Unable to register core GPIOs
  ");
  }
20118ff97   Andrew Victor   [ARM] 4603/1: KS8...
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
  
  /* .... Debug interface ..................................................... */
  
  #ifdef CONFIG_DEBUG_FS
  
  static int ks8695_gpio_show(struct seq_file *s, void *unused)
  {
  	unsigned int enable[] = { IOPC_IOEINT0EN, IOPC_IOEINT1EN, IOPC_IOEINT2EN, IOPC_IOEINT3EN, IOPC_IOTIM0EN, IOPC_IOTIM1EN };
  	unsigned int intmask[] = { IOPC_IOEINT0TM, IOPC_IOEINT1TM, IOPC_IOEINT2TM, IOPC_IOEINT3TM };
  	unsigned long mode, ctrl, data;
  	int i;
  
  	mode = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
  	ctrl = __raw_readl(KS8695_GPIO_VA + KS8695_IOPC);
  	data = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
  
  	seq_printf(s, "Pin\tI/O\tFunction\tState
  
  ");
  
  	for (i = KS8695_GPIO_0; i <= KS8695_GPIO_15 ; i++) {
  		seq_printf(s, "%i:\t", i);
8d163b3fa   Andrew Victor   [ARM] 5296/1: [KS...
262
  		seq_printf(s, "%s\t", (mode & IOPM(i)) ? "Output" : "Input");
20118ff97   Andrew Victor   [ARM] 4603/1: KS8...
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
  
  		if (i <= KS8695_GPIO_3) {
  			if (ctrl & enable[i]) {
  				seq_printf(s, "EXT%i ", i);
  
  				switch ((ctrl & intmask[i]) >> (4 * i)) {
  					case IOPC_TM_LOW:
  						seq_printf(s, "(Low)");		break;
  					case IOPC_TM_HIGH:
  						seq_printf(s, "(High)");	break;
  					case IOPC_TM_RISING:
  						seq_printf(s, "(Rising)");	break;
  					case IOPC_TM_FALLING:
  						seq_printf(s, "(Falling)");	break;
  					case IOPC_TM_EDGE:
  						seq_printf(s, "(Edges)");	break;
  				}
  			}
  			else
  				seq_printf(s, "GPIO\t");
  		}
  		else if (i <= KS8695_GPIO_5) {
  			if (ctrl & enable[i])
  				seq_printf(s, "TOUT%i\t", i - KS8695_GPIO_4);
  			else
  				seq_printf(s, "GPIO\t");
  		}
  		else
  			seq_printf(s, "GPIO\t");
  
  		seq_printf(s, "\t");
8d163b3fa   Andrew Victor   [ARM] 5296/1: [KS...
294
295
  		seq_printf(s, "%i
  ", (data & IOPD(i)) ? 1 : 0);
20118ff97   Andrew Victor   [ARM] 4603/1: KS8...
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
  	}
  	return 0;
  }
  
  static int ks8695_gpio_open(struct inode *inode, struct file *file)
  {
  	return single_open(file, ks8695_gpio_show, NULL);
  }
  
  static const struct file_operations ks8695_gpio_operations = {
  	.open		= ks8695_gpio_open,
  	.read		= seq_read,
  	.llseek		= seq_lseek,
  	.release	= single_release,
  };
  
  static int __init ks8695_gpio_debugfs_init(void)
  {
  	/* /sys/kernel/debug/ks8695_gpio */
  	(void) debugfs_create_file("ks8695_gpio", S_IFREG | S_IRUGO, NULL, NULL, &ks8695_gpio_operations);
  	return 0;
  }
  postcore_initcall(ks8695_gpio_debugfs_init);
  
  #endif