summaryrefslogtreecommitdiffstats
path: root/arch/sh/cchips/hd6446x/hd64461/io.c
blob: f77f18f2ba7fac6dd9c86f0f7da451c651bbf2e4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/*
 *	Copyright (C) 2000 YAEGASHI Takeshi
 *	Typical I/O routines for HD64461 system.
 */

#include <asm/io.h>
#include <asm/hd64461.h>

#define MEM_BASE (CONFIG_HD64461_IOBASE - HD64461_STBCR)

static __inline__ unsigned long PORT2ADDR(unsigned long port)
{
	/* 16550A: HD64461 internal */
	if (0x3f8<=port && port<=0x3ff)
		return CONFIG_HD64461_IOBASE + 0x8000 + ((port-0x3f8)<<1);
	if (0x2f8<=port && port<=0x2ff)
		return CONFIG_HD64461_IOBASE + 0x7000 + ((port-0x2f8)<<1);

#ifdef CONFIG_HD64461_ENABLER
	/* NE2000: HD64461 PCMCIA channel 0 (I/O) */
	if (0x300<=port && port<=0x31f)
		return 0xba000000 + port;

	/* ide0: HD64461 PCMCIA channel 1 (memory) */
	/* On HP690, CF in slot 1 is configured as a memory card
	   device.  See CF+ and CompactFlash Specification for the
	   detail of CF's memory mapped addressing. */
	if (0x1f0<=port && port<=0x1f7)	return 0xb5000000 + port;
	if (port == 0x3f6) return 0xb50001fe;
	if (port == 0x3f7) return 0xb50001ff;

	/* ide1 */
	if (0x170<=port && port<=0x177)	return 0xba000000 + port;
	if (port == 0x376) return 0xba000376;
	if (port == 0x377) return 0xba000377;
#endif

	/* ??? */
	if (port < 0xf000) return 0xa0000000 + port;
	/* PCMCIA channel 0, I/O (0xba000000) */
	if (port < 0x10000) return 0xba000000 + port - 0xf000;

	/* HD64461 internal devices (0xb0000000) */
	if (port < 0x20000) return CONFIG_HD64461_IOBASE + port - 0x10000;

	/* PCMCIA channel 0, I/O (0xba000000) */
	if (port < 0x30000) return 0xba000000 + port - 0x20000;

	/* PCMCIA channel 1, memory (0xb5000000) */
	if (port < 0x40000) return 0xb5000000 + port - 0x30000;

	/* Whole physical address space (0xa0000000) */
	return 0xa0000000 + (port & 0x1fffffff);
}

static inline void delay(void)
{
	ctrl_inw(0xa0000000);
}

unsigned char hd64461_inb(unsigned long port)
{
	return *(volatile unsigned char*)PORT2ADDR(port);
}

unsigned char hd64461_inb_p(unsigned long port)
{
	unsigned long v = *(volatile unsigned char*)PORT2ADDR(port);
	delay();
	return v;
}

unsigned short hd64461_inw(unsigned long port)
{
	return *(volatile unsigned short*)PORT2ADDR(port);
}

unsigned int hd64461_inl(unsigned long port)
{
	return *(volatile unsigned long*)PORT2ADDR(port);
}

void hd64461_outb(unsigned char b, unsigned long port)
{
	*(volatile unsigned char*)PORT2ADDR(port) = b;
}

void hd64461_outb_p(unsigned char b, unsigned long port)
{
	*(volatile unsigned char*)PORT2ADDR(port) = b;
	delay();
}

void hd64461_outw(unsigned short b, unsigned long port)
{
	*(volatile unsigned short*)PORT2ADDR(port) = b;
}

void hd64461_outl(unsigned int b, unsigned long port)
{
        *(volatile unsigned long*)PORT2ADDR(port) = b;
}

void hd64461_insb(unsigned long port, void *buffer, unsigned long count)
{
	volatile unsigned char* addr=(volatile unsigned char*)PORT2ADDR(port);
	unsigned char *buf=buffer;
	while(count--) *buf++=*addr;
}

void hd64461_insw(unsigned long port, void *buffer, unsigned long count)
{
	volatile unsigned short* addr=(volatile unsigned short*)PORT2ADDR(port);
	unsigned short *buf=buffer;
	while(count--) *buf++=*addr;
}

void hd64461_insl(unsigned long port, void *buffer, unsigned long count)
{
	volatile unsigned long* addr=(volatile unsigned long*)PORT2ADDR(port);
	unsigned long *buf=buffer;
	while(count--) *buf++=*addr;
}

void hd64461_outsb(unsigned long port, const void *buffer, unsigned long count)
{
	volatile unsigned char* addr=(volatile unsigned char*)PORT2ADDR(port);
	const unsigned char *buf=buffer;
	while(count--) *addr=*buf++;
}

void hd64461_outsw(unsigned long port, const void *buffer, unsigned long count)
{
	volatile unsigned short* addr=(volatile unsigned short*)PORT2ADDR(port);
	const unsigned short *buf=buffer;
	while(count--) *addr=*buf++;
}

void hd64461_outsl(unsigned long port, const void *buffer, unsigned long count)
{
	volatile unsigned long* addr=(volatile unsigned long*)PORT2ADDR(port);
	const unsigned long *buf=buffer;
	while(count--) *addr=*buf++;
}

unsigned short hd64461_readw(void __iomem *addr)
{
	return ctrl_inw(MEM_BASE+(unsigned long __force)addr);
}

void hd64461_writew(unsigned short b, void __iomem *addr)
{
	ctrl_outw(b, MEM_BASE+(unsigned long __force)addr);
}