aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/boards
diff options
context:
space:
mode:
authorkogiidena <kogiidena@eggplant.ddo.jp>2007-03-19 03:24:12 -0400
committerPaul Mundt <lethal@hera.kernel.org>2007-05-06 22:10:54 -0400
commit00e8c494a1603eac0a2cae9836e624a752ad45b1 (patch)
tree078da0b39207f1265ae307140e10d1b36618da14 /arch/sh/boards
parent5753171b8234b98d35d559abc0d88b9e4b520b14 (diff)
sh: landisk updates.
Updates for the landisk board: - The push_switch framework was used. - landisk_pwb.c was divided into psw.c and gio.c. - pata_platform was supported in USL-5P. - irq.c was rewritten. - io.c was replaced with generic I/O routines. Signed-off-by: kogiidena <kogiidena@eggplant.ddo.jp> Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh/boards')
-rw-r--r--arch/sh/boards/landisk/Makefile2
-rw-r--r--arch/sh/boards/landisk/gio.c167
-rw-r--r--arch/sh/boards/landisk/io.c250
-rw-r--r--arch/sh/boards/landisk/irq.c83
-rw-r--r--arch/sh/boards/landisk/landisk_pwb.c346
-rw-r--r--arch/sh/boards/landisk/psw.c143
-rw-r--r--arch/sh/boards/landisk/rtc.c91
-rw-r--r--arch/sh/boards/landisk/setup.c163
8 files changed, 375 insertions, 870 deletions
diff --git a/arch/sh/boards/landisk/Makefile b/arch/sh/boards/landisk/Makefile
index 89e4beb2ad47..a696b4277fa9 100644
--- a/arch/sh/boards/landisk/Makefile
+++ b/arch/sh/boards/landisk/Makefile
@@ -2,4 +2,4 @@
2# Makefile for I-O DATA DEVICE, INC. "LANDISK Series" 2# Makefile for I-O DATA DEVICE, INC. "LANDISK Series"
3# 3#
4 4
5obj-y := setup.o io.o irq.o rtc.o landisk_pwb.o 5obj-y := setup.o irq.o psw.o gio.o
diff --git a/arch/sh/boards/landisk/gio.c b/arch/sh/boards/landisk/gio.c
new file mode 100644
index 000000000000..50d38be62f01
--- /dev/null
+++ b/arch/sh/boards/landisk/gio.c
@@ -0,0 +1,167 @@
1/*
2 * arch/sh/boards/landisk/gio.c - driver for landisk
3 *
4 * This driver will also support the I-O DATA Device, Inc. LANDISK Board.
5 * LANDISK and USL-5P Button, LED and GIO driver drive function.
6 *
7 * Copylight (C) 2006 kogiidena
8 * Copylight (C) 2002 Atom Create Engineering Co., Ltd. *
9 *
10 * This file is subject to the terms and conditions of the GNU General Public
11 * License. See the file "COPYING" in the main directory of this archive
12 * for more details.
13 *
14 */
15#include <linux/module.h>
16#include <linux/init.h>
17#include <linux/kdev_t.h>
18#include <linux/cdev.h>
19#include <linux/fs.h>
20#include <asm/io.h>
21#include <asm/uaccess.h>
22#include <asm/landisk/gio.h>
23#include <asm/landisk/iodata_landisk.h>
24
25#define DEVCOUNT 4
26#define GIO_MINOR 2 /* GIO minor no. */
27
28static dev_t dev;
29static struct cdev *cdev_p;
30static int openCnt;
31
32static int gio_open(struct inode *inode, struct file *filp)
33{
34 int minor;
35
36 minor = MINOR(inode->i_rdev);
37 if (minor < DEVCOUNT) {
38 if (openCnt > 0) {
39 return -EALREADY;
40 } else {
41 openCnt++;
42 return 0;
43 }
44 }
45 return -ENOENT;
46}
47
48static int gio_close(struct inode *inode, struct file *filp)
49{
50 int minor;
51
52 minor = MINOR(inode->i_rdev);
53 if (minor < DEVCOUNT) {
54 openCnt--;
55 }
56 return 0;
57}
58
59static int gio_ioctl(struct inode *inode, struct file *filp,
60 unsigned int cmd, unsigned long arg)
61{
62 unsigned int data;
63 static unsigned int addr = 0;
64
65 if (cmd & 0x01) { /* write */
66 if (copy_from_user(&data, (int *)arg, sizeof(int))) {
67 return -EFAULT;
68 }
69 }
70
71 switch (cmd) {
72 case GIODRV_IOCSGIOSETADDR: /* addres set */
73 addr = data;
74 break;
75
76 case GIODRV_IOCSGIODATA1: /* write byte */
77 ctrl_outb((unsigned char)(0x0ff & data), addr);
78 break;
79
80 case GIODRV_IOCSGIODATA2: /* write word */
81 if (addr & 0x01) {
82 return -EFAULT;
83 }
84 ctrl_outw((unsigned short int)(0x0ffff & data), addr);
85 break;
86
87 case GIODRV_IOCSGIODATA4: /* write long */
88 if (addr & 0x03) {
89 return -EFAULT;
90 }
91 ctrl_outl(data, addr);
92 break;
93
94 case GIODRV_IOCGGIODATA1: /* read byte */
95 data = ctrl_inb(addr);
96 break;
97
98 case GIODRV_IOCGGIODATA2: /* read word */
99 if (addr & 0x01) {
100 return -EFAULT;
101 }
102 data = ctrl_inw(addr);
103 break;
104
105 case GIODRV_IOCGGIODATA4: /* read long */
106 if (addr & 0x03) {
107 return -EFAULT;
108 }
109 data = ctrl_inl(addr);
110 break;
111 default:
112 return -EFAULT;
113 break;
114 }
115
116 if ((cmd & 0x01) == 0) { /* read */
117 if (copy_to_user((int *)arg, &data, sizeof(int))) {
118 return -EFAULT;
119 }
120 }
121 return 0;
122}
123
124static struct file_operations gio_fops = {
125 .owner = THIS_MODULE,
126 .open = gio_open, /* open */
127 .release = gio_close, /* release */
128 .ioctl = gio_ioctl, /* ioctl */
129};
130
131static int __init gio_init(void)
132{
133 int error;
134
135 printk(KERN_INFO "gio: driver initialized\n");
136
137 openCnt = 0;
138
139 if ((error = alloc_chrdev_region(&dev, 0, DEVCOUNT, "gio")) < 0) {
140 printk(KERN_ERR
141 "gio: Couldn't alloc_chrdev_region, error=%d\n",
142 error);
143 return 1;
144 }
145
146 cdev_p = cdev_alloc();
147 cdev_p->ops = &gio_fops;
148 error = cdev_add(cdev_p, dev, DEVCOUNT);
149 if (error) {
150 printk(KERN_ERR
151 "gio: Couldn't cdev_add, error=%d\n", error);
152 return 1;
153 }
154
155 return 0;
156}
157
158static void __exit gio_exit(void)
159{
160 cdev_del(cdev_p);
161 unregister_chrdev_region(dev, DEVCOUNT);
162}
163
164module_init(gio_init);
165module_exit(gio_exit);
166
167MODULE_LICENSE("GPL");
diff --git a/arch/sh/boards/landisk/io.c b/arch/sh/boards/landisk/io.c
deleted file mode 100644
index 92498b4947d5..000000000000
--- a/arch/sh/boards/landisk/io.c
+++ /dev/null
@@ -1,250 +0,0 @@
1/*
2 * arch/sh/boards/landisk/io.c
3 *
4 * Copyright (C) 2001 Ian da Silva, Jeremy Siegel
5 * Based largely on io_se.c.
6 *
7 * I/O routine for I-O Data Device, Inc. LANDISK.
8 *
9 * Initial version only to support LAN access; some
10 * placeholder code from io_landisk.c left in with the
11 * expectation of later SuperIO and PCMCIA access.
12 */
13/*
14 * modifed by kogiidena
15 * 2005.03.03
16 */
17#include <linux/kernel.h>
18#include <linux/types.h>
19#include <linux/pci.h>
20#include <asm/landisk/iodata_landisk.h>
21#include <asm/addrspace.h>
22#include <asm/io.h>
23
24extern void *area5_io_base; /* Area 5 I/O Base address */
25extern void *area6_io_base; /* Area 6 I/O Base address */
26
27static inline unsigned long port2adr(unsigned int port)
28{
29 if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6)
30 if (port == 0x3f6)
31 return ((unsigned long)area5_io_base + 0x2c);
32 else
33 return ((unsigned long)area5_io_base + PA_PIDE_OFFSET +
34 ((port - 0x1f0) << 1));
35 else if ((0x170 <= port && port < 0x178) || port == 0x376)
36 if (port == 0x376)
37 return ((unsigned long)area6_io_base + 0x2c);
38 else
39 return ((unsigned long)area6_io_base + PA_SIDE_OFFSET +
40 ((port - 0x170) << 1));
41 else
42 maybebadio((unsigned long)port);
43
44 return port;
45}
46
47/*
48 * General outline: remap really low stuff [eventually] to SuperIO,
49 * stuff in PCI IO space (at or above window at pci.h:PCIBIOS_MIN_IO)
50 * is mapped through the PCI IO window. Stuff with high bits (PXSEG)
51 * should be way beyond the window, and is used w/o translation for
52 * compatibility.
53 */
54u8 landisk_inb(unsigned long port)
55{
56 if (PXSEG(port))
57 return ctrl_inb(port);
58 else if (is_pci_ioaddr(port))
59 return ctrl_inb(pci_ioaddr(port));
60
61 return ctrl_inw(port2adr(port)) & 0xff;
62}
63
64u8 landisk_inb_p(unsigned long port)
65{
66 u8 v;
67
68 if (PXSEG(port))
69 v = ctrl_inb(port);
70 else if (is_pci_ioaddr(port))
71 v = ctrl_inb(pci_ioaddr(port));
72 else
73 v = ctrl_inw(port2adr(port)) & 0xff;
74
75 ctrl_delay();
76
77 return v;
78}
79
80u16 landisk_inw(unsigned long port)
81{
82 if (PXSEG(port))
83 return ctrl_inw(port);
84 else if (is_pci_ioaddr(port))
85 return ctrl_inw(pci_ioaddr(port));
86 else
87 maybebadio(port);
88
89 return 0;
90}
91
92u32 landisk_inl(unsigned long port)
93{
94 if (PXSEG(port))
95 return ctrl_inl(port);
96 else if (is_pci_ioaddr(port))
97 return ctrl_inl(pci_ioaddr(port));
98 else
99 maybebadio(port);
100
101 return 0;
102}
103
104void landisk_outb(u8 value, unsigned long port)
105{
106 if (PXSEG(port))
107 ctrl_outb(value, port);
108 else if (is_pci_ioaddr(port))
109 ctrl_outb(value, pci_ioaddr(port));
110 else
111 ctrl_outw(value, port2adr(port));
112}
113
114void landisk_outb_p(u8 value, unsigned long port)
115{
116 if (PXSEG(port))
117 ctrl_outb(value, port);
118 else if (is_pci_ioaddr(port))
119 ctrl_outb(value, pci_ioaddr(port));
120 else
121 ctrl_outw(value, port2adr(port));
122 ctrl_delay();
123}
124
125void landisk_outw(u16 value, unsigned long port)
126{
127 if (PXSEG(port))
128 ctrl_outw(value, port);
129 else if (is_pci_ioaddr(port))
130 ctrl_outw(value, pci_ioaddr(port));
131 else
132 maybebadio(port);
133}
134
135void landisk_outl(u32 value, unsigned long port)
136{
137 if (PXSEG(port))
138 ctrl_outl(value, port);
139 else if (is_pci_ioaddr(port))
140 ctrl_outl(value, pci_ioaddr(port));
141 else
142 maybebadio(port);
143}
144
145void landisk_insb(unsigned long port, void *dst, unsigned long count)
146{
147 volatile u16 *p;
148 u8 *buf = dst;
149
150 if (PXSEG(port)) {
151 while (count--)
152 *buf++ = *(volatile u8 *)port;
153 } else if (is_pci_ioaddr(port)) {
154 volatile u8 *bp = (volatile u8 *)pci_ioaddr(port);
155
156 while (count--)
157 *buf++ = *bp;
158 } else {
159 p = (volatile u16 *)port2adr(port);
160 while (count--)
161 *buf++ = *p & 0xff;
162 }
163}
164
165void landisk_insw(unsigned long port, void *dst, unsigned long count)
166{
167 volatile u16 *p;
168 u16 *buf = dst;
169
170 if (PXSEG(port))
171 p = (volatile u16 *)port;
172 else if (is_pci_ioaddr(port))
173 p = (volatile u16 *)pci_ioaddr(port);
174 else
175 p = (volatile u16 *)port2adr(port);
176 while (count--)
177 *buf++ = *p;
178}
179
180void landisk_insl(unsigned long port, void *dst, unsigned long count)
181{
182 u32 *buf = dst;
183
184 if (is_pci_ioaddr(port)) {
185 volatile u32 *p = (volatile u32 *)pci_ioaddr(port);
186
187 while (count--)
188 *buf++ = *p;
189 } else
190 maybebadio(port);
191}
192
193void landisk_outsb(unsigned long port, const void *src, unsigned long count)
194{
195 volatile u16 *p;
196 const u8 *buf = src;
197
198 if (PXSEG(port))
199 while (count--)
200 ctrl_outb(*buf++, port);
201 else if (is_pci_ioaddr(port)) {
202 volatile u8 *bp = (volatile u8 *)pci_ioaddr(port);
203
204 while (count--)
205 *bp = *buf++;
206 } else {
207 p = (volatile u16 *)port2adr(port);
208 while (count--)
209 *p = *buf++;
210 }
211}
212
213void landisk_outsw(unsigned long port, const void *src, unsigned long count)
214{
215 volatile u16 *p;
216 const u16 *buf = src;
217
218 if (PXSEG(port))
219 p = (volatile u16 *)port;
220 else if (is_pci_ioaddr(port))
221 p = (volatile u16 *)pci_ioaddr(port);
222 else
223 p = (volatile u16 *)port2adr(port);
224
225 while (count--)
226 *p = *buf++;
227}
228
229void landisk_outsl(unsigned long port, const void *src, unsigned long count)
230{
231 const u32 *buf = src;
232
233 if (is_pci_ioaddr(port)) {
234 volatile u32 *p = (volatile u32 *)pci_ioaddr(port);
235
236 while (count--)
237 *p = *buf++;
238 } else
239 maybebadio(port);
240}
241
242void __iomem *landisk_ioport_map(unsigned long port, unsigned int size)
243{
244 if (PXSEG(port))
245 return (void __iomem *)port;
246 else if (is_pci_ioaddr(port))
247 return (void __iomem *)pci_ioaddr(port);
248
249 return (void __iomem *)port2adr(port);
250}
diff --git a/arch/sh/boards/landisk/irq.c b/arch/sh/boards/landisk/irq.c
index 3eba6d086d7f..258649491d44 100644
--- a/arch/sh/boards/landisk/irq.c
+++ b/arch/sh/boards/landisk/irq.c
@@ -1,18 +1,16 @@
1/* 1/*
2 * arch/sh/boards/landisk/irq.c 2 * arch/sh/boards/landisk/irq.c
3 * 3 *
4 * I-O DATA Device, Inc. LANDISK Support
5 *
6 * Copyright (C) 2005-2007 kogiidena
7 *
4 * Copyright (C) 2001 Ian da Silva, Jeremy Siegel 8 * Copyright (C) 2001 Ian da Silva, Jeremy Siegel
5 * Based largely on io_se.c. 9 * Based largely on io_se.c.
6 * 10 *
7 * I/O routine for I-O Data Device, Inc. LANDISK. 11 * This file is subject to the terms and conditions of the GNU General Public
8 * 12 * License. See the file "COPYING" in the main directory of this archive
9 * Initial version only to support LAN access; some 13 * for more details.
10 * placeholder code from io_landisk.c left in with the
11 * expectation of later SuperIO and PCMCIA access.
12 */
13/*
14 * modified by kogiidena
15 * 2005.03.03
16 */ 14 */
17#include <linux/init.h> 15#include <linux/init.h>
18#include <linux/irq.h> 16#include <linux/irq.h>
@@ -20,71 +18,27 @@
20#include <linux/io.h> 18#include <linux/io.h>
21#include <asm/landisk/iodata_landisk.h> 19#include <asm/landisk/iodata_landisk.h>
22 20
23static void enable_landisk_irq(unsigned int irq);
24static void disable_landisk_irq(unsigned int irq);
25
26/* shutdown is same as "disable" */
27#define shutdown_landisk_irq disable_landisk_irq
28
29static void ack_landisk_irq(unsigned int irq);
30static void end_landisk_irq(unsigned int irq);
31
32static unsigned int startup_landisk_irq(unsigned int irq)
33{
34 enable_landisk_irq(irq);
35 return 0; /* never anything pending */
36}
37
38static void disable_landisk_irq(unsigned int irq) 21static void disable_landisk_irq(unsigned int irq)
39{ 22{
40 unsigned char val;
41 unsigned char mask = 0xff ^ (0x01 << (irq - 5)); 23 unsigned char mask = 0xff ^ (0x01 << (irq - 5));
42 24
43 /* Set the priority in IPR to 0 */ 25 ctrl_outb(ctrl_inb(PA_IMASK) & mask, PA_IMASK);
44 val = ctrl_inb(PA_IMASK);
45 val &= mask;
46 ctrl_outb(val, PA_IMASK);
47} 26}
48 27
49static void enable_landisk_irq(unsigned int irq) 28static void enable_landisk_irq(unsigned int irq)
50{ 29{
51 unsigned char val;
52 unsigned char value = (0x01 << (irq - 5)); 30 unsigned char value = (0x01 << (irq - 5));
53 31
54 /* Set priority in IPR back to original value */ 32 ctrl_outb(ctrl_inb(PA_IMASK) | value, PA_IMASK);
55 val = ctrl_inb(PA_IMASK);
56 val |= value;
57 ctrl_outb(val, PA_IMASK);
58}
59
60static void ack_landisk_irq(unsigned int irq)
61{
62 disable_landisk_irq(irq);
63}
64
65static void end_landisk_irq(unsigned int irq)
66{
67 if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
68 enable_landisk_irq(irq);
69} 33}
70 34
71static struct hw_interrupt_type landisk_irq_type = { 35static struct irq_chip landisk_irq_chip __read_mostly = {
72 .typename = "LANDISK IRQ", 36 .name = "LANDISK",
73 .startup = startup_landisk_irq, 37 .mask = disable_landisk_irq,
74 .shutdown = shutdown_landisk_irq, 38 .unmask = enable_landisk_irq,
75 .enable = enable_landisk_irq, 39 .mask_ack = disable_landisk_irq,
76 .disable = disable_landisk_irq,
77 .ack = ack_landisk_irq,
78 .end = end_landisk_irq
79}; 40};
80 41
81static void make_landisk_irq(unsigned int irq)
82{
83 disable_irq_nosync(irq);
84 irq_desc[irq].chip = &landisk_irq_type;
85 disable_landisk_irq(irq);
86}
87
88/* 42/*
89 * Initialize IRQ setting 43 * Initialize IRQ setting
90 */ 44 */
@@ -92,6 +46,11 @@ void __init init_landisk_IRQ(void)
92{ 46{
93 int i; 47 int i;
94 48
95 for (i = 5; i < 14; i++) 49 for (i = 5; i < 14; i++) {
96 make_landisk_irq(i); 50 disable_irq_nosync(i);
51 set_irq_chip_and_handler_name(i, &landisk_irq_chip,
52 handle_level_irq, "level");
53 enable_landisk_irq(i);
54 }
55 ctrl_outb(0x00, PA_PWRINT_CLR);
97} 56}
diff --git a/arch/sh/boards/landisk/landisk_pwb.c b/arch/sh/boards/landisk/landisk_pwb.c
deleted file mode 100644
index 47a63c6617ed..000000000000
--- a/arch/sh/boards/landisk/landisk_pwb.c
+++ /dev/null
@@ -1,346 +0,0 @@
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
36static int openCnt;
37static int openCntLED;
38static int openCntGio;
39static int openCntBtn;
40static int landisk_btn;
41static int landisk_btnctrlpid;
42/*
43 * Functions prototypes
44 */
45
46static int gio_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
47 unsigned long arg);
48
49static 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
89static 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
106static 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
126static 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
138static irqreturn_t sw_interrupt(int irq, void *dev_id)
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
153static const 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
162static char banner[] __initdata =
163 KERN_INFO "LANDISK and USL-5P Button, LED and GIO driver initialized\n";
164
165int __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
198module_init(swdrv_init);
199
200/*
201 * gio driver
202 *
203 */
204
205#include <asm/landisk/gio.h>
206
207static 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}
diff --git a/arch/sh/boards/landisk/psw.c b/arch/sh/boards/landisk/psw.c
new file mode 100644
index 000000000000..5a9b70b5decb
--- /dev/null
+++ b/arch/sh/boards/landisk/psw.c
@@ -0,0 +1,143 @@
1/*
2 * arch/sh/boards/landisk/psw.c
3 *
4 * push switch support for LANDISK and USL-5P
5 *
6 * Copyright (C) 2006-2007 Paul Mundt
7 * Copyright (C) 2007 kogiidena
8 *
9 * This file is subject to the terms and conditions of the GNU General Public
10 * License. See the file "COPYING" in the main directory of this archive
11 * for more details.
12 */
13#include <linux/io.h>
14#include <linux/init.h>
15#include <linux/interrupt.h>
16#include <linux/platform_device.h>
17#include <asm/landisk/iodata_landisk.h>
18#include <asm/push-switch.h>
19
20static irqreturn_t psw_irq_handler(int irq, void *arg)
21{
22 struct platform_device *pdev = arg;
23 struct push_switch *psw = platform_get_drvdata(pdev);
24 struct push_switch_platform_info *psw_info = pdev->dev.platform_data;
25 unsigned int sw_value;
26 int ret = 0;
27
28 sw_value = (0x0ff & (~ctrl_inb(PA_STATUS)));
29
30 /* Nothing to do if there's no state change */
31 if (psw->state) {
32 ret = 1;
33 goto out;
34 }
35
36 /* Figure out who raised it */
37 if (sw_value & (1 << psw_info->bit)) {
38 psw->state = 1;
39 mod_timer(&psw->debounce, jiffies + 50);
40 ret = 1;
41 }
42
43out:
44 /* Clear the switch IRQs */
45 ctrl_outb(0x00, PA_PWRINT_CLR);
46
47 return IRQ_RETVAL(ret);
48}
49
50static struct resource psw_power_resources[] = {
51 [0] = {
52 .start = IRQ_POWER,
53 .flags = IORESOURCE_IRQ,
54 },
55};
56
57static struct resource psw_usl5p_resources[] = {
58 [0] = {
59 .start = IRQ_BUTTON,
60 .flags = IORESOURCE_IRQ,
61 },
62};
63
64static struct push_switch_platform_info psw_power_platform_data = {
65 .name = "psw_power",
66 .bit = 4,
67 .irq_flags = IRQF_SHARED,
68 .irq_handler = psw_irq_handler,
69};
70
71static struct push_switch_platform_info psw1_platform_data = {
72 .name = "psw1",
73 .bit = 0,
74 .irq_flags = IRQF_SHARED,
75 .irq_handler = psw_irq_handler,
76};
77
78static struct push_switch_platform_info psw2_platform_data = {
79 .name = "psw2",
80 .bit = 2,
81 .irq_flags = IRQF_SHARED,
82 .irq_handler = psw_irq_handler,
83};
84
85static struct push_switch_platform_info psw3_platform_data = {
86 .name = "psw3",
87 .bit = 1,
88 .irq_flags = IRQF_SHARED,
89 .irq_handler = psw_irq_handler,
90};
91
92static struct platform_device psw_power_switch_device = {
93 .name = "push-switch",
94 .id = 0,
95 .num_resources = ARRAY_SIZE(psw_power_resources),
96 .resource = psw_power_resources,
97 .dev = {
98 .platform_data = &psw_power_platform_data,
99 },
100};
101
102static struct platform_device psw1_switch_device = {
103 .name = "push-switch",
104 .id = 1,
105 .num_resources = ARRAY_SIZE(psw_usl5p_resources),
106 .resource = psw_usl5p_resources,
107 .dev = {
108 .platform_data = &psw1_platform_data,
109 },
110};
111
112static struct platform_device psw2_switch_device = {
113 .name = "push-switch",
114 .id = 2,
115 .num_resources = ARRAY_SIZE(psw_usl5p_resources),
116 .resource = psw_usl5p_resources,
117 .dev = {
118 .platform_data = &psw2_platform_data,
119 },
120};
121
122static struct platform_device psw3_switch_device = {
123 .name = "push-switch",
124 .id = 3,
125 .num_resources = ARRAY_SIZE(psw_usl5p_resources),
126 .resource = psw_usl5p_resources,
127 .dev = {
128 .platform_data = &psw3_platform_data,
129 },
130};
131
132static struct platform_device *psw_devices[] = {
133 &psw_power_switch_device,
134 &psw1_switch_device,
135 &psw2_switch_device,
136 &psw3_switch_device,
137};
138
139static int __init psw_init(void)
140{
141 return platform_add_devices(psw_devices, ARRAY_SIZE(psw_devices));
142}
143module_init(psw_init);
diff --git a/arch/sh/boards/landisk/rtc.c b/arch/sh/boards/landisk/rtc.c
deleted file mode 100644
index 0a9a2a2ad05b..000000000000
--- a/arch/sh/boards/landisk/rtc.c
+++ /dev/null
@@ -1,91 +0,0 @@
1/*
2 * arch/sh/boards/landisk/rtc.c -- RTC support
3 *
4 * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
5 * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka
6 */
7/*
8 * modifed by kogiidena
9 * 2005.09.16
10 */
11#include <linux/init.h>
12#include <linux/kernel.h>
13#include <linux/sched.h>
14#include <linux/time.h>
15#include <linux/delay.h>
16#include <linux/spinlock.h>
17#include <linux/bcd.h>
18#include <asm/rtc.h>
19
20extern spinlock_t rtc_lock;
21
22extern void
23rs5c313_set_cmos_time(unsigned int BCD_yr, unsigned int BCD_mon,
24 unsigned int BCD_day, unsigned int BCD_hr,
25 unsigned int BCD_min, unsigned int BCD_sec);
26
27extern unsigned long
28rs5c313_get_cmos_time(unsigned int *BCD_yr, unsigned int *BCD_mon,
29 unsigned int *BCD_day, unsigned int *BCD_hr,
30 unsigned int *BCD_min, unsigned int *BCD_sec);
31
32void landisk_rtc_gettimeofday(struct timespec *tv)
33{
34 unsigned int BCD_yr, BCD_mon, BCD_day, BCD_hr, BCD_min, BCD_sec;
35 unsigned long flags;
36
37 spin_lock_irqsave(&rtc_lock, flags);
38 tv->tv_sec = rs5c313_get_cmos_time
39 (&BCD_yr, &BCD_mon, &BCD_day, &BCD_hr, &BCD_min, &BCD_sec);
40 tv->tv_nsec = 0;
41 spin_unlock_irqrestore(&rtc_lock, flags);
42}
43
44int landisk_rtc_settimeofday(const time_t secs)
45{
46 int retval = 0;
47 int real_seconds, real_minutes, cmos_minutes;
48 unsigned long flags;
49 unsigned long nowtime = secs;
50 unsigned int BCD_yr, BCD_mon, BCD_day, BCD_hr, BCD_min, BCD_sec;
51
52 spin_lock_irqsave(&rtc_lock, flags);
53
54 rs5c313_get_cmos_time
55 (&BCD_yr, &BCD_mon, &BCD_day, &BCD_hr, &BCD_min, &BCD_sec);
56 cmos_minutes = BCD_min;
57 BCD_TO_BIN(cmos_minutes);
58
59 /*
60 * since we're only adjusting minutes and seconds,
61 * don't interfere with hour overflow. This avoids
62 * messing with unknown time zones but requires your
63 * RTC not to be off by more than 15 minutes
64 */
65 real_seconds = nowtime % 60;
66 real_minutes = nowtime / 60;
67 if (((abs(real_minutes - cmos_minutes) + 15) / 30) & 1)
68 real_minutes += 30; /* correct for half hour time zone */
69 real_minutes %= 60;
70
71 if (abs(real_minutes - cmos_minutes) < 30) {
72 BIN_TO_BCD(real_seconds);
73 BIN_TO_BCD(real_minutes);
74 rs5c313_set_cmos_time(BCD_yr, BCD_mon, BCD_day, BCD_hr,
75 real_minutes, real_seconds);
76 } else {
77 printk(KERN_WARNING
78 "set_rtc_time: can't update from %d to %d\n",
79 cmos_minutes, real_minutes);
80 retval = -1;
81 }
82
83 spin_unlock_irqrestore(&rtc_lock, flags);
84 return retval;
85}
86
87void landisk_time_init(void)
88{
89 rtc_sh_get_time = landisk_rtc_gettimeofday;
90 rtc_sh_set_time = landisk_rtc_settimeofday;
91}
diff --git a/arch/sh/boards/landisk/setup.c b/arch/sh/boards/landisk/setup.c
index 122d69962637..a83a5d9587bb 100644
--- a/arch/sh/boards/landisk/setup.c
+++ b/arch/sh/boards/landisk/setup.c
@@ -1,144 +1,90 @@
1/* 1/*
2 * arch/sh/boards/landisk/setup.c 2 * arch/sh/boards/landisk/setup.c
3 * 3 *
4 * Copyright (C) 2000 Kazumoto Kojima
5 * Copyright (C) 2002 Paul Mundt
6 *
7 * I-O DATA Device, Inc. LANDISK Support. 4 * I-O DATA Device, Inc. LANDISK Support.
8 * 5 *
9 * Modified for LANDISK by 6 * Copyright (C) 2000 Kazumoto Kojima
10 * Atom Create Engineering Co., Ltd. 2002. 7 * Copyright (C) 2002 Paul Mundt
11 * 8 * Copylight (C) 2002 Atom Create Engineering Co., Ltd.
12 * modifed by kogiidena 9 * Copyright (C) 2005-2007 kogiidena
13 * 2005.09.16
14 * 10 *
15 * This file is subject to the terms and conditions of the GNU General Public 11 * This file is subject to the terms and conditions of the GNU General Public
16 * License. See the file "COPYING" in the main directory of this archive 12 * License. See the file "COPYING" in the main directory of this archive
17 * for more details. 13 * for more details.
18 */ 14 */
19#include <linux/init.h> 15#include <linux/init.h>
16#include <linux/platform_device.h>
17#include <linux/pata_platform.h>
20#include <linux/pm.h> 18#include <linux/pm.h>
21#include <linux/mm.h> 19#include <linux/mm.h>
22#include <asm/machvec.h> 20#include <asm/machvec.h>
23#include <asm/rtc.h>
24#include <asm/landisk/iodata_landisk.h> 21#include <asm/landisk/iodata_landisk.h>
25#include <asm/io.h> 22#include <asm/io.h>
26 23
27void landisk_time_init(void);
28void init_landisk_IRQ(void); 24void init_landisk_IRQ(void);
29 25
30int landisk_ledparam;
31int landisk_buzzerparam;
32int landisk_arch;
33
34/* cycle the led's in the clasic knightrider/sun pattern */
35static void heartbeat_landisk(void)
36{
37 static unsigned int cnt = 0, blink = 0x00, period = 25;
38 volatile u8 *p = (volatile u8 *)PA_LED;
39 char data;
40
41 if ((landisk_ledparam & 0x080) == 0)
42 return;
43
44 cnt += 1;
45
46 if (cnt < period)
47 return;
48
49 cnt = 0;
50 blink++;
51
52 data = (blink & 0x01) ? (landisk_ledparam >> 16) : 0;
53 data |= (blink & 0x02) ? (landisk_ledparam >> 8) : 0;
54 data |= landisk_ledparam;
55
56 /* buzzer */
57 if (landisk_buzzerparam & 0x1) {
58 data |= 0x80;
59 } else {
60 data &= 0x7f;
61 }
62 *p = data;
63
64 if (((landisk_ledparam & 0x007f7f00) == 0) &&
65 (landisk_buzzerparam == 0))
66 landisk_ledparam &= (~0x0080);
67
68 landisk_buzzerparam >>= 1;
69}
70
71static void landisk_power_off(void) 26static void landisk_power_off(void)
72{ 27{
73 ctrl_outb(0x01, PA_SHUTDOWN); 28 ctrl_outb(0x01, PA_SHUTDOWN);
74} 29}
75 30
76static void check_usl5p(void) 31static struct resource cf_ide_resources[3];
77{
78 volatile u8 *p = (volatile u8 *)PA_LED;
79 u8 tmp1, tmp2;
80 32
81 tmp1 = *p; 33static struct pata_platform_info pata_info = {
82 *p = 0x40; 34 .ioport_shift = 1,
83 tmp2 = *p; 35};
84 *p = tmp1;
85 36
86 landisk_arch = (tmp2 == 0x40); 37static struct platform_device cf_ide_device = {
87 if (landisk_arch == 1) { 38 .name = "pata_platform",
88 /* arch == usl-5p */ 39 .id = -1,
89 landisk_ledparam = 0x00000380; 40 .num_resources = ARRAY_SIZE(cf_ide_resources),
90 landisk_ledparam |= (tmp1 & 0x07c); 41 .resource = cf_ide_resources,
91 } else { 42 .dev = {
92 /* arch == landisk */ 43 .platform_data = &pata_info,
93 landisk_ledparam = 0x02000180; 44 },
94 landisk_ledparam |= 0x04; 45};
95 }
96}
97 46
98void *area5_io_base; 47static struct platform_device *landisk_devices[] __initdata = {
99void *area6_io_base; 48 &cf_ide_device,
49};
100 50
101static int __init landisk_cf_init(void) 51static int __init landisk_devices_setup(void)
102{ 52{
103 pgprot_t prot; 53 pgprot_t prot;
104 unsigned long paddrbase, psize; 54 unsigned long paddrbase;
55 void *cf_ide_base;
105 56
106 /* open I/O area window */ 57 /* open I/O area window */
107 paddrbase = virt_to_phys((void *)PA_AREA5_IO); 58 paddrbase = virt_to_phys((void *)PA_AREA5_IO);
108 psize = PAGE_SIZE;
109 prot = PAGE_KERNEL_PCC(1, _PAGE_PCC_IO16); 59 prot = PAGE_KERNEL_PCC(1, _PAGE_PCC_IO16);
110 area5_io_base = p3_ioremap(paddrbase, psize, prot.pgprot); 60 cf_ide_base = p3_ioremap(paddrbase, PAGE_SIZE, prot.pgprot);
111 if (!area5_io_base) { 61 if (!cf_ide_base) {
112 printk("allocate_cf_area : can't open CF I/O window!\n"); 62 printk("allocate_cf_area : can't open CF I/O window!\n");
113 return -ENOMEM; 63 return -ENOMEM;
114 } 64 }
115 65
116 paddrbase = virt_to_phys((void *)PA_AREA6_IO); 66 /* IDE cmd address : 0x1f0-0x1f7 and 0x3f6 */
117 psize = PAGE_SIZE; 67 cf_ide_resources[0].start = (unsigned long)cf_ide_base + 0x40;
118 prot = PAGE_KERNEL_PCC(0, _PAGE_PCC_IO16); 68 cf_ide_resources[0].end = (unsigned long)cf_ide_base + 0x40 + 0x0f;
119 area6_io_base = p3_ioremap(paddrbase, psize, prot.pgprot); 69 cf_ide_resources[0].flags = IORESOURCE_IO;
120 if (!area6_io_base) { 70 cf_ide_resources[1].start = (unsigned long)cf_ide_base + 0x2c;
121 printk("allocate_cf_area : can't open HDD I/O window!\n"); 71 cf_ide_resources[1].end = (unsigned long)cf_ide_base + 0x2c + 0x03;
122 return -ENOMEM; 72 cf_ide_resources[1].flags = IORESOURCE_IO;
123 } 73 cf_ide_resources[2].start = IRQ_FATA;
124 74 cf_ide_resources[2].flags = IORESOURCE_IRQ;
125 printk(KERN_INFO "Allocate Area5/6 success.\n"); 75
126 76 return platform_add_devices(landisk_devices,
127 /* XXX : do we need attribute and common-memory area also? */ 77 ARRAY_SIZE(landisk_devices));
128
129 return 0;
130} 78}
131 79
80__initcall(landisk_devices_setup);
81
132static void __init landisk_setup(char **cmdline_p) 82static void __init landisk_setup(char **cmdline_p)
133{ 83{
134 device_initcall(landisk_cf_init); 84 /* LED ON */
135 85 ctrl_outb(ctrl_inb(PA_LED) | 0x03, PA_LED);
136 landisk_buzzerparam = 0;
137 check_usl5p();
138 86
139 printk(KERN_INFO "I-O DATA DEVICE, INC. \"LANDISK Series\" support.\n"); 87 printk(KERN_INFO "I-O DATA DEVICE, INC. \"LANDISK Series\" support.\n");
140
141 board_time_init = landisk_time_init;
142 pm_power_off = landisk_power_off; 88 pm_power_off = landisk_power_off;
143} 89}
144 90
@@ -148,29 +94,6 @@ static void __init landisk_setup(char **cmdline_p)
148struct sh_machine_vector mv_landisk __initmv = { 94struct sh_machine_vector mv_landisk __initmv = {
149 .mv_name = "LANDISK", 95 .mv_name = "LANDISK",
150 .mv_setup = landisk_setup, 96 .mv_setup = landisk_setup,
151 .mv_nr_irqs = 72,
152 .mv_inb = landisk_inb,
153 .mv_inw = landisk_inw,
154 .mv_inl = landisk_inl,
155 .mv_outb = landisk_outb,
156 .mv_outw = landisk_outw,
157 .mv_outl = landisk_outl,
158 .mv_inb_p = landisk_inb_p,
159 .mv_inw_p = landisk_inw,
160 .mv_inl_p = landisk_inl,
161 .mv_outb_p = landisk_outb_p,
162 .mv_outw_p = landisk_outw,
163 .mv_outl_p = landisk_outl,
164 .mv_insb = landisk_insb,
165 .mv_insw = landisk_insw,
166 .mv_insl = landisk_insl,
167 .mv_outsb = landisk_outsb,
168 .mv_outsw = landisk_outsw,
169 .mv_outsl = landisk_outsl,
170 .mv_ioport_map = landisk_ioport_map,
171 .mv_init_irq = init_landisk_IRQ, 97 .mv_init_irq = init_landisk_IRQ,
172#ifdef CONFIG_HEARTBEAT
173 .mv_heartbeat = heartbeat_landisk,
174#endif
175}; 98};
176ALIAS_MV(landisk) 99ALIAS_MV(landisk)