#include <linux/vmalloc.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/pci.h>
#include <linux/io.h>
#include <asm/io_trapped.h>
#include <asm/page.h>
#include <asm/pgalloc.h>
#include <asm/addrspace.h>
#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
#include <asm/mmu.h>
#include "ioremap.h"
#ifdef CONFIG_29BIT
static void __iomem *
__ioremap_29bit(phys_addr_t offset, unsigned long size, pgprot_t prot)
{
phys_addr_t last_addr = offset + size - 1;
if (likely(PXSEG(offset) < P3SEG && PXSEG(last_addr) < P3SEG)) {
u64 flags = pgprot_val(prot);
if (unlikely(flags & _PAGE_PCC_MASK))
return NULL;
if (unlikely(flags & _PAGE_CACHABLE))
return (void __iomem *)P1SEGADDR(offset);
return (void __iomem *)P2SEGADDR(offset);
}
if (unlikely(offset >= P3_ADDR_MAX))
return (void __iomem *)P4SEGADDR(offset);
return NULL;
}
#else
#define __ioremap_29bit(offset, size, prot) NULL
#endif
void __iomem __ref *ioremap_prot(phys_addr_t phys_addr, size_t size,
pgprot_t pgprot)
{
void __iomem *mapped;
mapped = __ioremap_trapped(phys_addr, size);
if (mapped)
return mapped;
mapped = __ioremap_29bit(phys_addr, size, pgprot);
if (mapped)
return mapped;
if (!mem_init_done)
return ioremap_fixed(phys_addr, size, pgprot);
mapped = pmb_remap_caller(phys_addr, size, pgprot,
__builtin_return_address(0));
if (mapped && !IS_ERR(mapped))
return mapped;
return generic_ioremap_prot(phys_addr, size, pgprot);
}
EXPORT_SYMBOL(ioremap_prot);
static inline int iomapping_nontranslatable(unsigned long offset)
{
#ifdef CONFIG_29BIT
if (PXSEG(offset) < P3SEG || offset >= P3_ADDR_MAX)
return 1;
#endif
return 0;
}
void iounmap(volatile void __iomem *addr)
{
unsigned long vaddr = (unsigned long __force)addr;
if (iomapping_nontranslatable(vaddr))
return;
if (iounmap_fixed((void __iomem *)addr) == 0)
return;
if (pmb_unmap((void __iomem *)addr) == 0)
return;
generic_iounmap(addr);
}
EXPORT_SYMBOL(iounmap);