aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/boards/landisk/landisk_pwb.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sh/boards/landisk/landisk_pwb.c')
-rw-r--r--arch/sh/boards/landisk/landisk_pwb.c348
1 files changed, 348 insertions, 0 deletions
diff --git a/arch/sh/boards/landisk/landisk_pwb.c b/arch/sh/boards/landisk/landisk_pwb.c
new file mode 100644
index 000000000000..e75cb578a28b
--- /dev/null
+++ b/arch/sh/boards/landisk/landisk_pwb.c
@@ -0,0 +1,348 @@
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
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>
26
27#include <asm/system.h>
28#include <asm/io.h>
29#include <asm/irq.h>
30#include <asm/uaccess.h>
31#include <asm/landisk/iodata_landisk.h>
32
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. */
37
38static int openCnt;
39static int openCntLED;
40static int openCntGio;
41static int openCntBtn;
42static int landisk_btn;
43static int landisk_btnctrlpid;
44/*
45 * Functions prototypes
46 */
47
48static int gio_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
49 unsigned long arg);
50
51static int swdrv_open(struct inode *inode, struct file *filp)
52{
53 int minor;
54
55 minor = MINOR(inode->i_rdev);
56 filp->private_data = (void *)minor;
57
58 if (minor == SHUTDOWN_BTN_MINOR) {
59 if (openCnt > 0) {
60 return -EALREADY;
61 } else {
62 openCnt++;
63 return 0;
64 }
65 } else if (minor == LED_MINOR) {
66 if (openCntLED > 0) {
67 return -EALREADY;
68 } else {
69 openCntLED++;
70 return 0;
71 }
72 } else if (minor == BTN_MINOR) {
73 if (openCntBtn > 0) {
74 return -EALREADY;
75 } else {
76 openCntBtn++;
77 return 0;
78 }
79 } else if (minor == GIO_MINOR) {
80 if (openCntGio > 0) {
81 return -EALREADY;
82 } else {
83 openCntGio++;
84 return 0;
85 }
86 }
87 return -ENOENT;
88
89}
90
91static int swdrv_close(struct inode *inode, struct file *filp)
92{
93 int minor;
94
95 minor = MINOR(inode->i_rdev);
96 if (minor == SHUTDOWN_BTN_MINOR) {
97 openCnt--;
98 } else if (minor == LED_MINOR) {
99 openCntLED--;
100 } else if (minor == BTN_MINOR) {
101 openCntBtn--;
102 } else if (minor == GIO_MINOR) {
103 openCntGio--;
104 }
105 return 0;
106}
107
108static int swdrv_read(struct file *filp, char *buff, size_t count,
109 loff_t * ppos)
110{
111 int minor;
112 minor = (int)(filp->private_data);
113
114 if (!access_ok(VERIFY_WRITE, (void *)buff, count))
115 return -EFAULT;
116
117 if (minor == SHUTDOWN_BTN_MINOR) {
118 if (landisk_btn & 0x10) {
119 put_user(1, buff);
120 return 1;
121 } else {
122 return 0;
123 }
124 }
125 return 0;
126}
127
128static int swdrv_write(struct file *filp, const char *buff, size_t count,
129 loff_t * ppos)
130{
131 int minor;
132 minor = (int)(filp->private_data);
133
134 if (minor == SHUTDOWN_BTN_MINOR) {
135 return count;
136 }
137 return count;
138}
139
140static irqreturn_t sw_interrupt(int irq, void *dev_id, struct pt_regs *regs)
141{
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);
146
147 if (landisk_btnctrlpid != 0) {
148 kill_proc(landisk_btnctrlpid, SIGUSR1, 1);
149 landisk_btnctrlpid = 0;
150 }
151
152 return IRQ_HANDLED;
153}
154
155static 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 */
161
162};
163
164static char banner[] __initdata =
165 KERN_INFO "LANDISK and USL-5P Button, LED and GIO driver initialized\n";
166
167int __init swdrv_init(void)
168{
169 int error;
170
171 printk("%s", banner);
172
173 openCnt = 0;
174 openCntLED = 0;
175 openCntBtn = 0;
176 openCntGio = 0;
177 landisk_btn = 0;
178 landisk_btnctrlpid = 0;
179
180 if ((error = register_chrdev(SHUTDOWN_BTN_MAJOR, "swdrv", &swdrv_fops))) {
181 printk(KERN_ERR
182 "Button, LED and GIO driver:Couldn't register driver, error=%d\n",
183 error);
184 return 1;
185 }
186
187 if (request_irq(IRQ_POWER, sw_interrupt, 0, "SHUTDOWNSWITCH", NULL)) {
188 printk(KERN_ERR "Unable to get IRQ 11.\n");
189 return 1;
190 }
191 if (request_irq(IRQ_BUTTON, sw_interrupt, 0, "USL-5P BUTTON", NULL)) {
192 printk(KERN_ERR "Unable to get IRQ 12.\n");
193 return 1;
194 }
195 ctrl_outb(0x00, PA_PWRINT_CLR);
196
197 return 0;
198}
199
200module_init(swdrv_init);
201
202/*
203 * gio driver
204 *
205 */
206
207#include <asm/landisk/gio.h>
208
209static int gio_ioctl(struct inode *inode, struct file *filp,
210 unsigned int cmd, unsigned long arg)
211{
212 int minor;
213 unsigned int data, mask;
214 static unsigned int addr = 0;
215
216 minor = (int)(filp->private_data);
217
218 /* access control */
219 if (minor == GIO_MINOR) {
220 ;
221 } else if (minor == LED_MINOR) {
222 if (((cmd & 0x0ff) >= 9) && ((cmd & 0x0ff) < 20)) {
223 ;
224 } else {
225 return -EINVAL;
226 }
227 } else if (minor == BTN_MINOR) {
228 if (((cmd & 0x0ff) >= 20) && ((cmd & 0x0ff) < 30)) {
229 ;
230 } else {
231 return -EINVAL;
232 }
233 } else {
234 return -EINVAL;
235 }
236
237 if (cmd & 0x01) { /* write */
238 if (copy_from_user(&data, (int *)arg, sizeof(int))) {
239 return -EFAULT;
240 }
241 }
242
243 switch (cmd) {
244 case GIODRV_IOCSGIOSETADDR: /* addres set */
245 addr = data;
246 break;
247
248 case GIODRV_IOCSGIODATA1: /* write byte */
249 ctrl_outb((unsigned char)(0x0ff & data), addr);
250 break;
251
252 case GIODRV_IOCSGIODATA2: /* write word */
253 if (addr & 0x01) {
254 return -EFAULT;
255 }
256 ctrl_outw((unsigned short int)(0x0ffff & data), addr);
257 break;
258
259 case GIODRV_IOCSGIODATA4: /* write long */
260 if (addr & 0x03) {
261 return -EFAULT;
262 }
263 ctrl_outl(data, addr);
264 break;
265
266 case GIODRV_IOCGGIODATA1: /* read byte */
267 data = ctrl_inb(addr);
268 break;
269
270 case GIODRV_IOCGGIODATA2: /* read word */
271 if (addr & 0x01) {
272 return -EFAULT;
273 }
274 data = ctrl_inw(addr);
275 break;
276
277 case GIODRV_IOCGGIODATA4: /* read long */
278 if (addr & 0x03) {
279 return -EFAULT;
280 }
281 data = ctrl_inl(addr);
282 break;
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;
296 }
297 landisk_ledparam |= 0x80;
298 break;
299 case GIODRV_IOCGGIO_LED: /* read */
300 data = landisk_ledparam;
301 if (landisk_arch == 0) { /* arch == landisk */
302 data &= 0x03030303;
303 } else { /* arch == usl-5p */
304 ;
305 }
306 data &= (~0x080);
307 break;
308 case GIODRV_IOCSGIO_BUZZER: /* write */
309 landisk_buzzerparam = data;
310 landisk_ledparam |= 0x80;
311 break;
312 case GIODRV_IOCGGIO_LANDISK: /* read */
313 data = landisk_arch & 0x01;
314 break;
315 case GIODRV_IOCGGIO_BTN: /* read */
316 data = (0x0ff & ctrl_inb(PA_PWRINT_CLR));
317 data <<= 8;
318 data |= (0x0ff & ctrl_inb(PA_IMASK));
319 data <<= 8;
320 data |= (0x0ff & landisk_btn);
321 data <<= 8;
322 data |= (0x0ff & (~ctrl_inb(PA_STATUS)));
323 break;
324 case GIODRV_IOCSGIO_BTNPID: /* write */
325 landisk_btnctrlpid = data;
326 landisk_btn = 0;
327 if (irq_desc[IRQ_BUTTON].depth) {
328 enable_irq(IRQ_BUTTON);
329 }
330 if (irq_desc[IRQ_POWER].depth) {
331 enable_irq(IRQ_POWER);
332 }
333 break;
334 case GIODRV_IOCGGIO_BTNPID: /* read */
335 data = landisk_btnctrlpid;
336 break;
337 default:
338 return -EFAULT;
339 break;
340 }
341
342 if ((cmd & 0x01) == 0) { /* read */
343 if (copy_to_user((int *)arg, &data, sizeof(int))) {
344 return -EFAULT;
345 }
346 }
347 return 0;
348}