uboot/arch/arm/cpu/armv7/virt-dt.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2013 - ARM Ltd
   3 * Author: Marc Zyngier <marc.zyngier@arm.com>
   4 *
   5 * This program is free software; you can redistribute it and/or modify
   6 * it under the terms of the GNU General Public License version 2 as
   7 * published by the Free Software Foundation.
   8 *
   9 * This program is distributed in the hope that it will be useful,
  10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12 * GNU General Public License for more details.
  13 *
  14 * You should have received a copy of the GNU General Public License
  15 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  16 */
  17
  18#include <common.h>
  19#include <errno.h>
  20#include <stdio_dev.h>
  21#include <linux/ctype.h>
  22#include <linux/types.h>
  23#include <asm/global_data.h>
  24#include <libfdt.h>
  25#include <fdt_support.h>
  26#include <asm/armv7.h>
  27#include <asm/psci.h>
  28
  29static int fdt_psci(void *fdt)
  30{
  31#ifdef CONFIG_ARMV7_PSCI
  32        int nodeoff;
  33        int tmp;
  34
  35        nodeoff = fdt_path_offset(fdt, "/cpus");
  36        if (nodeoff < 0) {
  37                printf("couldn't find /cpus\n");
  38                return nodeoff;
  39        }
  40
  41        /* add 'enable-method = "psci"' to each cpu node */
  42        for (tmp = fdt_first_subnode(fdt, nodeoff);
  43             tmp >= 0;
  44             tmp = fdt_next_subnode(fdt, tmp)) {
  45                const struct fdt_property *prop;
  46                int len;
  47
  48                prop = fdt_get_property(fdt, tmp, "device_type", &len);
  49                if (!prop)
  50                        continue;
  51                if (len < 4)
  52                        continue;
  53                if (strcmp(prop->data, "cpu"))
  54                        continue;
  55
  56                fdt_setprop_string(fdt, tmp, "enable-method", "psci");
  57        }
  58
  59        nodeoff = fdt_path_offset(fdt, "/psci");
  60        if (nodeoff < 0) {
  61                nodeoff = fdt_path_offset(fdt, "/");
  62                if (nodeoff < 0)
  63                        return nodeoff;
  64
  65                nodeoff = fdt_add_subnode(fdt, nodeoff, "psci");
  66                if (nodeoff < 0)
  67                        return nodeoff;
  68        }
  69
  70        tmp = fdt_setprop_string(fdt, nodeoff, "compatible", "arm,psci");
  71        if (tmp)
  72                return tmp;
  73        tmp = fdt_setprop_string(fdt, nodeoff, "method", "smc");
  74        if (tmp)
  75                return tmp;
  76        tmp = fdt_setprop_u32(fdt, nodeoff, "cpu_suspend", ARM_PSCI_FN_CPU_SUSPEND);
  77        if (tmp)
  78                return tmp;
  79        tmp = fdt_setprop_u32(fdt, nodeoff, "cpu_off", ARM_PSCI_FN_CPU_OFF);
  80        if (tmp)
  81                return tmp;
  82        tmp = fdt_setprop_u32(fdt, nodeoff, "cpu_on", ARM_PSCI_FN_CPU_ON);
  83        if (tmp)
  84                return tmp;
  85        tmp = fdt_setprop_u32(fdt, nodeoff, "migrate", ARM_PSCI_FN_MIGRATE);
  86        if (tmp)
  87                return tmp;
  88#endif
  89        return 0;
  90}
  91
  92int armv7_apply_memory_carveout(u64 *start, u64 *size)
  93{
  94#ifdef CONFIG_ARMV7_SECURE_RESERVE_SIZE
  95        if (*start + *size < CONFIG_ARMV7_SECURE_BASE ||
  96            *start >= (u64)CONFIG_ARMV7_SECURE_BASE +
  97                      CONFIG_ARMV7_SECURE_RESERVE_SIZE)
  98                return 0;
  99
 100        /* carveout must be at the beginning or the end of the bank */
 101        if (*start == CONFIG_ARMV7_SECURE_BASE ||
 102            *start + *size == (u64)CONFIG_ARMV7_SECURE_BASE +
 103                              CONFIG_ARMV7_SECURE_RESERVE_SIZE) {
 104                if (*size < CONFIG_ARMV7_SECURE_RESERVE_SIZE) {
 105                        debug("Secure monitor larger than RAM bank!?\n");
 106                        return -EINVAL;
 107                }
 108                *size -= CONFIG_ARMV7_SECURE_RESERVE_SIZE;
 109                if (*start == CONFIG_ARMV7_SECURE_BASE)
 110                        *start += CONFIG_ARMV7_SECURE_RESERVE_SIZE;
 111                return 0;
 112        }
 113        debug("Secure monitor not located at beginning or end of RAM bank\n");
 114        return -EINVAL;
 115#else /* !CONFIG_ARMV7_SECURE_RESERVE_SIZE */
 116        return 0;
 117#endif
 118}
 119
 120int psci_update_dt(void *fdt)
 121{
 122#ifdef CONFIG_ARMV7_NONSEC
 123        if (!armv7_boot_nonsec())
 124                return 0;
 125#endif
 126#ifndef CONFIG_ARMV7_SECURE_BASE
 127        /* secure code lives in RAM, keep it alive */
 128        fdt_add_mem_rsv(fdt, (unsigned long)__secure_start,
 129                        __secure_end - __secure_start);
 130#endif
 131
 132        return fdt_psci(fdt);
 133}
 134