]> pilppa.com Git - linux-2.6-omap-h63xx.git/commitdiff
SRAM patcher: add SRAM virtual address patcher
authorPaul Walmsley <paul@pwsan.com>
Wed, 14 Nov 2007 08:30:11 +0000 (01:30 -0700)
committerTony Lindgren <tony@atomide.com>
Fri, 16 Nov 2007 22:30:44 +0000 (14:30 -0800)
Add omap_sram_patch_va(), which patches a virtual address into SRAM
code at runtime.  This will be used in a future patch series to implement
part of multiboot support for OMAP2/3.

If CONFIG_OMAP_DEBUG_SRAM_PATCH is defined (the default), the code
will be very careful to ensure that the target location to patch is
valid.  It will only overwrite a location if the location contains a
32-bit magic number, defined as SRAM_VA_MAGIC.  Also, defining DEBUG
at the top of the file and enabling CONFIG_DEBUG_LL will log patch
locations and data via printk.

Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
arch/arm/plat-omap/Kconfig
arch/arm/plat-omap/sram.c
include/asm-arm/arch-omap/sram.h
include/linux/poison.h

index a747610af8e3eba339beb1f765c0697333e620bd..d1558dfcc0cdb27ab1c522884c59d403fb5b8ce9 100644 (file)
@@ -32,6 +32,16 @@ config OMAP_DEBUG_LEDS
        depends on OMAP_DEBUG_DEVICES
        default y if LEDS || LEDS_OMAP_DEBUG
 
+config OMAP_DEBUG_SRAM_PATCH
+       bool "Extra sanity checking for SRAM patch code"
+       depends on ARCH_OMAP
+       default y
+       help
+         Say Y here if you want the kernel to use extra caution
+         in patching SRAM virtual addresses.  If you are
+         confident in your SRAM code, disabling this will save
+         about 600 bytes.
+
 config OMAP_RESET_CLOCKS
        bool "Reset unused clocks during boot"
        depends on ARCH_OMAP
index e3a85b9ff2031d52ca6daa5a8151962dbccd896b..e6cfa11eb301273efc492747472907b836e29b76 100644 (file)
@@ -10,6 +10,7 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#undef DEBUG
 
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -195,6 +196,66 @@ void * omap_sram_push(void * start, unsigned long size)
        return (void *)omap_sram_ceil;
 }
 
+/**
+ * omap_sram_patch_va - patch a virtual address into SRAM code
+ * @srcfn: original start address (in DRAM) of function to patch
+ * @srcd: original address (in DRAM) of location to patch
+ * @sramfn: start address (in SRAM) of function to patch
+ * @d: virtual address to insert
+ *
+ * Replace a location in SRAM containing a magic number
+ * (SRAM_VA_MAGIC) with a caller-specified virtual address.  Used to
+ * dynamically patch SRAM code at runtime for multiboot, since some
+ * register addresses change depending on the OMAP chip in use.
+ * Returns 1 upon success, 0 upon failure.
+ */
+int omap_sram_patch_va(void *srcfn, void *srcd, void *sramfn, void __iomem *d)
+{
+       unsigned long sram_addr;
+       long offs;
+
+       offs = (unsigned long)srcd - (unsigned long)srcfn;
+       sram_addr = (unsigned long)sramfn + offs;
+
+#ifdef CONFIG_OMAP_DEBUG_SRAM_PATCH
+       if (offs < 0) {
+               printk(KERN_ERR "sram: patch address 0x%0lx < function start "
+                      "address 0x%0lx\n", (unsigned long)srcd,
+                      (unsigned long)srcfn);
+               WARN_ON(1);
+               return 0;
+       }
+
+       /*
+        * REVISIT: We should probably pass in the function's size also,
+        * so we can verify that the address to patch exists within
+        * the function
+        */
+       if (sram_addr > omap_sram_base + omap_sram_size ||
+           sram_addr < omap_sram_base + SRAM_BOOTLOADER_SZ) {
+               printk(KERN_ERR "sram: invalid patch address 0x%0lx\n",
+                      sram_addr);
+               WARN_ON(1);
+               return 0;
+       }
+
+       if (*(typeof(SRAM_VA_MAGIC) *)sram_addr != SRAM_VA_MAGIC) {
+               printk(KERN_ERR "sram: will not patch address 0x%0lx: "
+                      "no magic\n", sram_addr);
+               WARN_ON(1);
+               return 0;
+       }
+#endif /* CONFIG_OMAP_DEBUG_SRAM_PATCH */
+
+       pr_debug("sram: patching 0x%0lx with 0x%0lx\n", sram_addr,
+                (unsigned long)d);
+
+       *(unsigned long *)sram_addr = (unsigned long)d;
+
+       return 1;
+}
+
+
 static void omap_sram_error(void)
 {
        panic("Uninitialized SRAM function\n");
index bb9bb3fd532f7c88e715db8fe4ddf48f4507844e..5bfbe370e27c5c08697d87964cd6eb5cb9d18c4e 100644 (file)
 #ifndef __ARCH_ARM_OMAP_SRAM_H
 #define __ARCH_ARM_OMAP_SRAM_H
 
+#include <linux/poison.h>    /* for SRAM_VA_MAGIC */
+
 extern void * omap_sram_push(void * start, unsigned long size);
+extern int omap_sram_patch_va(void *srcfn, void *srcd, void *sramfn, void __iomem *d);
 extern void omap_sram_reprogram_clock(u32 dpllctl, u32 ckctl);
 
 extern void omap2_sram_ddr_init(u32 *slow_dll_ctrl, u32 fast_dll_ctrl,
index a9c31be7052c4bcbd4593963ebf32303b338e04f..9384d24f65fe3c2971a89b75cd8c1cf13d541d1e 100644 (file)
 /********** sound/oss/ **********/
 #define OSS_POISON_FREE                0xAB
 
+/*
+ * Used in arch/arm/plat-omap/sram.h to mark SRAM addresses that
+ * will be patched at runtime
+ */
+#define SRAM_VA_MAGIC          0xbadfeed1
+
 #endif