blob: b1ec085b8673091c692a710698435e6a751b76fa [file] [log] [blame]
Nobuhiro Iwamatsufafb7a92008-06-24 13:00:52 +09001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 * Copyright (C) 2000 Kazumoto Kojima
3 *
4 * I/O routine for Hitachi SolutionEngine.
Linus Torvalds1da177e2005-04-16 15:20:36 -07005 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006#include <linux/kernel.h>
7#include <linux/types.h>
8#include <asm/io.h>
Paul Mundt373e68b2006-09-27 15:41:24 +09009#include <asm/se.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070010
Linus Torvalds1da177e2005-04-16 15:20:36 -070011/* MS7750 requires special versions of in*, out* routines, since
12 PC-like io ports are located at upper half byte of 16-bit word which
13 can be accessed only with 16-bit wide. */
14
15static inline volatile __u16 *
16port2adr(unsigned int port)
17{
Nobuhiro Iwamatsu9465a542007-03-27 18:13:51 +090018 if (port & 0xff000000)
19 return ( volatile __u16 *) port;
Linus Torvalds1da177e2005-04-16 15:20:36 -070020 if (port >= 0x2000)
21 return (volatile __u16 *) (PA_MRSHPC + (port - 0x2000));
22 else if (port >= 0x1000)
23 return (volatile __u16 *) (PA_83902 + (port << 1));
Linus Torvalds1da177e2005-04-16 15:20:36 -070024 else
25 return (volatile __u16 *) (PA_SUPERIO + (port << 1));
26}
27
28static inline int
29shifted_port(unsigned long port)
30{
31 /* For IDE registers, value is not shifted */
32 if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6)
33 return 0;
34 else
35 return 1;
36}
37
Linus Torvalds1da177e2005-04-16 15:20:36 -070038unsigned char se_inb(unsigned long port)
39{
Nobuhiro Iwamatsufafb7a92008-06-24 13:00:52 +090040 if (shifted_port(port))
41 return (*port2adr(port) >> 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -070042 else
Nobuhiro Iwamatsufafb7a92008-06-24 13:00:52 +090043 return (*port2adr(port))&0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -070044}
45
46unsigned char se_inb_p(unsigned long port)
47{
48 unsigned long v;
49
Nobuhiro Iwamatsufafb7a92008-06-24 13:00:52 +090050 if (shifted_port(port))
51 v = (*port2adr(port) >> 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -070052 else
Nobuhiro Iwamatsufafb7a92008-06-24 13:00:52 +090053 v = (*port2adr(port))&0xff;
Paul Mundt959f85f2006-09-27 16:43:28 +090054 ctrl_delay();
Linus Torvalds1da177e2005-04-16 15:20:36 -070055 return v;
56}
57
58unsigned short se_inw(unsigned long port)
59{
Nobuhiro Iwamatsufafb7a92008-06-24 13:00:52 +090060 if (port >= 0x2000)
Linus Torvalds1da177e2005-04-16 15:20:36 -070061 return *port2adr(port);
62 else
Paul Mundt373e68b2006-09-27 15:41:24 +090063 maybebadio(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -070064 return 0;
65}
66
67unsigned int se_inl(unsigned long port)
68{
Paul Mundt373e68b2006-09-27 15:41:24 +090069 maybebadio(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -070070 return 0;
71}
72
73void se_outb(unsigned char value, unsigned long port)
74{
Nobuhiro Iwamatsufafb7a92008-06-24 13:00:52 +090075 if (shifted_port(port))
Linus Torvalds1da177e2005-04-16 15:20:36 -070076 *(port2adr(port)) = value << 8;
77 else
78 *(port2adr(port)) = value;
79}
80
81void se_outb_p(unsigned char value, unsigned long port)
82{
Nobuhiro Iwamatsufafb7a92008-06-24 13:00:52 +090083 if (shifted_port(port))
Linus Torvalds1da177e2005-04-16 15:20:36 -070084 *(port2adr(port)) = value << 8;
85 else
86 *(port2adr(port)) = value;
Paul Mundt959f85f2006-09-27 16:43:28 +090087 ctrl_delay();
Linus Torvalds1da177e2005-04-16 15:20:36 -070088}
89
90void se_outw(unsigned short value, unsigned long port)
91{
Nobuhiro Iwamatsufafb7a92008-06-24 13:00:52 +090092 if (port >= 0x2000)
Linus Torvalds1da177e2005-04-16 15:20:36 -070093 *port2adr(port) = value;
94 else
Paul Mundt373e68b2006-09-27 15:41:24 +090095 maybebadio(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -070096}
97
98void se_outl(unsigned int value, unsigned long port)
99{
Paul Mundt373e68b2006-09-27 15:41:24 +0900100 maybebadio(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101}
102
103void se_insb(unsigned long port, void *addr, unsigned long count)
104{
105 volatile __u16 *p = port2adr(port);
106 __u8 *ap = addr;
107
Nobuhiro Iwamatsufafb7a92008-06-24 13:00:52 +0900108 if (shifted_port(port)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109 while (count--)
110 *ap++ = *p >> 8;
111 } else {
112 while (count--)
113 *ap++ = *p;
114 }
115}
116
117void se_insw(unsigned long port, void *addr, unsigned long count)
118{
119 volatile __u16 *p = port2adr(port);
120 __u16 *ap = addr;
121 while (count--)
122 *ap++ = *p;
123}
124
125void se_insl(unsigned long port, void *addr, unsigned long count)
126{
Paul Mundt373e68b2006-09-27 15:41:24 +0900127 maybebadio(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128}
129
130void se_outsb(unsigned long port, const void *addr, unsigned long count)
131{
132 volatile __u16 *p = port2adr(port);
133 const __u8 *ap = addr;
134
Nobuhiro Iwamatsufafb7a92008-06-24 13:00:52 +0900135 if (shifted_port(port)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136 while (count--)
137 *p = *ap++ << 8;
138 } else {
139 while (count--)
140 *p = *ap++;
141 }
142}
143
144void se_outsw(unsigned long port, const void *addr, unsigned long count)
145{
146 volatile __u16 *p = port2adr(port);
147 const __u16 *ap = addr;
Nobuhiro Iwamatsufafb7a92008-06-24 13:00:52 +0900148
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149 while (count--)
150 *p = *ap++;
151}
152
153void se_outsl(unsigned long port, const void *addr, unsigned long count)
154{
Paul Mundt373e68b2006-09-27 15:41:24 +0900155 maybebadio(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700156}