Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bca28f8f authored by Tomasz Figa's avatar Tomasz Figa Committed by Kukjin Kim
Browse files

ARM: EXYNOS: Add support for Exynos secure firmware



Some Exynos-based boards contain secure firmware and must use firmware
operations to set up some hardware.

This patch adds firmware operations for Exynos secure firmware and a way
for board code and device tree to specify that they must be used.

Example of use:

In board code:

  ...MACHINE_START(...)
          /* ... */
          .init_early   = exynos_firmware_init,
          /* ... */
  MACHINE_END

In device tree:

  / {
          /* ... */

          firmware@0203F000 {
                  compatible = "samsung,secure-firmware";
                  reg = <0x0203F000 0x1000>;
          };

          /* ... */
  };

Signed-off-by: default avatarKyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: default avatarTomasz Figa <t.figa@samsung.com>
Signed-off-by: default avatarKukjin Kim <kgene.kim@samsung.com>
parent a4a18d2b
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -6,3 +6,13 @@ Required root node properties:
    - compatible = should be one or more of the following.
        (a) "samsung,smdkv310" - for Samsung's SMDKV310 eval board.
        (b) "samsung,exynos4210"  - for boards based on Exynos4210 SoC.

Optional:
    - firmware node, specifying presence and type of secure firmware:
        - compatible: only "samsung,secure-firmware" is currently supported
        - reg: address of non-secure SYSRAM used for communication with firmware

	firmware@0203F000 {
		compatible = "samsung,secure-firmware";
		reg = <0x0203F000 0x1000>;
	};
+1 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ obj-$(CONFIG_SMP) += platsmp.o headsmp.o
obj-$(CONFIG_HOTPLUG_CPU)	+= hotplug.o

obj-$(CONFIG_ARCH_EXYNOS)	+= exynos-smc.o
obj-$(CONFIG_ARCH_EXYNOS)	+= firmware.o

plus_sec := $(call as-instr,.arch_extension sec,+sec)
AFLAGS_exynos-smc.o		:=-Wa,-march=armv7-a$(plus_sec)
+2 −0
Original line number Diff line number Diff line
@@ -30,6 +30,8 @@ void exynos_init_late(void);
void exynos4_clk_init(struct device_node *np);
void exynos4_clk_register_fixed_ext(unsigned long, unsigned long);

void exynos_firmware_init(void);

#ifdef CONFIG_PM_GENERIC_DOMAINS
int exynos_pm_late_initcall(void);
#else
+70 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2012 Samsung Electronics.
 * Kyungmin Park <kyungmin.park@samsung.com>
 * Tomasz Figa <t.figa@samsung.com>
 *
 * This program is free software,you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/kernel.h>
#include <linux/io.h>
#include <linux/init.h>
#include <linux/of.h>
#include <linux/of_address.h>

#include <asm/firmware.h>

#include <mach/map.h>

#include "smc.h"

static int exynos_do_idle(void)
{
	exynos_smc(SMC_CMD_SLEEP, 0, 0, 0);
	return 0;
}

static int exynos_cpu_boot(int cpu)
{
	exynos_smc(SMC_CMD_CPU1BOOT, cpu, 0, 0);
	return 0;
}

static int exynos_set_cpu_boot_addr(int cpu, unsigned long boot_addr)
{
	void __iomem *boot_reg = S5P_VA_SYSRAM_NS + 0x1c + 4*cpu;

	__raw_writel(boot_addr, boot_reg);
	return 0;
}

static const struct firmware_ops exynos_firmware_ops = {
	.do_idle		= exynos_do_idle,
	.set_cpu_boot_addr	= exynos_set_cpu_boot_addr,
	.cpu_boot		= exynos_cpu_boot,
};

void __init exynos_firmware_init(void)
{
	if (of_have_populated_dt()) {
		struct device_node *nd;
		const __be32 *addr;

		nd = of_find_compatible_node(NULL, NULL,
						"samsung,secure-firmware");
		if (!nd)
			return;

		addr = of_get_address(nd, 0, NULL, NULL);
		if (!addr) {
			pr_err("%s: No address specified.\n", __func__);
			return;
		}
	}

	pr_info("Running under secure firmware.\n");

	register_firmware_ops(&exynos_firmware_ops);
}
+1 −0
Original line number Diff line number Diff line
@@ -57,6 +57,7 @@ DT_MACHINE_START(EXYNOS4210_DT, "Samsung Exynos4 (Flattened Device Tree)")
	.smp		= smp_ops(exynos_smp_ops),
	.init_irq	= exynos4_init_irq,
	.map_io		= exynos4_dt_map_io,
	.init_early	= exynos_firmware_init,
	.init_machine	= exynos4_dt_machine_init,
	.init_late	= exynos_init_late,
	.init_time	= exynos_init_time,