linux/arch/arm/mach-keystone/keystone.c
<<
>>
Prefs
   1/*
   2 * Keystone2 based boards and SOC related code.
   3 *
   4 * Copyright 2013 Texas Instruments, Inc.
   5 *      Cyril Chemparathy <cyril@ti.com>
   6 *      Santosh Shilimkar <santosh.shillimkar@ti.com>
   7 *
   8 * This program is free software; you can redistribute it and/or modify it
   9 * under the terms and conditions of the GNU General Public License,
  10 * version 2, as published by the Free Software Foundation.
  11 */
  12#include <linux/io.h>
  13#include <linux/of.h>
  14#include <linux/init.h>
  15#include <linux/of_platform.h>
  16#include <linux/of_address.h>
  17#include <linux/memblock.h>
  18
  19#include <asm/setup.h>
  20#include <asm/mach/map.h>
  21#include <asm/mach/arch.h>
  22#include <asm/mach/time.h>
  23#include <asm/smp_plat.h>
  24#include <asm/memory.h>
  25
  26#include "memory.h"
  27
  28#include "keystone.h"
  29
  30static unsigned long keystone_dma_pfn_offset __read_mostly;
  31
  32static int keystone_platform_notifier(struct notifier_block *nb,
  33                                      unsigned long event, void *data)
  34{
  35        struct device *dev = data;
  36
  37        if (event != BUS_NOTIFY_ADD_DEVICE)
  38                return NOTIFY_DONE;
  39
  40        if (!dev)
  41                return NOTIFY_BAD;
  42
  43        if (!dev->of_node) {
  44                dev->dma_pfn_offset = keystone_dma_pfn_offset;
  45                dev_err(dev, "set dma_pfn_offset%08lx\n",
  46                        dev->dma_pfn_offset);
  47        }
  48        return NOTIFY_OK;
  49}
  50
  51static struct notifier_block platform_nb = {
  52        .notifier_call = keystone_platform_notifier,
  53};
  54
  55static void __init keystone_init(void)
  56{
  57        if (PHYS_OFFSET >= KEYSTONE_HIGH_PHYS_START) {
  58                keystone_dma_pfn_offset = PFN_DOWN(KEYSTONE_HIGH_PHYS_START -
  59                                                   KEYSTONE_LOW_PHYS_START);
  60                bus_register_notifier(&platform_bus_type, &platform_nb);
  61        }
  62        keystone_pm_runtime_init();
  63        of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
  64}
  65
  66static phys_addr_t keystone_virt_to_idmap(unsigned long x)
  67{
  68        return (phys_addr_t)(x) - CONFIG_PAGE_OFFSET + KEYSTONE_LOW_PHYS_START;
  69}
  70
  71static long long __init keystone_pv_fixup(void)
  72{
  73        long long offset;
  74        phys_addr_t mem_start, mem_end;
  75
  76        mem_start = memblock_start_of_DRAM();
  77        mem_end = memblock_end_of_DRAM();
  78
  79        /* nothing to do if we are running out of the <32-bit space */
  80        if (mem_start >= KEYSTONE_LOW_PHYS_START &&
  81            mem_end   <= KEYSTONE_LOW_PHYS_END)
  82                return 0;
  83
  84        if (mem_start < KEYSTONE_HIGH_PHYS_START ||
  85            mem_end   > KEYSTONE_HIGH_PHYS_END) {
  86                pr_crit("Invalid address space for memory (%08llx-%08llx)\n",
  87                        (u64)mem_start, (u64)mem_end);
  88                return 0;
  89        }
  90
  91        offset = KEYSTONE_HIGH_PHYS_START - KEYSTONE_LOW_PHYS_START;
  92
  93        /* Populate the arch idmap hook */
  94        arch_virt_to_idmap = keystone_virt_to_idmap;
  95
  96        return offset;
  97}
  98
  99static const char *const keystone_match[] __initconst = {
 100        "ti,keystone",
 101        NULL,
 102};
 103
 104DT_MACHINE_START(KEYSTONE, "Keystone")
 105#if defined(CONFIG_ZONE_DMA) && defined(CONFIG_ARM_LPAE)
 106        .dma_zone_size  = SZ_2G,
 107#endif
 108        .smp            = smp_ops(keystone_smp_ops),
 109        .init_machine   = keystone_init,
 110        .dt_compat      = keystone_match,
 111        .pv_fixup       = keystone_pv_fixup,
 112MACHINE_END
 113