Merge git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6
[linux-2.6] / arch / sh / boards / mach-edosk7705 / io.c
1 /*
2  * arch/sh/boards/renesas/edosk7705/io.c
3  *
4  * Copyright (C) 2001  Ian da Silva, Jeremy Siegel
5  * Based largely on io_se.c.
6  *
7  * I/O routines for Hitachi EDOSK7705 board.
8  *
9  */
10
11 #include <linux/kernel.h>
12 #include <linux/types.h>
13 #include <linux/io.h>
14 #include <mach/edosk7705.h>
15 #include <asm/addrspace.h>
16
17 #define SMC_IOADDR      0xA2000000
18
19 /* Map the Ethernet addresses as if it is at 0x300 - 0x320 */
20 static unsigned long sh_edosk7705_isa_port2addr(unsigned long port)
21 {
22         /*
23          * SMC91C96 registers are 4 byte aligned rather than the
24          * usual 2 byte!
25          */
26         if (port >= 0x300 && port < 0x320)
27                 return SMC_IOADDR + ((port - 0x300) * 2);
28
29         maybebadio(port);
30         return port;
31 }
32
33 /* Trying to read / write bytes on odd-byte boundaries to the Ethernet
34  * registers causes problems. So we bit-shift the value and read / write
35  * in 2 byte chunks. Setting the low byte to 0 does not cause problems
36  * now as odd byte writes are only made on the bit mask / interrupt
37  * register. This may not be the case in future Mar-2003 SJD
38  */
39 unsigned char sh_edosk7705_inb(unsigned long port)
40 {
41         if (port >= 0x300 && port < 0x320 && port & 0x01)
42                 return __raw_readw(port - 1) >> 8;
43
44         return __raw_readb(sh_edosk7705_isa_port2addr(port));
45 }
46
47 void sh_edosk7705_outb(unsigned char value, unsigned long port)
48 {
49         if (port >= 0x300 && port < 0x320 && port & 0x01) {
50                 __raw_writew(((unsigned short)value << 8), port - 1);
51                 return;
52         }
53
54         __raw_writeb(value, sh_edosk7705_isa_port2addr(port));
55 }
56
57 void sh_edosk7705_insb(unsigned long port, void *addr, unsigned long count)
58 {
59         unsigned char *p = addr;
60
61         while (count--)
62                 *p++ = sh_edosk7705_inb(port);
63 }
64
65 void sh_edosk7705_outsb(unsigned long port, const void *addr, unsigned long count)
66 {
67         unsigned char *p = (unsigned char *)addr;
68
69         while (count--)
70                 sh_edosk7705_outb(*p++, port);
71 }