From 72af2fc8504daccd2f8ae2459e3e225e9c2cc512 Mon Sep 17 00:00:00 2001 From: Inderpal Singh Date: Thu, 4 Apr 2013 23:09:19 +0000 Subject: exynos: move tzpc_init to armv7/exynos tzpc_init is common for all exynos5 boards, hence move it to armv7/exynos so that all other boards can use it. Also update the smdk5250 Makefile and config file. Signed-off-by: Inderpal Singh Acked-by: Chander Kashyap Signed-off-by: Minkyu Kang --- board/samsung/smdk5250/Makefile | 1 - board/samsung/smdk5250/setup.h | 25 -------------------- board/samsung/smdk5250/tzpc_init.c | 48 -------------------------------------- 3 files changed, 74 deletions(-) delete mode 100644 board/samsung/smdk5250/tzpc_init.c (limited to 'board') diff --git a/board/samsung/smdk5250/Makefile b/board/samsung/smdk5250/Makefile index 47c6a5a46b..d079f4ce78 100644 --- a/board/samsung/smdk5250/Makefile +++ b/board/samsung/smdk5250/Makefile @@ -28,7 +28,6 @@ SOBJS := lowlevel_init.o COBJS := clock_init.o COBJS += dmc_common.o dmc_init_ddr3.o -COBJS += tzpc_init.o COBJS += smdk5250_spl.o ifndef CONFIG_SPL_BUILD diff --git a/board/samsung/smdk5250/setup.h b/board/samsung/smdk5250/setup.h index 34d8bc31f4..eb91d13109 100644 --- a/board/samsung/smdk5250/setup.h +++ b/board/samsung/smdk5250/setup.h @@ -28,18 +28,6 @@ #include #include -/* TZPC : Register Offsets */ -#define TZPC0_BASE 0x10100000 -#define TZPC1_BASE 0x10110000 -#define TZPC2_BASE 0x10120000 -#define TZPC3_BASE 0x10130000 -#define TZPC4_BASE 0x10140000 -#define TZPC5_BASE 0x10150000 -#define TZPC6_BASE 0x10160000 -#define TZPC7_BASE 0x10170000 -#define TZPC8_BASE 0x10180000 -#define TZPC9_BASE 0x10190000 - /* APLL_CON1 */ #define APLL_CON1_VAL (0x00203800) @@ -458,18 +446,6 @@ /* CLK_GATE_IP_DISP1 */ #define CLK_GATE_DP1_ALLOW (1 << 4) -/* - * TZPC Register Value : - * R0SIZE: 0x0 : Size of secured ram - */ -#define R0SIZE 0x0 - -/* - * TZPC Decode Protection Register Value : - * DECPROTXSET: 0xFF : Set Decode region to non-secure - */ -#define DECPROTXSET 0xFF - #define DDR3PHY_CTRL_PHY_RESET (1 << 0) #define DDR3PHY_CTRL_PHY_RESET_OFF (0 << 0) @@ -590,5 +566,4 @@ void update_reset_dll(struct exynos5_dmc *, enum ddr_mode); void sdelay(unsigned long); void mem_ctrl_init(void); void system_clock_init(void); -void tzpc_init(void); #endif diff --git a/board/samsung/smdk5250/tzpc_init.c b/board/samsung/smdk5250/tzpc_init.c deleted file mode 100644 index c833541fd0..0000000000 --- a/board/samsung/smdk5250/tzpc_init.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Lowlevel setup for SMDK5250 board based on S5PC520 - * - * Copyright (C) 2012 Samsung Electronics - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include -#include"setup.h" - -/* Setting TZPC[TrustZone Protection Controller] */ -void tzpc_init(void) -{ - struct exynos_tzpc *tzpc; - unsigned int addr; - - for (addr = TZPC0_BASE; addr <= TZPC9_BASE; addr += TZPC_BASE_OFFSET) { - tzpc = (struct exynos_tzpc *)addr; - - if (addr == TZPC0_BASE) - writel(R0SIZE, &tzpc->r0size); - - writel(DECPROTXSET, &tzpc->decprot0set); - writel(DECPROTXSET, &tzpc->decprot1set); - - if (addr != TZPC9_BASE) { - writel(DECPROTXSET, &tzpc->decprot2set); - writel(DECPROTXSET, &tzpc->decprot3set); - } - } -} -- cgit v1.2.3 From b5f9756f7f2449cf1b6c3e64dbc40f159f7dcbe2 Mon Sep 17 00:00:00 2001 From: Inderpal Singh Date: Thu, 4 Apr 2013 23:09:20 +0000 Subject: exynos: update tzpc to make it common for exynos4 and exynos5 This requires that cpu_is_exynos4/5 should be made available before tzpc_init. Hence this patch also makes necessary changes to have cpu_info in spl and invokes arch_cpu_init before tzpc_init in low_level_init.S for smdk5250. Signed-off-by: Inderpal Singh Acked-by: Chander Kashyap Signed-off-by: Minkyu Kang --- board/samsung/smdk5250/lowlevel_init.S | 2 ++ 1 file changed, 2 insertions(+) (limited to 'board') diff --git a/board/samsung/smdk5250/lowlevel_init.S b/board/samsung/smdk5250/lowlevel_init.S index bc6cb6f738..edc565ef72 100644 --- a/board/samsung/smdk5250/lowlevel_init.S +++ b/board/samsung/smdk5250/lowlevel_init.S @@ -75,12 +75,14 @@ lowlevel_init: bl mem_ctrl_init 1: + bl arch_cpu_init bl tzpc_init ldmia r13!, {ip,pc} wakeup_reset: bl system_clock_init bl mem_ctrl_init + bl arch_cpu_init bl tzpc_init exit_wakeup: -- cgit v1.2.3 From 8a00061e203f0e0e7e7afdd9c56d56c063055ee5 Mon Sep 17 00:00:00 2001 From: Inderpal Singh Date: Thu, 4 Apr 2013 23:09:21 +0000 Subject: exynos: Update origen and smdkv310 to use common tzpc_init Signed-off-by: Inderpal Singh Acked-by: Chander Kashyap Signed-off-by: Minkyu Kang --- board/samsung/origen/lowlevel_init.S | 44 ++----------------------- board/samsung/origen/origen_setup.h | 25 -------------- board/samsung/smdkv310/lowlevel_init.S | 60 ++-------------------------------- 3 files changed, 4 insertions(+), 125 deletions(-) (limited to 'board') diff --git a/board/samsung/origen/lowlevel_init.S b/board/samsung/origen/lowlevel_init.S index 9daa0da614..be9d418265 100644 --- a/board/samsung/origen/lowlevel_init.S +++ b/board/samsung/origen/lowlevel_init.S @@ -87,12 +87,14 @@ lowlevel_init: 1: /* for UART */ bl uart_asm_init + bl arch_cpu_init bl tzpc_init pop {pc} wakeup_reset: bl system_clock_init bl mem_ctrl_asm_init + bl arch_cpu_init bl tzpc_init exit_wakeup: @@ -353,45 +355,3 @@ uart_asm_init: nop nop -/* Setting TZPC[TrustZone Protection Controller] */ -tzpc_init: - ldr r0, =TZPC0_BASE - mov r1, #R0SIZE - str r1, [r0] - mov r1, #DECPROTXSET - str r1, [r0, #TZPC_DECPROT0SET_OFFSET] - str r1, [r0, #TZPC_DECPROT1SET_OFFSET] - str r1, [r0, #TZPC_DECPROT2SET_OFFSET] - str r1, [r0, #TZPC_DECPROT3SET_OFFSET] - - ldr r0, =TZPC1_BASE - str r1, [r0, #TZPC_DECPROT0SET_OFFSET] - str r1, [r0, #TZPC_DECPROT1SET_OFFSET] - str r1, [r0, #TZPC_DECPROT2SET_OFFSET] - str r1, [r0, #TZPC_DECPROT3SET_OFFSET] - - ldr r0, =TZPC2_BASE - str r1, [r0, #TZPC_DECPROT0SET_OFFSET] - str r1, [r0, #TZPC_DECPROT1SET_OFFSET] - str r1, [r0, #TZPC_DECPROT2SET_OFFSET] - str r1, [r0, #TZPC_DECPROT3SET_OFFSET] - - ldr r0, =TZPC3_BASE - str r1, [r0, #TZPC_DECPROT0SET_OFFSET] - str r1, [r0, #TZPC_DECPROT1SET_OFFSET] - str r1, [r0, #TZPC_DECPROT2SET_OFFSET] - str r1, [r0, #TZPC_DECPROT3SET_OFFSET] - - ldr r0, =TZPC4_BASE - str r1, [r0, #TZPC_DECPROT0SET_OFFSET] - str r1, [r0, #TZPC_DECPROT1SET_OFFSET] - str r1, [r0, #TZPC_DECPROT2SET_OFFSET] - str r1, [r0, #TZPC_DECPROT3SET_OFFSET] - - ldr r0, =TZPC5_BASE - str r1, [r0, #TZPC_DECPROT0SET_OFFSET] - str r1, [r0, #TZPC_DECPROT1SET_OFFSET] - str r1, [r0, #TZPC_DECPROT2SET_OFFSET] - str r1, [r0, #TZPC_DECPROT3SET_OFFSET] - - mov pc, lr diff --git a/board/samsung/origen/origen_setup.h b/board/samsung/origen/origen_setup.h index 930b948505..926a4ccc29 100644 --- a/board/samsung/origen/origen_setup.h +++ b/board/samsung/origen/origen_setup.h @@ -121,19 +121,6 @@ #define UBRDIV_OFFSET 0x28 #define UFRACVAL_OFFSET 0x2C -/* TZPC : Register Offsets */ -#define TZPC0_BASE 0x10110000 -#define TZPC1_BASE 0x10120000 -#define TZPC2_BASE 0x10130000 -#define TZPC3_BASE 0x10140000 -#define TZPC4_BASE 0x10150000 -#define TZPC5_BASE 0x10160000 - -#define TZPC_DECPROT0SET_OFFSET 0x804 -#define TZPC_DECPROT1SET_OFFSET 0x810 -#define TZPC_DECPROT2SET_OFFSET 0x81C -#define TZPC_DECPROT3SET_OFFSET 0x828 - /* CLK_SRC_CPU */ #define MUX_HPM_SEL_MOUTAPLL 0x0 #define MUX_HPM_SEL_SCLKMPLL 0x1 @@ -617,16 +604,4 @@ * UBRFRACVAL = ((((800MHz*10/(115200*16) -10))%10)*16/10) */ #define UFRACVAL_VAL 0x4 - -/* - * TZPC Register Value : - * R0SIZE: 0x0 : Size of secured ram - */ -#define R0SIZE 0x0 - -/* - * TZPC Decode Protection Register Value : - * DECPROTXSET: 0xFF : Set Decode region to non-secure - */ -#define DECPROTXSET 0xFF #endif diff --git a/board/samsung/smdkv310/lowlevel_init.S b/board/samsung/smdkv310/lowlevel_init.S index 7a1ea98aed..31e0e2edaf 100644 --- a/board/samsung/smdkv310/lowlevel_init.S +++ b/board/samsung/smdkv310/lowlevel_init.S @@ -85,12 +85,14 @@ lowlevel_init: 1: /* for UART */ bl uart_asm_init + bl arch_cpu_init bl tzpc_init pop {pc} wakeup_reset: bl system_clock_init bl mem_ctrl_asm_init + bl arch_cpu_init bl tzpc_init exit_wakeup: @@ -410,61 +412,3 @@ uart_asm_init: nop nop nop - -/* Setting TZPC[TrustZone Protection Controller] */ -tzpc_init: - ldr r0, =0x10110000 - mov r1, #0x0 - str r1, [r0] - mov r1, #0xff - str r1, [r0, #0x0804] - str r1, [r0, #0x0810] - str r1, [r0, #0x081C] - str r1, [r0, #0x0828] - - ldr r0, =0x10120000 - mov r1, #0x0 - str r1, [r0] - mov r1, #0xff - str r1, [r0, #0x0804] - str r1, [r0, #0x0810] - str r1, [r0, #0x081C] - str r1, [r0, #0x0828] - - ldr r0, =0x10130000 - mov r1, #0x0 - str r1, [r0] - mov r1, #0xff - str r1, [r0, #0x0804] - str r1, [r0, #0x0810] - str r1, [r0, #0x081C] - str r1, [r0, #0x0828] - - ldr r0, =0x10140000 - mov r1, #0x0 - str r1, [r0] - mov r1, #0xff - str r1, [r0, #0x0804] - str r1, [r0, #0x0810] - str r1, [r0, #0x081C] - str r1, [r0, #0x0828] - - ldr r0, =0x10150000 - mov r1, #0x0 - str r1, [r0] - mov r1, #0xff - str r1, [r0, #0x0804] - str r1, [r0, #0x0810] - str r1, [r0, #0x081C] - str r1, [r0, #0x0828] - - ldr r0, =0x10160000 - mov r1, #0x0 - str r1, [r0] - mov r1, #0xff - str r1, [r0, #0x0804] - str r1, [r0, #0x0810] - str r1, [r0, #0x081C] - str r1, [r0, #0x0828] - - mov pc, lr -- cgit v1.2.3 From 07eb5f9ce70cbed40d0bb2799430a0978e054ef2 Mon Sep 17 00:00:00 2001 From: Amar Date: Sat, 27 Apr 2013 11:42:53 +0530 Subject: EXYNOS5: FDT: Add DWMMC device node data This patch adds DWMMC device node data for exynos5. This patch also adds binding file for DWMMC device node. Signed-off-by: Vivek Gautam Signed-off-by: Amar Acked-by: Jaehoon Chung Acked-by: Simon Glass Signed-off-by: Minkyu Kang --- board/samsung/dts/exynos5250-smdk5250.dts | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'board') diff --git a/board/samsung/dts/exynos5250-smdk5250.dts b/board/samsung/dts/exynos5250-smdk5250.dts index 8da973b305..93375a64b2 100644 --- a/board/samsung/dts/exynos5250-smdk5250.dts +++ b/board/samsung/dts/exynos5250-smdk5250.dts @@ -30,6 +30,10 @@ spi2 = "/spi@12d40000"; spi3 = "/spi@131a0000"; spi4 = "/spi@131b0000"; + mmc0 = "/mmc@12200000"; + mmc1 = "/mmc@12210000"; + mmc2 = "/mmc@12220000"; + mmc3 = "/mmc@12230000"; }; sromc@12250000 { @@ -119,4 +123,24 @@ samsung,ycbcr-coeff = <0>; samsung,color-depth = <1>; }; + + mmc@12200000 { + samsung,bus-width = <8>; + samsung,timing = <1 3 3>; + samsung,removable = <0>; + }; + + mmc@12210000 { + status = "disabled"; + }; + + mmc@12220000 { + samsung,bus-width = <4>; + samsung,timing = <1 2 3>; + samsung,removable = <1>; + }; + + mmc@12230000 { + status = "disabled"; + }; }; -- cgit v1.2.3 From 752f4c4a9c232bba6f27a70db587aebd3dd6bb3f Mon Sep 17 00:00:00 2001 From: Amar Date: Sat, 27 Apr 2013 11:42:57 +0530 Subject: SMDK5250: Initialise and Enable DWMMC, support FDT and non-FDT This patch enables and initialises DWMMC for SMDK5250. Supports both FDT and non-FDT. This patch creates a new file 'exynos5-dt.c' meant for FDT support. exynos5-dt.c: This file shall contain all code which supports FDT. Any addition of FDT support for any module needs to be added in this file. smdk5250.c: This file shall contain the code which supports non-FDT. version. Any addition of non-FDT support for any module needs to be added in this file. May be, the file smdk5250.c can be removed in near future when non-FDT is not required. The Makefile is updated to compile only one of the files exynos5-dt.c / smdk5250.c based on FDT configuration. NOTE: Please note that all additions corresponding to FDT need to be added into the file exynos5-dt.c. At same time if non-FDT support is required then add the corresponding updations into smdk5250.c. Signed-off-by: Amar Signed-off-by: Minkyu Kang --- board/samsung/smdk5250/Makefile | 4 + board/samsung/smdk5250/exynos5-dt.c | 423 ++++++++++++++++++++++++++++++++++++ board/samsung/smdk5250/smdk5250.c | 223 +++++-------------- 3 files changed, 483 insertions(+), 167 deletions(-) create mode 100644 board/samsung/smdk5250/exynos5-dt.c (limited to 'board') diff --git a/board/samsung/smdk5250/Makefile b/board/samsung/smdk5250/Makefile index d079f4ce78..f2c32ee4c8 100644 --- a/board/samsung/smdk5250/Makefile +++ b/board/samsung/smdk5250/Makefile @@ -31,8 +31,12 @@ COBJS += dmc_common.o dmc_init_ddr3.o COBJS += smdk5250_spl.o ifndef CONFIG_SPL_BUILD +ifdef CONFIG_OF_CONTROL +COBJS += exynos5-dt.o +else COBJS += smdk5250.o endif +endif ifdef CONFIG_SPL_BUILD COBJS += spl_boot.o diff --git a/board/samsung/smdk5250/exynos5-dt.c b/board/samsung/smdk5250/exynos5-dt.c new file mode 100644 index 0000000000..813150586f --- /dev/null +++ b/board/samsung/smdk5250/exynos5-dt.c @@ -0,0 +1,423 @@ +/* + * Copyright (C) 2012 Samsung Electronics + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +#if defined CONFIG_EXYNOS_TMU +/* + * Boot Time Thermal Analysis for SoC temperature threshold breach + */ +static void boot_temp_check(void) +{ + int temp; + + switch (tmu_monitor(&temp)) { + /* Status TRIPPED ans WARNING means corresponding threshold breach */ + case TMU_STATUS_TRIPPED: + puts("EXYNOS_TMU: TRIPPING! Device power going down ...\n"); + set_ps_hold_ctrl(); + hang(); + break; + case TMU_STATUS_WARNING: + puts("EXYNOS_TMU: WARNING! Temperature very high\n"); + break; + /* + * TMU_STATUS_INIT means something is wrong with temperature sensing + * and TMU status was changed back from NORMAL to INIT. + */ + case TMU_STATUS_INIT: + default: + debug("EXYNOS_TMU: Unknown TMU state\n"); + } +} +#endif + +#ifdef CONFIG_USB_EHCI_EXYNOS +int board_usb_vbus_init(void) +{ + struct exynos5_gpio_part1 *gpio1 = (struct exynos5_gpio_part1 *) + samsung_get_base_gpio_part1(); + + /* Enable VBUS power switch */ + s5p_gpio_direction_output(&gpio1->x2, 6, 1); + + /* VBUS turn ON time */ + mdelay(3); + + return 0; +} +#endif + +#ifdef CONFIG_SOUND_MAX98095 +static void board_enable_audio_codec(void) +{ + struct exynos5_gpio_part1 *gpio1 = (struct exynos5_gpio_part1 *) + samsung_get_base_gpio_part1(); + + /* Enable MAX98095 Codec */ + s5p_gpio_direction_output(&gpio1->x1, 7, 1); + s5p_gpio_set_pull(&gpio1->x1, 7, GPIO_PULL_NONE); +} +#endif + +int board_init(void) +{ + gd->bd->bi_boot_params = (PHYS_SDRAM_1 + 0x100UL); + +#if defined CONFIG_EXYNOS_TMU + if (tmu_init(gd->fdt_blob) != TMU_STATUS_NORMAL) { + debug("%s: Failed to init TMU\n", __func__); + return -1; + } + boot_temp_check(); +#endif + +#ifdef CONFIG_EXYNOS_SPI + spi_init(); +#endif +#ifdef CONFIG_USB_EHCI_EXYNOS + board_usb_vbus_init(); +#endif +#ifdef CONFIG_SOUND_MAX98095 + board_enable_audio_codec(); +#endif + return 0; +} + +int dram_init(void) +{ + int i; + u32 addr; + + for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { + addr = CONFIG_SYS_SDRAM_BASE + (i * SDRAM_BANK_SIZE); + gd->ram_size += get_ram_size((long *)addr, SDRAM_BANK_SIZE); + } + return 0; +} + +#if defined(CONFIG_POWER) +static int pmic_reg_update(struct pmic *p, int reg, uint regval) +{ + u32 val; + int ret = 0; + + ret = pmic_reg_read(p, reg, &val); + if (ret) { + debug("%s: PMIC %d register read failed\n", __func__, reg); + return -1; + } + val |= regval; + ret = pmic_reg_write(p, reg, val); + if (ret) { + debug("%s: PMIC %d register write failed\n", __func__, reg); + return -1; + } + return 0; +} + +int power_init_board(void) +{ + struct pmic *p; + + set_ps_hold_ctrl(); + + i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); + + if (pmic_init(I2C_PMIC)) + return -1; + + p = pmic_get("MAX77686_PMIC"); + if (!p) + return -ENODEV; + + if (pmic_probe(p)) + return -1; + + if (pmic_reg_update(p, MAX77686_REG_PMIC_32KHZ, MAX77686_32KHCP_EN)) + return -1; + + if (pmic_reg_update(p, MAX77686_REG_PMIC_BBAT, + MAX77686_BBCHOSTEN | MAX77686_BBCVS_3_5V)) + return -1; + + /* VDD_MIF */ + if (pmic_reg_write(p, MAX77686_REG_PMIC_BUCK1OUT, + MAX77686_BUCK1OUT_1V)) { + debug("%s: PMIC %d register write failed\n", __func__, + MAX77686_REG_PMIC_BUCK1OUT); + return -1; + } + + if (pmic_reg_update(p, MAX77686_REG_PMIC_BUCK1CRTL, + MAX77686_BUCK1CTRL_EN)) + return -1; + + /* VDD_ARM */ + if (pmic_reg_write(p, MAX77686_REG_PMIC_BUCK2DVS1, + MAX77686_BUCK2DVS1_1_3V)) { + debug("%s: PMIC %d register write failed\n", __func__, + MAX77686_REG_PMIC_BUCK2DVS1); + return -1; + } + + if (pmic_reg_update(p, MAX77686_REG_PMIC_BUCK2CTRL1, + MAX77686_BUCK2CTRL_ON)) + return -1; + + /* VDD_INT */ + if (pmic_reg_write(p, MAX77686_REG_PMIC_BUCK3DVS1, + MAX77686_BUCK3DVS1_1_0125V)) { + debug("%s: PMIC %d register write failed\n", __func__, + MAX77686_REG_PMIC_BUCK3DVS1); + return -1; + } + + if (pmic_reg_update(p, MAX77686_REG_PMIC_BUCK3CTRL, + MAX77686_BUCK3CTRL_ON)) + return -1; + + /* VDD_G3D */ + if (pmic_reg_write(p, MAX77686_REG_PMIC_BUCK4DVS1, + MAX77686_BUCK4DVS1_1_2V)) { + debug("%s: PMIC %d register write failed\n", __func__, + MAX77686_REG_PMIC_BUCK4DVS1); + return -1; + } + + if (pmic_reg_update(p, MAX77686_REG_PMIC_BUCK4CTRL1, + MAX77686_BUCK3CTRL_ON)) + return -1; + + /* VDD_LDO2 */ + if (pmic_reg_update(p, MAX77686_REG_PMIC_LDO2CTRL1, + MAX77686_LD02CTRL1_1_5V | EN_LDO)) + return -1; + + /* VDD_LDO3 */ + if (pmic_reg_update(p, MAX77686_REG_PMIC_LDO3CTRL1, + MAX77686_LD03CTRL1_1_8V | EN_LDO)) + return -1; + + /* VDD_LDO5 */ + if (pmic_reg_update(p, MAX77686_REG_PMIC_LDO5CTRL1, + MAX77686_LD05CTRL1_1_8V | EN_LDO)) + return -1; + + /* VDD_LDO10 */ + if (pmic_reg_update(p, MAX77686_REG_PMIC_LDO10CTRL1, + MAX77686_LD10CTRL1_1_8V | EN_LDO)) + return -1; + + return 0; +} +#endif + +void dram_init_banksize(void) +{ + int i; + u32 addr, size; + + for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { + addr = CONFIG_SYS_SDRAM_BASE + (i * SDRAM_BANK_SIZE); + size = get_ram_size((long *)addr, SDRAM_BANK_SIZE); + + gd->bd->bi_dram[i].start = addr; + gd->bd->bi_dram[i].size = size; + } +} + +static int decode_sromc(const void *blob, struct fdt_sromc *config) +{ + int err; + int node; + + node = fdtdec_next_compatible(blob, 0, COMPAT_SAMSUNG_EXYNOS5_SROMC); + if (node < 0) { + debug("Could not find SROMC node\n"); + return node; + } + + config->bank = fdtdec_get_int(blob, node, "bank", 0); + config->width = fdtdec_get_int(blob, node, "width", 2); + + err = fdtdec_get_int_array(blob, node, "srom-timing", config->timing, + FDT_SROM_TIMING_COUNT); + if (err < 0) { + debug("Could not decode SROMC configuration Error: %s\n", + fdt_strerror(err)); + return -FDT_ERR_NOTFOUND; + } + return 0; +} + +int board_eth_init(bd_t *bis) +{ +#ifdef CONFIG_SMC911X + u32 smc_bw_conf, smc_bc_conf; + struct fdt_sromc config; + fdt_addr_t base_addr; + int node; + + node = decode_sromc(gd->fdt_blob, &config); + if (node < 0) { + debug("%s: Could not find sromc configuration\n", __func__); + return 0; + } + node = fdtdec_next_compatible(gd->fdt_blob, node, COMPAT_SMSC_LAN9215); + if (node < 0) { + debug("%s: Could not find lan9215 configuration\n", __func__); + return 0; + } + + /* We now have a node, so any problems from now on are errors */ + base_addr = fdtdec_get_addr(gd->fdt_blob, node, "reg"); + if (base_addr == FDT_ADDR_T_NONE) { + debug("%s: Could not find lan9215 address\n", __func__); + return -1; + } + + /* Ethernet needs data bus width of 16 bits */ + if (config.width != 2) { + debug("%s: Unsupported bus width %d\n", __func__, + config.width); + return -1; + } + smc_bw_conf = SROMC_DATA16_WIDTH(config.bank) + | SROMC_BYTE_ENABLE(config.bank); + + smc_bc_conf = SROMC_BC_TACS(config.timing[FDT_SROM_TACS]) | + SROMC_BC_TCOS(config.timing[FDT_SROM_TCOS]) | + SROMC_BC_TACC(config.timing[FDT_SROM_TACC]) | + SROMC_BC_TCOH(config.timing[FDT_SROM_TCOH]) | + SROMC_BC_TAH(config.timing[FDT_SROM_TAH]) | + SROMC_BC_TACP(config.timing[FDT_SROM_TACP]) | + SROMC_BC_PMC(config.timing[FDT_SROM_PMC]); + + /* Select and configure the SROMC bank */ + exynos_pinmux_config(PERIPH_ID_SROMC, config.bank); + s5p_config_sromc(config.bank, smc_bw_conf, smc_bc_conf); + return smc911x_initialize(0, base_addr); +#endif + return 0; +} + +#ifdef CONFIG_DISPLAY_BOARDINFO +int checkboard(void) +{ + const char *board_name; + + board_name = fdt_getprop(gd->fdt_blob, 0, "model", NULL); + if (board_name == NULL) + printf("\nUnknown Board\n"); + else + printf("\nBoard: %s\n", board_name); + + return 0; +} +#endif + +#ifdef CONFIG_GENERIC_MMC +int board_mmc_init(bd_t *bis) +{ + int ret; + /* dwmmc initializattion for available channels */ + ret = exynos_dwmmc_init(gd->fdt_blob); + if (ret) + debug("dwmmc init failed\n"); + + return ret; +} +#endif + +static int board_uart_init(void) +{ + int err, uart_id, ret = 0; + + for (uart_id = PERIPH_ID_UART0; uart_id <= PERIPH_ID_UART3; uart_id++) { + err = exynos_pinmux_config(uart_id, PINMUX_FLAG_NONE); + if (err) { + debug("UART%d not configured\n", + (uart_id - PERIPH_ID_UART0)); + ret |= err; + } + } + return ret; +} + +#ifdef CONFIG_BOARD_EARLY_INIT_F +int board_early_init_f(void) +{ + int err; + err = board_uart_init(); + if (err) { + debug("UART init failed\n"); + return err; + } +#ifdef CONFIG_SYS_I2C_INIT_BOARD + board_i2c_init(gd->fdt_blob); +#endif + return err; +} +#endif + +#ifdef CONFIG_LCD +void exynos_cfg_lcd_gpio(void) +{ + struct exynos5_gpio_part1 *gpio1 = + (struct exynos5_gpio_part1 *)samsung_get_base_gpio_part1(); + + /* For Backlight */ + s5p_gpio_cfg_pin(&gpio1->b2, 0, GPIO_OUTPUT); + s5p_gpio_set_value(&gpio1->b2, 0, 1); + + /* LCD power on */ + s5p_gpio_cfg_pin(&gpio1->x1, 5, GPIO_OUTPUT); + s5p_gpio_set_value(&gpio1->x1, 5, 1); + + /* Set Hotplug detect for DP */ + s5p_gpio_cfg_pin(&gpio1->x0, 7, GPIO_FUNC(0x3)); +} + +void exynos_set_dp_phy(unsigned int onoff) +{ + set_dp_phy_ctrl(onoff); +} +#endif diff --git a/board/samsung/smdk5250/smdk5250.c b/board/samsung/smdk5250/smdk5250.c index 8b09e1de42..276fd41328 100644 --- a/board/samsung/smdk5250/smdk5250.c +++ b/board/samsung/smdk5250/smdk5250.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -37,39 +38,9 @@ #include #include #include -#include DECLARE_GLOBAL_DATA_PTR; -#if defined CONFIG_EXYNOS_TMU -/* - * Boot Time Thermal Analysis for SoC temperature threshold breach - */ -static void boot_temp_check(void) -{ - int temp; - - switch (tmu_monitor(&temp)) { - /* Status TRIPPED ans WARNING means corresponding threshold breach */ - case TMU_STATUS_TRIPPED: - puts("EXYNOS_TMU: TRIPPING! Device power going down ...\n"); - set_ps_hold_ctrl(); - hang(); - break; - case TMU_STATUS_WARNING: - puts("EXYNOS_TMU: WARNING! Temperature very high\n"); - break; - /* - * TMU_STATUS_INIT means something is wrong with temperature sensing - * and TMU status was changed back from NORMAL to INIT. - */ - case TMU_STATUS_INIT: - default: - debug("EXYNOS_TMU: Unknown TMU state\n"); - } -} -#endif - #ifdef CONFIG_USB_EHCI_EXYNOS int board_usb_vbus_init(void) { @@ -102,14 +73,6 @@ int board_init(void) { gd->bd->bi_boot_params = (PHYS_SDRAM_1 + 0x100UL); -#if defined CONFIG_EXYNOS_TMU - if (tmu_init(gd->fdt_blob) != TMU_STATUS_NORMAL) { - debug("%s: Failed to init TMU\n", __func__); - return -1; - } - boot_temp_check(); -#endif - #ifdef CONFIG_EXYNOS_SPI spi_init(); #endif @@ -124,14 +87,13 @@ int board_init(void) int dram_init(void) { - gd->ram_size = get_ram_size((long *)PHYS_SDRAM_1, PHYS_SDRAM_1_SIZE) - + get_ram_size((long *)PHYS_SDRAM_2, PHYS_SDRAM_2_SIZE) - + get_ram_size((long *)PHYS_SDRAM_3, PHYS_SDRAM_3_SIZE) - + get_ram_size((long *)PHYS_SDRAM_4, PHYS_SDRAM_4_SIZE) - + get_ram_size((long *)PHYS_SDRAM_5, PHYS_SDRAM_7_SIZE) - + get_ram_size((long *)PHYS_SDRAM_6, PHYS_SDRAM_7_SIZE) - + get_ram_size((long *)PHYS_SDRAM_7, PHYS_SDRAM_7_SIZE) - + get_ram_size((long *)PHYS_SDRAM_8, PHYS_SDRAM_8_SIZE); + int i; + u32 addr; + + for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { + addr = CONFIG_SYS_SDRAM_BASE + (i * SDRAM_BANK_SIZE); + gd->ram_size += get_ram_size((long *)addr, SDRAM_BANK_SIZE); + } return 0; } @@ -254,57 +216,15 @@ int power_init_board(void) void dram_init_banksize(void) { - gd->bd->bi_dram[0].start = PHYS_SDRAM_1; - gd->bd->bi_dram[0].size = get_ram_size((long *)PHYS_SDRAM_1, - PHYS_SDRAM_1_SIZE); - gd->bd->bi_dram[1].start = PHYS_SDRAM_2; - gd->bd->bi_dram[1].size = get_ram_size((long *)PHYS_SDRAM_2, - PHYS_SDRAM_2_SIZE); - gd->bd->bi_dram[2].start = PHYS_SDRAM_3; - gd->bd->bi_dram[2].size = get_ram_size((long *)PHYS_SDRAM_3, - PHYS_SDRAM_3_SIZE); - gd->bd->bi_dram[3].start = PHYS_SDRAM_4; - gd->bd->bi_dram[3].size = get_ram_size((long *)PHYS_SDRAM_4, - PHYS_SDRAM_4_SIZE); - gd->bd->bi_dram[4].start = PHYS_SDRAM_5; - gd->bd->bi_dram[4].size = get_ram_size((long *)PHYS_SDRAM_5, - PHYS_SDRAM_5_SIZE); - gd->bd->bi_dram[5].start = PHYS_SDRAM_6; - gd->bd->bi_dram[5].size = get_ram_size((long *)PHYS_SDRAM_6, - PHYS_SDRAM_6_SIZE); - gd->bd->bi_dram[6].start = PHYS_SDRAM_7; - gd->bd->bi_dram[6].size = get_ram_size((long *)PHYS_SDRAM_7, - PHYS_SDRAM_7_SIZE); - gd->bd->bi_dram[7].start = PHYS_SDRAM_8; - gd->bd->bi_dram[7].size = get_ram_size((long *)PHYS_SDRAM_8, - PHYS_SDRAM_8_SIZE); -} - -#ifdef CONFIG_OF_CONTROL -static int decode_sromc(const void *blob, struct fdt_sromc *config) -{ - int err; - int node; - - node = fdtdec_next_compatible(blob, 0, COMPAT_SAMSUNG_EXYNOS5_SROMC); - if (node < 0) { - debug("Could not find SROMC node\n"); - return node; - } - - config->bank = fdtdec_get_int(blob, node, "bank", 0); - config->width = fdtdec_get_int(blob, node, "width", 2); - - err = fdtdec_get_int_array(blob, node, "srom-timing", config->timing, - FDT_SROM_TIMING_COUNT); - if (err < 0) { - debug("Could not decode SROMC configuration\n"); - return -FDT_ERR_NOTFOUND; + int i; + u32 addr, size; + for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { + addr = CONFIG_SYS_SDRAM_BASE + (i * SDRAM_BANK_SIZE); + size = get_ram_size((long *)addr, SDRAM_BANK_SIZE); + gd->bd->bi_dram[i].start = addr; + gd->bd->bi_dram[i].size = size; } - - return 0; } -#endif int board_eth_init(bd_t *bis) { @@ -313,27 +233,6 @@ int board_eth_init(bd_t *bis) struct fdt_sromc config; fdt_addr_t base_addr; -#ifdef CONFIG_OF_CONTROL - int node; - - node = decode_sromc(gd->fdt_blob, &config); - if (node < 0) { - debug("%s: Could not find sromc configuration\n", __func__); - return 0; - } - node = fdtdec_next_compatible(gd->fdt_blob, node, COMPAT_SMSC_LAN9215); - if (node < 0) { - debug("%s: Could not find lan9215 configuration\n", __func__); - return 0; - } - - /* We now have a node, so any problems from now on are errors */ - base_addr = fdtdec_get_addr(gd->fdt_blob, node, "reg"); - if (base_addr == FDT_ADDR_T_NONE) { - debug("%s: Could not find lan9215 address\n", __func__); - return -1; - } -#else /* Non-FDT configuration - bank number and timing parameters*/ config.bank = CONFIG_ENV_SROM_BANK; config.width = 2; @@ -346,7 +245,6 @@ int board_eth_init(bd_t *bis) config.timing[FDT_SROM_TACP] = 0x09; config.timing[FDT_SROM_PMC] = 0x01; base_addr = CONFIG_SMC911X_BASE; -#endif /* Ethernet needs data bus width of 16 bits */ if (config.width != 2) { @@ -376,17 +274,7 @@ int board_eth_init(bd_t *bis) #ifdef CONFIG_DISPLAY_BOARDINFO int checkboard(void) { -#ifdef CONFIG_OF_CONTROL - const char *board_name; - - board_name = fdt_getprop(gd->fdt_blob, 0, "model", NULL); - if (board_name == NULL) - printf("\nUnknown Board\n"); - else - printf("\nBoard: %s\n", board_name); -#else printf("\nBoard: SMDK5250\n"); -#endif return 0; } #endif @@ -394,48 +282,54 @@ int checkboard(void) #ifdef CONFIG_GENERIC_MMC int board_mmc_init(bd_t *bis) { - int err; + int err, ret = 0, index, bus_width; + u32 base; err = exynos_pinmux_config(PERIPH_ID_SDMMC0, PINMUX_FLAG_8BIT_MODE); - if (err) { + if (err) debug("SDMMC0 not configured\n"); - return err; - } - - err = s5p_mmc_init(0, 8); - return err; + ret |= err; + + /*EMMC: dwmmc Channel-0 with 8 bit bus width */ + index = 0; + base = samsung_get_base_mmc() + (0x10000 * index); + bus_width = 8; + err = exynos_dwmci_add_port(index, base, bus_width, (u32)NULL); + if (err) + debug("dwmmc Channel-0 init failed\n"); + ret |= err; + + err = exynos_pinmux_config(PERIPH_ID_SDMMC2, PINMUX_FLAG_NONE); + if (err) + debug("SDMMC2 not configured\n"); + ret |= err; + + /*SD: dwmmc Channel-2 with 4 bit bus width */ + index = 2; + base = samsung_get_base_mmc() + (0x10000 * index); + bus_width = 4; + err = exynos_dwmci_add_port(index, base, bus_width, (u32)NULL); + if (err) + debug("dwmmc Channel-2 init failed\n"); + ret |= err; + + return ret; } #endif static int board_uart_init(void) { - int err; - - err = exynos_pinmux_config(PERIPH_ID_UART0, PINMUX_FLAG_NONE); - if (err) { - debug("UART0 not configured\n"); - return err; + int err, uart_id, ret = 0; + + for (uart_id = PERIPH_ID_UART0; uart_id <= PERIPH_ID_UART3; uart_id++) { + err = exynos_pinmux_config(uart_id, PINMUX_FLAG_NONE); + if (err) { + debug("UART%d not configured\n", + (uart_id - PERIPH_ID_UART0)); + ret |= err; + } } - - err = exynos_pinmux_config(PERIPH_ID_UART1, PINMUX_FLAG_NONE); - if (err) { - debug("UART1 not configured\n"); - return err; - } - - err = exynos_pinmux_config(PERIPH_ID_UART2, PINMUX_FLAG_NONE); - if (err) { - debug("UART2 not configured\n"); - return err; - } - - err = exynos_pinmux_config(PERIPH_ID_UART3, PINMUX_FLAG_NONE); - if (err) { - debug("UART3 not configured\n"); - return err; - } - - return 0; + return ret; } #ifdef CONFIG_BOARD_EARLY_INIT_F @@ -448,7 +342,7 @@ int board_early_init_f(void) return err; } #ifdef CONFIG_SYS_I2C_INIT_BOARD - board_i2c_init(gd->fdt_blob); + board_i2c_init(NULL); #endif return err; } @@ -477,7 +371,6 @@ void exynos_set_dp_phy(unsigned int onoff) set_dp_phy_ctrl(onoff); } -#ifndef CONFIG_OF_CONTROL vidinfo_t panel_info = { .vl_freq = 60, .vl_col = 2560, @@ -543,13 +436,9 @@ static struct exynos_dp_platform_data dp_platform_data = { .edp_dev_info = &edp_info, }; -#endif void init_panel_info(vidinfo_t *vid) { -#ifndef CONFIG_OF_CONTROL - vid->rgb_mode = MODE_RGB_P, - + vid->rgb_mode = MODE_RGB_P; exynos_set_dp_platform_data(&dp_platform_data); -#endif } #endif -- cgit v1.2.3 From c748be0d30f3df538a897f8aad6db447c1d9580f Mon Sep 17 00:00:00 2001 From: Amar Date: Sat, 27 Apr 2013 11:42:59 +0530 Subject: SMDK5250: Enable EMMC booting This patch adds support for EMMC booting on SMDK5250. Signed-off-by: Amar Signed-off-by: Minkyu Kang --- board/samsung/smdk5250/clock_init.c | 18 +++++++++++ board/samsung/smdk5250/clock_init.h | 5 +++ board/samsung/smdk5250/spl_boot.c | 64 +++++++++++++++++++++++++++++-------- 3 files changed, 74 insertions(+), 13 deletions(-) (limited to 'board') diff --git a/board/samsung/smdk5250/clock_init.c b/board/samsung/smdk5250/clock_init.c index 5b9e82fdf7..b288e66f0e 100644 --- a/board/samsung/smdk5250/clock_init.c +++ b/board/samsung/smdk5250/clock_init.c @@ -28,10 +28,14 @@ #include #include #include +#include #include "clock_init.h" #include "setup.h" +#define FSYS1_MMC0_DIV_MASK 0xff0f +#define FSYS1_MMC0_DIV_VAL 0x0701 + DECLARE_GLOBAL_DATA_PTR; struct arm_clk_ratios arm_clk_ratios[] = { @@ -664,3 +668,17 @@ void clock_init_dp_clock(void) /* We run DP at 267 Mhz */ setbits_le32(&clk->div_disp1_0, CLK_DIV_DISP1_0_FIMD1); } + +/* + * Set clock divisor value for booting from EMMC. + * Set DWMMC channel-0 clk div to operate mmc0 device at 50MHz. + */ +void emmc_boot_clk_div_set(void) +{ + struct exynos5_clock *clk = (struct exynos5_clock *)EXYNOS5_CLOCK_BASE; + unsigned int div_mmc; + + div_mmc = readl((unsigned int) &clk->div_fsys1) & ~FSYS1_MMC0_DIV_MASK; + div_mmc |= FSYS1_MMC0_DIV_VAL; + writel(div_mmc, (unsigned int) &clk->div_fsys1); +} diff --git a/board/samsung/smdk5250/clock_init.h b/board/samsung/smdk5250/clock_init.h index f751bcb65a..20a1d47e06 100644 --- a/board/samsung/smdk5250/clock_init.h +++ b/board/samsung/smdk5250/clock_init.h @@ -146,4 +146,9 @@ struct mem_timings *clock_get_mem_timings(void); * Initialize clock for the device */ void system_clock_init(void); + +/* + * Set clock divisor value for booting from EMMC. + */ +void emmc_boot_clk_div_set(void); #endif diff --git a/board/samsung/smdk5250/spl_boot.c b/board/samsung/smdk5250/spl_boot.c index c0bcf460f1..98f2286f9e 100644 --- a/board/samsung/smdk5250/spl_boot.c +++ b/board/samsung/smdk5250/spl_boot.c @@ -23,16 +23,44 @@ #include #include +#include +#include +#include + +#include "clock_init.h" + +/* Index into irom ptr table */ +enum index { + MMC_INDEX, + EMMC44_INDEX, + EMMC44_END_INDEX, + SPI_INDEX, + USB_INDEX, +}; + +/* IROM Function Pointers Table */ +u32 irom_ptr_table[] = { + [MMC_INDEX] = 0x02020030, /* iROM Function Pointer-SDMMC boot */ + [EMMC44_INDEX] = 0x02020044, /* iROM Function Pointer-EMMC4.4 boot*/ + [EMMC44_END_INDEX] = 0x02020048,/* iROM Function Pointer + -EMMC4.4 end boot operation */ + [SPI_INDEX] = 0x02020058, /* iROM Function Pointer-SPI boot */ + [USB_INDEX] = 0x02020070, /* iROM Function Pointer-USB boot*/ + }; + enum boot_mode { BOOT_MODE_MMC = 4, BOOT_MODE_SERIAL = 20, + BOOT_MODE_EMMC = 8, /* EMMC4.4 */ /* Boot based on Operating Mode pin settings */ BOOT_MODE_OM = 32, BOOT_MODE_USB, /* Boot using USB download */ }; - typedef u32 (*spi_copy_func_t)(u32 offset, u32 nblock, u32 dst); - typedef u32 (*usb_copy_func_t)(void); +void *get_irom_func(int index) +{ + return (void *)*(u32 *)irom_ptr_table[index]; +} /* * Set/clear program flow prediction and return the previous state. @@ -55,13 +83,15 @@ static int config_branch_prediction(int set_cr_z) */ void copy_uboot_to_ram(void) { - spi_copy_func_t spi_copy; - usb_copy_func_t usb_copy; - int is_cr_z_set; unsigned int sec_boot_check; enum boot_mode bootmode = BOOT_MODE_OM; - u32 (*copy_bl2)(u32, u32, u32); + + u32 (*spi_copy)(u32 offset, u32 nblock, u32 dst); + u32 (*copy_bl2)(u32 offset, u32 nblock, u32 dst); + u32 (*copy_bl2_from_emmc)(u32 nblock, u32 dst); + void (*end_bootop_from_emmc)(void); + u32 (*usb_copy)(void); /* Read iRAM location to check for secondary USB boot mode */ sec_boot_check = readl(EXYNOS_IRAM_SECONDARY_BASE); @@ -73,14 +103,24 @@ void copy_uboot_to_ram(void) switch (bootmode) { case BOOT_MODE_SERIAL: - spi_copy = *(spi_copy_func_t *)EXYNOS_COPY_SPI_FNPTR_ADDR; + spi_copy = get_irom_func(SPI_INDEX); spi_copy(SPI_FLASH_UBOOT_POS, CONFIG_BL2_SIZE, - CONFIG_SYS_TEXT_BASE); + CONFIG_SYS_TEXT_BASE); break; case BOOT_MODE_MMC: - copy_bl2 = (void *) *(u32 *)COPY_BL2_FNPTR_ADDR; + copy_bl2 = get_irom_func(MMC_INDEX); copy_bl2(BL2_START_OFFSET, BL2_SIZE_BLOC_COUNT, - CONFIG_SYS_TEXT_BASE); + CONFIG_SYS_TEXT_BASE); + break; + case BOOT_MODE_EMMC: + /* Set the FSYS1 clock divisor value for EMMC boot */ + emmc_boot_clk_div_set(); + + copy_bl2_from_emmc = get_irom_func(EMMC44_INDEX); + end_bootop_from_emmc = get_irom_func(EMMC44_END_INDEX); + + copy_bl2_from_emmc(BL2_SIZE_BLOC_COUNT, CONFIG_SYS_TEXT_BASE); + end_bootop_from_emmc(); break; case BOOT_MODE_USB: /* @@ -88,8 +128,7 @@ void copy_uboot_to_ram(void) * before copy from USB device to RAM */ is_cr_z_set = config_branch_prediction(0); - usb_copy = *(usb_copy_func_t *) - EXYNOS_COPY_USB_FNPTR_ADDR; + usb_copy = get_irom_func(USB_INDEX); usb_copy(); config_branch_prediction(is_cr_z_set); break; @@ -117,5 +156,4 @@ void board_init_r(gd_t *id, ulong dest_addr) while (1) ; } - void save_boot_params(u32 r0, u32 r1, u32 r2, u32 r3) {} -- cgit v1.2.3