1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#include <linux/kernel.h>
21#include <linux/mm.h>
22#include <linux/init.h>
23#include <linux/module.h>
24
25#include <asm/io.h>
26#include <asm/hardware.h>
27#include <asm/mach/irq.h>
28
29#include <asm/arch/regs-gpio.h>
30#include <asm/arch/gpio.h>
31
32
33
34
35
36static void __init_or_module ks8695_gpio_mode(unsigned int pin, short gpio)
37{
38 unsigned int enable[] = { IOPC_IOEINT0EN, IOPC_IOEINT1EN, IOPC_IOEINT2EN, IOPC_IOEINT3EN, IOPC_IOTIM0EN, IOPC_IOTIM1EN };
39 unsigned long x, flags;
40
41 if (pin > KS8695_GPIO_5)
42 return;
43
44 local_irq_save(flags);
45
46 x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPC);
47 if (gpio)
48 x &= ~enable[pin];
49 else
50 x |= enable[pin];
51 __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPC);
52
53 local_irq_restore(flags);
54}
55
56
57static unsigned short gpio_irq[] = { KS8695_IRQ_EXTERN0, KS8695_IRQ_EXTERN1, KS8695_IRQ_EXTERN2, KS8695_IRQ_EXTERN3 };
58
59
60
61
62int __init_or_module ks8695_gpio_interrupt(unsigned int pin, unsigned int type)
63{
64 unsigned long x, flags;
65
66 if (pin > KS8695_GPIO_3)
67 return -EINVAL;
68
69 local_irq_save(flags);
70
71
72 x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
73 x &= ~IOPM_(pin);
74 __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM);
75
76 local_irq_restore(flags);
77
78
79 set_irq_type(gpio_irq[pin], type);
80
81
82 ks8695_gpio_mode(pin, 0);
83
84 return 0;
85}
86EXPORT_SYMBOL(ks8695_gpio_interrupt);
87
88
89
90
91
92
93
94
95int __init_or_module gpio_direction_input(unsigned int pin)
96{
97 unsigned long x, flags;
98
99 if (pin > KS8695_GPIO_15)
100 return -EINVAL;
101
102
103 ks8695_gpio_mode(pin, 1);
104
105 local_irq_save(flags);
106
107
108 x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
109 x &= ~IOPM_(pin);
110 __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM);
111
112 local_irq_restore(flags);
113
114 return 0;
115}
116EXPORT_SYMBOL(gpio_direction_input);
117
118
119
120
121
122int __init_or_module gpio_direction_output(unsigned int pin, unsigned int state)
123{
124 unsigned long x, flags;
125
126 if (pin > KS8695_GPIO_15)
127 return -EINVAL;
128
129
130 ks8695_gpio_mode(pin, 1);
131
132 local_irq_save(flags);
133
134
135 x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
136 if (state)
137 x |= (1 << pin);
138 else
139 x &= ~(1 << pin);
140 __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPD);
141
142
143 x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
144 x |= IOPM_(pin);
145 __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM);
146
147 local_irq_restore(flags);
148
149 return 0;
150}
151EXPORT_SYMBOL(gpio_direction_output);
152
153
154
155
156
157void gpio_set_value(unsigned int pin, unsigned int state)
158{
159 unsigned long x, flags;
160
161 if (pin > KS8695_GPIO_15)
162 return;
163
164 local_irq_save(flags);
165
166
167 x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
168 if (state)
169 x |= (1 << pin);
170 else
171 x &= ~(1 << pin);
172 __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPD);
173
174 local_irq_restore(flags);
175}
176EXPORT_SYMBOL(gpio_set_value);
177
178
179
180
181
182int gpio_get_value(unsigned int pin)
183{
184 unsigned long x;
185
186 if (pin > KS8695_GPIO_15)
187 return -EINVAL;
188
189 x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
190 return (x & (1 << pin)) != 0;
191}
192EXPORT_SYMBOL(gpio_get_value);
193
194
195
196
197
198int gpio_to_irq(unsigned int pin)
199{
200 if (pin > KS8695_GPIO_3)
201 return -EINVAL;
202
203 return gpio_irq[pin];
204}
205EXPORT_SYMBOL(gpio_to_irq);
206
207
208
209
210
211int irq_to_gpio(unsigned int irq)
212{
213 if ((irq < KS8695_IRQ_EXTERN0) || (irq > KS8695_IRQ_EXTERN3))
214 return -EINVAL;
215
216 return (irq - KS8695_IRQ_EXTERN0);
217}
218EXPORT_SYMBOL(irq_to_gpio);
219