2 * arch/sh/boards/landisk/landisk_pwb.c -- driver for the Power control switch.
4 * This driver will also support the I-O DATA Device, Inc. LANDISK Board.
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
10 * Copylight (C) 2002 Atom Create Engineering Co., Ltd.
12 * LED control drive function added by kogiidena
15 #include <linux/config.h>
16 #include <linux/module.h>
17 #include <linux/errno.h>
18 #include <linux/signal.h>
19 #include <linux/major.h>
20 #include <linux/poll.h>
21 #include <linux/init.h>
22 #include <linux/delay.h>
23 #include <linux/sched.h>
24 #include <linux/timer.h>
25 #include <linux/interrupt.h>
27 #include <asm/system.h>
30 #include <asm/uaccess.h>
31 #include <asm/landisk/iodata_landisk.h>
33 #define SHUTDOWN_BTN_MINOR 1 /* Shutdown button device minor no. */
34 #define LED_MINOR 21 /* LED minor no. */
35 #define BTN_MINOR 22 /* BUTTON minor no. */
36 #define GIO_MINOR 40 /* GIO minor no. */
39 static int openCntLED
;
40 static int openCntGio
;
41 static int openCntBtn
;
42 static int landisk_btn
;
43 static int landisk_btnctrlpid
;
45 * Functions prototypes
48 static int gio_ioctl(struct inode
*inode
, struct file
*filp
, unsigned int cmd
,
51 static int swdrv_open(struct inode
*inode
, struct file
*filp
)
55 minor
= MINOR(inode
->i_rdev
);
56 filp
->private_data
= (void *)minor
;
58 if (minor
== SHUTDOWN_BTN_MINOR
) {
65 } else if (minor
== LED_MINOR
) {
72 } else if (minor
== BTN_MINOR
) {
79 } else if (minor
== GIO_MINOR
) {
91 static int swdrv_close(struct inode
*inode
, struct file
*filp
)
95 minor
= MINOR(inode
->i_rdev
);
96 if (minor
== SHUTDOWN_BTN_MINOR
) {
98 } else if (minor
== LED_MINOR
) {
100 } else if (minor
== BTN_MINOR
) {
102 } else if (minor
== GIO_MINOR
) {
108 static int swdrv_read(struct file
*filp
, char *buff
, size_t count
,
112 minor
= (int)(filp
->private_data
);
114 if (!access_ok(VERIFY_WRITE
, (void *)buff
, count
))
117 if (minor
== SHUTDOWN_BTN_MINOR
) {
118 if (landisk_btn
& 0x10) {
128 static int swdrv_write(struct file
*filp
, const char *buff
, size_t count
,
132 minor
= (int)(filp
->private_data
);
134 if (minor
== SHUTDOWN_BTN_MINOR
) {
140 static irqreturn_t
sw_interrupt(int irq
, void *dev_id
, struct pt_regs
*regs
)
142 landisk_btn
= (0x0ff & (~ctrl_inb(PA_STATUS
)));
143 disable_irq(IRQ_BUTTON
);
144 disable_irq(IRQ_POWER
);
145 ctrl_outb(0x00, PA_PWRINT_CLR
);
147 if (landisk_btnctrlpid
!= 0) {
148 kill_proc(landisk_btnctrlpid
, SIGUSR1
, 1);
149 landisk_btnctrlpid
= 0;
155 static struct file_operations swdrv_fops
= {
156 .read
= swdrv_read
, /* read */
157 .write
= swdrv_write
, /* write */
158 .open
= swdrv_open
, /* open */
159 .release
= swdrv_close
, /* release */
160 .ioctl
= gio_ioctl
, /* ioctl */
164 static char banner
[] __initdata
=
165 KERN_INFO
"LANDISK and USL-5P Button, LED and GIO driver initialized\n";
167 int __init
swdrv_init(void)
171 printk("%s", banner
);
178 landisk_btnctrlpid
= 0;
180 if ((error
= register_chrdev(SHUTDOWN_BTN_MAJOR
, "swdrv", &swdrv_fops
))) {
182 "Button, LED and GIO driver:Couldn't register driver, error=%d\n",
187 if (request_irq(IRQ_POWER
, sw_interrupt
, 0, "SHUTDOWNSWITCH", NULL
)) {
188 printk(KERN_ERR
"Unable to get IRQ 11.\n");
191 if (request_irq(IRQ_BUTTON
, sw_interrupt
, 0, "USL-5P BUTTON", NULL
)) {
192 printk(KERN_ERR
"Unable to get IRQ 12.\n");
195 ctrl_outb(0x00, PA_PWRINT_CLR
);
200 module_init(swdrv_init
);
207 #include <asm/landisk/gio.h>
209 static int gio_ioctl(struct inode
*inode
, struct file
*filp
,
210 unsigned int cmd
, unsigned long arg
)
213 unsigned int data
, mask
;
214 static unsigned int addr
= 0;
216 minor
= (int)(filp
->private_data
);
219 if (minor
== GIO_MINOR
) {
221 } else if (minor
== LED_MINOR
) {
222 if (((cmd
& 0x0ff) >= 9) && ((cmd
& 0x0ff) < 20)) {
227 } else if (minor
== BTN_MINOR
) {
228 if (((cmd
& 0x0ff) >= 20) && ((cmd
& 0x0ff) < 30)) {
237 if (cmd
& 0x01) { /* write */
238 if (copy_from_user(&data
, (int *)arg
, sizeof(int))) {
244 case GIODRV_IOCSGIOSETADDR
: /* addres set */
248 case GIODRV_IOCSGIODATA1
: /* write byte */
249 ctrl_outb((unsigned char)(0x0ff & data
), addr
);
252 case GIODRV_IOCSGIODATA2
: /* write word */
256 ctrl_outw((unsigned short int)(0x0ffff & data
), addr
);
259 case GIODRV_IOCSGIODATA4
: /* write long */
263 ctrl_outl(data
, addr
);
266 case GIODRV_IOCGGIODATA1
: /* read byte */
267 data
= ctrl_inb(addr
);
270 case GIODRV_IOCGGIODATA2
: /* read word */
274 data
= ctrl_inw(addr
);
277 case GIODRV_IOCGGIODATA4
: /* read long */
281 data
= ctrl_inl(addr
);
283 case GIODRV_IOCSGIO_LED
: /* write */
284 mask
= ((data
& 0x00ffffff) << 8)
285 | ((data
& 0x0000ffff) << 16)
286 | ((data
& 0x000000ff) << 24);
287 landisk_ledparam
= data
& (~mask
);
288 if (landisk_arch
== 0) { /* arch == landisk */
289 landisk_ledparam
&= 0x03030303;
290 mask
= (~(landisk_ledparam
>> 22)) & 0x000c;
291 landisk_ledparam
|= mask
;
292 } else { /* arch == usl-5p */
293 mask
= (landisk_ledparam
>> 24) & 0x0001;
294 landisk_ledparam
|= mask
;
295 landisk_ledparam
&= 0x007f7f7f;
297 landisk_ledparam
|= 0x80;
299 case GIODRV_IOCGGIO_LED
: /* read */
300 data
= landisk_ledparam
;
301 if (landisk_arch
== 0) { /* arch == landisk */
303 } else { /* arch == usl-5p */
308 case GIODRV_IOCSGIO_BUZZER
: /* write */
309 landisk_buzzerparam
= data
;
310 landisk_ledparam
|= 0x80;
312 case GIODRV_IOCGGIO_LANDISK
: /* read */
313 data
= landisk_arch
& 0x01;
315 case GIODRV_IOCGGIO_BTN
: /* read */
316 data
= (0x0ff & ctrl_inb(PA_PWRINT_CLR
));
318 data
|= (0x0ff & ctrl_inb(PA_IMASK
));
320 data
|= (0x0ff & landisk_btn
);
322 data
|= (0x0ff & (~ctrl_inb(PA_STATUS
)));
324 case GIODRV_IOCSGIO_BTNPID
: /* write */
325 landisk_btnctrlpid
= data
;
327 if (irq_desc
[IRQ_BUTTON
].depth
) {
328 enable_irq(IRQ_BUTTON
);
330 if (irq_desc
[IRQ_POWER
].depth
) {
331 enable_irq(IRQ_POWER
);
334 case GIODRV_IOCGGIO_BTNPID
: /* read */
335 data
= landisk_btnctrlpid
;
342 if ((cmd
& 0x01) == 0) { /* read */
343 if (copy_to_user((int *)arg
, &data
, sizeof(int))) {