blob: 23071f97eec31ff6e61156e7aaf60915dbb5ec06 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Uwe Zeisbergerf30c2262006-10-03 23:01:26 +02002 * arch/sh/boards/bigsur/io.c
Linus Torvalds1da177e2005-04-16 15:20:36 -07003 *
4 * By Dustin McIntire (dustin@sensoria.com) (c)2001
5 * Derived from io_hd64465.h, which bore the message:
6 * By Greg Banks <gbanks@pocketpenguins.com>
7 * (c) 2000 PocketPenguins Inc.
8 * and from io_hd64461.h, which bore the message:
9 * Copyright 2000 Stuart Menefy (stuart.menefy@st.com)
10 *
11 * May be copied or modified under the terms of the GNU General Public
12 * License. See linux/COPYING for more information.
13 *
14 * IO functions for a Hitachi Big Sur Evaluation Board.
15 */
16
Linus Torvalds1da177e2005-04-16 15:20:36 -070017#include <linux/kernel.h>
18#include <linux/module.h>
19#include <asm/machvec.h>
20#include <asm/io.h>
21#include <asm/bigsur/bigsur.h>
22
23/* Low iomap maps port 0-1K to addresses in 8byte chunks */
24#define BIGSUR_IOMAP_LO_THRESH 0x400
25#define BIGSUR_IOMAP_LO_SHIFT 3
26#define BIGSUR_IOMAP_LO_MASK ((1<<BIGSUR_IOMAP_LO_SHIFT)-1)
27#define BIGSUR_IOMAP_LO_NMAP (BIGSUR_IOMAP_LO_THRESH>>BIGSUR_IOMAP_LO_SHIFT)
28static u32 bigsur_iomap_lo[BIGSUR_IOMAP_LO_NMAP];
29static u8 bigsur_iomap_lo_shift[BIGSUR_IOMAP_LO_NMAP];
30
31/* High iomap maps port 1K-64K to addresses in 1K chunks */
32#define BIGSUR_IOMAP_HI_THRESH 0x10000
33#define BIGSUR_IOMAP_HI_SHIFT 10
34#define BIGSUR_IOMAP_HI_MASK ((1<<BIGSUR_IOMAP_HI_SHIFT)-1)
35#define BIGSUR_IOMAP_HI_NMAP (BIGSUR_IOMAP_HI_THRESH>>BIGSUR_IOMAP_HI_SHIFT)
36static u32 bigsur_iomap_hi[BIGSUR_IOMAP_HI_NMAP];
37static u8 bigsur_iomap_hi_shift[BIGSUR_IOMAP_HI_NMAP];
38
Linus Torvalds1da177e2005-04-16 15:20:36 -070039void bigsur_port_map(u32 baseport, u32 nports, u32 addr, u8 shift)
40{
41 u32 port, endport = baseport + nports;
42
43 pr_debug("bigsur_port_map(base=0x%0x, n=0x%0x, addr=0x%08x)\n",
44 baseport, nports, addr);
45
46 for (port = baseport ;
47 port < endport && port < BIGSUR_IOMAP_LO_THRESH ;
48 port += (1<<BIGSUR_IOMAP_LO_SHIFT)) {
49 pr_debug(" maplo[0x%x] = 0x%08x\n", port, addr);
50 bigsur_iomap_lo[port>>BIGSUR_IOMAP_LO_SHIFT] = addr;
51 bigsur_iomap_lo_shift[port>>BIGSUR_IOMAP_LO_SHIFT] = shift;
52 addr += (1<<(BIGSUR_IOMAP_LO_SHIFT));
53 }
54
Michael Veeck0e8bbf52005-09-10 00:27:11 -070055 for (port = max_t(u32, baseport, BIGSUR_IOMAP_LO_THRESH);
Linus Torvalds1da177e2005-04-16 15:20:36 -070056 port < endport && port < BIGSUR_IOMAP_HI_THRESH ;
57 port += (1<<BIGSUR_IOMAP_HI_SHIFT)) {
58 pr_debug(" maphi[0x%x] = 0x%08x\n", port, addr);
59 bigsur_iomap_hi[port>>BIGSUR_IOMAP_HI_SHIFT] = addr;
60 bigsur_iomap_hi_shift[port>>BIGSUR_IOMAP_HI_SHIFT] = shift;
61 addr += (1<<(BIGSUR_IOMAP_HI_SHIFT));
62 }
63}
64EXPORT_SYMBOL(bigsur_port_map);
65
66void bigsur_port_unmap(u32 baseport, u32 nports)
67{
68 u32 port, endport = baseport + nports;
69
70 pr_debug("bigsur_port_unmap(base=0x%0x, n=0x%0x)\n", baseport, nports);
71
72 for (port = baseport ;
73 port < endport && port < BIGSUR_IOMAP_LO_THRESH ;
74 port += (1<<BIGSUR_IOMAP_LO_SHIFT)) {
75 bigsur_iomap_lo[port>>BIGSUR_IOMAP_LO_SHIFT] = 0;
76 }
77
Michael Veeck0e8bbf52005-09-10 00:27:11 -070078 for (port = max_t(u32, baseport, BIGSUR_IOMAP_LO_THRESH);
Linus Torvalds1da177e2005-04-16 15:20:36 -070079 port < endport && port < BIGSUR_IOMAP_HI_THRESH ;
80 port += (1<<BIGSUR_IOMAP_HI_SHIFT)) {
81 bigsur_iomap_hi[port>>BIGSUR_IOMAP_HI_SHIFT] = 0;
82 }
83}
84EXPORT_SYMBOL(bigsur_port_unmap);
85
86unsigned long bigsur_isa_port2addr(unsigned long port)
87{
88 unsigned long addr = 0;
89 unsigned char shift;
90
91 /* Physical address not in P0, do nothing */
92 if (PXSEG(port)) {
93 addr = port;
94 /* physical address in P0, map to P2 */
95 } else if (port >= 0x30000) {
96 addr = P2SEGADDR(port);
97 /* Big Sur I/O + HD64465 registers 0x10000-0x30000 */
98 } else if (port >= BIGSUR_IOMAP_HI_THRESH) {
99 addr = BIGSUR_INTERNAL_BASE + (port - BIGSUR_IOMAP_HI_THRESH);
100 /* Handle remapping of high IO/PCI IO ports */
101 } else if (port >= BIGSUR_IOMAP_LO_THRESH) {
102 addr = bigsur_iomap_hi[port >> BIGSUR_IOMAP_HI_SHIFT];
103 shift = bigsur_iomap_hi_shift[port >> BIGSUR_IOMAP_HI_SHIFT];
104
105 if (addr != 0)
106 addr += (port & BIGSUR_IOMAP_HI_MASK) << shift;
107 } else {
108 /* Handle remapping of low IO ports */
109 addr = bigsur_iomap_lo[port >> BIGSUR_IOMAP_LO_SHIFT];
110 shift = bigsur_iomap_lo_shift[port >> BIGSUR_IOMAP_LO_SHIFT];
111
112 if (addr != 0)
113 addr += (port & BIGSUR_IOMAP_LO_MASK) << shift;
114 }
115
116 pr_debug("%s(0x%08lx) = 0x%08lx\n", __FUNCTION__, port, addr);
117
118 return addr;
119}
120