aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2006-12-07 09:35:43 -0500
committerRalf Baechle <ralf@linux-mips.org>2007-02-18 16:31:34 -0500
commit140c1729a221dc6eacfcbf2a073dbf00fad13e43 (patch)
treeb6baff7c6e68f7ca45aacded88b02ccb5f2cd286
parent4c1569949a756327aa0ad7aa15a62266b6a00c3e (diff)
[MIPS] Iomap implementation.
This implementation has support for the concept of one separate ioport address space by PCI domain. A pointer to the virtual address where the port space of a domain has been mapped has been added to struct pci_controller and systems should be fixed to fill in this value. For single domain systems this will be the same value as passed to set_io_port_base(). Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r--arch/mips/lib/Makefile3
-rw-r--r--arch/mips/lib/iomap-pci.c74
-rw-r--r--arch/mips/lib/iomap.c253
-rw-r--r--arch/mips/pci/pci.c8
-rw-r--r--include/asm-mips/io.h29
-rw-r--r--include/asm-mips/pci.h1
6 files changed, 287 insertions, 81 deletions
diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile
index 5ad501b30b43..9e5d985936b3 100644
--- a/arch/mips/lib/Makefile
+++ b/arch/mips/lib/Makefile
@@ -5,7 +5,8 @@
5lib-y += csum_partial.o memcpy.o memset.o promlib.o \ 5lib-y += csum_partial.o memcpy.o memset.o promlib.o \
6 strlen_user.o strncpy_user.o strnlen_user.o uncached.o 6 strlen_user.o strncpy_user.o strnlen_user.o uncached.o
7 7
8obj-y += iomap.o 8obj-y += iomap.o
9obj-$(CONFIG_PCI) += iomap-pci.o
9 10
10# libgcc-style stuff needed in the kernel 11# libgcc-style stuff needed in the kernel
11lib-y += ashldi3.o ashrdi3.o lshrdi3.o 12lib-y += ashldi3.o ashrdi3.o lshrdi3.o
diff --git a/arch/mips/lib/iomap-pci.c b/arch/mips/lib/iomap-pci.c
new file mode 100644
index 000000000000..c11b2494bb6e
--- /dev/null
+++ b/arch/mips/lib/iomap-pci.c
@@ -0,0 +1,74 @@
1/*
2 * Implement the default iomap interfaces
3 *
4 * (C) Copyright 2004 Linus Torvalds
5 * (C) Copyright 2006 Ralf Baechle <ralf@linux-mips.org>
6 * (C) Copyright 2007 MIPS Technologies, Inc.
7 * written by Ralf Baechle <ralf@linux-mips.org>
8 */
9#include <linux/pci.h>
10#include <linux/module.h>
11#include <asm/io.h>
12
13static void __iomem *ioport_map_pci(struct pci_dev *dev,
14 unsigned long port, unsigned int nr)
15{
16 struct pci_controller *ctrl = dev->bus->sysdata;
17 unsigned long base = ctrl->io_map_base;
18
19 /* This will eventually become a BUG_ON but for now be gentle */
20 if (unlikely(!ctrl->io_map_base)) {
21 struct pci_bus *bus = dev->bus;
22 char name[8];
23
24 while (bus->parent)
25 bus = bus->parent;
26
27 ctrl->io_map_base = base = mips_io_port_base;
28
29 sprintf(name, "%04x:%02x", pci_domain_nr(bus), bus->number);
30 printk(KERN_WARNING "io_map_base of root PCI bus %s unset. "
31 "Trying to continue but you better\nfix this issue or "
32 "report it to linux-mips@linux-mips.org or your "
33 "vendor.\n", name);
34#ifdef CONFIG_PCI_DOMAINS
35 panic("To avoid data corruption io_map_base MUST be set with "
36 "multiple PCI domains.");
37#endif
38 }
39
40 return (void __iomem *) (ctrl->io_map_base + port);
41}
42
43/*
44 * Create a virtual mapping cookie for a PCI BAR (memory or IO)
45 */
46void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
47{
48 unsigned long start = pci_resource_start(dev, bar);
49 unsigned long len = pci_resource_len(dev, bar);
50 unsigned long flags = pci_resource_flags(dev, bar);
51
52 if (!len || !start)
53 return NULL;
54 if (maxlen && len > maxlen)
55 len = maxlen;
56 if (flags & IORESOURCE_IO)
57 return ioport_map_pci(dev, start, len);
58 if (flags & IORESOURCE_MEM) {
59 if (flags & IORESOURCE_CACHEABLE)
60 return ioremap(start, len);
61 return ioremap_nocache(start, len);
62 }
63 /* What? */
64 return NULL;
65}
66
67EXPORT_SYMBOL(pci_iomap);
68
69void pci_iounmap(struct pci_dev *dev, void __iomem * addr)
70{
71 iounmap(addr);
72}
73
74EXPORT_SYMBOL(pci_iounmap);
diff --git a/arch/mips/lib/iomap.c b/arch/mips/lib/iomap.c
index f4ac5bbcd81f..d51d5cb0a4a9 100644
--- a/arch/mips/lib/iomap.c
+++ b/arch/mips/lib/iomap.c
@@ -1,78 +1,227 @@
1/* 1/*
2 * iomap.c, Memory Mapped I/O routines for MIPS architecture. 2 * Implement the default iomap interfaces
3 * 3 *
4 * This code is based on lib/iomap.c, by Linus Torvalds. 4 * (C) Copyright 2004 Linus Torvalds
5 * 5 * (C) Copyright 2006 Ralf Baechle <ralf@linux-mips.org>
6 * Copyright (C) 2004-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> 6 * (C) Copyright 2007 MIPS Technologies, Inc.
7 * 7 * written by Ralf Baechle <ralf@linux-mips.org>
8 * This program is free software; you can redistribute it and/or modify 8 */
9 * it under the terms of the GNU General Public License as published by 9#include <linux/pci.h>
10 * the Free Software Foundation; either version 2 of the License, or 10#include <linux/module.h>
11 * (at your option) any later version. 11#include <asm/io.h>
12
13/*
14 * Read/write from/to an (offsettable) iomem cookie. It might be a PIO
15 * access or a MMIO access, these functions don't care. The info is
16 * encoded in the hardware mapping set up by the mapping functions
17 * (or the cookie itself, depending on implementation and hw).
12 * 18 *
13 * This program is distributed in the hope that it will be useful, 19 * The generic routines don't assume any hardware mappings, and just
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 * encode the PIO/MMIO as part of the cookie. They coldly assume that
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 * the MMIO IO mappings are not in the low address range.
16 * GNU General Public License for more details.
17 * 22 *
18 * You should have received a copy of the GNU General Public License 23 * Architectures for which this is not true can't use this generic
19 * along with this program; if not, write to the Free Software 24 * implementation and should do their own copy.
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */ 25 */
22#include <linux/ioport.h>
23#include <linux/module.h>
24#include <linux/pci.h>
25 26
26#include <asm/io.h> 27#define PIO_MASK 0x0ffffUL
27 28
28void __iomem *ioport_map(unsigned long port, unsigned int nr) 29unsigned int ioread8(void __iomem *addr)
29{ 30{
30 unsigned long end; 31 return readb(addr);
32}
31 33
32 end = port + nr - 1UL; 34EXPORT_SYMBOL(ioread8);
33 if (ioport_resource.start > port ||
34 ioport_resource.end < end || port > end)
35 return NULL;
36 35
37 return (void __iomem *)(mips_io_port_base + port); 36unsigned int ioread16(void __iomem *addr)
37{
38 return readw(addr);
38} 39}
39 40
40void ioport_unmap(void __iomem *addr) 41EXPORT_SYMBOL(ioread16);
42
43unsigned int ioread16be(void __iomem *addr)
41{ 44{
45 return be16_to_cpu(__raw_readw(addr));
42} 46}
43EXPORT_SYMBOL(ioport_map);
44EXPORT_SYMBOL(ioport_unmap);
45 47
46void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen) 48EXPORT_SYMBOL(ioread16be);
49
50unsigned int ioread32(void __iomem *addr)
47{ 51{
48 unsigned long start, len, flags; 52 return readl(addr);
53}
49 54
50 if (dev == NULL) 55EXPORT_SYMBOL(ioread32);
51 return NULL;
52 56
53 start = pci_resource_start(dev, bar); 57unsigned int ioread32be(void __iomem *addr)
54 len = pci_resource_len(dev, bar); 58{
55 if (!start || !len) 59 return be32_to_cpu(__raw_readl(addr));
56 return NULL; 60}
57 61
58 if (maxlen != 0 && len > maxlen) 62EXPORT_SYMBOL(ioread32be);
59 len = maxlen; 63
64void iowrite8(u8 val, void __iomem *addr)
65{
66 writeb(val, addr);
67}
60 68
61 flags = pci_resource_flags(dev, bar); 69EXPORT_SYMBOL(iowrite8);
62 if (flags & IORESOURCE_IO) 70
63 return ioport_map(start, len); 71void iowrite16(u16 val, void __iomem *addr)
64 if (flags & IORESOURCE_MEM) { 72{
65 if (flags & IORESOURCE_CACHEABLE) 73 writew(val, addr);
66 return ioremap_cachable(start, len); 74}
67 return ioremap_nocache(start, len); 75
76EXPORT_SYMBOL(iowrite16);
77
78void iowrite16be(u16 val, void __iomem *addr)
79{
80 __raw_writew(cpu_to_be16(val), addr);
81}
82
83EXPORT_SYMBOL(iowrite16be);
84
85void iowrite32(u32 val, void __iomem *addr)
86{
87 writel(val, addr);
88}
89
90EXPORT_SYMBOL(iowrite32);
91
92void iowrite32be(u32 val, void __iomem *addr)
93{
94 __raw_writel(cpu_to_be32(val), addr);
95}
96
97EXPORT_SYMBOL(iowrite32be);
98
99/*
100 * These are the "repeat MMIO read/write" functions.
101 * Note the "__raw" accesses, since we don't want to
102 * convert to CPU byte order. We write in "IO byte
103 * order" (we also don't have IO barriers).
104 */
105static inline void mmio_insb(void __iomem *addr, u8 *dst, int count)
106{
107 while (--count >= 0) {
108 u8 data = __raw_readb(addr);
109 *dst = data;
110 dst++;
68 } 111 }
112}
69 113
70 return NULL; 114static inline void mmio_insw(void __iomem *addr, u16 *dst, int count)
115{
116 while (--count >= 0) {
117 u16 data = __raw_readw(addr);
118 *dst = data;
119 dst++;
120 }
71} 121}
72 122
73void pci_iounmap(struct pci_dev *dev, void __iomem *addr) 123static inline void mmio_insl(void __iomem *addr, u32 *dst, int count)
74{ 124{
75 iounmap(addr); 125 while (--count >= 0) {
126 u32 data = __raw_readl(addr);
127 *dst = data;
128 dst++;
129 }
76} 130}
77EXPORT_SYMBOL(pci_iomap); 131
78EXPORT_SYMBOL(pci_iounmap); 132static inline void mmio_outsb(void __iomem *addr, const u8 *src, int count)
133{
134 while (--count >= 0) {
135 __raw_writeb(*src, addr);
136 src++;
137 }
138}
139
140static inline void mmio_outsw(void __iomem *addr, const u16 *src, int count)
141{
142 while (--count >= 0) {
143 __raw_writew(*src, addr);
144 src++;
145 }
146}
147
148static inline void mmio_outsl(void __iomem *addr, const u32 *src, int count)
149{
150 while (--count >= 0) {
151 __raw_writel(*src, addr);
152 src++;
153 }
154}
155
156void ioread8_rep(void __iomem *addr, void *dst, unsigned long count)
157{
158 mmio_insb(addr, dst, count);
159}
160
161EXPORT_SYMBOL(ioread8_rep);
162
163void ioread16_rep(void __iomem *addr, void *dst, unsigned long count)
164{
165 mmio_insw(addr, dst, count);
166}
167
168EXPORT_SYMBOL(ioread16_rep);
169
170void ioread32_rep(void __iomem *addr, void *dst, unsigned long count)
171{
172 mmio_insl(addr, dst, count);
173}
174
175EXPORT_SYMBOL(ioread32_rep);
176
177void iowrite8_rep(void __iomem *addr, const void *src, unsigned long count)
178{
179 mmio_outsb(addr, src, count);
180}
181
182EXPORT_SYMBOL(iowrite8_rep);
183
184void iowrite16_rep(void __iomem *addr, const void *src, unsigned long count)
185{
186 mmio_outsw(addr, src, count);
187}
188
189EXPORT_SYMBOL(iowrite16_rep);
190
191void iowrite32_rep(void __iomem *addr, const void *src, unsigned long count)
192{
193 mmio_outsl(addr, src, count);
194}
195
196EXPORT_SYMBOL(iowrite32_rep);
197
198/*
199 * Create a virtual mapping cookie for an IO port range
200 *
201 * This uses the same mapping are as the in/out family which has to be setup
202 * by the platform initialization code.
203 *
204 * Just to make matters somewhat more interesting on MIPS systems with
205 * multiple host bridge each will have it's own ioport address space.
206 */
207static void __iomem *ioport_map_legacy(unsigned long port, unsigned int nr)
208{
209 return (void __iomem *) (mips_io_port_base + port);
210}
211
212void __iomem *ioport_map(unsigned long port, unsigned int nr)
213{
214 if (port > PIO_MASK)
215 return NULL;
216
217 return ioport_map_legacy(port, nr);
218}
219
220EXPORT_SYMBOL(ioport_map);
221
222void ioport_unmap(void __iomem *addr)
223{
224 /* Nothing to do */
225}
226
227EXPORT_SYMBOL(ioport_unmap);
diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c
index 5ace368657ad..697a7e48cb8d 100644
--- a/arch/mips/pci/pci.c
+++ b/arch/mips/pci/pci.c
@@ -79,6 +79,14 @@ void __init register_pci_controller(struct pci_controller *hose)
79{ 79{
80 *hose_tail = hose; 80 *hose_tail = hose;
81 hose_tail = &hose->next; 81 hose_tail = &hose->next;
82
83 /*
84 * Do not panic here but later - this might hapen before console init.
85 */
86 if (!hose->io_map_base) {
87 printk(KERN_WARNING
88 "registering PCI controller with io_map_base unset\n");
89 }
82} 90}
83 91
84/* Most MIPS systems have straight-forward swizzling needs. */ 92/* Most MIPS systems have straight-forward swizzling needs. */
diff --git a/include/asm-mips/io.h b/include/asm-mips/io.h
index b6a2eb816628..92ec2618560c 100644
--- a/include/asm-mips/io.h
+++ b/include/asm-mips/io.h
@@ -20,6 +20,7 @@
20#include <asm/byteorder.h> 20#include <asm/byteorder.h>
21#include <asm/cpu.h> 21#include <asm/cpu.h>
22#include <asm/cpu-features.h> 22#include <asm/cpu-features.h>
23#include <asm-generic/iomap.h>
23#include <asm/page.h> 24#include <asm/page.h>
24#include <asm/pgtable-bits.h> 25#include <asm/pgtable-bits.h>
25#include <asm/processor.h> 26#include <asm/processor.h>
@@ -518,34 +519,6 @@ static inline void memcpy_toio(volatile void __iomem *dst, const void *src, int
518} 519}
519 520
520/* 521/*
521 * Memory Mapped I/O
522 */
523#define ioread8(addr) readb(addr)
524#define ioread16(addr) readw(addr)
525#define ioread32(addr) readl(addr)
526
527#define iowrite8(b,addr) writeb(b,addr)
528#define iowrite16(w,addr) writew(w,addr)
529#define iowrite32(l,addr) writel(l,addr)
530
531#define ioread8_rep(a,b,c) readsb(a,b,c)
532#define ioread16_rep(a,b,c) readsw(a,b,c)
533#define ioread32_rep(a,b,c) readsl(a,b,c)
534
535#define iowrite8_rep(a,b,c) writesb(a,b,c)
536#define iowrite16_rep(a,b,c) writesw(a,b,c)
537#define iowrite32_rep(a,b,c) writesl(a,b,c)
538
539/* Create a virtual mapping cookie for an IO port range */
540extern void __iomem *ioport_map(unsigned long port, unsigned int nr);
541extern void ioport_unmap(void __iomem *);
542
543/* Create a virtual mapping cookie for a PCI BAR (memory or IO) */
544struct pci_dev;
545extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max);
546extern void pci_iounmap(struct pci_dev *dev, void __iomem *);
547
548/*
549 * ISA space is 'always mapped' on currently supported MIPS systems, no need 522 * ISA space is 'always mapped' on currently supported MIPS systems, no need
550 * to explicitly ioremap() it. The fact that the ISA IO space is mapped 523 * to explicitly ioremap() it. The fact that the ISA IO space is mapped
551 * to PAGE_OFFSET is pure coincidence - it does not mean ISA values 524 * to PAGE_OFFSET is pure coincidence - it does not mean ISA values
diff --git a/include/asm-mips/pci.h b/include/asm-mips/pci.h
index 7f0f120ca07c..3eea3ba0fca5 100644
--- a/include/asm-mips/pci.h
+++ b/include/asm-mips/pci.h
@@ -32,6 +32,7 @@ struct pci_controller {
32 unsigned long mem_offset; 32 unsigned long mem_offset;
33 struct resource *io_resource; 33 struct resource *io_resource;
34 unsigned long io_offset; 34 unsigned long io_offset;
35 unsigned long io_map_base;
35 36
36 unsigned int index; 37 unsigned int index;
37 /* For compatibility with current (as of July 2003) pciutils 38 /* For compatibility with current (as of July 2003) pciutils