1bca28f8fSTomasz Figa /* 2bca28f8fSTomasz Figa * Copyright (C) 2012 Samsung Electronics. 3bca28f8fSTomasz Figa * Kyungmin Park <kyungmin.park@samsung.com> 4bca28f8fSTomasz Figa * Tomasz Figa <t.figa@samsung.com> 5bca28f8fSTomasz Figa * 6bca28f8fSTomasz Figa * This program is free software,you can redistribute it and/or modify 7bca28f8fSTomasz Figa * it under the terms of the GNU General Public License version 2 as 8bca28f8fSTomasz Figa * published by the Free Software Foundation. 9bca28f8fSTomasz Figa */ 10bca28f8fSTomasz Figa 11bca28f8fSTomasz Figa #include <linux/kernel.h> 12bca28f8fSTomasz Figa #include <linux/io.h> 13bca28f8fSTomasz Figa #include <linux/init.h> 14bca28f8fSTomasz Figa #include <linux/of.h> 15bca28f8fSTomasz Figa #include <linux/of_address.h> 16bca28f8fSTomasz Figa 17bca28f8fSTomasz Figa #include <asm/firmware.h> 18bca28f8fSTomasz Figa 19bca28f8fSTomasz Figa #include <mach/map.h> 20bca28f8fSTomasz Figa 21b3205deaSSachin Kamat #include "common.h" 22bca28f8fSTomasz Figa #include "smc.h" 23bca28f8fSTomasz Figa 24bca28f8fSTomasz Figa static int exynos_do_idle(void) 25bca28f8fSTomasz Figa { 26bca28f8fSTomasz Figa exynos_smc(SMC_CMD_SLEEP, 0, 0, 0); 27bca28f8fSTomasz Figa return 0; 28bca28f8fSTomasz Figa } 29bca28f8fSTomasz Figa 30bca28f8fSTomasz Figa static int exynos_cpu_boot(int cpu) 31bca28f8fSTomasz Figa { 32989ff3fdSKyungmin Park /* 336457158aSChanwoo Choi * Exynos3250 doesn't need to send smc command for secondary CPU boot 346457158aSChanwoo Choi * because Exynos3250 removes WFE in secure mode. 356457158aSChanwoo Choi */ 366457158aSChanwoo Choi if (soc_is_exynos3250()) 376457158aSChanwoo Choi return 0; 386457158aSChanwoo Choi 396457158aSChanwoo Choi /* 40989ff3fdSKyungmin Park * The second parameter of SMC_CMD_CPU1BOOT command means CPU id. 41989ff3fdSKyungmin Park * But, Exynos4212 has only one secondary CPU so second parameter 42989ff3fdSKyungmin Park * isn't used for informing secure firmware about CPU id. 43989ff3fdSKyungmin Park */ 44989ff3fdSKyungmin Park if (soc_is_exynos4212()) 45989ff3fdSKyungmin Park cpu = 0; 46989ff3fdSKyungmin Park 47bca28f8fSTomasz Figa exynos_smc(SMC_CMD_CPU1BOOT, cpu, 0, 0); 48bca28f8fSTomasz Figa return 0; 49bca28f8fSTomasz Figa } 50bca28f8fSTomasz Figa 51bca28f8fSTomasz Figa static int exynos_set_cpu_boot_addr(int cpu, unsigned long boot_addr) 52bca28f8fSTomasz Figa { 53b3205deaSSachin Kamat void __iomem *boot_reg; 54b3205deaSSachin Kamat 55b3205deaSSachin Kamat if (!sysram_ns_base_addr) 56b3205deaSSachin Kamat return -ENODEV; 57b3205deaSSachin Kamat 58fe388facSOlof Johansson boot_reg = sysram_ns_base_addr + 0x1c; 59989ff3fdSKyungmin Park 606457158aSChanwoo Choi if (!soc_is_exynos4212() && !soc_is_exynos3250()) 61989ff3fdSKyungmin Park boot_reg += 4*cpu; 62bca28f8fSTomasz Figa 63bca28f8fSTomasz Figa __raw_writel(boot_addr, boot_reg); 64bca28f8fSTomasz Figa return 0; 65bca28f8fSTomasz Figa } 66bca28f8fSTomasz Figa 67bca28f8fSTomasz Figa static const struct firmware_ops exynos_firmware_ops = { 68bca28f8fSTomasz Figa .do_idle = exynos_do_idle, 69bca28f8fSTomasz Figa .set_cpu_boot_addr = exynos_set_cpu_boot_addr, 70bca28f8fSTomasz Figa .cpu_boot = exynos_cpu_boot, 71bca28f8fSTomasz Figa }; 72bca28f8fSTomasz Figa 73bca28f8fSTomasz Figa void __init exynos_firmware_init(void) 74bca28f8fSTomasz Figa { 75bca28f8fSTomasz Figa struct device_node *nd; 76bca28f8fSTomasz Figa const __be32 *addr; 77bca28f8fSTomasz Figa 78bca28f8fSTomasz Figa nd = of_find_compatible_node(NULL, NULL, 79bca28f8fSTomasz Figa "samsung,secure-firmware"); 80bca28f8fSTomasz Figa if (!nd) 81bca28f8fSTomasz Figa return; 82bca28f8fSTomasz Figa 83bca28f8fSTomasz Figa addr = of_get_address(nd, 0, NULL, NULL); 84bca28f8fSTomasz Figa if (!addr) { 85bca28f8fSTomasz Figa pr_err("%s: No address specified.\n", __func__); 86bca28f8fSTomasz Figa return; 87bca28f8fSTomasz Figa } 88bca28f8fSTomasz Figa 89bca28f8fSTomasz Figa pr_info("Running under secure firmware.\n"); 90bca28f8fSTomasz Figa 91bca28f8fSTomasz Figa register_firmware_ops(&exynos_firmware_ops); 92bca28f8fSTomasz Figa } 93