-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge tag 'secure-exynos-for-v3.10' of git://git.kernel.org/pub/scm/l…
…inux/kernel/git/kgene/linux-samsung into next/firmware From Kukjin Kim <kgene.kim@samsung.com>: add support secure firmware for exynos * tag 'secure-exynos-for-v3.10' of git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung: ARM: EXYNOS: Add secure firmware support to secondary CPU bring-up ARM: EXYNOS: Add IO mapping for non-secure SYSRAM. ARM: EXYNOS: Add support for Exynos secure firmware ARM: EXYNOS: Add support for secure monitor calls ARM: Add interface for registering and calling firmware-specific operations Signed-off-by: Arnd Bergmann <arnd@arndb.de>
- Loading branch information
Showing
15 changed files
with
382 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
Interface for registering and calling firmware-specific operations for ARM. | ||
---- | ||
Written by Tomasz Figa <t.figa@samsung.com> | ||
|
||
Some boards are running with secure firmware running in TrustZone secure | ||
world, which changes the way some things have to be initialized. This makes | ||
a need to provide an interface for such platforms to specify available firmware | ||
operations and call them when needed. | ||
|
||
Firmware operations can be specified using struct firmware_ops | ||
|
||
struct firmware_ops { | ||
/* | ||
* Enters CPU idle mode | ||
*/ | ||
int (*do_idle)(void); | ||
/* | ||
* Sets boot address of specified physical CPU | ||
*/ | ||
int (*set_cpu_boot_addr)(int cpu, unsigned long boot_addr); | ||
/* | ||
* Boots specified physical CPU | ||
*/ | ||
int (*cpu_boot)(int cpu); | ||
/* | ||
* Initializes L2 cache | ||
*/ | ||
int (*l2x0_init)(void); | ||
}; | ||
|
||
and then registered with register_firmware_ops function | ||
|
||
void register_firmware_ops(const struct firmware_ops *ops) | ||
|
||
the ops pointer must be non-NULL. | ||
|
||
There is a default, empty set of operations provided, so there is no need to | ||
set anything if platform does not require firmware operations. | ||
|
||
To call a firmware operation, a helper macro is provided | ||
|
||
#define call_firmware_op(op, ...) \ | ||
((firmware_ops->op) ? firmware_ops->op(__VA_ARGS__) : (-ENOSYS)) | ||
|
||
the macro checks if the operation is provided and calls it or otherwise returns | ||
-ENOSYS to signal that given operation is not available (for example, to allow | ||
fallback to legacy operation). | ||
|
||
Example of registering firmware operations: | ||
|
||
/* board file */ | ||
|
||
static int platformX_do_idle(void) | ||
{ | ||
/* tell platformX firmware to enter idle */ | ||
return 0; | ||
} | ||
|
||
static int platformX_cpu_boot(int i) | ||
{ | ||
/* tell platformX firmware to boot CPU i */ | ||
return 0; | ||
} | ||
|
||
static const struct firmware_ops platformX_firmware_ops = { | ||
.do_idle = exynos_do_idle, | ||
.cpu_boot = exynos_cpu_boot, | ||
/* other operations not available on platformX */ | ||
}; | ||
|
||
/* init_early callback of machine descriptor */ | ||
static void __init board_init_early(void) | ||
{ | ||
register_firmware_ops(&platformX_firmware_ops); | ||
} | ||
|
||
Example of using a firmware operation: | ||
|
||
/* some platform code, e.g. SMP initialization */ | ||
|
||
__raw_writel(virt_to_phys(exynos4_secondary_startup), | ||
CPU1_BOOT_REG); | ||
|
||
/* Call Exynos specific smc call */ | ||
if (call_firmware_op(cpu_boot, cpu) == -ENOSYS) | ||
cpu_boot_legacy(...); /* Try legacy way */ | ||
|
||
gic_raise_softirq(cpumask_of(cpu), 1); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
/* | ||
* 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/suspend.h> | ||
|
||
#include <asm/firmware.h> | ||
|
||
static const struct firmware_ops default_firmware_ops; | ||
|
||
const struct firmware_ops *firmware_ops = &default_firmware_ops; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
/* | ||
* 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. | ||
*/ | ||
|
||
#ifndef __ASM_ARM_FIRMWARE_H | ||
#define __ASM_ARM_FIRMWARE_H | ||
|
||
#include <linux/bug.h> | ||
|
||
/* | ||
* struct firmware_ops | ||
* | ||
* A structure to specify available firmware operations. | ||
* | ||
* A filled up structure can be registered with register_firmware_ops(). | ||
*/ | ||
struct firmware_ops { | ||
/* | ||
* Enters CPU idle mode | ||
*/ | ||
int (*do_idle)(void); | ||
/* | ||
* Sets boot address of specified physical CPU | ||
*/ | ||
int (*set_cpu_boot_addr)(int cpu, unsigned long boot_addr); | ||
/* | ||
* Boots specified physical CPU | ||
*/ | ||
int (*cpu_boot)(int cpu); | ||
/* | ||
* Initializes L2 cache | ||
*/ | ||
int (*l2x0_init)(void); | ||
}; | ||
|
||
/* Global pointer for current firmware_ops structure, can't be NULL. */ | ||
extern const struct firmware_ops *firmware_ops; | ||
|
||
/* | ||
* call_firmware_op(op, ...) | ||
* | ||
* Checks if firmware operation is present and calls it, | ||
* otherwise returns -ENOSYS | ||
*/ | ||
#define call_firmware_op(op, ...) \ | ||
((firmware_ops->op) ? firmware_ops->op(__VA_ARGS__) : (-ENOSYS)) | ||
|
||
/* | ||
* register_firmware_ops(ops) | ||
* | ||
* A function to register platform firmware_ops struct. | ||
*/ | ||
static inline void register_firmware_ops(const struct firmware_ops *ops) | ||
{ | ||
BUG_ON(!ops); | ||
|
||
firmware_ops = ops; | ||
} | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
/* | ||
* Copyright (C) 2012 Samsung Electronics. | ||
* | ||
* Copied from omap-smc.S Copyright (C) 2010 Texas Instruments, Inc. | ||
* | ||
* 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/linkage.h> | ||
|
||
/* | ||
* Function signature: void exynos_smc(u32 cmd, u32 arg1, u32 arg2, u32 arg3) | ||
*/ | ||
|
||
ENTRY(exynos_smc) | ||
stmfd sp!, {r4-r11, lr} | ||
dsb | ||
smc #0 | ||
ldmfd sp!, {r4-r11, pc} | ||
ENDPROC(exynos_smc) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
/* | ||
* 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); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.