diff options
42 files changed, 1358 insertions, 469 deletions
| diff --git a/arch/arm/cpu/armv7/exynos/Makefile b/arch/arm/cpu/armv7/exynos/Makefile index 9119961d9..b2f9152e1 100644 --- a/arch/arm/cpu/armv7/exynos/Makefile +++ b/arch/arm/cpu/armv7/exynos/Makefile @@ -22,7 +22,7 @@ include $(TOPDIR)/config.mk  LIB	= $(obj)lib$(SOC).o -COBJS	+= clock.o power.o soc.o system.o pinmux.o +COBJS	+= clock.o power.o soc.o system.o pinmux.o tzpc.o  SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c)  OBJS	:= $(addprefix $(obj),$(COBJS) $(SOBJS)) diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c index 223660aab..e1c42462e 100644 --- a/arch/arm/cpu/armv7/exynos/clock.c +++ b/arch/arm/cpu/armv7/exynos/clock.c @@ -116,10 +116,8 @@ static int exynos_get_pll_clk(int pllreg, unsigned int r, unsigned int k)  		/* FOUT = (MDIV + K / 1024) * FIN / (PDIV * 2^SDIV) */  		fout = (m + k / 1024) * (freq / (p * (1 << s)));  	} else { -		if (s < 1) -			s = 1; -		/* FOUT = MDIV * FIN / (PDIV * 2^(SDIV - 1)) */ -		fout = m * (freq / (p * (1 << (s - 1)))); +		/* FOUT = MDIV * FIN / (PDIV * 2^SDIV) */ +		fout = m * (freq / (p * (1 << s)));  	}  	return fout; @@ -613,7 +611,7 @@ static unsigned long exynos4_get_mmc_clk(int dev_index)  		(struct exynos4_clock *)samsung_get_base_clock();  	unsigned long uclk, sclk;  	unsigned int sel, ratio, pre_ratio; -	int shift; +	int shift = 0;  	sel = readl(&clk->src_fsys);  	sel = (sel >> (dev_index << 2)) & 0xf; @@ -662,7 +660,7 @@ static unsigned long exynos5_get_mmc_clk(int dev_index)  		(struct exynos5_clock *)samsung_get_base_clock();  	unsigned long uclk, sclk;  	unsigned int sel, ratio, pre_ratio; -	int shift; +	int shift = 0;  	sel = readl(&clk->src_fsys);  	sel = (sel >> (dev_index << 2)) & 0xf; diff --git a/board/samsung/smdk5250/tzpc_init.c b/arch/arm/cpu/armv7/exynos/tzpc.c index c833541fd..f5e8e9c47 100644 --- a/board/samsung/smdk5250/tzpc_init.c +++ b/arch/arm/cpu/armv7/exynos/tzpc.c @@ -22,27 +22,36 @@   * MA 02111-1307 USA   */ +#include <common.h>  #include <asm/arch/tzpc.h> -#include"setup.h" +#include <asm/io.h>  /* Setting TZPC[TrustZone Protection Controller] */  void tzpc_init(void)  {  	struct exynos_tzpc *tzpc; -	unsigned int addr; +	unsigned int addr, start = 0, end = 0; -	for (addr = TZPC0_BASE; addr <= TZPC9_BASE; addr += TZPC_BASE_OFFSET) { +	start = samsung_get_base_tzpc(); + +	if (cpu_is_exynos5()) +		end = start + ((EXYNOS5_NR_TZPC_BANKS - 1) * TZPC_BASE_OFFSET); +	else if (cpu_is_exynos4()) +		end = start + ((EXYNOS4_NR_TZPC_BANKS - 1) * TZPC_BASE_OFFSET); + +	for (addr = start; addr <= end; addr += TZPC_BASE_OFFSET) {  		tzpc = (struct exynos_tzpc *)addr; -		if (addr == TZPC0_BASE) +		if (addr == start)  			writel(R0SIZE, &tzpc->r0size);  		writel(DECPROTXSET, &tzpc->decprot0set);  		writel(DECPROTXSET, &tzpc->decprot1set); -		if (addr != TZPC9_BASE) { -			writel(DECPROTXSET, &tzpc->decprot2set); -			writel(DECPROTXSET, &tzpc->decprot3set); -		} +		if (cpu_is_exynos5() && (addr == end)) +			break; + +		writel(DECPROTXSET, &tzpc->decprot2set); +		writel(DECPROTXSET, &tzpc->decprot3set);  	}  } diff --git a/arch/arm/cpu/armv7/s5p-common/Makefile b/arch/arm/cpu/armv7/s5p-common/Makefile index 17053995b..0c38bd0d2 100644 --- a/arch/arm/cpu/armv7/s5p-common/Makefile +++ b/arch/arm/cpu/armv7/s5p-common/Makefile @@ -26,9 +26,11 @@ include $(TOPDIR)/config.mk  LIB	= $(obj)libs5p-common.o  COBJS-y		+= cpu_info.o +ifndef CONFIG_SPL_BUILD  COBJS-y		+= timer.o  COBJS-y		+= sromc.o  COBJS-$(CONFIG_PWM)	+= pwm.o +endif  SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c)  OBJS	:= $(addprefix $(obj),$(COBJS-y) $(SOBJS)) diff --git a/arch/arm/dts/exynos5250.dtsi b/arch/arm/dts/exynos5250.dtsi index df4b231cf..cee4fe82c 100644 --- a/arch/arm/dts/exynos5250.dtsi +++ b/arch/arm/dts/exynos5250.dtsi @@ -169,4 +169,37 @@  		#address-cells = <1>;  		#size-cells = <1>;  	}; + +	mmc@12200000 { +		#address-cells = <1>; +		#size-cells = <0>; +		compatible = "samsung,exynos5250-dwmmc"; +		reg = <0x12200000 0x1000>; +		interrupts = <0 75 0>; +	}; + +	mmc@12210000 { +		#address-cells = <1>; +		#size-cells = <0>; +		compatible = "samsung,exynos5250-dwmmc"; +		reg = <0x12210000 0x1000>; +		interrupts = <0 76 0>; +	}; + +	mmc@12220000 { +		#address-cells = <1>; +		#size-cells = <0>; +		compatible = "samsung,exynos5250-dwmmc"; +		reg = <0x12220000 0x1000>; +		interrupts = <0 77 0>; +	}; + +	mmc@12230000 { +		#address-cells = <1>; +		#size-cells = <0>; +		compatible = "samsung,exynos5250-dwmmc"; +		reg = <0x12230000 0x1000>; +		interrupts = <0 78 0>; +	}; +  }; diff --git a/arch/arm/include/asm/arch-exynos/cpu.h b/arch/arm/include/asm/arch-exynos/cpu.h index f76e4897e..36b98c83e 100644 --- a/arch/arm/include/asm/arch-exynos/cpu.h +++ b/arch/arm/include/asm/arch-exynos/cpu.h @@ -38,6 +38,7 @@  #define EXYNOS4_CLOCK_BASE		0x10030000  #define EXYNOS4_SYSTIMER_BASE		0x10050000  #define EXYNOS4_WATCHDOG_BASE		0x10060000 +#define EXYNOS4_TZPC_BASE		0x10110000  #define EXYNOS4_MIU_BASE		0x10600000  #define EXYNOS4_DMC0_BASE		0x10400000  #define EXYNOS4_DMC1_BASE		0x10410000 @@ -74,6 +75,7 @@  #define EXYNOS4X12_CLOCK_BASE		0x10030000  #define EXYNOS4X12_SYSTIMER_BASE	0x10050000  #define EXYNOS4X12_WATCHDOG_BASE	0x10060000 +#define EXYNOS4X12_TZPC_BASE		0x10110000  #define EXYNOS4X12_DMC0_BASE		0x10600000  #define EXYNOS4X12_DMC1_BASE		0x10610000  #define EXYNOS4X12_GPIO_PART4_BASE	0x106E0000 @@ -107,6 +109,7 @@  #define EXYNOS5_POWER_BASE		0x10040000  #define EXYNOS5_SWRESET			0x10040400  #define EXYNOS5_SYSREG_BASE		0x10050000 +#define EXYNOS5_TZPC_BASE		0x10100000  #define EXYNOS5_WATCHDOG_BASE		0x101D0000  #define EXYNOS5_ACE_SFR_BASE            0x10830000  #define EXYNOS5_DMC_PHY0_BASE		0x10C00000 @@ -233,6 +236,7 @@ SAMSUNG_BASE(watchdog, WATCHDOG_BASE)  SAMSUNG_BASE(power, POWER_BASE)  SAMSUNG_BASE(spi, SPI_BASE)  SAMSUNG_BASE(spi_isp, SPI_ISP_BASE) +SAMSUNG_BASE(tzpc, TZPC_BASE)  #endif  #endif	/* _EXYNOS4_CPU_H */ diff --git a/arch/arm/include/asm/arch-exynos/dwmmc.h b/arch/arm/include/asm/arch-exynos/dwmmc.h index 8acdf9b72..3b147b86e 100644 --- a/arch/arm/include/asm/arch-exynos/dwmmc.h +++ b/arch/arm/include/asm/arch-exynos/dwmmc.h @@ -27,10 +27,7 @@  #define DWMCI_SET_DRV_CLK(x)	((x) << 16)  #define DWMCI_SET_DIV_RATIO(x)	((x) << 24) -int exynos_dwmci_init(u32 regbase, int bus_width, int index); - -static inline unsigned int exynos_dwmmc_init(int index, int bus_width) -{ -	unsigned int base = samsung_get_base_mmc() + (0x10000 * index); -	return exynos_dwmci_init(base, bus_width, index); -} +#ifdef CONFIG_OF_CONTROL +int exynos_dwmmc_init(const void *blob); +#endif +int exynos_dwmci_add_port(int index, u32 regbase, int bus_width, u32 clksel); diff --git a/arch/arm/include/asm/arch-exynos/tmu.h b/arch/arm/include/asm/arch-exynos/tmu.h index 7e0158efb..cad35694f 100644 --- a/arch/arm/include/asm/arch-exynos/tmu.h +++ b/arch/arm/include/asm/arch-exynos/tmu.h @@ -21,38 +21,30 @@  #define __ASM_ARCH_TMU_H  struct exynos5_tmu_reg { -	unsigned triminfo; -	unsigned rsvd1; -	unsigned rsvd2; -	unsigned rsvd3; -	unsigned rsvd4; -	unsigned triminfo_control; -	unsigned rsvd5; -	unsigned rsvd6; -	unsigned tmu_control; -	unsigned rsvd7; -	unsigned tmu_status; -	unsigned sampling_internal; -	unsigned counter_value0; -	unsigned counter_value1; -	unsigned rsvd8; -	unsigned rsvd9; -	unsigned current_temp; -	unsigned rsvd10; -	unsigned rsvd11; -	unsigned rsvd12; -	unsigned threshold_temp_rise; -	unsigned threshold_temp_fall; -	unsigned rsvd13; -	unsigned rsvd14; -	unsigned past_temp3_0; -	unsigned past_temp7_4; -	unsigned past_temp11_8; -	unsigned past_temp15_12; -	unsigned inten; -	unsigned intstat; -	unsigned intclear; -	unsigned rsvd15; -	unsigned emul_con; +	u32 triminfo; +	u32 rsvd1[4]; +	u32 triminfo_control; +	u32 rsvd5[2]; +	u32 tmu_control; +	u32 rsvd7; +	u32 tmu_status; +	u32 sampling_internal; +	u32 counter_value0; +	u32 counter_value1; +	u32 rsvd8[2]; +	u32 current_temp; +	u32 rsvd10[3]; +	u32 threshold_temp_rise; +	u32 threshold_temp_fall; +	u32 rsvd13[2]; +	u32 past_temp3_0; +	u32 past_temp7_4; +	u32 past_temp11_8; +	u32 past_temp15_12; +	u32 inten; +	u32 intstat; +	u32 intclear; +	u32 rsvd15; +	u32 emul_con;  };  #endif /* __ASM_ARCH_TMU_H */ diff --git a/arch/arm/include/asm/arch-exynos/tzpc.h b/arch/arm/include/asm/arch-exynos/tzpc.h index c5eb4b1cc..4d9c3a32f 100644 --- a/arch/arm/include/asm/arch-exynos/tzpc.h +++ b/arch/arm/include/asm/arch-exynos/tzpc.h @@ -47,6 +47,26 @@ struct exynos_tzpc {  	unsigned int pcellid2;  	unsigned int pcellid3;  }; + +#define EXYNOS4_NR_TZPC_BANKS		6 +#define EXYNOS5_NR_TZPC_BANKS		10 + +/* TZPC : Register Offsets */ +#define TZPC_BASE_OFFSET		0x10000 + +/* + * 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 +void tzpc_init(void); +  #endif  #endif diff --git a/board/samsung/dts/exynos5250-smdk5250.dts b/board/samsung/dts/exynos5250-smdk5250.dts index 8da973b30..93375a64b 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"; +	};  }; diff --git a/board/samsung/origen/lowlevel_init.S b/board/samsung/origen/lowlevel_init.S index 9daa0da61..be9d41826 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 930b94850..926a4ccc2 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/smdk5250/Makefile b/board/samsung/smdk5250/Makefile index 47c6a5a46..f2c32ee4c 100644 --- a/board/samsung/smdk5250/Makefile +++ b/board/samsung/smdk5250/Makefile @@ -28,12 +28,15 @@ 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 +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/clock_init.c b/board/samsung/smdk5250/clock_init.c index 5b9e82fdf..b288e66f0 100644 --- a/board/samsung/smdk5250/clock_init.c +++ b/board/samsung/smdk5250/clock_init.c @@ -28,10 +28,14 @@  #include <asm/arch/clk.h>  #include <asm/arch/clock.h>  #include <asm/arch/spl.h> +#include <asm/arch/dwmmc.h>  #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 f751bcb65..20a1d47e0 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/exynos5-dt.c b/board/samsung/smdk5250/exynos5-dt.c new file mode 100644 index 000000000..813150586 --- /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 <common.h> +#include <fdtdec.h> +#include <asm/io.h> +#include <errno.h> +#include <i2c.h> +#include <netdev.h> +#include <spi.h> +#include <asm/arch/cpu.h> +#include <asm/arch/dwmmc.h> +#include <asm/arch/gpio.h> +#include <asm/arch/mmc.h> +#include <asm/arch/pinmux.h> +#include <asm/arch/power.h> +#include <asm/arch/sromc.h> +#include <power/pmic.h> +#include <power/max77686_pmic.h> +#include <tmu.h> + +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/lowlevel_init.S b/board/samsung/smdk5250/lowlevel_init.S index bc6cb6f73..edc565ef7 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: diff --git a/board/samsung/smdk5250/setup.h b/board/samsung/smdk5250/setup.h index 34d8bc31f..eb91d1310 100644 --- a/board/samsung/smdk5250/setup.h +++ b/board/samsung/smdk5250/setup.h @@ -28,18 +28,6 @@  #include <config.h>  #include <asm/arch/dmc.h> -/* 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/smdk5250.c b/board/samsung/smdk5250/smdk5250.c index 8b09e1de4..276fd4132 100644 --- a/board/samsung/smdk5250/smdk5250.c +++ b/board/samsung/smdk5250/smdk5250.c @@ -29,6 +29,7 @@  #include <netdev.h>  #include <spi.h>  #include <asm/arch/cpu.h> +#include <asm/arch/dwmmc.h>  #include <asm/arch/gpio.h>  #include <asm/arch/mmc.h>  #include <asm/arch/pinmux.h> @@ -37,39 +38,9 @@  #include <asm/arch/dp_info.h>  #include <power/pmic.h>  #include <power/max77686_pmic.h> -#include <tmu.h>  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; -	} +	ret |= err; -	err = s5p_mmc_init(0, 8); -	return 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; +	int err, uart_id, ret = 0; -	err = exynos_pinmux_config(PERIPH_ID_UART0, PINMUX_FLAG_NONE); -	if (err) { -		debug("UART0 not configured\n"); -		return err; +	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 diff --git a/board/samsung/smdk5250/spl_boot.c b/board/samsung/smdk5250/spl_boot.c index c0bcf460f..98f2286f9 100644 --- a/board/samsung/smdk5250/spl_boot.c +++ b/board/samsung/smdk5250/spl_boot.c @@ -23,16 +23,44 @@  #include<common.h>  #include<config.h> +#include <asm/arch-exynos/dmc.h> +#include <asm/arch/clock.h> +#include <asm/arch/clk.h> + +#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) {} diff --git a/board/samsung/smdkv310/lowlevel_init.S b/board/samsung/smdkv310/lowlevel_init.S index 7a1ea98ae..31e0e2eda 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 diff --git a/common/cmd_mmc.c b/common/cmd_mmc.c index 7d824690b..5f1ed430e 100644 --- a/common/cmd_mmc.c +++ b/common/cmd_mmc.c @@ -147,6 +147,36 @@ U_BOOT_CMD(  	"- display info of the current MMC device"  ); +#ifdef CONFIG_SUPPORT_EMMC_BOOT +static int boot_part_access(struct mmc *mmc, u8 ack, u8 part_num, u8 access) +{ +	int err; +	err = mmc_boot_part_access(mmc, ack, part_num, access); + +	if ((err == 0) && (access != 0)) { +		printf("\t\t\t!!!Notice!!!\n"); + +		printf("!You must close EMMC boot Partition"); +		printf("after all images are written\n"); + +		printf("!EMMC boot partition has continuity"); +		printf("at image writing time.\n"); + +		printf("!So, do not close the boot partition"); +		printf("before all images are written.\n"); +		return 0; +	} else if ((err == 0) && (access == 0)) +		return 0; +	else if ((err != 0) && (access != 0)) { +		printf("EMMC boot partition-%d OPEN Failed.\n", part_num); +		return 1; +	} else { +		printf("EMMC boot partition-%d CLOSE Failed.\n", part_num); +		return 1; +	} +} +#endif +  static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  {  	enum mmc_state state; @@ -258,8 +288,74 @@ static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  				curr_device, mmc->part_num);  		return 0; -	} +#ifdef CONFIG_SUPPORT_EMMC_BOOT +	} else if ((strcmp(argv[1], "open") == 0) || +			(strcmp(argv[1], "close") == 0)) { +		int dev; +		struct mmc *mmc; +		u8 part_num, access = 0; + +		if (argc == 4) { +			dev = simple_strtoul(argv[2], NULL, 10); +			part_num = simple_strtoul(argv[3], NULL, 10); +		} else { +			return CMD_RET_USAGE; +		} + +		mmc = find_mmc_device(dev); +		if (!mmc) { +			printf("no mmc device at slot %x\n", dev); +			return 1; +		} +		if (IS_SD(mmc)) { +			printf("SD device cannot be opened/closed\n"); +			return 1; +		} + +		if ((part_num <= 0) || (part_num > MMC_NUM_BOOT_PARTITION)) { +			printf("Invalid boot partition number:\n"); +			printf("Boot partition number cannot be <= 0\n"); +			printf("EMMC44 supports only 2 boot partitions\n"); +			return 1; +		} + +		if (strcmp(argv[1], "open") == 0) +			access = part_num; /* enable R/W access to boot part*/ +		else +			access = 0; /* No access to boot partition */ + +		/* acknowledge to be sent during boot operation */ +		return boot_part_access(mmc, 1, part_num, access); + +	} else if (strcmp(argv[1], "bootpart") == 0) { +		int dev; +		dev = simple_strtoul(argv[2], NULL, 10); + +		u32 bootsize = simple_strtoul(argv[3], NULL, 10); +		u32 rpmbsize = simple_strtoul(argv[4], NULL, 10); +		struct mmc *mmc = find_mmc_device(dev); +		if (!mmc) { +			printf("no mmc device at slot %x\n", dev); +			return 1; +		} + +		if (IS_SD(mmc)) { +			printf("It is not a EMMC device\n"); +			return 1; +		} + +		if (0 == mmc_boot_partition_size_change(mmc, +							bootsize, rpmbsize)) { +			printf("EMMC boot partition Size %d MB\n", bootsize); +			printf("EMMC RPMB partition Size %d MB\n", rpmbsize); +			return 0; +		} else { +			printf("EMMC boot partition Size change Failed.\n"); +			return 1; +		} +#endif /* CONFIG_SUPPORT_EMMC_BOOT */ +	}  	state = MMC_INVALID;  	if (argc == 5 && strcmp(argv[1], "read") == 0)  		state = MMC_READ; @@ -334,5 +430,14 @@ U_BOOT_CMD(  	"mmc rescan\n"  	"mmc part - lists available partition on current mmc device\n"  	"mmc dev [dev] [part] - show or set current mmc device [partition]\n" -	"mmc list - lists available devices"); +	"mmc list - lists available devices\n" +#ifdef CONFIG_SUPPORT_EMMC_BOOT +	"mmc open <dev> <boot_partition>\n" +	" - Enable boot_part for booting and enable R/W access of boot_part\n" +	"mmc close <dev> <boot_partition>\n" +	" - Enable boot_part for booting and disable access to boot_part\n" +	"mmc bootpart <device num> <boot part size MB> <RPMB part size MB>\n" +	" - change sizes of boot and RPMB partions of specified device\n"  #endif +	); +#endif /* !CONFIG_GENERIC_MMC */ diff --git a/doc/device-tree-bindings/exynos/dwmmc.txt b/doc/device-tree-bindings/exynos/dwmmc.txt new file mode 100644 index 000000000..566da3b63 --- /dev/null +++ b/doc/device-tree-bindings/exynos/dwmmc.txt @@ -0,0 +1,54 @@ +* Exynos 5250 DWC_mobile_storage + +The Exynos 5250 provides DWC_mobile_storage interface which supports +. Embedded Multimedia Cards (EMMC-version 4.5) +. Secure Digital memory (SD mem-version 2.0) +. Secure Digital I/O (SDIO-version 3.0) +. Consumer Electronics Advanced Transport Architecture (CE-ATA-version 1.1) + +The Exynos 5250 DWC_mobile_storage provides four channels. +SOC specific and Board specific properties are channel specific. + +Required SoC Specific Properties: + +- compatible: should be +	- samsung,exynos5250-dwmmc: for exynos5250 platforms + +- reg: physical base address of the controller and length of memory mapped +	region. + +- interrupts: The interrupt number to the cpu. + +Required Board Specific Properties: + +- #address-cells: should be 1. +- #size-cells: should be 0. +- samsung,bus-width: The width of the bus used to interface the devices +	supported by DWC_mobile_storage (SD-MMC/EMMC/SDIO). +	. Typically the bus width is 4 or 8. +- samsung,timing: The timing values to be written into the +	Drv/sample clock selection register of corresponding channel. +	. It is comprised of 3 values corresponding to the 3 fileds +	  'SelClk_sample', 'SelClk_drv' and 'DIVRATIO' of CLKSEL register. +	. SelClk_sample: Select sample clock among 8 shifted clocks. +	. SelClk_drv: Select drv clock among 8 shifted clocks. +	. DIVRATIO: Clock Divide ratio select. +	. The above 3 values are used by the clock phase shifter. + +Example: + +mmc@12200000 { +	samsung,bus-width = <8>; +	samsung,timing = <1 3 3>; +	samsung,removable = <1>; +} +In the above example, +	. The bus width is 8 +	. Timing is comprised of 3 values as explained below +		1 - SelClk_sample +		3 - SelClk_drv +		3 - DIVRATIO +	. The 'removable' flag indicates whether the the particilar device +	  cannot be removed (always present) or it is a removable device. +		1 - Indicates that the device is removable. +		0 - Indicates that the device cannot be removed. diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c index 4070d4ea5..5da20eda5 100644 --- a/drivers/mmc/dw_mmc.c +++ b/drivers/mmc/dw_mmc.c @@ -129,13 +129,13 @@ static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,  	unsigned int timeout = 100000;  	u32 retry = 10000;  	u32 mask, ctrl; +	ulong start = get_timer(0);  	while (dwmci_readl(host, DWMCI_STATUS) & DWMCI_BUSY) { -		if (timeout == 0) { +		if (get_timer(start) > timeout) {  			printf("Timeout on data busy\n");  			return TIMEOUT;  		} -		timeout--;  	}  	dwmci_writel(host, DWMCI_RINTSTS, DWMCI_INTMSK_ALL); @@ -143,7 +143,6 @@ static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,  	if (data)  		dwmci_prepare_data(host, data); -  	dwmci_writel(host, DWMCI_CMDARG, cmd->cmdarg);  	if (data) @@ -231,9 +230,8 @@ static int dwmci_setup_bus(struct dwmci_host *host, u32 freq)  	int timeout = 10000;  	unsigned long sclk; -	if (freq == host->clock) +	if ((freq == host->clock) || (freq == 0))  		return 0; -  	/*  	 * If host->mmc_clk didn't define,  	 * then assume that host->bus_hz is source clock value. @@ -314,7 +312,7 @@ static void dwmci_set_ios(struct mmc *mmc)  static int dwmci_init(struct mmc *mmc)  {  	struct dwmci_host *host = (struct dwmci_host *)mmc->priv; -	u32 fifo_size, fifoth_val; +	u32 fifo_size;  	dwmci_writel(host, DWMCI_PWREN, 1); @@ -323,6 +321,9 @@ static int dwmci_init(struct mmc *mmc)  		return -1;  	} +	/* Enumerate at 400KHz */ +	dwmci_setup_bus(host, mmc->f_min); +  	dwmci_writel(host, DWMCI_RINTSTS, 0xFFFFFFFF);  	dwmci_writel(host, DWMCI_INTMASK, 0); @@ -331,13 +332,13 @@ static int dwmci_init(struct mmc *mmc)  	dwmci_writel(host, DWMCI_IDINTEN, 0);  	dwmci_writel(host, DWMCI_BMOD, 1); -	fifo_size = dwmci_readl(host, DWMCI_FIFOTH); -	if (host->fifoth_val) -		fifoth_val = host->fifoth_val; -	else -		fifoth_val = MSIZE(0x2) | RX_WMARK(fifo_size/2 -1) | -			TX_WMARK(fifo_size/2); -	dwmci_writel(host, DWMCI_FIFOTH, fifoth_val); +	if (!host->fifoth_val) { +		fifo_size = dwmci_readl(host, DWMCI_FIFOTH); +		fifo_size = ((fifo_size & RX_WMARK_MASK) >> RX_WMARK_SHIFT) + 1; +		host->fifoth_val = MSIZE(0x2) | RX_WMARK(fifo_size / 2 - 1) | +			TX_WMARK(fifo_size / 2); +	} +	dwmci_writel(host, DWMCI_FIFOTH, host->fifoth_val);  	dwmci_writel(host, DWMCI_CLKENA, 0);  	dwmci_writel(host, DWMCI_CLKSRC, 0); diff --git a/drivers/mmc/exynos_dw_mmc.c b/drivers/mmc/exynos_dw_mmc.c index 72a31b73f..4238dd933 100644 --- a/drivers/mmc/exynos_dw_mmc.c +++ b/drivers/mmc/exynos_dw_mmc.c @@ -19,39 +19,146 @@   */  #include <common.h> -#include <malloc.h>  #include <dwmmc.h> +#include <fdtdec.h> +#include <libfdt.h> +#include <malloc.h>  #include <asm/arch/dwmmc.h>  #include <asm/arch/clk.h> +#include <asm/arch/pinmux.h> -static char *EXYNOS_NAME = "EXYNOS DWMMC"; +#define	DWMMC_MAX_CH_NUM		4 +#define	DWMMC_MAX_FREQ			52000000 +#define	DWMMC_MIN_FREQ			400000 +#define	DWMMC_MMC0_CLKSEL_VAL		0x03030001 +#define	DWMMC_MMC2_CLKSEL_VAL		0x03020001 +/* + * Function used as callback function to initialise the + * CLKSEL register for every mmc channel. + */  static void exynos_dwmci_clksel(struct dwmci_host *host)  { -	u32 val; -	val = DWMCI_SET_SAMPLE_CLK(DWMCI_SHIFT_0) | -		DWMCI_SET_DRV_CLK(DWMCI_SHIFT_0) | DWMCI_SET_DIV_RATIO(0); +	dwmci_writel(host, DWMCI_CLKSEL, host->clksel_val); +} -	dwmci_writel(host, DWMCI_CLKSEL, val); +unsigned int exynos_dwmci_get_clk(int dev_index) +{ +	return get_mmc_clk(dev_index);  } -int exynos_dwmci_init(u32 regbase, int bus_width, int index) +/* + * This function adds the mmc channel to be registered with mmc core. + * index -	mmc channel number. + * regbase -	register base address of mmc channel specified in 'index'. + * bus_width -	operating bus width of mmc channel specified in 'index'. + * clksel -	value to be written into CLKSEL register in case of FDT. + *		NULL in case od non-FDT. + */ +int exynos_dwmci_add_port(int index, u32 regbase, int bus_width, u32 clksel)  {  	struct dwmci_host *host = NULL; +	unsigned int div; +	unsigned long freq, sclk;  	host = malloc(sizeof(struct dwmci_host));  	if (!host) {  		printf("dwmci_host malloc fail!\n");  		return 1;  	} +	/* request mmc clock vlaue of 52MHz.  */ +	freq = 52000000; +	sclk = get_mmc_clk(index); +	div = DIV_ROUND_UP(sclk, freq); +	/* set the clock divisor for mmc */ +	set_mmc_clk(index, div); -	host->name = EXYNOS_NAME; +	host->name = "EXYNOS DWMMC";  	host->ioaddr = (void *)regbase;  	host->buswidth = bus_width; + +	if (clksel) { +		host->clksel_val = clksel; +	} else { +		if (0 == index) +			host->clksel_val = DWMMC_MMC0_CLKSEL_VAL; +		if (2 == index) +			host->clksel_val = DWMMC_MMC2_CLKSEL_VAL; +	} +  	host->clksel = exynos_dwmci_clksel;  	host->dev_index = index; +	host->mmc_clk = exynos_dwmci_get_clk; +	/* Add the mmc channel to be registered with mmc core */ +	if (add_dwmci(host, DWMMC_MAX_FREQ, DWMMC_MIN_FREQ)) { +		debug("dwmmc%d registration failed\n", index); +		return -1; +	} +	return 0; +} + +#ifdef CONFIG_OF_CONTROL +int exynos_dwmmc_init(const void *blob) +{ +	int index, bus_width; +	int node_list[DWMMC_MAX_CH_NUM]; +	int err = 0, dev_id, flag, count, i; +	u32 clksel_val, base, timing[3]; + +	count = fdtdec_find_aliases_for_id(blob, "mmc", +				COMPAT_SAMSUNG_EXYNOS5_DWMMC, node_list, +				DWMMC_MAX_CH_NUM); + +	for (i = 0; i < count; i++) { +		int node = node_list[i]; + +		if (node <= 0) +			continue; -	add_dwmci(host, 52000000, 400000); +		/* Extract device id for each mmc channel */ +		dev_id = pinmux_decode_periph_id(blob, node); +		/* Get the bus width from the device node */ +		bus_width = fdtdec_get_int(blob, node, "samsung,bus-width", 0); +		if (bus_width <= 0) { +			debug("DWMMC: Can't get bus-width\n"); +			return -1; +		} +		if (8 == bus_width) +			flag = PINMUX_FLAG_8BIT_MODE; +		else +			flag = PINMUX_FLAG_NONE; + +		/* config pinmux for each mmc channel */ +		err = exynos_pinmux_config(dev_id, flag); +		if (err) { +			debug("DWMMC not configured\n"); +			return err; +		} + +		index = dev_id - PERIPH_ID_SDMMC0; + +		/* Get the base address from the device node */ +		base = fdtdec_get_addr(blob, node, "reg"); +		if (!base) { +			debug("DWMMC: Can't get base address\n"); +			return -1; +		} +		/* Extract the timing info from the node */ +		err = fdtdec_get_int_array(blob, node, "samsung,timing", +					timing, 3); +		if (err) { +			debug("Can't get sdr-timings for divider\n"); +			return -1; +		} + +		clksel_val = (DWMCI_SET_SAMPLE_CLK(timing[0]) | +				DWMCI_SET_DRV_CLK(timing[1]) | +				DWMCI_SET_DIV_RATIO(timing[2])); +		/* Initialise each mmc channel */ +		err = exynos_dwmci_add_port(index, base, bus_width, clksel_val); +		if (err) +			debug("dwmmc Channel-%d init failed\n", index); +	}  	return 0;  } - +#endif diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 0a2f5358e..a492bbb41 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -1447,3 +1447,137 @@ int mmc_initialize(bd_t *bis)  	do_preinit();  	return 0;  } + +#ifdef CONFIG_SUPPORT_EMMC_BOOT +/* + * This function changes the size of boot partition and the size of rpmb + * partition present on EMMC devices. + * + * Input Parameters: + * struct *mmc: pointer for the mmc device strcuture + * bootsize: size of boot partition + * rpmbsize: size of rpmb partition + * + * Returns 0 on success. + */ + +int mmc_boot_partition_size_change(struct mmc *mmc, unsigned long bootsize, +				unsigned long rpmbsize) +{ +	int err; +	struct mmc_cmd cmd; + +	/* Only use this command for raw EMMC moviNAND. Enter backdoor mode */ +	cmd.cmdidx = MMC_CMD_RES_MAN; +	cmd.resp_type = MMC_RSP_R1b; +	cmd.cmdarg = MMC_CMD62_ARG1; + +	err = mmc_send_cmd(mmc, &cmd, NULL); +	if (err) { +		debug("mmc_boot_partition_size_change: Error1 = %d\n", err); +		return err; +	} + +	/* Boot partition changing mode */ +	cmd.cmdidx = MMC_CMD_RES_MAN; +	cmd.resp_type = MMC_RSP_R1b; +	cmd.cmdarg = MMC_CMD62_ARG2; + +	err = mmc_send_cmd(mmc, &cmd, NULL); +	if (err) { +		debug("mmc_boot_partition_size_change: Error2 = %d\n", err); +		return err; +	} +	/* boot partition size is multiple of 128KB */ +	bootsize = (bootsize * 1024) / 128; + +	/* Arg: boot partition size */ +	cmd.cmdidx = MMC_CMD_RES_MAN; +	cmd.resp_type = MMC_RSP_R1b; +	cmd.cmdarg = bootsize; + +	err = mmc_send_cmd(mmc, &cmd, NULL); +	if (err) { +		debug("mmc_boot_partition_size_change: Error3 = %d\n", err); +		return err; +	} +	/* RPMB partition size is multiple of 128KB */ +	rpmbsize = (rpmbsize * 1024) / 128; +	/* Arg: RPMB partition size */ +	cmd.cmdidx = MMC_CMD_RES_MAN; +	cmd.resp_type = MMC_RSP_R1b; +	cmd.cmdarg = rpmbsize; + +	err = mmc_send_cmd(mmc, &cmd, NULL); +	if (err) { +		debug("mmc_boot_partition_size_change: Error4 = %d\n", err); +		return err; +	} +	return 0; +} + +/* + * This function shall form and send the commands to open / close the + * boot partition specified by user. + * + * Input Parameters: + * ack: 0x0 - No boot acknowledge sent (default) + *	0x1 - Boot acknowledge sent during boot operation + * part_num: User selects boot data that will be sent to master + *	0x0 - Device not boot enabled (default) + *	0x1 - Boot partition 1 enabled for boot + *	0x2 - Boot partition 2 enabled for boot + * access: User selects partitions to access + *	0x0 : No access to boot partition (default) + *	0x1 : R/W boot partition 1 + *	0x2 : R/W boot partition 2 + *	0x3 : R/W Replay Protected Memory Block (RPMB) + * + * Returns 0 on success. + */ +int mmc_boot_part_access(struct mmc *mmc, u8 ack, u8 part_num, u8 access) +{ +	int err; +	struct mmc_cmd cmd; + +	/* Boot ack enable, boot partition enable , boot partition access */ +	cmd.cmdidx = MMC_CMD_SWITCH; +	cmd.resp_type = MMC_RSP_R1b; + +	cmd.cmdarg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | +			(EXT_CSD_PART_CONF << 16) | +			((EXT_CSD_BOOT_ACK(ack) | +			EXT_CSD_BOOT_PART_NUM(part_num) | +			EXT_CSD_PARTITION_ACCESS(access)) << 8); + +	err = mmc_send_cmd(mmc, &cmd, NULL); +	if (err) { +		if (access) { +			debug("mmc boot partition#%d open fail:Error1 = %d\n", +			      part_num, err); +		} else { +			debug("mmc boot partition#%d close fail:Error = %d\n", +			      part_num, err); +		} +		return err; +	} + +	if (access) { +		/* 4bit transfer mode at booting time. */ +		cmd.cmdidx = MMC_CMD_SWITCH; +		cmd.resp_type = MMC_RSP_R1b; + +		cmd.cmdarg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | +				(EXT_CSD_BOOT_BUS_WIDTH << 16) | +				((1 << 0) << 8); + +		err = mmc_send_cmd(mmc, &cmd, NULL); +		if (err) { +			debug("mmc boot partition#%d open fail:Error2 = %d\n", +			      part_num, err); +			return err; +		} +	} +	return 0; +} +#endif diff --git a/drivers/mtd/spi/Makefile b/drivers/mtd/spi/Makefile index 90f83924e..ecbb2108f 100644 --- a/drivers/mtd/spi/Makefile +++ b/drivers/mtd/spi/Makefile @@ -32,6 +32,7 @@ endif  COBJS-$(CONFIG_SPI_FLASH)	+= spi_flash.o  COBJS-$(CONFIG_SPI_FLASH_ATMEL)	+= atmel.o  COBJS-$(CONFIG_SPI_FLASH_EON)	+= eon.o +COBJS-$(CONFIG_SPI_FLASH_GIGADEVICE)	+= gigadevice.o  COBJS-$(CONFIG_SPI_FLASH_MACRONIX)	+= macronix.o  COBJS-$(CONFIG_SPI_FLASH_SPANSION)	+= spansion.o  COBJS-$(CONFIG_SPI_FLASH_SST)	+= sst.o diff --git a/drivers/mtd/spi/gigadevice.c b/drivers/mtd/spi/gigadevice.c new file mode 100644 index 000000000..b5e1ebedf --- /dev/null +++ b/drivers/mtd/spi/gigadevice.c @@ -0,0 +1,81 @@ +/* + * Gigadevice SPI flash driver + * Copyright 2013, Samsung Electronics Co., Ltd. + * Author: Banajit Goswami <banajit.g@samsung.com> + * + * 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 <common.h> +#include <malloc.h> +#include <spi_flash.h> + +#include "spi_flash_internal.h" + +struct gigadevice_spi_flash_params { +	uint16_t	id; +	uint16_t	nr_blocks; +	const char	*name; +}; + +static const struct gigadevice_spi_flash_params gigadevice_spi_flash_table[] = { +	{ +		.id			= 0x6016, +		.nr_blocks		= 64, +		.name			= "GD25LQ", +	}, +	{ +		.id			= 0x4017, +		.nr_blocks		= 128, +		.name			= "GD25Q64B", +	}, +}; + +struct spi_flash *spi_flash_probe_gigadevice(struct spi_slave *spi, u8 *idcode) +{ +	const struct gigadevice_spi_flash_params *params; +	struct spi_flash *flash; +	unsigned int i; + +	for (i = 0; i < ARRAY_SIZE(gigadevice_spi_flash_table); i++) { +		params = &gigadevice_spi_flash_table[i]; +		if (params->id == ((idcode[1] << 8) | idcode[2])) +			break; +	} + +	if (i == ARRAY_SIZE(gigadevice_spi_flash_table)) { +		debug("SF: Unsupported Gigadevice ID %02x%02x\n", +				idcode[1], idcode[2]); +		return NULL; +	} + +	flash = spi_flash_alloc_base(spi, params->name); +	if (!flash) { +		debug("SF: Failed to allocate memory\n"); +		return NULL; +	} +	/* page_size */ +	flash->page_size = 256; +	/* sector_size = page_size * pages_per_sector */ +	flash->sector_size = flash->page_size * 16; +	/* size = sector_size * sector_per_block * number of blocks */ +	flash->size = flash->sector_size * 16 * params->nr_blocks; + +	return flash; +} diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c index 111185af1..6507aa34b 100644 --- a/drivers/mtd/spi/spi_flash.c +++ b/drivers/mtd/spi/spi_flash.c @@ -346,6 +346,9 @@ static const struct {  #ifdef CONFIG_SPI_FLASH_EON  	{ 0, 0x1c, spi_flash_probe_eon, },  #endif +#ifdef CONFIG_SPI_FLASH_GIGADEVICE +	{ 0, 0xc8, spi_flash_probe_gigadevice, }, +#endif  #ifdef CONFIG_SPI_FLASH_MACRONIX  	{ 0, 0xc2, spi_flash_probe_macronix, },  #endif diff --git a/drivers/mtd/spi/spi_flash_internal.h b/drivers/mtd/spi/spi_flash_internal.h index 141cfa8b2..e0afbc3d8 100644 --- a/drivers/mtd/spi/spi_flash_internal.h +++ b/drivers/mtd/spi/spi_flash_internal.h @@ -106,3 +106,4 @@ struct spi_flash *spi_flash_probe_sst(struct spi_slave *spi, u8 *idcode);  struct spi_flash *spi_flash_probe_stmicro(struct spi_slave *spi, u8 *idcode);  struct spi_flash *spi_flash_probe_winbond(struct spi_slave *spi, u8 *idcode);  struct spi_flash *spi_fram_probe_ramtron(struct spi_slave *spi, u8 *idcode); +struct spi_flash *spi_flash_probe_gigadevice(struct spi_slave *spi, u8 *idcode); diff --git a/drivers/power/exynos-tmu.c b/drivers/power/exynos-tmu.c index d4b3e65a3..9a093a5bd 100644 --- a/drivers/power/exynos-tmu.c +++ b/drivers/power/exynos-tmu.c @@ -50,15 +50,15 @@  /* Tmeperature threshold values for various thermal events */  struct temperature_params {  	/* minimum value in temperature code range */ -	unsigned int min_val; +	unsigned min_val;  	/* maximum value in temperature code range */ -	unsigned int max_val; +	unsigned max_val;  	/* temperature threshold to start warning */ -	unsigned int start_warning; +	unsigned start_warning;  	/* temperature threshold CPU tripping */ -	unsigned int start_tripping; +	unsigned start_tripping;  	/* temperature threshold for HW tripping */ -	unsigned int hardware_tripping; +	unsigned hardware_tripping;  };  /* Pre-defined values and thresholds for calibration of current temperature */ @@ -66,25 +66,27 @@ struct tmu_data {  	/* pre-defined temperature thresholds */  	struct temperature_params ts;  	/* pre-defined efuse range minimum value */ -	unsigned int efuse_min_value; +	unsigned efuse_min_value;  	/* pre-defined efuse value for temperature calibration */ -	unsigned int efuse_value; +	unsigned efuse_value;  	/* pre-defined efuse range maximum value */ -	unsigned int efuse_max_value; +	unsigned efuse_max_value;  	/* current temperature sensing slope */ -	unsigned int slope; +	unsigned slope;  };  /* TMU device specific details and status */  struct tmu_info {  	/* base Address for the TMU */ -	unsigned tmu_base; +	struct exynos5_tmu_reg *tmu_base; +	/* mux Address for the TMU */ +	int tmu_mux;  	/* pre-defined values for calibration and thresholds */  	struct tmu_data data;  	/* value required for triminfo_25 calibration */ -	unsigned int te1; +	unsigned te1;  	/* value required for triminfo_85 calibration */ -	unsigned int te2; +	unsigned te2;  	/* Value for measured data calibration */  	int dc_value;  	/* enum value indicating status of the TMU */ @@ -103,17 +105,24 @@ static struct tmu_info gbl_info;   */  static int get_cur_temp(struct tmu_info *info)  { -	int cur_temp; -	struct exynos5_tmu_reg *reg = (struct exynos5_tmu_reg *)info->tmu_base; +	struct exynos5_tmu_reg *reg = info->tmu_base; +	ulong start; +	int cur_temp = 0;  	/*  	 * Temperature code range between min 25 and max 125.  	 * May run more than once for first call as initial sensing  	 * has not yet happened.  	 */ -	do { -		cur_temp = readl(®->current_temp) & 0xff; -	} while (cur_temp == 0 && info->tmu_state == TMU_STATUS_NORMAL); +	if (info->tmu_state == TMU_STATUS_NORMAL) { +		start = get_timer(0); +		do { +			cur_temp = readl(®->current_temp) & 0xff; +		} while ((cur_temp == 0) || (get_timer(start) > 100)); +	} + +	if (cur_temp == 0) +		return cur_temp;  	/* Calibrate current temperature */  	cur_temp = cur_temp - info->te1 + info->dc_value; @@ -137,23 +146,29 @@ enum tmu_status_t tmu_monitor(int *temp)  	/* Read current temperature of the SOC */  	cur_temp = get_cur_temp(&gbl_info); + +	if (!cur_temp) +		goto out; +  	*temp = cur_temp;  	/* Temperature code lies between min 25 and max 125 */ -	if (cur_temp >= data->ts.start_tripping && -			cur_temp <= data->ts.max_val) { +	if ((cur_temp >= data->ts.start_tripping) && +	    (cur_temp <= data->ts.max_val))  		return TMU_STATUS_TRIPPED; -	} else if (cur_temp >= data->ts.start_warning) { + +	if (cur_temp >= data->ts.start_warning)  		return TMU_STATUS_WARNING; -	} else if (cur_temp < data->ts.start_warning && -			cur_temp >= data->ts.min_val) { + +	if ((cur_temp < data->ts.start_warning) && +	    (cur_temp >= data->ts.min_val))  		return TMU_STATUS_NORMAL; -	} else { -		/* Temperature code does not lie between min 25 and max 125 */ -		gbl_info.tmu_state = TMU_STATUS_INIT; -		debug("EXYNOS_TMU: Thermal reading failed\n"); -		return TMU_STATUS_INIT; -	} + + out: +	/* Temperature code does not lie between min 25 and max 125 */ +	gbl_info.tmu_state = TMU_STATUS_INIT; +	debug("EXYNOS_TMU: Thermal reading failed\n"); +	return TMU_STATUS_INIT;  }  /* @@ -166,6 +181,7 @@ enum tmu_status_t tmu_monitor(int *temp)  static int get_tmu_fdt_values(struct tmu_info *info, const void *blob)  {  #ifdef CONFIG_OF_CONTROL +	fdt_addr_t addr;  	int node;  	int error = 0; @@ -183,46 +199,58 @@ static int get_tmu_fdt_values(struct tmu_info *info, const void *blob)  	 * miscalculation of register values in tmu_setup_parameters  	 * may result in misleading current temperature.  	 */ -	info->tmu_base = fdtdec_get_addr(blob, node, "reg"); -	if (info->tmu_base == FDT_ADDR_T_NONE) { +	addr = fdtdec_get_addr(blob, node, "reg"); +	if (addr == FDT_ADDR_T_NONE) {  		debug("%s: Missing tmu-base\n", __func__);  		return -1;  	} +	info->tmu_base = (struct exynos5_tmu_reg *)addr; + +	/* Optional field. */ +	info->tmu_mux = fdtdec_get_int(blob, +				node, "samsung,mux", -1); +	/* Take default value as per the user manual b(110) */ +	if (info->tmu_mux == -1) +		info->tmu_mux = 0x6; +  	info->data.ts.min_val = fdtdec_get_int(blob,  				node, "samsung,min-temp", -1); -	error |= info->data.ts.min_val; +	error |= (info->data.ts.min_val == -1);  	info->data.ts.max_val = fdtdec_get_int(blob,  				node, "samsung,max-temp", -1); -	error |= info->data.ts.max_val; +	error |= (info->data.ts.max_val == -1);  	info->data.ts.start_warning = fdtdec_get_int(blob,  				node, "samsung,start-warning", -1); -	error |= info->data.ts.start_warning; +	error |= (info->data.ts.start_warning == -1);  	info->data.ts.start_tripping = fdtdec_get_int(blob,  				node, "samsung,start-tripping", -1); -	error |= info->data.ts.start_tripping; +	error |= (info->data.ts.start_tripping == -1);  	info->data.ts.hardware_tripping = fdtdec_get_int(blob,  				node, "samsung,hw-tripping", -1); -	error |= info->data.ts.hardware_tripping; +	error |= (info->data.ts.hardware_tripping == -1);  	info->data.efuse_min_value = fdtdec_get_int(blob,  				node, "samsung,efuse-min-value", -1); -	error |= info->data.efuse_min_value; +	error |= (info->data.efuse_min_value == -1);  	info->data.efuse_value = fdtdec_get_int(blob,  				node, "samsung,efuse-value", -1); -	error |= info->data.efuse_value; +	error |= (info->data.efuse_value == -1);  	info->data.efuse_max_value = fdtdec_get_int(blob,  				node, "samsung,efuse-max-value", -1); -	error |= info->data.efuse_max_value; +	error |= (info->data.efuse_max_value == -1);  	info->data.slope = fdtdec_get_int(blob,  				node, "samsung,slope", -1); -	error |= info->data.slope; +	error |= (info->data.slope == -1);  	info->dc_value = fdtdec_get_int(blob,  				node, "samsung,dc-value", -1); -	error |= info->dc_value; +	error |= (info->dc_value == -1); -	if (error == -1) { +	if (error) {  		debug("fail to get tmu node properties\n");  		return -1;  	} +#else +	/* Non DT support may never be added. Just in case  */ +	return -1;  #endif  	return 0; @@ -236,12 +264,12 @@ static int get_tmu_fdt_values(struct tmu_info *info, const void *blob)   */  static void tmu_setup_parameters(struct tmu_info *info)  { -	unsigned int te_code, con; -	unsigned int warning_code, trip_code, hwtrip_code; -	unsigned int cooling_temp; -	unsigned int rising_value; +	unsigned te_code, con; +	unsigned warning_code, trip_code, hwtrip_code; +	unsigned cooling_temp; +	unsigned rising_value;  	struct tmu_data *data = &info->data; -	struct exynos5_tmu_reg *reg = (struct exynos5_tmu_reg *)info->tmu_base; +	struct exynos5_tmu_reg *reg = info->tmu_base;  	/* Must reload for reading efuse value from triminfo register */  	writel(TRIMINFO_RELOAD, ®->triminfo_control); @@ -288,7 +316,7 @@ static void tmu_setup_parameters(struct tmu_info *info)  	/* TMU core enable */  	con = readl(®->tmu_control); -	con |= THERM_TRIP_EN | CORE_EN; +	con |= THERM_TRIP_EN | CORE_EN | (info->tmu_mux << 20);  	writel(con, ®->tmu_control); @@ -314,6 +342,5 @@ int tmu_init(const void *blob)  	tmu_setup_parameters(&gbl_info);  	gbl_info.tmu_state = TMU_STATUS_NORMAL;  ret: -  	return gbl_info.tmu_state;  } diff --git a/drivers/serial/serial_s5p.c b/drivers/serial/serial_s5p.c index 3c41242a8..e65125ccd 100644 --- a/drivers/serial/serial_s5p.c +++ b/drivers/serial/serial_s5p.c @@ -30,6 +30,10 @@  DECLARE_GLOBAL_DATA_PTR; +#define RX_FIFO_COUNT_MASK	0xff +#define RX_FIFO_FULL_MASK	(1 << 8) +#define TX_FIFO_FULL_MASK	(1 << 24) +  static inline struct s5p_uart *s5p_get_base_uart(int dev_index)  {  	u32 offset = dev_index * sizeof(struct s5p_uart); @@ -87,8 +91,8 @@ int serial_init_dev(const int dev_index)  {  	struct s5p_uart *const uart = s5p_get_base_uart(dev_index); -	/* reset and enable FIFOs, set triggers to the maximum */ -	writel(0, &uart->ufcon); +	/* enable FIFOs */ +	writel(0x1, &uart->ufcon);  	writel(0, &uart->umcon);  	/* 8N1 */  	writel(0x3, &uart->ulcon); @@ -130,7 +134,8 @@ int serial_getc_dev(const int dev_index)  	struct s5p_uart *const uart = s5p_get_base_uart(dev_index);  	/* wait for character to arrive */ -	while (!(readl(&uart->utrstat) & 0x1)) { +	while (!(readl(&uart->ufstat) & (RX_FIFO_COUNT_MASK | +					 RX_FIFO_FULL_MASK))) {  		if (serial_err_check(dev_index, 0))  			return 0;  	} @@ -146,7 +151,7 @@ void serial_putc_dev(const char c, const int dev_index)  	struct s5p_uart *const uart = s5p_get_base_uart(dev_index);  	/* wait for room in the tx FIFO */ -	while (!(readl(&uart->utrstat) & 0x2)) { +	while ((readl(&uart->ufstat) & TX_FIFO_FULL_MASK)) {  		if (serial_err_check(dev_index, 1))  			return;  	} diff --git a/drivers/video/exynos_fb.c b/drivers/video/exynos_fb.c index ed0823bf9..c3606d5b0 100644 --- a/drivers/video/exynos_fb.c +++ b/drivers/video/exynos_fb.c @@ -319,10 +319,10 @@ void lcd_ctrl_init(void *lcdbase)  #ifdef CONFIG_OF_CONTROL  	if (exynos_fimd_parse_dt(gd->fdt_blob))  		debug("Can't get proper panel info\n"); -#endif +#else  	/* initialize parameters which is specific to panel. */  	init_panel_info(&panel_info); - +#endif  	panel_width = panel_info.vl_width;  	panel_height = panel_info.vl_height; diff --git a/include/configs/exynos5250-dt.h b/include/configs/exynos5250-dt.h index 8a82892f4..9b97d4fb0 100644 --- a/include/configs/exynos5250-dt.h +++ b/include/configs/exynos5250-dt.h @@ -93,13 +93,15 @@  #define CONFIG_EXTRA_ENV_SETTINGS \  	EXYNOS_DEVICE_SETTINGS -#define TZPC_BASE_OFFSET		0x10000 -  /* SD/MMC configuration */  #define CONFIG_GENERIC_MMC  #define CONFIG_MMC  #define CONFIG_SDHCI  #define CONFIG_S5P_SDHCI +#define CONFIG_DWMMC +#define CONFIG_EXYNOS_DWMMC +#define CONFIG_SUPPORT_EMMC_BOOT +  #define CONFIG_BOARD_EARLY_INIT_F @@ -232,6 +234,10 @@  #define SPI_FLASH_UBOOT_POS		(CONFIG_SEC_FW_SIZE + CONFIG_BL1_SIZE)  #define CONFIG_DOS_PARTITION +#define CONFIG_EFI_PARTITION +#define CONFIG_CMD_PART +#define CONFIG_PARTITION_UUIDS +  #define CONFIG_IRAM_STACK	0x02050000 @@ -262,6 +268,7 @@  #define CONFIG_CMD_SF  #define CONFIG_CMD_SPI  #define CONFIG_SPI_FLASH_WINBOND +#define CONFIG_SPI_FLASH_GIGADEVICE  #define CONFIG_SF_DEFAULT_MODE		SPI_MODE_0  #define CONFIG_SF_DEFAULT_SPEED		50000000  #define EXYNOS5_SPI_NUM_CONTROLLERS	5 diff --git a/include/configs/origen.h b/include/configs/origen.h index ff2b24d97..e179911d0 100644 --- a/include/configs/origen.h +++ b/include/configs/origen.h @@ -96,6 +96,8 @@  #define CONFIG_SPL  #define COPY_BL2_FNPTR_ADDR	0x02020030 +#define CONFIG_SPL_TEXT_BASE	0x02021410 +  #define CONFIG_BOOTCOMMAND	"fatload mmc 0 40007000 uImage; bootm 40007000"  /* Miscellaneous configurable options */ diff --git a/include/configs/smdkv310.h b/include/configs/smdkv310.h index b796b46a7..5e430660f 100644 --- a/include/configs/smdkv310.h +++ b/include/configs/smdkv310.h @@ -95,6 +95,8 @@  #define CONFIG_SPL  #define COPY_BL2_FNPTR_ADDR	0x00002488 +#define CONFIG_SPL_TEXT_BASE	0x02021410 +  #define CONFIG_BOOTCOMMAND	"fatload mmc 0 40007000 uImage; bootm 40007000"  /* Miscellaneous configurable options */ diff --git a/include/configs/trats.h b/include/configs/trats.h index fd58558be..c70838b91 100644 --- a/include/configs/trats.h +++ b/include/configs/trats.h @@ -146,7 +146,8 @@  #define CONFIG_DFU_ALT \  	"u-boot mmc 80 400;" \ -	"uImage ext4 0 2\0" \ +	"uImage ext4 0 2;" \ +	"exynos4210-trats.dtb ext4 0 2\0"  #define CONFIG_ENV_OVERWRITE  #define CONFIG_SYS_CONSOLE_INFO_QUIET @@ -154,7 +155,7 @@  #define CONFIG_EXTRA_ENV_SETTINGS \  	"bootk=" \ -		"run loaduimage; bootm 0x40007FC0\0" \ +		"run loaddtb; run loaduimage; bootm 0x40007FC0 - ${fdtaddr}\0" \  	"updatemmc=" \  		"mmc boot 0 1 1 1; mmc write 0 0x42008000 0 0x200;" \  		"mmc boot 0 1 1 0\0" \ @@ -177,7 +178,7 @@  	"mmcboot=" \  		"setenv bootargs root=/dev/mmcblk${mmcdev}p${mmcrootpart} " \  		"${lpj} rootwait ${console} ${meminfo} ${opts} ${lcdinfo}; " \ -		"run loaduimage; bootm 0x40007FC0\0" \ +		"run loaddtb; run loaduimage; bootm 0x40007FC0 - ${fdtaddr}\0" \  	"bootchart=setenv opts init=/sbin/bootchartd; run bootcmd\0" \  	"boottrace=setenv opts initcall_debug; run bootcmd\0" \  	"mmcoops=mmc read 0 0x40000000 0x40 8; md 0x40000000 0x400\0" \ @@ -188,6 +189,8 @@  	"nfsroot=/nfsroot/arm\0" \  	"bootblock=" CONFIG_BOOTBLOCK "\0" \  	"loaduimage=ext4load mmc ${mmcdev}:${mmcbootpart} 0x40007FC0 uImage\0" \ +	"loaddtb=ext4load mmc ${mmcdev}:${mmcbootpart} ${fdtaddr}" \ +		"${fdtfile}\0" \  	"mmcdev=0\0" \  	"mmcbootpart=2\0" \  	"mmcrootpart=5\0" \ @@ -212,7 +215,10 @@  		   " /${splfile} ${spl_imgaddr} ${spl_imgsize};" \  		   "setenv spl_imgsize;" \  		   "setenv spl_imgaddr;" \ -		   "setenv spl_addr_tmp;\0" +		   "setenv spl_addr_tmp;\0" \ +	"fdtaddr=40800000\0" \ +	"fdtfile=exynos4210-trats.dtb\0" +  /* Miscellaneous configurable options */  #define CONFIG_SYS_LONGHELP		/* undef to save memory */ @@ -322,4 +328,7 @@  #define CONFIG_USB_GADGET_MASS_STORAGE  #endif +/* Pass open firmware flat tree */ +#define CONFIG_OF_LIBFDT    1 +  #endif	/* __CONFIG_H */ diff --git a/include/dwmmc.h b/include/dwmmc.h index c8b1d408e..e142f3ec4 100644 --- a/include/dwmmc.h +++ b/include/dwmmc.h @@ -123,6 +123,8 @@  #define MSIZE(x)		((x) << 28)  #define RX_WMARK(x)		((x) << 16)  #define TX_WMARK(x)		(x) +#define RX_WMARK_SHIFT		16 +#define RX_WMARK_MASK		(0xfff << RX_WMARK_SHIFT)  #define DWMCI_IDMAC_OWN		(1 << 31)  #define DWMCI_IDMAC_CH		(1 << 4) @@ -144,6 +146,7 @@ struct dwmci_host {  	unsigned int bus_hz;  	int dev_index;  	int buswidth; +	u32 clksel_val;  	u32 fifoth_val;  	struct mmc *mmc; diff --git a/include/fdtdec.h b/include/fdtdec.h index 4e8032ba6..bc3b89bc0 100644 --- a/include/fdtdec.h +++ b/include/fdtdec.h @@ -89,6 +89,7 @@ enum fdt_compat_id {  	COMPAT_SAMSUNG_EXYNOS_TMU,	/* Exynos TMU */  	COMPAT_SAMSUNG_EXYNOS_FIMD,	/* Exynos Display controller */  	COMPAT_SAMSUNG_EXYNOS5_DP,	/* Exynos Display port controller */ +	COMPAT_SAMSUNG_EXYNOS5_DWMMC,	/* Exynos5 DWMMC controller */  	COMPAT_MAXIM_MAX77686_PMIC,	/* MAX77686 PMIC */  	COMPAT_GENERIC_SPI_FLASH,	/* Generic SPI Flash chip */  	COMPAT_MAXIM_98095_CODEC,	/* MAX98095 Codec */ diff --git a/include/mmc.h b/include/mmc.h index 566db59ac..f88f672f1 100644 --- a/include/mmc.h +++ b/include/mmc.h @@ -93,6 +93,11 @@  #define MMC_CMD_APP_CMD			55  #define MMC_CMD_SPI_READ_OCR		58  #define MMC_CMD_SPI_CRC_ON_OFF		59 +#define MMC_CMD_RES_MAN			62 + +#define MMC_CMD62_ARG1			0xefac62ec +#define MMC_CMD62_ARG2			0xcbaea7 +  #define SD_CMD_SEND_RELATIVE_ADDR	3  #define SD_CMD_SWITCH_FUNC		6 @@ -160,6 +165,7 @@   */  #define EXT_CSD_PARTITIONING_SUPPORT	160	/* RO */  #define EXT_CSD_ERASE_GROUP_DEF		175	/* R/W */ +#define EXT_CSD_BOOT_BUS_WIDTH		177  #define EXT_CSD_PART_CONF		179	/* R/W */  #define EXT_CSD_BUS_WIDTH		183	/* R/W */  #define EXT_CSD_HS_TIMING		185	/* R/W */ @@ -184,6 +190,16 @@  #define EXT_CSD_BUS_WIDTH_4	1	/* Card is in 4 bit mode */  #define EXT_CSD_BUS_WIDTH_8	2	/* Card is in 8 bit mode */ +#define EXT_CSD_BOOT_ACK_ENABLE			(1 << 6) +#define EXT_CSD_BOOT_PARTITION_ENABLE		(1 << 3) +#define EXT_CSD_PARTITION_ACCESS_ENABLE		(1 << 0) +#define EXT_CSD_PARTITION_ACCESS_DISABLE	(0 << 0) + +#define EXT_CSD_BOOT_ACK(x)		(x << 6) +#define EXT_CSD_BOOT_PART_NUM(x)	(x << 3) +#define EXT_CSD_PARTITION_ACCESS(x)	(x << 0) + +  #define R1_ILLEGAL_COMMAND		(1 << 22)  #define R1_APP_CMD			(1 << 5) @@ -211,6 +227,11 @@  /* Maximum block size for MMC */  #define MMC_MAX_BLOCK_LEN	512 +/* The number of MMC physical partitions.  These consist of: + * boot partitions (2), general purpose partitions (4) in MMC v4.4. + */ +#define MMC_NUM_BOOT_PARTITION	2 +  struct mmc_cid {  	unsigned long psn;  	unsigned short oid; @@ -291,6 +312,11 @@ int mmc_switch_part(int dev_num, unsigned int part_num);  int mmc_getcd(struct mmc *mmc);  int mmc_getwp(struct mmc *mmc);  void spl_mmc_load(void) __noreturn; +/* Function to change the size of boot partition and rpmb partitions */ +int mmc_boot_partition_size_change(struct mmc *mmc, unsigned long bootsize, +					unsigned long rpmbsize); +/* Function to send commands to open/close the specified boot partition */ +int mmc_boot_part_access(struct mmc *mmc, u8 ack, u8 part_num, u8 access);  /**   * Start device initialization and return immediately; it does not block on diff --git a/lib/fdtdec.c b/lib/fdtdec.c index ac1fe0be2..e3142cbdf 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -62,6 +62,7 @@ static const char * const compat_names[COMPAT_COUNT] = {  	COMPAT(SAMSUNG_EXYNOS_TMU, "samsung,exynos-tmu"),  	COMPAT(SAMSUNG_EXYNOS_FIMD, "samsung,exynos-fimd"),  	COMPAT(SAMSUNG_EXYNOS5_DP, "samsung,exynos5-dp"), +	COMPAT(SAMSUNG_EXYNOS5_DWMMC, "samsung,exynos5250-dwmmc"),  	COMPAT(MAXIM_MAX77686_PMIC, "maxim,max77686_pmic"),  	COMPAT(GENERIC_SPI_FLASH, "spi-flash"),  	COMPAT(MAXIM_98095_CODEC, "maxim,max98095-codec"), diff --git a/spl/Makefile b/spl/Makefile index d8fe948ff..01873de2b 100644 --- a/spl/Makefile +++ b/spl/Makefile @@ -98,6 +98,14 @@ LIBS-y += arch/$(ARCH)/cpu/tegra-common/libcputegra-common.o  LIBS-y += $(CPUDIR)/tegra-common/libtegra-common.o  endif +ifneq ($(CONFIG_MX23)$(CONFIG_MX35),) +LIBS-y += arch/$(ARCH)/imx-common/libimx-common.o +endif + +ifeq ($(SOC),exynos) +LIBS-y += $(CPUDIR)/s5p-common/libs5p-common.o +endif +  # Add GCC lib  ifeq ("$(USE_PRIVATE_LIBGCC)", "yes")  PLATFORM_LIBGCC = $(SPLTREE)/arch/$(ARCH)/lib/libgcc.o |