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

Grant Likely grant.likely at secretlab.ca
Fri Aug 15 01:00:46 EST 2008


On Thu, Aug 14, 2008 at 7:00 AM, Kumar Gala <galak at kernel.crashing.org> wrote:
>
> 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?

Then it returns NULL and the caller must handle it.  The board port
maintainer needs understand the board/CPU/SoC and not depend on more
BATs than are available.  They also need to understand that there is a
tradeoff between BATs for IO and BATs for RAM.  If the board port uses
up all the BATs for IO, then RAM above 256MB ends up getting mapped
with PTEs and there is a performance hit.  My expectation is that only
platform code will use this facility.  Device drivers should continue
to use ioremap() and will gain the benefit of the BATs if platform
code already set them up.  I can add some text to the documentation to
describe this.

I'm not going to make any attempt to fallback to PTEs for IO when
there isn't enough BATs.  Doing so adds an order of magnitude more
complexity.

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

Heh, oops.  I had built the older version of this on 4xx, but I didn't
do this one.  I'll fix it in v3

g.

-- 
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.



More information about the Linuxppc-dev mailing list