forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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 <[email protected]>
- Loading branch information
1 parent
4c15699
commit 140c172
Showing
6 changed files
with
287 additions
and
81 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
/* | ||
* Implement the default iomap interfaces | ||
* | ||
* (C) Copyright 2004 Linus Torvalds | ||
* (C) Copyright 2006 Ralf Baechle <[email protected]> | ||
* (C) Copyright 2007 MIPS Technologies, Inc. | ||
* written by Ralf Baechle <[email protected]> | ||
*/ | ||
#include <linux/pci.h> | ||
#include <linux/module.h> | ||
#include <asm/io.h> | ||
|
||
static void __iomem *ioport_map_pci(struct pci_dev *dev, | ||
unsigned long port, unsigned int nr) | ||
{ | ||
struct pci_controller *ctrl = dev->bus->sysdata; | ||
unsigned long base = ctrl->io_map_base; | ||
|
||
/* This will eventually become a BUG_ON but for now be gentle */ | ||
if (unlikely(!ctrl->io_map_base)) { | ||
struct pci_bus *bus = dev->bus; | ||
char name[8]; | ||
|
||
while (bus->parent) | ||
bus = bus->parent; | ||
|
||
ctrl->io_map_base = base = mips_io_port_base; | ||
|
||
sprintf(name, "%04x:%02x", pci_domain_nr(bus), bus->number); | ||
printk(KERN_WARNING "io_map_base of root PCI bus %s unset. " | ||
"Trying to continue but you better\nfix this issue or " | ||
"report it to [email protected] or your " | ||
"vendor.\n", name); | ||
#ifdef CONFIG_PCI_DOMAINS | ||
panic("To avoid data corruption io_map_base MUST be set with " | ||
"multiple PCI domains."); | ||
#endif | ||
} | ||
|
||
return (void __iomem *) (ctrl->io_map_base + port); | ||
} | ||
|
||
/* | ||
* Create a virtual mapping cookie for a PCI BAR (memory or IO) | ||
*/ | ||
void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen) | ||
{ | ||
unsigned long start = pci_resource_start(dev, bar); | ||
unsigned long len = pci_resource_len(dev, bar); | ||
unsigned long flags = pci_resource_flags(dev, bar); | ||
|
||
if (!len || !start) | ||
return NULL; | ||
if (maxlen && len > maxlen) | ||
len = maxlen; | ||
if (flags & IORESOURCE_IO) | ||
return ioport_map_pci(dev, start, len); | ||
if (flags & IORESOURCE_MEM) { | ||
if (flags & IORESOURCE_CACHEABLE) | ||
return ioremap(start, len); | ||
return ioremap_nocache(start, len); | ||
} | ||
/* What? */ | ||
return NULL; | ||
} | ||
|
||
EXPORT_SYMBOL(pci_iomap); | ||
|
||
void pci_iounmap(struct pci_dev *dev, void __iomem * addr) | ||
{ | ||
iounmap(addr); | ||
} | ||
|
||
EXPORT_SYMBOL(pci_iounmap); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,78 +1,227 @@ | ||
/* | ||
* iomap.c, Memory Mapped I/O routines for MIPS architecture. | ||
* Implement the default iomap interfaces | ||
* | ||
* This code is based on lib/iomap.c, by Linus Torvalds. | ||
* | ||
* Copyright (C) 2004-2005 Yoichi Yuasa <[email protected]> | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License as published by | ||
* the Free Software Foundation; either version 2 of the License, or | ||
* (at your option) any later version. | ||
* (C) Copyright 2004 Linus Torvalds | ||
* (C) Copyright 2006 Ralf Baechle <[email protected]> | ||
* (C) Copyright 2007 MIPS Technologies, Inc. | ||
* written by Ralf Baechle <[email protected]> | ||
*/ | ||
#include <linux/pci.h> | ||
#include <linux/module.h> | ||
#include <asm/io.h> | ||
|
||
/* | ||
* Read/write from/to an (offsettable) iomem cookie. It might be a PIO | ||
* access or a MMIO access, these functions don't care. The info is | ||
* encoded in the hardware mapping set up by the mapping functions | ||
* (or the cookie itself, depending on implementation and hw). | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
* The generic routines don't assume any hardware mappings, and just | ||
* encode the PIO/MMIO as part of the cookie. They coldly assume that | ||
* the MMIO IO mappings are not in the low address range. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program; if not, write to the Free Software | ||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
* Architectures for which this is not true can't use this generic | ||
* implementation and should do their own copy. | ||
*/ | ||
#include <linux/ioport.h> | ||
#include <linux/module.h> | ||
#include <linux/pci.h> | ||
|
||
#include <asm/io.h> | ||
#define PIO_MASK 0x0ffffUL | ||
|
||
void __iomem *ioport_map(unsigned long port, unsigned int nr) | ||
unsigned int ioread8(void __iomem *addr) | ||
{ | ||
unsigned long end; | ||
return readb(addr); | ||
} | ||
|
||
end = port + nr - 1UL; | ||
if (ioport_resource.start > port || | ||
ioport_resource.end < end || port > end) | ||
return NULL; | ||
EXPORT_SYMBOL(ioread8); | ||
|
||
return (void __iomem *)(mips_io_port_base + port); | ||
unsigned int ioread16(void __iomem *addr) | ||
{ | ||
return readw(addr); | ||
} | ||
|
||
void ioport_unmap(void __iomem *addr) | ||
EXPORT_SYMBOL(ioread16); | ||
|
||
unsigned int ioread16be(void __iomem *addr) | ||
{ | ||
return be16_to_cpu(__raw_readw(addr)); | ||
} | ||
EXPORT_SYMBOL(ioport_map); | ||
EXPORT_SYMBOL(ioport_unmap); | ||
|
||
void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen) | ||
EXPORT_SYMBOL(ioread16be); | ||
|
||
unsigned int ioread32(void __iomem *addr) | ||
{ | ||
unsigned long start, len, flags; | ||
return readl(addr); | ||
} | ||
|
||
if (dev == NULL) | ||
return NULL; | ||
EXPORT_SYMBOL(ioread32); | ||
|
||
start = pci_resource_start(dev, bar); | ||
len = pci_resource_len(dev, bar); | ||
if (!start || !len) | ||
return NULL; | ||
unsigned int ioread32be(void __iomem *addr) | ||
{ | ||
return be32_to_cpu(__raw_readl(addr)); | ||
} | ||
|
||
if (maxlen != 0 && len > maxlen) | ||
len = maxlen; | ||
EXPORT_SYMBOL(ioread32be); | ||
|
||
void iowrite8(u8 val, void __iomem *addr) | ||
{ | ||
writeb(val, addr); | ||
} | ||
|
||
flags = pci_resource_flags(dev, bar); | ||
if (flags & IORESOURCE_IO) | ||
return ioport_map(start, len); | ||
if (flags & IORESOURCE_MEM) { | ||
if (flags & IORESOURCE_CACHEABLE) | ||
return ioremap_cachable(start, len); | ||
return ioremap_nocache(start, len); | ||
EXPORT_SYMBOL(iowrite8); | ||
|
||
void iowrite16(u16 val, void __iomem *addr) | ||
{ | ||
writew(val, addr); | ||
} | ||
|
||
EXPORT_SYMBOL(iowrite16); | ||
|
||
void iowrite16be(u16 val, void __iomem *addr) | ||
{ | ||
__raw_writew(cpu_to_be16(val), addr); | ||
} | ||
|
||
EXPORT_SYMBOL(iowrite16be); | ||
|
||
void iowrite32(u32 val, void __iomem *addr) | ||
{ | ||
writel(val, addr); | ||
} | ||
|
||
EXPORT_SYMBOL(iowrite32); | ||
|
||
void iowrite32be(u32 val, void __iomem *addr) | ||
{ | ||
__raw_writel(cpu_to_be32(val), addr); | ||
} | ||
|
||
EXPORT_SYMBOL(iowrite32be); | ||
|
||
/* | ||
* These are the "repeat MMIO read/write" functions. | ||
* Note the "__raw" accesses, since we don't want to | ||
* convert to CPU byte order. We write in "IO byte | ||
* order" (we also don't have IO barriers). | ||
*/ | ||
static inline void mmio_insb(void __iomem *addr, u8 *dst, int count) | ||
{ | ||
while (--count >= 0) { | ||
u8 data = __raw_readb(addr); | ||
*dst = data; | ||
dst++; | ||
} | ||
} | ||
|
||
return NULL; | ||
static inline void mmio_insw(void __iomem *addr, u16 *dst, int count) | ||
{ | ||
while (--count >= 0) { | ||
u16 data = __raw_readw(addr); | ||
*dst = data; | ||
dst++; | ||
} | ||
} | ||
|
||
void pci_iounmap(struct pci_dev *dev, void __iomem *addr) | ||
static inline void mmio_insl(void __iomem *addr, u32 *dst, int count) | ||
{ | ||
iounmap(addr); | ||
while (--count >= 0) { | ||
u32 data = __raw_readl(addr); | ||
*dst = data; | ||
dst++; | ||
} | ||
} | ||
EXPORT_SYMBOL(pci_iomap); | ||
EXPORT_SYMBOL(pci_iounmap); | ||
|
||
static inline void mmio_outsb(void __iomem *addr, const u8 *src, int count) | ||
{ | ||
while (--count >= 0) { | ||
__raw_writeb(*src, addr); | ||
src++; | ||
} | ||
} | ||
|
||
static inline void mmio_outsw(void __iomem *addr, const u16 *src, int count) | ||
{ | ||
while (--count >= 0) { | ||
__raw_writew(*src, addr); | ||
src++; | ||
} | ||
} | ||
|
||
static inline void mmio_outsl(void __iomem *addr, const u32 *src, int count) | ||
{ | ||
while (--count >= 0) { | ||
__raw_writel(*src, addr); | ||
src++; | ||
} | ||
} | ||
|
||
void ioread8_rep(void __iomem *addr, void *dst, unsigned long count) | ||
{ | ||
mmio_insb(addr, dst, count); | ||
} | ||
|
||
EXPORT_SYMBOL(ioread8_rep); | ||
|
||
void ioread16_rep(void __iomem *addr, void *dst, unsigned long count) | ||
{ | ||
mmio_insw(addr, dst, count); | ||
} | ||
|
||
EXPORT_SYMBOL(ioread16_rep); | ||
|
||
void ioread32_rep(void __iomem *addr, void *dst, unsigned long count) | ||
{ | ||
mmio_insl(addr, dst, count); | ||
} | ||
|
||
EXPORT_SYMBOL(ioread32_rep); | ||
|
||
void iowrite8_rep(void __iomem *addr, const void *src, unsigned long count) | ||
{ | ||
mmio_outsb(addr, src, count); | ||
} | ||
|
||
EXPORT_SYMBOL(iowrite8_rep); | ||
|
||
void iowrite16_rep(void __iomem *addr, const void *src, unsigned long count) | ||
{ | ||
mmio_outsw(addr, src, count); | ||
} | ||
|
||
EXPORT_SYMBOL(iowrite16_rep); | ||
|
||
void iowrite32_rep(void __iomem *addr, const void *src, unsigned long count) | ||
{ | ||
mmio_outsl(addr, src, count); | ||
} | ||
|
||
EXPORT_SYMBOL(iowrite32_rep); | ||
|
||
/* | ||
* Create a virtual mapping cookie for an IO port range | ||
* | ||
* This uses the same mapping are as the in/out family which has to be setup | ||
* by the platform initialization code. | ||
* | ||
* Just to make matters somewhat more interesting on MIPS systems with | ||
* multiple host bridge each will have it's own ioport address space. | ||
*/ | ||
static void __iomem *ioport_map_legacy(unsigned long port, unsigned int nr) | ||
{ | ||
return (void __iomem *) (mips_io_port_base + port); | ||
} | ||
|
||
void __iomem *ioport_map(unsigned long port, unsigned int nr) | ||
{ | ||
if (port > PIO_MASK) | ||
return NULL; | ||
|
||
return ioport_map_legacy(port, nr); | ||
} | ||
|
||
EXPORT_SYMBOL(ioport_map); | ||
|
||
void ioport_unmap(void __iomem *addr) | ||
{ | ||
/* Nothing to do */ | ||
} | ||
|
||
EXPORT_SYMBOL(ioport_unmap); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters