aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/boards
diff options
context:
space:
mode:
authorkogiidena <kogiidena@eggplant.ddo.jp>2006-09-27 01:53:35 -0400
committerPaul Mundt <lethal@linux-sh.org>2006-09-27 01:53:35 -0400
commit94c0fa520cc169ccf661e9c03b5b95f74d1520b8 (patch)
tree2fc73ea11df222998a363083e03ef6c9e8066b28 /arch/sh/boards
parent634bf4f69b925950ddb09ef99ad7516a449a4333 (diff)
sh: landisk board support.
This adds support for the I-O DATA Landisk. 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/Makefile7
-rw-r--r--arch/sh/boards/landisk/io.c322
-rw-r--r--arch/sh/boards/landisk/irq.c105
-rw-r--r--arch/sh/boards/landisk/landisk_pwb.c348
-rw-r--r--arch/sh/boards/landisk/rtc.c102
-rw-r--r--arch/sh/boards/landisk/setup.c218
6 files changed, 1102 insertions, 0 deletions
diff --git a/arch/sh/boards/landisk/Makefile b/arch/sh/boards/landisk/Makefile
new file mode 100644
index 000000000000..60e75c6db0eb
--- /dev/null
+++ b/arch/sh/boards/landisk/Makefile
@@ -0,0 +1,7 @@
1#
2# Makefile for I-O DATA DEVICE, INC. "LANDISK Series"
3#
4
5obj-y := setup.o io.o irq.o rtc.o landisk_pwb.o
6
7obj-$(CONFIG_PCI) += pci.o
diff --git a/arch/sh/boards/landisk/io.c b/arch/sh/boards/landisk/io.c
new file mode 100644
index 000000000000..1f1679af09d0
--- /dev/null
+++ b/arch/sh/boards/landisk/io.c
@@ -0,0 +1,322 @@
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
18#include <linux/kernel.h>
19#include <linux/types.h>
20#include <asm/io.h>
21#include <asm/landisk/iodata_landisk.h>
22#include <asm/addrspace.h>
23
24#include <linux/module.h>
25#include <linux/pci.h>
26#include "../../drivers/pci/pci-sh7751.h"
27
28extern void *area5_io_base; /* Area 5 I/O Base address */
29extern void *area6_io_base; /* Area 6 I/O Base address */
30
31/*
32 * The 7751R LANDISK uses the built-in PCI controller (PCIC)
33 * of the 7751R processor, and has a SuperIO accessible via the PCI.
34 * The board also includes a PCMCIA controller on its memory bus,
35 * like the other Solution Engine boards.
36 */
37
38#define PCIIOBR (volatile long *)PCI_REG(SH7751_PCIIOBR)
39#define PCIMBR (volatile long *)PCI_REG(SH7751_PCIMBR)
40#define PCI_IO_AREA SH7751_PCI_IO_BASE
41#define PCI_MEM_AREA SH7751_PCI_CONFIG_BASE
42
43#define PCI_IOMAP(adr) (PCI_IO_AREA + (adr & ~SH7751_PCIIOBR_MASK))
44
45#define maybebadio(name,port) \
46 printk("bad PC-like io %s for port 0x%lx at 0x%08x\n", \
47 #name, (port), (__u32) __builtin_return_address(0))
48
49static inline void delay(void)
50{
51 ctrl_inw(0xa0000000);
52}
53
54static inline unsigned long port2adr(unsigned int port)
55{
56 if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6)
57 if (port == 0x3f6)
58 return ((unsigned long)area5_io_base + 0x2c);
59 else
60 return ((unsigned long)area5_io_base + PA_PIDE_OFFSET +
61 ((port - 0x1f0) << 1));
62 else if ((0x170 <= port && port < 0x178) || port == 0x376)
63 if (port == 0x376)
64 return ((unsigned long)area6_io_base + 0x2c);
65 else
66 return ((unsigned long)area6_io_base + PA_SIDE_OFFSET +
67 ((port - 0x170) << 1));
68 else
69 maybebadio(port2adr, (unsigned long)port);
70
71 return port;
72}
73
74/* In case someone configures the kernel w/o PCI support: in that */
75/* scenario, don't ever bother to check for PCI-window addresses */
76
77/* NOTE: WINDOW CHECK MAY BE A BIT OFF, HIGH PCIBIOS_MIN_IO WRAPS? */
78#if defined(CONFIG_PCI)
79#define CHECK_SH7751_PCIIO(port) \
80 ((port >= PCIBIOS_MIN_IO) && (port < (PCIBIOS_MIN_IO + SH7751_PCI_IO_SIZE)))
81#else
82#define CHECK_SH_7751_PCIIO(port) (0)
83#endif
84
85/*
86 * General outline: remap really low stuff [eventually] to SuperIO,
87 * stuff in PCI IO space (at or above window at pci.h:PCIBIOS_MIN_IO)
88 * is mapped through the PCI IO window. Stuff with high bits (PXSEG)
89 * should be way beyond the window, and is used w/o translation for
90 * compatibility.
91 */
92unsigned char landisk_inb(unsigned long port)
93{
94 if (PXSEG(port))
95 return *(volatile unsigned char *)port;
96 else if (CHECK_SH7751_PCIIO(port))
97 return *(volatile unsigned char *)PCI_IOMAP(port);
98 else
99 return (*(volatile unsigned short *)port2adr(port) & 0xff);
100}
101
102unsigned char landisk_inb_p(unsigned long port)
103{
104 unsigned char v;
105
106 if (PXSEG(port))
107 v = *(volatile unsigned char *)port;
108 else if (CHECK_SH7751_PCIIO(port))
109 v = *(volatile unsigned char *)PCI_IOMAP(port);
110 else
111 v = (*(volatile unsigned short *)port2adr(port) & 0xff);
112 delay();
113
114 return v;
115}
116
117unsigned short landisk_inw(unsigned long port)
118{
119 if (PXSEG(port))
120 return *(volatile unsigned short *)port;
121 else if (CHECK_SH7751_PCIIO(port))
122 return *(volatile unsigned short *)PCI_IOMAP(port);
123 else
124 maybebadio(inw, port);
125
126 return 0;
127}
128
129unsigned int landisk_inl(unsigned long port)
130{
131 if (PXSEG(port))
132 return *(volatile unsigned long *)port;
133 else if (CHECK_SH7751_PCIIO(port))
134 return *(volatile unsigned long *)PCI_IOMAP(port);
135 else
136 maybebadio(inl, port);
137
138 return 0;
139}
140
141void landisk_outb(unsigned char value, unsigned long port)
142{
143
144 if (PXSEG(port))
145 *(volatile unsigned char *)port = value;
146 else if (CHECK_SH7751_PCIIO(port))
147 *(volatile unsigned char *)PCI_IOMAP(port) = value;
148 else
149 *(volatile unsigned short *)port2adr(port) = value;
150}
151
152void landisk_outb_p(unsigned char value, unsigned long port)
153{
154 if (PXSEG(port))
155 *(volatile unsigned char *)port = value;
156 else if (CHECK_SH7751_PCIIO(port))
157 *(volatile unsigned char *)PCI_IOMAP(port) = value;
158 else
159 *(volatile unsigned short *)port2adr(port) = value;
160 delay();
161}
162
163void landisk_outw(unsigned short value, unsigned long port)
164{
165 if (PXSEG(port))
166 *(volatile unsigned short *)port = value;
167 else if (CHECK_SH7751_PCIIO(port))
168 *(volatile unsigned short *)PCI_IOMAP(port) = value;
169 else
170 maybebadio(outw, port);
171}
172
173void landisk_outl(unsigned int value, unsigned long port)
174{
175 if (PXSEG(port))
176 *(volatile unsigned long *)port = value;
177 else if (CHECK_SH7751_PCIIO(port))
178 *(volatile unsigned long *)PCI_IOMAP(port) = value;
179 else
180 maybebadio(outl, port);
181}
182
183void landisk_insb(unsigned long port, void *addr, unsigned long count)
184{
185 if (PXSEG(port))
186 while (count--)
187 *((unsigned char *)addr)++ =
188 *(volatile unsigned char *)port;
189 else if (CHECK_SH7751_PCIIO(port)) {
190 volatile __u8 *bp = (__u8 *) PCI_IOMAP(port);
191
192 while (count--)
193 *((volatile unsigned char *)addr)++ = *bp;
194 } else {
195 volatile __u16 *p = (volatile unsigned short *)port2adr(port);
196
197 while (count--)
198 *((unsigned char *)addr)++ = *p;
199 }
200}
201
202void landisk_insw(unsigned long port, void *addr, unsigned long count)
203{
204 volatile __u16 *p;
205
206 if (PXSEG(port))
207 p = (volatile unsigned short *)port;
208 else if (CHECK_SH7751_PCIIO(port))
209 p = (volatile unsigned short *)PCI_IOMAP(port);
210 else
211 p = (volatile unsigned short *)port2adr(port);
212 while (count--)
213 *((__u16 *) addr)++ = *p;
214}
215
216void landisk_insl(unsigned long port, void *addr, unsigned long count)
217{
218 if (CHECK_SH7751_PCIIO(port)) {
219 volatile __u32 *p = (__u32 *) PCI_IOMAP(port);
220
221 while (count--)
222 *((__u32 *) addr)++ = *p;
223 } else
224 maybebadio(insl, port);
225}
226
227void landisk_outsb(unsigned long port, const void *addr, unsigned long count)
228{
229 if (PXSEG(port))
230 while (count--)
231 *(volatile unsigned char *)port =
232 *((unsigned char *)addr)++;
233 else if (CHECK_SH7751_PCIIO(port)) {
234 volatile __u8 *bp = (__u8 *) PCI_IOMAP(port);
235
236 while (count--)
237 *bp = *((volatile unsigned char *)addr)++;
238 } else {
239 volatile __u16 *p = (volatile unsigned short *)port2adr(port);
240
241 while (count--)
242 *p = *((unsigned char *)addr)++;
243 }
244}
245
246void landisk_outsw(unsigned long port, const void *addr, unsigned long count)
247{
248 volatile __u16 *p;
249
250 if (PXSEG(port))
251 p = (volatile unsigned short *)port;
252 else if (CHECK_SH7751_PCIIO(port))
253 p = (volatile unsigned short *)PCI_IOMAP(port);
254 else
255 p = (volatile unsigned short *)port2adr(port);
256 while (count--)
257 *p = *((__u16 *) addr)++;
258}
259
260void landisk_outsl(unsigned long port, const void *addr, unsigned long count)
261{
262 if (CHECK_SH7751_PCIIO(port)) {
263 volatile __u32 *p = (__u32 *) PCI_IOMAP(port);
264
265 while (count--)
266 *p = *((__u32 *) addr)++;
267 } else
268 maybebadio(outsl, port);
269}
270
271/* For read/write calls, just copy generic (pass-thru); PCIMBR is */
272/* already set up. For a larger memory space, these would need to */
273/* reset PCIMBR as needed on a per-call basis... */
274
275unsigned char landisk_readb(unsigned long addr)
276{
277 return *(volatile unsigned char *)addr;
278}
279
280unsigned short landisk_readw(unsigned long addr)
281{
282 return *(volatile unsigned short *)addr;
283}
284
285unsigned int landisk_readl(unsigned long addr)
286{
287 return *(volatile unsigned long *)addr;
288}
289
290void landisk_writeb(unsigned char b, unsigned long addr)
291{
292 *(volatile unsigned char *)addr = b;
293}
294
295void landisk_writew(unsigned short b, unsigned long addr)
296{
297 *(volatile unsigned short *)addr = b;
298}
299
300void landisk_writel(unsigned int b, unsigned long addr)
301{
302 *(volatile unsigned long *)addr = b;
303}
304
305void *landisk_ioremap(unsigned long offset, unsigned long size)
306{
307 if (offset >= 0xfd000000)
308 return (void *)offset;
309 else
310 return (void *)P2SEGADDR(offset);
311}
312
313void landisk_iounmap(void *addr)
314{
315}
316
317/* Map ISA bus address to the real address. Only for PCMCIA. */
318
319unsigned long landisk_isa_port2addr(unsigned long offset)
320{
321 return port2adr(offset);
322}
diff --git a/arch/sh/boards/landisk/irq.c b/arch/sh/boards/landisk/irq.c
new file mode 100644
index 000000000000..1dcc3feb7a44
--- /dev/null
+++ b/arch/sh/boards/landisk/irq.c
@@ -0,0 +1,105 @@
1/*
2 * arch/sh/boards/landisk/irq.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 * modified by kogiidena
15 * 2005.03.03
16 */
17
18#include <linux/config.h>
19#include <linux/init.h>
20#include <linux/irq.h>
21#include <asm/io.h>
22#include <asm/irq.h>
23#include <asm/landisk/iodata_landisk.h>
24
25static void enable_landisk_irq(unsigned int irq);
26static void disable_landisk_irq(unsigned int irq);
27
28/* shutdown is same as "disable" */
29#define shutdown_landisk_irq disable_landisk_irq
30
31static void ack_landisk_irq(unsigned int irq);
32static void end_landisk_irq(unsigned int irq);
33
34static unsigned int startup_landisk_irq(unsigned int irq)
35{
36 enable_landisk_irq(irq);
37 return 0; /* never anything pending */
38}
39
40static void disable_landisk_irq(unsigned int irq)
41{
42 unsigned long flags;
43 unsigned char val;
44 unsigned char mask = 0xff ^ (0x01 << (irq - 5));
45
46 /* Set the priority in IPR to 0 */
47 local_irq_save(flags);
48 val = ctrl_inb(PA_IMASK);
49 val &= mask;
50 ctrl_outb(val, PA_IMASK);
51 local_irq_restore(flags);
52}
53
54static void enable_landisk_irq(unsigned int irq)
55{
56 unsigned long flags;
57 unsigned char val;
58 unsigned char value = (0x01 << (irq - 5));
59
60 /* Set priority in IPR back to original value */
61 local_irq_save(flags);
62 val = ctrl_inb(PA_IMASK);
63 val |= value;
64 ctrl_outb(val, PA_IMASK);
65 local_irq_restore(flags);
66}
67
68static void ack_landisk_irq(unsigned int irq)
69{
70 disable_landisk_irq(irq);
71}
72
73static void end_landisk_irq(unsigned int irq)
74{
75 if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
76 enable_landisk_irq(irq);
77}
78
79static struct hw_interrupt_type landisk_irq_type = {
80 .typename = "LANDISK IRQ",
81 .startup = startup_landisk_irq,
82 .shutdown = shutdown_landisk_irq,
83 .enable = enable_landisk_irq,
84 .disable = disable_landisk_irq,
85 .ack = ack_landisk_irq,
86 .end = end_landisk_irq
87};
88
89static void make_landisk_irq(unsigned int irq)
90{
91 disable_irq_nosync(irq);
92 irq_desc[irq].handler = &landisk_irq_type;
93 disable_landisk_irq(irq);
94}
95
96/*
97 * Initialize IRQ setting
98 */
99void __init init_landisk_IRQ(void)
100{
101 int i;
102
103 for (i = 5; i < 14; i++)
104 make_landisk_irq(i);
105}
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}
diff --git a/arch/sh/boards/landisk/rtc.c b/arch/sh/boards/landisk/rtc.c
new file mode 100644
index 000000000000..d666aa63303f
--- /dev/null
+++ b/arch/sh/boards/landisk/rtc.c
@@ -0,0 +1,102 @@
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
12#include <linux/config.h>
13#include <linux/init.h>
14#include <linux/kernel.h>
15#include <linux/sched.h>
16#include <linux/time.h>
17#include <linux/delay.h>
18#include <linux/spinlock.h>
19
20#ifndef BCD_TO_BIN
21#define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10)
22#endif
23
24#ifndef BIN_TO_BCD
25#define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10)
26#endif
27
28extern void (*rtc_get_time) (struct timespec *);
29extern int (*rtc_set_time) (const time_t);
30extern spinlock_t rtc_lock;
31
32extern void
33rs5c313_set_cmos_time(unsigned int BCD_yr, unsigned int BCD_mon,
34 unsigned int BCD_day, unsigned int BCD_hr,
35 unsigned int BCD_min, unsigned int BCD_sec);
36
37extern unsigned long
38rs5c313_get_cmos_time(unsigned int *BCD_yr, unsigned int *BCD_mon,
39 unsigned int *BCD_day, unsigned int *BCD_hr,
40 unsigned int *BCD_min, unsigned int *BCD_sec);
41
42void landisk_rtc_gettimeofday(struct timespec *tv)
43{
44 unsigned int BCD_yr, BCD_mon, BCD_day, BCD_hr, BCD_min, BCD_sec;
45 unsigned long flags;
46
47 spin_lock_irqsave(&rtc_lock, flags);
48 tv->tv_sec = rs5c313_get_cmos_time
49 (&BCD_yr, &BCD_mon, &BCD_day, &BCD_hr, &BCD_min, &BCD_sec);
50 tv->tv_nsec = 0;
51 spin_unlock_irqrestore(&rtc_lock, flags);
52}
53
54int landisk_rtc_settimeofday(const time_t secs)
55{
56 int retval = 0;
57 int real_seconds, real_minutes, cmos_minutes;
58 unsigned long flags;
59 unsigned long nowtime = secs;
60 unsigned int BCD_yr, BCD_mon, BCD_day, BCD_hr, BCD_min, BCD_sec;
61
62 spin_lock_irqsave(&rtc_lock, flags);
63
64 rs5c313_get_cmos_time
65 (&BCD_yr, &BCD_mon, &BCD_day, &BCD_hr, &BCD_min, &BCD_sec);
66 cmos_minutes = BCD_min;
67 BCD_TO_BIN(cmos_minutes);
68
69 /*
70 * since we're only adjusting minutes and seconds,
71 * don't interfere with hour overflow. This avoids
72 * messing with unknown time zones but requires your
73 * RTC not to be off by more than 15 minutes
74 */
75 real_seconds = nowtime % 60;
76 real_minutes = nowtime / 60;
77 if (((abs(real_minutes - cmos_minutes) + 15) / 30) & 1)
78 real_minutes += 30; /* correct for half hour time zone */
79 real_minutes %= 60;
80
81 if (abs(real_minutes - cmos_minutes) < 30) {
82 BIN_TO_BCD(real_seconds);
83 BIN_TO_BCD(real_minutes);
84 rs5c313_set_cmos_time(BCD_yr, BCD_mon, BCD_day, BCD_hr,
85 real_minutes, real_seconds);
86 } else {
87 printk(KERN_WARNING
88 "set_rtc_time: can't update from %d to %d\n",
89 cmos_minutes, real_minutes);
90 retval = -1;
91 }
92
93 spin_unlock_irqrestore(&rtc_lock, flags);
94 return retval;
95}
96
97
98void landisk_time_init(void)
99{
100 rtc_get_time = landisk_rtc_gettimeofday;
101 rtc_set_time = landisk_rtc_settimeofday;
102}
diff --git a/arch/sh/boards/landisk/setup.c b/arch/sh/boards/landisk/setup.c
new file mode 100644
index 000000000000..0c60eaa10ba7
--- /dev/null
+++ b/arch/sh/boards/landisk/setup.c
@@ -0,0 +1,218 @@
1/*
2 * arch/sh/boards/landisk/setup.c
3 *
4 * Copyright (C) 2002 Paul Mundt
5 *
6 * May be copied or modified under the terms of the GNU General Public
7 * License. See linux/COPYING for more information.
8 *
9 * Setup code for an unknown machine (internal peripherials only)
10 */
11/*
12 * linux/arch/sh/kernel/setup_landisk.c
13 *
14 * Copyright (C) 2000 Kazumoto Kojima
15 *
16 * I-O DATA Device, Inc. LANDISK Support.
17 *
18 * Modified for LANDISK by
19 * Atom Create Engineering Co., Ltd. 2002.
20 */
21/*
22 * modifed by kogiidena
23 * 2005.09.16
24 */
25
26#include <linux/config.h>
27#include <linux/init.h>
28#include <linux/irq.h>
29#include <linux/pm.h>
30
31#include <linux/hdreg.h>
32#include <linux/ide.h>
33#include <linux/pci.h>
34
35#include <asm/machvec.h>
36#include <asm/rtc.h>
37#include <asm/machvec_init.h>
38#include <asm/io.h>
39#include <asm/landisk/iodata_landisk.h>
40#include <asm/landisk/io.h>
41
42#include <linux/mm.h>
43#include <linux/vmalloc.h>
44
45extern void (*board_time_init) (void);
46void landisk_time_init(void);
47extern void init_landisk_IRQ(void);
48
49int landisk_ledparam;
50int landisk_buzzerparam;
51int landisk_arch;
52
53/* defined in mm/ioremap.c */
54extern void *p3_ioremap(unsigned long phys_addr, unsigned long size,
55 unsigned long flags);
56
57/*
58 * Initialize the board
59 */
60
61const char *get_system_type(void)
62{
63 return "LANDISK";
64}
65
66static void landisk_power_off(void)
67{
68 ctrl_outb(0x01, PA_SHUTDOWN);
69}
70
71void check_usl5p(void)
72{
73 volatile unsigned char *p = (volatile unsigned char *)PA_LED;
74 unsigned char tmp1, tmp2;
75 tmp1 = *p;
76 *p = 0x40;
77 tmp2 = *p;
78 *p = tmp1;
79 landisk_arch = (tmp2 == 0x40) ? 1 : 0;
80 if (landisk_arch == 1) { /* arch == usl-5p */
81 landisk_ledparam = 0x00000380;
82 landisk_ledparam |= (tmp1 & 0x07c);
83 } else { /* arch == landisk */
84 landisk_ledparam = 0x02000180;
85 landisk_ledparam |= 0x04;
86 }
87 return;
88}
89
90void __init platform_setup(void)
91{
92
93 landisk_buzzerparam = 0;
94 check_usl5p();
95
96 printk(KERN_INFO "I-O DATA DEVICE, INC. \"LANDISK Series\" support.\n");
97 board_time_init = landisk_time_init;
98 pm_power_off = landisk_power_off;
99
100}
101
102void *area5_io_base;
103void *area6_io_base;
104
105int __init cf_init(void)
106{
107 pgprot_t prot;
108 unsigned long paddrbase, psize;
109
110 /* open I/O area window */
111 paddrbase = virt_to_phys((void *)PA_AREA5_IO);
112 psize = PAGE_SIZE;
113 prot = PAGE_KERNEL_PCC(1, _PAGE_PCC_IO16);
114 area5_io_base = p3_ioremap(paddrbase, psize, prot.pgprot);
115 if (!area5_io_base) {
116 printk("allocate_cf_area : can't open CF I/O window!\n");
117 return -ENOMEM;
118 }
119
120 paddrbase = virt_to_phys((void *)PA_AREA6_IO);
121 psize = PAGE_SIZE;
122 prot = PAGE_KERNEL_PCC(0, _PAGE_PCC_IO16);
123 area6_io_base = p3_ioremap(paddrbase, psize, prot.pgprot);
124 if (!area6_io_base) {
125 printk("allocate_cf_area : can't open HDD I/O window!\n");
126 return -ENOMEM;
127 }
128
129 printk(KERN_INFO "Allocate Area5/6 success.\n");
130
131 /* XXX : do we need attribute and common-memory area also? */
132
133 return 0;
134}
135
136__initcall(cf_init);
137
138#include <linux/sched.h>
139
140/* Cycle the LED's in the clasic knightrider/Sun pattern */
141
142void heartbeat_landisk(void)
143{
144 static unsigned int cnt = 0, blink = 0x00, period = 25;
145 volatile unsigned char *p = (volatile unsigned char *)PA_LED;
146 char data;
147
148 if ((landisk_ledparam & 0x080) == 0) {
149 return;
150 }
151 cnt += 1;
152 if (cnt < period) {
153 return;
154 }
155 cnt = 0;
156 blink++;
157
158 data = (blink & 0x01) ? (landisk_ledparam >> 16) : 0;
159 data |= (blink & 0x02) ? (landisk_ledparam >> 8) : 0;
160 data |= landisk_ledparam;
161
162 /* buzzer */
163 if (landisk_buzzerparam & 0x1) {
164 data |= 0x80;
165 } else {
166 data &= 0x7f;
167 }
168 *p = data;
169
170 if (((landisk_ledparam & 0x007f7f00) == 0)
171 && (landisk_buzzerparam == 0)) {
172 landisk_ledparam &= (~0x0080);
173 }
174 landisk_buzzerparam >>= 1;
175}
176
177/*
178 * The Machine Vector
179 */
180
181struct sh_machine_vector mv_landisk __initmv = {
182 .mv_nr_irqs = 72,
183 .mv_inb = landisk_inb,
184 .mv_inw = landisk_inw,
185 .mv_inl = landisk_inl,
186 .mv_outb = landisk_outb,
187 .mv_outw = landisk_outw,
188 .mv_outl = landisk_outl,
189 .mv_inb_p = landisk_inb_p,
190 .mv_inw_p = landisk_inw,
191 .mv_inl_p = landisk_inl,
192 .mv_outb_p = landisk_outb_p,
193 .mv_outw_p = landisk_outw,
194 .mv_outl_p = landisk_outl,
195 .mv_insb = landisk_insb,
196 .mv_insw = landisk_insw,
197 .mv_insl = landisk_insl,
198 .mv_outsb = landisk_outsb,
199 .mv_outsw = landisk_outsw,
200 .mv_outsl = landisk_outsl,
201 .mv_readb = landisk_readb,
202 .mv_readw = landisk_readw,
203 .mv_readl = landisk_readl,
204 .mv_writeb = landisk_writeb,
205 .mv_writew = landisk_writew,
206 .mv_writel = landisk_writel,
207 .mv_ioremap = landisk_ioremap,
208 .mv_iounmap = landisk_iounmap,
209 .mv_isa_port2addr = landisk_isa_port2addr,
210 .mv_init_irq = init_landisk_IRQ,
211
212#ifdef CONFIG_HEARTBEAT
213 .mv_heartbeat = heartbeat_landisk,
214#endif
215
216};
217
218ALIAS_MV(landisk)