Merge commit 'AU_LINUX_ANDROID_ICS.04.00.04.00.126' into msm-3.4
AU_LINUX_ANDROID_ICS.04.00.04.00.126 from msm-3.0.
First parent is from google/android-3.4.
* commit 'AU_LINUX_ANDROID_ICS.04.00.04.00.126': (8712 commits)
PRNG: Device tree entry for qrng device.
vidc:1080p: Set video core timeout value for Thumbnail mode
msm: sps: improve the debugging support in SPS driver
board-8064 msm: Overlap secure and non secure video firmware heaps.
msm: clock: Add handoff ops for 7x30 and copper XO clocks
msm_fb: display: Wait for external vsync before DTV IOMMU unmap
msm: Fix ciruclar dependency in debug UART settings
msm: gdsc: Add GDSC regulator driver for msm-copper
defconfig: Enable Mobicore Driver.
mobicore: Add mobicore driver.
mobicore: rename variable to lower case.
mobicore: rename folder.
mobicore: add makefiles
mobicore: initial import of kernel driver
ASoC: msm: Add SLIMBUS_2_RX CPU DAI
board-8064-gpio: Update FUNC for EPM SPI CS
msm_fb: display: Remove chicken bit config during video playback
mmc: msm_sdcc: enable the sanitize capability
msm-fb: display: lm2 writeback support on mpq platfroms
msm_fb: display: Disable LVDS phy & pll during panel off
...
Signed-off-by: Steve Muckle <smuckle@codeaurora.org>
diff --git a/arch/arm/mach-msm/memory.c b/arch/arm/mach-msm/memory.c
new file mode 100644
index 0000000..40845d7
--- /dev/null
+++ b/arch/arm/mach-msm/memory.c
@@ -0,0 +1,441 @@
+/* arch/arm/mach-msm/memory.c
+ *
+ * Copyright (C) 2007 Google, Inc.
+ * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/mm.h>
+#include <linux/mm_types.h>
+#include <linux/bootmem.h>
+#include <linux/module.h>
+#include <linux/memory_alloc.h>
+#include <linux/memblock.h>
+#include <asm/pgtable.h>
+#include <asm/io.h>
+#include <asm/mach/map.h>
+#include <asm/cacheflush.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <mach/msm_memtypes.h>
+#include <linux/hardirq.h>
+#if defined(CONFIG_MSM_NPA_REMOTE)
+#include "npa_remote.h"
+#include <linux/completion.h>
+#include <linux/err.h>
+#endif
+#include <linux/android_pmem.h>
+#include <mach/msm_iomap.h>
+#include <mach/socinfo.h>
+#include <linux/sched.h>
+
+/* fixme */
+#include <asm/tlbflush.h>
+#include <../../mm/mm.h>
+#include <linux/fmem.h>
+
+void *strongly_ordered_page;
+char strongly_ordered_mem[PAGE_SIZE*2-4];
+
+void map_page_strongly_ordered(void)
+{
+#if defined(CONFIG_ARCH_MSM7X27) && !defined(CONFIG_ARCH_MSM7X27A)
+ long unsigned int phys;
+ struct map_desc map;
+
+ if (strongly_ordered_page)
+ return;
+
+ strongly_ordered_page = (void*)PFN_ALIGN((int)&strongly_ordered_mem);
+ phys = __pa(strongly_ordered_page);
+
+ map.pfn = __phys_to_pfn(phys);
+ map.virtual = MSM_STRONGLY_ORDERED_PAGE;
+ map.length = PAGE_SIZE;
+ map.type = MT_DEVICE_STRONGLY_ORDERED;
+ create_mapping(&map);
+
+ printk(KERN_ALERT "Initialized strongly ordered page successfully\n");
+#endif
+}
+EXPORT_SYMBOL(map_page_strongly_ordered);
+
+void write_to_strongly_ordered_memory(void)
+{
+#if defined(CONFIG_ARCH_MSM7X27) && !defined(CONFIG_ARCH_MSM7X27A)
+ if (!strongly_ordered_page) {
+ if (!in_interrupt())
+ map_page_strongly_ordered();
+ else {
+ printk(KERN_ALERT "Cannot map strongly ordered page in "
+ "Interrupt Context\n");
+ /* capture it here before the allocation fails later */
+ BUG();
+ }
+ }
+ *(int *)MSM_STRONGLY_ORDERED_PAGE = 0;
+#endif
+}
+EXPORT_SYMBOL(write_to_strongly_ordered_memory);
+
+/* These cache related routines make the assumption (if outer cache is
+ * available) that the associated physical memory is contiguous.
+ * They will operate on all (L1 and L2 if present) caches.
+ */
+void clean_and_invalidate_caches(unsigned long vstart,
+ unsigned long length, unsigned long pstart)
+{
+ dmac_flush_range((void *)vstart, (void *) (vstart + length));
+ outer_flush_range(pstart, pstart + length);
+}
+
+void clean_caches(unsigned long vstart,
+ unsigned long length, unsigned long pstart)
+{
+ dmac_clean_range((void *)vstart, (void *) (vstart + length));
+ outer_clean_range(pstart, pstart + length);
+}
+
+void invalidate_caches(unsigned long vstart,
+ unsigned long length, unsigned long pstart)
+{
+ dmac_inv_range((void *)vstart, (void *) (vstart + length));
+ outer_inv_range(pstart, pstart + length);
+}
+
+void * __init alloc_bootmem_aligned(unsigned long size, unsigned long alignment)
+{
+ void *unused_addr = NULL;
+ unsigned long addr, tmp_size, unused_size;
+
+ /* Allocate maximum size needed, see where it ends up.
+ * Then free it -- in this path there are no other allocators
+ * so we can depend on getting the same address back
+ * when we allocate a smaller piece that is aligned
+ * at the end (if necessary) and the piece we really want,
+ * then free the unused first piece.
+ */
+
+ tmp_size = size + alignment - PAGE_SIZE;
+ addr = (unsigned long)alloc_bootmem(tmp_size);
+ free_bootmem(__pa(addr), tmp_size);
+
+ unused_size = alignment - (addr % alignment);
+ if (unused_size)
+ unused_addr = alloc_bootmem(unused_size);
+
+ addr = (unsigned long)alloc_bootmem(size);
+ if (unused_size)
+ free_bootmem(__pa(unused_addr), unused_size);
+
+ return (void *)addr;
+}
+
+int (*change_memory_power)(u64, u64, int);
+
+int platform_physical_remove_pages(u64 start, u64 size)
+{
+ if (!change_memory_power)
+ return 0;
+ return change_memory_power(start, size, MEMORY_DEEP_POWERDOWN);
+}
+
+int platform_physical_active_pages(u64 start, u64 size)
+{
+ if (!change_memory_power)
+ return 0;
+ return change_memory_power(start, size, MEMORY_ACTIVE);
+}
+
+int platform_physical_low_power_pages(u64 start, u64 size)
+{
+ if (!change_memory_power)
+ return 0;
+ return change_memory_power(start, size, MEMORY_SELF_REFRESH);
+}
+
+char *memtype_name[] = {
+ "SMI_KERNEL",
+ "SMI",
+ "EBI0",
+ "EBI1"
+};
+
+struct reserve_info *reserve_info;
+
+static unsigned long stable_size(struct membank *mb,
+ unsigned long unstable_limit)
+{
+ unsigned long upper_limit = mb->start + mb->size;
+
+ if (!unstable_limit)
+ return mb->size;
+
+ /* Check for 32 bit roll-over */
+ if (upper_limit >= mb->start) {
+ /* If we didn't roll over we can safely make the check below */
+ if (upper_limit <= unstable_limit)
+ return mb->size;
+ }
+
+ if (mb->start >= unstable_limit)
+ return 0;
+ return unstable_limit - mb->start;
+}
+
+/* stable size of all memory banks contiguous to and below this one */
+static unsigned long total_stable_size(unsigned long bank)
+{
+ int i;
+ struct membank *mb = &meminfo.bank[bank];
+ int memtype = reserve_info->paddr_to_memtype(mb->start);
+ unsigned long size;
+
+ size = stable_size(mb, reserve_info->low_unstable_address);
+ for (i = bank - 1, mb = &meminfo.bank[bank - 1]; i >= 0; i--, mb--) {
+ if (mb->start + mb->size != (mb + 1)->start)
+ break;
+ if (reserve_info->paddr_to_memtype(mb->start) != memtype)
+ break;
+ size += stable_size(mb, reserve_info->low_unstable_address);
+ }
+ return size;
+}
+
+static void __init calculate_reserve_limits(void)
+{
+ int i;
+ struct membank *mb;
+ int memtype;
+ struct memtype_reserve *mt;
+ unsigned long size;
+
+ for (i = 0, mb = &meminfo.bank[0]; i < meminfo.nr_banks; i++, mb++) {
+ memtype = reserve_info->paddr_to_memtype(mb->start);
+ if (memtype == MEMTYPE_NONE) {
+ pr_warning("unknown memory type for bank at %lx\n",
+ (long unsigned int)mb->start);
+ continue;
+ }
+ mt = &reserve_info->memtype_reserve_table[memtype];
+ size = total_stable_size(i);
+ mt->limit = max(mt->limit, size);
+ }
+}
+
+static void __init adjust_reserve_sizes(void)
+{
+ int i;
+ struct memtype_reserve *mt;
+
+ mt = &reserve_info->memtype_reserve_table[0];
+ for (i = 0; i < MEMTYPE_MAX; i++, mt++) {
+ if (mt->flags & MEMTYPE_FLAGS_1M_ALIGN)
+ mt->size = (mt->size + SECTION_SIZE - 1) & SECTION_MASK;
+ if (mt->size > mt->limit) {
+ pr_warning("%lx size for %s too large, setting to %lx\n",
+ mt->size, memtype_name[i], mt->limit);
+ mt->size = mt->limit;
+ }
+ }
+}
+
+static void __init reserve_memory_for_mempools(void)
+{
+ int i, memtype, membank_type;
+ struct memtype_reserve *mt;
+ struct membank *mb;
+ int ret;
+ unsigned long size;
+
+ mt = &reserve_info->memtype_reserve_table[0];
+ for (memtype = 0; memtype < MEMTYPE_MAX; memtype++, mt++) {
+ if (mt->flags & MEMTYPE_FLAGS_FIXED || !mt->size)
+ continue;
+
+ /* We know we will find memory bank(s) of the proper size
+ * as we have limited the size of the memory pool for
+ * each memory type to the largest total size of the memory
+ * banks which are contiguous and of the correct memory type.
+ * Choose the memory bank with the highest physical
+ * address which is large enough, so that we will not
+ * take memory from the lowest memory bank which the kernel
+ * is in (and cause boot problems) and so that we might
+ * be able to steal memory that would otherwise become
+ * highmem. However, do not use unstable memory.
+ */
+ for (i = meminfo.nr_banks - 1; i >= 0; i--) {
+ mb = &meminfo.bank[i];
+ membank_type =
+ reserve_info->paddr_to_memtype(mb->start);
+ if (memtype != membank_type)
+ continue;
+ size = total_stable_size(i);
+ if (size >= mt->size) {
+ size = stable_size(mb,
+ reserve_info->low_unstable_address);
+ if (!size)
+ continue;
+ /* mt->size may be larger than size, all this
+ * means is that we are carving the memory pool
+ * out of multiple contiguous memory banks.
+ */
+ mt->start = mb->start + (size - mt->size);
+ ret = memblock_remove(mt->start, mt->size);
+ BUG_ON(ret);
+ break;
+ }
+ }
+ }
+}
+
+static void __init initialize_mempools(void)
+{
+ struct mem_pool *mpool;
+ int memtype;
+ struct memtype_reserve *mt;
+
+ mt = &reserve_info->memtype_reserve_table[0];
+ for (memtype = 0; memtype < MEMTYPE_MAX; memtype++, mt++) {
+ if (!mt->size)
+ continue;
+ mpool = initialize_memory_pool(mt->start, mt->size, memtype);
+ if (!mpool)
+ pr_warning("failed to create %s mempool\n",
+ memtype_name[memtype]);
+ }
+}
+
+#define MAX_FIXED_AREA_SIZE 0x11000000
+
+void __init msm_reserve(void)
+{
+ unsigned long msm_fixed_area_size;
+ unsigned long msm_fixed_area_start;
+
+ memory_pool_init();
+ reserve_info->calculate_reserve_sizes();
+
+ msm_fixed_area_size = reserve_info->fixed_area_size;
+ msm_fixed_area_start = reserve_info->fixed_area_start;
+ if (msm_fixed_area_size)
+ if (msm_fixed_area_start > reserve_info->low_unstable_address
+ - MAX_FIXED_AREA_SIZE)
+ reserve_info->low_unstable_address =
+ msm_fixed_area_start;
+
+ calculate_reserve_limits();
+ adjust_reserve_sizes();
+ reserve_memory_for_mempools();
+ initialize_mempools();
+}
+
+static int get_ebi_memtype(void)
+{
+ /* on 7x30 and 8x55 "EBI1 kernel PMEM" is really on EBI0 */
+ if (cpu_is_msm7x30() || cpu_is_msm8x55())
+ return MEMTYPE_EBI0;
+ return MEMTYPE_EBI1;
+}
+
+void *allocate_contiguous_ebi(unsigned long size,
+ unsigned long align, int cached)
+{
+ return allocate_contiguous_memory(size, get_ebi_memtype(),
+ align, cached);
+}
+EXPORT_SYMBOL(allocate_contiguous_ebi);
+
+unsigned long allocate_contiguous_ebi_nomap(unsigned long size,
+ unsigned long align)
+{
+ return _allocate_contiguous_memory_nomap(size, get_ebi_memtype(),
+ align, __builtin_return_address(0));
+}
+EXPORT_SYMBOL(allocate_contiguous_ebi_nomap);
+
+/* emulation of the deprecated pmem_kalloc and pmem_kfree */
+int32_t pmem_kalloc(const size_t size, const uint32_t flags)
+{
+ int pmem_memtype;
+ int memtype = MEMTYPE_NONE;
+ int ebi1_memtype = MEMTYPE_EBI1;
+ unsigned int align;
+ int32_t paddr;
+
+ switch (flags & PMEM_ALIGNMENT_MASK) {
+ case PMEM_ALIGNMENT_4K:
+ align = SZ_4K;
+ break;
+ case PMEM_ALIGNMENT_1M:
+ align = SZ_1M;
+ break;
+ default:
+ pr_alert("Invalid alignment %x\n",
+ (flags & PMEM_ALIGNMENT_MASK));
+ return -EINVAL;
+ }
+
+ /* on 7x30 and 8x55 "EBI1 kernel PMEM" is really on EBI0 */
+ if (cpu_is_msm7x30() || cpu_is_msm8x55())
+ ebi1_memtype = MEMTYPE_EBI0;
+
+ pmem_memtype = flags & PMEM_MEMTYPE_MASK;
+ if (pmem_memtype == PMEM_MEMTYPE_EBI1)
+ memtype = ebi1_memtype;
+ else if (pmem_memtype == PMEM_MEMTYPE_SMI)
+ memtype = MEMTYPE_SMI_KERNEL;
+ else {
+ pr_alert("Invalid memory type %x\n",
+ flags & PMEM_MEMTYPE_MASK);
+ return -EINVAL;
+ }
+
+ paddr = _allocate_contiguous_memory_nomap(size, memtype, align,
+ __builtin_return_address(0));
+
+ if (!paddr && pmem_memtype == PMEM_MEMTYPE_SMI)
+ paddr = _allocate_contiguous_memory_nomap(size,
+ ebi1_memtype, align, __builtin_return_address(0));
+
+ if (!paddr)
+ return -ENOMEM;
+ return paddr;
+}
+EXPORT_SYMBOL(pmem_kalloc);
+
+int pmem_kfree(const int32_t physaddr)
+{
+ free_contiguous_memory_by_paddr(physaddr);
+
+ return 0;
+}
+EXPORT_SYMBOL(pmem_kfree);
+
+unsigned int msm_ttbr0;
+
+void store_ttbr0(void)
+{
+ /* Store TTBR0 for post-mortem debugging purposes. */
+ asm("mrc p15, 0, %0, c2, c0, 0\n"
+ : "=r" (msm_ttbr0));
+}
+
+int request_fmem_c_region(void *unused)
+{
+ return fmem_set_state(FMEM_C_STATE);
+}
+
+int release_fmem_c_region(void *unused)
+{
+ return fmem_set_state(FMEM_T_STATE);
+}