summaryrefslogtreecommitdiffstats
path: root/arch/sh/kernel/io_hd64461.c
blob: 3fbe6f2d0af30f8ebaaa79377a0c702711bc1729 (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
/*
 *	$Id: io_hd64461.c,v 1.1 2000/06/10 21:45:18 yaegashi Exp $
 *	Copyright (C) 2000 YAEGASHI Takeshi
 *	Typical I/O routines for HD64461 system.
 */

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

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;
#endif

	/* ??? */
	if (port < 0x10000) return 0xa0000000 + port;

	/* 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 long hd64461_inb(unsigned int port)
{
	return *(volatile unsigned char*)PORT2ADDR(port);
}

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

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

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

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

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

void hd64461_insl(unsigned int port, void *buffer, unsigned long count)
{
	unsigned long *buf=buffer;
	while(count--) *buf++=inl(port);
}

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

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

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

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

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

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

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