linux/arch/arm/plat-omap/sram.c
<<
>>
Prefs
   1/*
   2 * linux/arch/arm/plat-omap/sram.c
   3 *
   4 * OMAP SRAM detection and management
   5 *
   6 * Copyright (C) 2005 Nokia Corporation
   7 * Written by Tony Lindgren <tony@atomide.com>
   8 *
   9 * Copyright (C) 2009-2012 Texas Instruments
  10 * Added OMAP4/5 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
  11 *
  12 * This program is free software; you can redistribute it and/or modify
  13 * it under the terms of the GNU General Public License version 2 as
  14 * published by the Free Software Foundation.
  15 */
  16#undef DEBUG
  17
  18#include <linux/module.h>
  19#include <linux/kernel.h>
  20#include <linux/init.h>
  21#include <linux/io.h>
  22
  23#include <asm/fncpy.h>
  24#include <asm/tlb.h>
  25#include <asm/cacheflush.h>
  26
  27#include <asm/mach/map.h>
  28
  29#include <plat/sram.h>
  30
  31#define ROUND_DOWN(value,boundary)      ((value) & (~((boundary)-1)))
  32
  33static void __iomem *omap_sram_base;
  34static unsigned long omap_sram_skip;
  35static unsigned long omap_sram_size;
  36static void __iomem *omap_sram_ceil;
  37
  38/*
  39 * Memory allocator for SRAM: calculates the new ceiling address
  40 * for pushing a function using the fncpy API.
  41 *
  42 * Note that fncpy requires the returned address to be aligned
  43 * to an 8-byte boundary.
  44 */
  45void *omap_sram_push_address(unsigned long size)
  46{
  47        unsigned long available, new_ceil = (unsigned long)omap_sram_ceil;
  48
  49        available = omap_sram_ceil - (omap_sram_base + omap_sram_skip);
  50
  51        if (size > available) {
  52                pr_err("Not enough space in SRAM\n");
  53                return NULL;
  54        }
  55
  56        new_ceil -= size;
  57        new_ceil = ROUND_DOWN(new_ceil, FNCPY_ALIGN);
  58        omap_sram_ceil = IOMEM(new_ceil);
  59
  60        return (void *)omap_sram_ceil;
  61}
  62
  63/*
  64 * The SRAM context is lost during off-idle and stack
  65 * needs to be reset.
  66 */
  67void omap_sram_reset(void)
  68{
  69        omap_sram_ceil = omap_sram_base + omap_sram_size;
  70}
  71
  72/*
  73 * Note that we cannot use ioremap for SRAM, as clock init needs SRAM early.
  74 */
  75void __init omap_map_sram(unsigned long start, unsigned long size,
  76                                 unsigned long skip, int cached)
  77{
  78        if (size == 0)
  79                return;
  80
  81        start = ROUND_DOWN(start, PAGE_SIZE);
  82        omap_sram_size = size;
  83        omap_sram_skip = skip;
  84        omap_sram_base = __arm_ioremap_exec(start, size, cached);
  85        if (!omap_sram_base) {
  86                pr_err("SRAM: Could not map\n");
  87                return;
  88        }
  89
  90        omap_sram_reset();
  91
  92        /*
  93         * Looks like we need to preserve some bootloader code at the
  94         * beginning of SRAM for jumping to flash for reboot to work...
  95         */
  96        memset_io(omap_sram_base + omap_sram_skip, 0,
  97                  omap_sram_size - omap_sram_skip);
  98}
  99