[RFC/PATCH v2] powerpc: add ioremap_early() function for mapping IO regions before MMU_init()

Kumar Gala galak at kernel.crashing.org
Thu Aug 14 23:00:48 EST 2008


On Aug 12, 2008, at 10:03 PM, Grant Likely wrote:

> +/**
> + * ioremap_early - Allow large persistant IO regions to be mapped  
> early.
> + * @addr: physical address of region
> + * @size: size of region
> + *
> + * This routine uses setbat() to set up IO ranges before the MMU is
> + * fully configured.
> + *
> + * This routine can be called really early, before MMU_init() is  
> called.  It
> + * is useful for setting up early debug output consoles and  
> frequently
> + * accessed IO regions, like the internally memory mapped registers  
> (IMMR)
> + * in an SoC.  Ranges mapped with this function persist even after  
> MMU_init()
> + * is called and the MMU is turned on 'for real.'
> + *
> + * The region mapped is large (minimum size of 128k) and virtual  
> mapping must
> + * be aligned against this boundary.  Therefore, to avoid  
> fragmentation all
> + * calls to ioremap_early() are best made before any calls to ioremap
> + * for smaller regions.
> + */
> +void __iomem * __init
> +ioremap_early(phys_addr_t addr, unsigned long size)
> +{
> +	unsigned long v, p;
> +	int i;
> +
> +	/* Be loud and annoying if someone calls this too late.
> +	 * No need to crash the kernel though */
> +	WARN_ON(mem_init_done);
> +	if (mem_init_done)
> +		return NULL;
> +
> +	/* Make sure request is sane */
> +	if (size == 0)
> +		return NULL;
> +
> +	/* If the region is already block mapped, then there is nothing
> +	 * to do; just return the mapped address */
> +	v = p_mapped_by_bats(addr);
> +	if (v)
> +		return (void __iomem *)v;
> +
> +	/* Adjust size to reflect aligned region */
> +	p = _ALIGN_DOWN(addr, 128 << 10); /* BATs align on 128k boundaries  
> */
> +	size = ALIGN(addr - p + size, 128 << 10);
> +
> +	/* Allocate the aligned virtual base address.  ALIGN_DOWN is used
> +	 * to ensure no overlaps occur with normal 4k ioremaps. */
> +	v = ioremap_bot = _ALIGN_DOWN(ioremap_bot, 128 << 10) - size;
> +
> +	/* Set up a BAT for this IO region */
> +	i = loadbat(v, p, size, _PAGE_IO);

what happens if we run out of bats?


does this actually build on any non-BAT based ppc32 system?

>
> +	if (i < 0)
> +		return NULL;
> +
> +	return (void __iomem *) (v + (addr - p));
> +}
> +




More information about the Linuxppc-dev mailing list