Merge commit 'v2.6.28-rc2' into topic/asoc
[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 <asm/io.h>
14 #include <mach/edosk7705.h>
15 #include <asm/addrspace.h>
16
17 #define SMC_IOADDR      0xA2000000
18
19 #define maybebadio(name,port) \
20   printk("bad PC-like io %s for port 0x%lx at 0x%08x\n", \
21          #name, (port), (__u32) __builtin_return_address(0))
22
23 /* Map the Ethernet addresses as if it is at 0x300 - 0x320 */
24 unsigned long sh_edosk7705_isa_port2addr(unsigned long port)
25 {
26      if (port >= 0x300 && port < 0x320) {
27           /* SMC91C96 registers are 4 byte aligned rather than the
28            * usual 2 byte!
29            */
30           return SMC_IOADDR + ( (port - 0x300) * 2);
31      }
32
33      maybebadio(sh_edosk7705_isa_port2addr, port);
34      return port;
35 }
36
37 /* Trying to read / write bytes on odd-byte boundaries to the Ethernet
38  * registers causes problems. So we bit-shift the value and read / write
39  * in 2 byte chunks. Setting the low byte to 0 does not cause problems
40  * now as odd byte writes are only made on the bit mask / interrupt
41  * register. This may not be the case in future Mar-2003 SJD
42  */
43 unsigned char sh_edosk7705_inb(unsigned long port)
44 {
45         if (port >= 0x300 && port < 0x320 && port & 0x01) {
46                 return (volatile unsigned char)(generic_inw(port -1) >> 8);
47         }
48         return *(volatile unsigned char *)sh_edosk7705_isa_port2addr(port);
49 }
50
51 unsigned int sh_edosk7705_inl(unsigned long port)
52 {
53         return *(volatile unsigned long *)port;
54 }
55
56 void sh_edosk7705_outb(unsigned char value, unsigned long port)
57 {
58         if (port >= 0x300 && port < 0x320 && port & 0x01) {
59                 generic_outw(((unsigned short)value << 8), port -1);
60                 return;
61         }
62         *(volatile unsigned char *)sh_edosk7705_isa_port2addr(port) = value;
63 }
64
65 void sh_edosk7705_outl(unsigned int value, unsigned long port)
66 {
67         *(volatile unsigned long *)port = value;
68 }
69
70 void sh_edosk7705_insb(unsigned long port, void *addr, unsigned long count)
71 {
72         unsigned char *p = addr;
73         while (count--) *p++ = sh_edosk7705_inb(port);
74 }
75
76 void sh_edosk7705_insl(unsigned long port, void *addr, unsigned long count)
77 {
78         unsigned long *p = (unsigned long*)addr;
79         while (count--)
80                 *p++ = *(volatile unsigned long *)port;
81 }
82
83 void sh_edosk7705_outsb(unsigned long port, const void *addr, unsigned long count)
84 {
85         unsigned char *p = (unsigned char*)addr;
86         while (count--) sh_edosk7705_outb(*p++, port);
87 }
88
89 void sh_edosk7705_outsl(unsigned long port, const void *addr, unsigned long count)
90 {
91         unsigned long *p = (unsigned long*)addr;
92         while (count--) sh_edosk7705_outl(*p++, port);
93 }
94