• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-WNDR4500-V1.0.1.40_1.0.68/src/linux/linux-2.6/arch/sh/cchips/hd6446x/hd64465/
1/*
2 * $Id: io.c,v 1.1.1.1 2007/08/03 18:52:15 Exp $
3 * by Greg Banks <gbanks@pocketpenguins.com>
4 * (c) 2000 PocketPenguins Inc
5 *
6 * Derived from io_hd64461.c, which bore the message:
7 * Copyright (C) 2000 YAEGASHI Takeshi
8 *
9 * Typical I/O routines for HD64465 system.
10 */
11
12#include <linux/kernel.h>
13#include <linux/module.h>
14#include <asm/io.h>
15#include <asm/hd64465/hd64465.h>
16
17
18#define HD64465_DEBUG 0
19
20#if HD64465_DEBUG
21#define DPRINTK(args...)	printk(args)
22#define DIPRINTK(n, args...)	if (hd64465_io_debug>(n)) printk(args)
23#else
24#define DPRINTK(args...)
25#define DIPRINTK(n, args...)
26#endif
27
28
29
30/* This is a hack suitable only for debugging IO port problems */
31int hd64465_io_debug;
32EXPORT_SYMBOL(hd64465_io_debug);
33
34/* Low iomap maps port 0-1K to addresses in 8byte chunks */
35#define HD64465_IOMAP_LO_THRESH 0x400
36#define HD64465_IOMAP_LO_SHIFT	3
37#define HD64465_IOMAP_LO_MASK	((1<<HD64465_IOMAP_LO_SHIFT)-1)
38#define HD64465_IOMAP_LO_NMAP	(HD64465_IOMAP_LO_THRESH>>HD64465_IOMAP_LO_SHIFT)
39static unsigned long	hd64465_iomap_lo[HD64465_IOMAP_LO_NMAP];
40static unsigned char	hd64465_iomap_lo_shift[HD64465_IOMAP_LO_NMAP];
41
42/* High iomap maps port 1K-64K to addresses in 1K chunks */
43#define HD64465_IOMAP_HI_THRESH 0x10000
44#define HD64465_IOMAP_HI_SHIFT	10
45#define HD64465_IOMAP_HI_MASK	((1<<HD64465_IOMAP_HI_SHIFT)-1)
46#define HD64465_IOMAP_HI_NMAP	(HD64465_IOMAP_HI_THRESH>>HD64465_IOMAP_HI_SHIFT)
47static unsigned long	hd64465_iomap_hi[HD64465_IOMAP_HI_NMAP];
48static unsigned char	hd64465_iomap_hi_shift[HD64465_IOMAP_HI_NMAP];
49
50#define PORT2ADDR(x) (sh_mv.mv_isa_port2addr(x))
51
52void hd64465_port_map(unsigned short baseport, unsigned int nports,
53		      unsigned long addr, unsigned char shift)
54{
55    	unsigned int port, endport = baseport + nports;
56
57    	DPRINTK("hd64465_port_map(base=0x%04hx, n=0x%04hx, addr=0x%08lx,endport=0x%04x)\n",
58	    baseport, nports, addr,endport);
59
60	for (port = baseport ;
61	     port < endport && port < HD64465_IOMAP_LO_THRESH ;
62	     port += (1<<HD64465_IOMAP_LO_SHIFT)) {
63	    DPRINTK("    maplo[0x%x] = 0x%08lx\n", port, addr);
64    	    hd64465_iomap_lo[port>>HD64465_IOMAP_LO_SHIFT] = addr;
65    	    hd64465_iomap_lo_shift[port>>HD64465_IOMAP_LO_SHIFT] = shift;
66	    addr += (1<<(HD64465_IOMAP_LO_SHIFT));
67	}
68
69	for (port = max_t(unsigned int, baseport, HD64465_IOMAP_LO_THRESH);
70	     port < endport && port < HD64465_IOMAP_HI_THRESH ;
71	     port += (1<<HD64465_IOMAP_HI_SHIFT)) {
72	    DPRINTK("    maphi[0x%x] = 0x%08lx\n", port, addr);
73    	    hd64465_iomap_hi[port>>HD64465_IOMAP_HI_SHIFT] = addr;
74    	    hd64465_iomap_hi_shift[port>>HD64465_IOMAP_HI_SHIFT] = shift;
75	    addr += (1<<(HD64465_IOMAP_HI_SHIFT));
76	}
77}
78EXPORT_SYMBOL(hd64465_port_map);
79
80void hd64465_port_unmap(unsigned short baseport, unsigned int nports)
81{
82    	unsigned int port, endport = baseport + nports;
83
84    	DPRINTK("hd64465_port_unmap(base=0x%04hx, n=0x%04hx)\n",
85	    baseport, nports);
86
87	for (port = baseport ;
88	     port < endport && port < HD64465_IOMAP_LO_THRESH ;
89	     port += (1<<HD64465_IOMAP_LO_SHIFT)) {
90    	    hd64465_iomap_lo[port>>HD64465_IOMAP_LO_SHIFT] = 0;
91	}
92
93	for (port = max_t(unsigned int, baseport, HD64465_IOMAP_LO_THRESH);
94	     port < endport && port < HD64465_IOMAP_HI_THRESH ;
95	     port += (1<<HD64465_IOMAP_HI_SHIFT)) {
96    	    hd64465_iomap_hi[port>>HD64465_IOMAP_HI_SHIFT] = 0;
97	}
98}
99EXPORT_SYMBOL(hd64465_port_unmap);
100
101unsigned long hd64465_isa_port2addr(unsigned long port)
102{
103    	unsigned long addr = 0;
104	unsigned char shift;
105
106	/* handle remapping of low IO ports */
107	if (port < HD64465_IOMAP_LO_THRESH) {
108	    addr = hd64465_iomap_lo[port >> HD64465_IOMAP_LO_SHIFT];
109	    shift = hd64465_iomap_lo_shift[port >> HD64465_IOMAP_LO_SHIFT];
110	    if (addr != 0)
111	    	addr += (port & HD64465_IOMAP_LO_MASK) << shift;
112	    else
113		printk(KERN_NOTICE "io_hd64465: access to un-mapped port %lx\n", port);
114	} else if (port < HD64465_IOMAP_HI_THRESH) {
115	    addr = hd64465_iomap_hi[port >> HD64465_IOMAP_HI_SHIFT];
116	    shift = hd64465_iomap_hi_shift[port >> HD64465_IOMAP_HI_SHIFT];
117	    if (addr != 0)
118		addr += (port & HD64465_IOMAP_HI_MASK) << shift;
119	    else
120		printk(KERN_NOTICE "io_hd64465: access to un-mapped port %lx\n", port);
121	}
122
123	/* HD64465 internal devices (0xb0000000) */
124	else if (port < 0x20000)
125	    addr = CONFIG_HD64465_IOBASE + port - 0x10000;
126
127	/* Whole physical address space (0xa0000000) */
128	else
129	    addr = P2SEGADDR(port);
130
131    	DIPRINTK(2, "PORT2ADDR(0x%08lx) = 0x%08lx\n", port, addr);
132
133	return addr;
134}
135
136static inline void delay(void)
137{
138	ctrl_inw(0xa0000000);
139}
140
141unsigned char hd64465_inb(unsigned long port)
142{
143	unsigned long addr = PORT2ADDR(port);
144	unsigned long b = (addr == 0 ? 0 : *(volatile unsigned char*)addr);
145
146	DIPRINTK(0, "inb(%08lx) = %02x\n", addr, (unsigned)b);
147	return b;
148}
149
150unsigned char hd64465_inb_p(unsigned long port)
151{
152    	unsigned long v;
153	unsigned long addr = PORT2ADDR(port);
154
155	v = (addr == 0 ? 0 : *(volatile unsigned char*)addr);
156	delay();
157	DIPRINTK(0, "inb_p(%08lx) = %02x\n", addr, (unsigned)v);
158	return v;
159}
160
161unsigned short hd64465_inw(unsigned long port)
162{
163    	unsigned long addr = PORT2ADDR(port);
164	unsigned long b = (addr == 0 ? 0 : *(volatile unsigned short*)addr);
165	DIPRINTK(0, "inw(%08lx) = %04lx\n", addr, b);
166	return b;
167}
168
169unsigned int hd64465_inl(unsigned long port)
170{
171    	unsigned long addr = PORT2ADDR(port);
172	unsigned int b = (addr == 0 ? 0 : *(volatile unsigned long*)addr);
173	DIPRINTK(0, "inl(%08lx) = %08x\n", addr, b);
174	return b;
175}
176
177void hd64465_outb(unsigned char b, unsigned long port)
178{
179	unsigned long addr = PORT2ADDR(port);
180
181	DIPRINTK(0, "outb(%02x, %08lx)\n", (unsigned)b, addr);
182	if (addr != 0)
183	    *(volatile unsigned char*)addr = b;
184}
185
186void hd64465_outb_p(unsigned char b, unsigned long port)
187{
188	unsigned long addr = PORT2ADDR(port);
189
190	DIPRINTK(0, "outb_p(%02x, %08lx)\n", (unsigned)b, addr);
191    	if (addr != 0)
192	    *(volatile unsigned char*)addr = b;
193	delay();
194}
195
196void hd64465_outw(unsigned short b, unsigned long port)
197{
198	unsigned long addr = PORT2ADDR(port);
199	DIPRINTK(0, "outw(%04x, %08lx)\n", (unsigned)b, addr);
200	if (addr != 0)
201	    *(volatile unsigned short*)addr = b;
202}
203
204void hd64465_outl(unsigned int b, unsigned long port)
205{
206	unsigned long addr = PORT2ADDR(port);
207	DIPRINTK(0, "outl(%08x, %08lx)\n", b, addr);
208	if (addr != 0)
209            *(volatile unsigned long*)addr = b;
210}
211