sh: Kill off remaining config.h references.
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / arch / sh / boards / landisk / landisk_pwb.c
1 /*
2 * arch/sh/boards/landisk/landisk_pwb.c -- driver for the Power control switch.
3 *
4 * This driver will also support the I-O DATA Device, Inc. LANDISK Board.
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 *
10 * Copylight (C) 2002 Atom Create Engineering Co., Ltd.
11 *
12 * LED control drive function added by kogiidena
13 */
14 #include <linux/module.h>
15 #include <linux/errno.h>
16 #include <linux/signal.h>
17 #include <linux/major.h>
18 #include <linux/poll.h>
19 #include <linux/init.h>
20 #include <linux/delay.h>
21 #include <linux/sched.h>
22 #include <linux/timer.h>
23 #include <linux/interrupt.h>
24
25 #include <asm/system.h>
26 #include <asm/io.h>
27 #include <asm/irq.h>
28 #include <asm/uaccess.h>
29 #include <asm/landisk/iodata_landisk.h>
30
31 #define SHUTDOWN_BTN_MINOR 1 /* Shutdown button device minor no. */
32 #define LED_MINOR 21 /* LED minor no. */
33 #define BTN_MINOR 22 /* BUTTON minor no. */
34 #define GIO_MINOR 40 /* GIO minor no. */
35
36 static int openCnt;
37 static int openCntLED;
38 static int openCntGio;
39 static int openCntBtn;
40 static int landisk_btn;
41 static int landisk_btnctrlpid;
42 /*
43 * Functions prototypes
44 */
45
46 static int gio_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
47 unsigned long arg);
48
49 static int swdrv_open(struct inode *inode, struct file *filp)
50 {
51 int minor;
52
53 minor = MINOR(inode->i_rdev);
54 filp->private_data = (void *)minor;
55
56 if (minor == SHUTDOWN_BTN_MINOR) {
57 if (openCnt > 0) {
58 return -EALREADY;
59 } else {
60 openCnt++;
61 return 0;
62 }
63 } else if (minor == LED_MINOR) {
64 if (openCntLED > 0) {
65 return -EALREADY;
66 } else {
67 openCntLED++;
68 return 0;
69 }
70 } else if (minor == BTN_MINOR) {
71 if (openCntBtn > 0) {
72 return -EALREADY;
73 } else {
74 openCntBtn++;
75 return 0;
76 }
77 } else if (minor == GIO_MINOR) {
78 if (openCntGio > 0) {
79 return -EALREADY;
80 } else {
81 openCntGio++;
82 return 0;
83 }
84 }
85 return -ENOENT;
86
87 }
88
89 static int swdrv_close(struct inode *inode, struct file *filp)
90 {
91 int minor;
92
93 minor = MINOR(inode->i_rdev);
94 if (minor == SHUTDOWN_BTN_MINOR) {
95 openCnt--;
96 } else if (minor == LED_MINOR) {
97 openCntLED--;
98 } else if (minor == BTN_MINOR) {
99 openCntBtn--;
100 } else if (minor == GIO_MINOR) {
101 openCntGio--;
102 }
103 return 0;
104 }
105
106 static int swdrv_read(struct file *filp, char *buff, size_t count,
107 loff_t * ppos)
108 {
109 int minor;
110 minor = (int)(filp->private_data);
111
112 if (!access_ok(VERIFY_WRITE, (void *)buff, count))
113 return -EFAULT;
114
115 if (minor == SHUTDOWN_BTN_MINOR) {
116 if (landisk_btn & 0x10) {
117 put_user(1, buff);
118 return 1;
119 } else {
120 return 0;
121 }
122 }
123 return 0;
124 }
125
126 static int swdrv_write(struct file *filp, const char *buff, size_t count,
127 loff_t * ppos)
128 {
129 int minor;
130 minor = (int)(filp->private_data);
131
132 if (minor == SHUTDOWN_BTN_MINOR) {
133 return count;
134 }
135 return count;
136 }
137
138 static irqreturn_t sw_interrupt(int irq, void *dev_id, struct pt_regs *regs)
139 {
140 landisk_btn = (0x0ff & (~ctrl_inb(PA_STATUS)));
141 disable_irq(IRQ_BUTTON);
142 disable_irq(IRQ_POWER);
143 ctrl_outb(0x00, PA_PWRINT_CLR);
144
145 if (landisk_btnctrlpid != 0) {
146 kill_proc(landisk_btnctrlpid, SIGUSR1, 1);
147 landisk_btnctrlpid = 0;
148 }
149
150 return IRQ_HANDLED;
151 }
152
153 static struct file_operations swdrv_fops = {
154 .read = swdrv_read, /* read */
155 .write = swdrv_write, /* write */
156 .open = swdrv_open, /* open */
157 .release = swdrv_close, /* release */
158 .ioctl = gio_ioctl, /* ioctl */
159
160 };
161
162 static char banner[] __initdata =
163 KERN_INFO "LANDISK and USL-5P Button, LED and GIO driver initialized\n";
164
165 int __init swdrv_init(void)
166 {
167 int error;
168
169 printk("%s", banner);
170
171 openCnt = 0;
172 openCntLED = 0;
173 openCntBtn = 0;
174 openCntGio = 0;
175 landisk_btn = 0;
176 landisk_btnctrlpid = 0;
177
178 if ((error = register_chrdev(SHUTDOWN_BTN_MAJOR, "swdrv", &swdrv_fops))) {
179 printk(KERN_ERR
180 "Button, LED and GIO driver:Couldn't register driver, error=%d\n",
181 error);
182 return 1;
183 }
184
185 if (request_irq(IRQ_POWER, sw_interrupt, 0, "SHUTDOWNSWITCH", NULL)) {
186 printk(KERN_ERR "Unable to get IRQ 11.\n");
187 return 1;
188 }
189 if (request_irq(IRQ_BUTTON, sw_interrupt, 0, "USL-5P BUTTON", NULL)) {
190 printk(KERN_ERR "Unable to get IRQ 12.\n");
191 return 1;
192 }
193 ctrl_outb(0x00, PA_PWRINT_CLR);
194
195 return 0;
196 }
197
198 module_init(swdrv_init);
199
200 /*
201 * gio driver
202 *
203 */
204
205 #include <asm/landisk/gio.h>
206
207 static int gio_ioctl(struct inode *inode, struct file *filp,
208 unsigned int cmd, unsigned long arg)
209 {
210 int minor;
211 unsigned int data, mask;
212 static unsigned int addr = 0;
213
214 minor = (int)(filp->private_data);
215
216 /* access control */
217 if (minor == GIO_MINOR) {
218 ;
219 } else if (minor == LED_MINOR) {
220 if (((cmd & 0x0ff) >= 9) && ((cmd & 0x0ff) < 20)) {
221 ;
222 } else {
223 return -EINVAL;
224 }
225 } else if (minor == BTN_MINOR) {
226 if (((cmd & 0x0ff) >= 20) && ((cmd & 0x0ff) < 30)) {
227 ;
228 } else {
229 return -EINVAL;
230 }
231 } else {
232 return -EINVAL;
233 }
234
235 if (cmd & 0x01) { /* write */
236 if (copy_from_user(&data, (int *)arg, sizeof(int))) {
237 return -EFAULT;
238 }
239 }
240
241 switch (cmd) {
242 case GIODRV_IOCSGIOSETADDR: /* addres set */
243 addr = data;
244 break;
245
246 case GIODRV_IOCSGIODATA1: /* write byte */
247 ctrl_outb((unsigned char)(0x0ff & data), addr);
248 break;
249
250 case GIODRV_IOCSGIODATA2: /* write word */
251 if (addr & 0x01) {
252 return -EFAULT;
253 }
254 ctrl_outw((unsigned short int)(0x0ffff & data), addr);
255 break;
256
257 case GIODRV_IOCSGIODATA4: /* write long */
258 if (addr & 0x03) {
259 return -EFAULT;
260 }
261 ctrl_outl(data, addr);
262 break;
263
264 case GIODRV_IOCGGIODATA1: /* read byte */
265 data = ctrl_inb(addr);
266 break;
267
268 case GIODRV_IOCGGIODATA2: /* read word */
269 if (addr & 0x01) {
270 return -EFAULT;
271 }
272 data = ctrl_inw(addr);
273 break;
274
275 case GIODRV_IOCGGIODATA4: /* read long */
276 if (addr & 0x03) {
277 return -EFAULT;
278 }
279 data = ctrl_inl(addr);
280 break;
281 case GIODRV_IOCSGIO_LED: /* write */
282 mask = ((data & 0x00ffffff) << 8)
283 | ((data & 0x0000ffff) << 16)
284 | ((data & 0x000000ff) << 24);
285 landisk_ledparam = data & (~mask);
286 if (landisk_arch == 0) { /* arch == landisk */
287 landisk_ledparam &= 0x03030303;
288 mask = (~(landisk_ledparam >> 22)) & 0x000c;
289 landisk_ledparam |= mask;
290 } else { /* arch == usl-5p */
291 mask = (landisk_ledparam >> 24) & 0x0001;
292 landisk_ledparam |= mask;
293 landisk_ledparam &= 0x007f7f7f;
294 }
295 landisk_ledparam |= 0x80;
296 break;
297 case GIODRV_IOCGGIO_LED: /* read */
298 data = landisk_ledparam;
299 if (landisk_arch == 0) { /* arch == landisk */
300 data &= 0x03030303;
301 } else { /* arch == usl-5p */
302 ;
303 }
304 data &= (~0x080);
305 break;
306 case GIODRV_IOCSGIO_BUZZER: /* write */
307 landisk_buzzerparam = data;
308 landisk_ledparam |= 0x80;
309 break;
310 case GIODRV_IOCGGIO_LANDISK: /* read */
311 data = landisk_arch & 0x01;
312 break;
313 case GIODRV_IOCGGIO_BTN: /* read */
314 data = (0x0ff & ctrl_inb(PA_PWRINT_CLR));
315 data <<= 8;
316 data |= (0x0ff & ctrl_inb(PA_IMASK));
317 data <<= 8;
318 data |= (0x0ff & landisk_btn);
319 data <<= 8;
320 data |= (0x0ff & (~ctrl_inb(PA_STATUS)));
321 break;
322 case GIODRV_IOCSGIO_BTNPID: /* write */
323 landisk_btnctrlpid = data;
324 landisk_btn = 0;
325 if (irq_desc[IRQ_BUTTON].depth) {
326 enable_irq(IRQ_BUTTON);
327 }
328 if (irq_desc[IRQ_POWER].depth) {
329 enable_irq(IRQ_POWER);
330 }
331 break;
332 case GIODRV_IOCGGIO_BTNPID: /* read */
333 data = landisk_btnctrlpid;
334 break;
335 default:
336 return -EFAULT;
337 break;
338 }
339
340 if ((cmd & 0x01) == 0) { /* read */
341 if (copy_to_user((int *)arg, &data, sizeof(int))) {
342 return -EFAULT;
343 }
344 }
345 return 0;
346 }