1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * (C) Copyright 2013 SAMSUNG Electronics
3*4882a593Smuzhiyun * Rajeshwari Shinde <rajeshwari.s@samsung.com>
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * SPDX-License-Identifier: GPL-2.0+
6*4882a593Smuzhiyun */
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun #include <common.h>
9*4882a593Smuzhiyun #include <cros_ec.h>
10*4882a593Smuzhiyun #include <errno.h>
11*4882a593Smuzhiyun #include <fdtdec.h>
12*4882a593Smuzhiyun #include <spi.h>
13*4882a593Smuzhiyun #include <tmu.h>
14*4882a593Smuzhiyun #include <netdev.h>
15*4882a593Smuzhiyun #include <asm/io.h>
16*4882a593Smuzhiyun #include <asm/gpio.h>
17*4882a593Smuzhiyun #include <asm/arch/board.h>
18*4882a593Smuzhiyun #include <asm/arch/cpu.h>
19*4882a593Smuzhiyun #include <asm/arch/dwmmc.h>
20*4882a593Smuzhiyun #include <asm/arch/mmc.h>
21*4882a593Smuzhiyun #include <asm/arch/pinmux.h>
22*4882a593Smuzhiyun #include <asm/arch/power.h>
23*4882a593Smuzhiyun #include <asm/arch/system.h>
24*4882a593Smuzhiyun #include <asm/arch/sromc.h>
25*4882a593Smuzhiyun #include <lcd.h>
26*4882a593Smuzhiyun #include <i2c.h>
27*4882a593Smuzhiyun #include <usb.h>
28*4882a593Smuzhiyun #include <dwc3-uboot.h>
29*4882a593Smuzhiyun #include <samsung/misc.h>
30*4882a593Smuzhiyun #include <dm/pinctrl.h>
31*4882a593Smuzhiyun #include <dm.h>
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun DECLARE_GLOBAL_DATA_PTR;
34*4882a593Smuzhiyun
exynos_early_init_f(void)35*4882a593Smuzhiyun __weak int exynos_early_init_f(void)
36*4882a593Smuzhiyun {
37*4882a593Smuzhiyun return 0;
38*4882a593Smuzhiyun }
39*4882a593Smuzhiyun
exynos_power_init(void)40*4882a593Smuzhiyun __weak int exynos_power_init(void)
41*4882a593Smuzhiyun {
42*4882a593Smuzhiyun return 0;
43*4882a593Smuzhiyun }
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun #if defined CONFIG_EXYNOS_TMU
46*4882a593Smuzhiyun /* Boot Time Thermal Analysis for SoC temperature threshold breach */
boot_temp_check(void)47*4882a593Smuzhiyun static void boot_temp_check(void)
48*4882a593Smuzhiyun {
49*4882a593Smuzhiyun int temp;
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun switch (tmu_monitor(&temp)) {
52*4882a593Smuzhiyun case TMU_STATUS_NORMAL:
53*4882a593Smuzhiyun break;
54*4882a593Smuzhiyun case TMU_STATUS_TRIPPED:
55*4882a593Smuzhiyun /*
56*4882a593Smuzhiyun * Status TRIPPED ans WARNING means corresponding threshold
57*4882a593Smuzhiyun * breach
58*4882a593Smuzhiyun */
59*4882a593Smuzhiyun puts("EXYNOS_TMU: TRIPPING! Device power going down ...\n");
60*4882a593Smuzhiyun set_ps_hold_ctrl();
61*4882a593Smuzhiyun hang();
62*4882a593Smuzhiyun break;
63*4882a593Smuzhiyun case TMU_STATUS_WARNING:
64*4882a593Smuzhiyun puts("EXYNOS_TMU: WARNING! Temperature very high\n");
65*4882a593Smuzhiyun break;
66*4882a593Smuzhiyun case TMU_STATUS_INIT:
67*4882a593Smuzhiyun /*
68*4882a593Smuzhiyun * TMU_STATUS_INIT means something is wrong with temperature
69*4882a593Smuzhiyun * sensing and TMU status was changed back from NORMAL to INIT.
70*4882a593Smuzhiyun */
71*4882a593Smuzhiyun puts("EXYNOS_TMU: WARNING! Temperature sensing not done\n");
72*4882a593Smuzhiyun break;
73*4882a593Smuzhiyun default:
74*4882a593Smuzhiyun debug("EXYNOS_TMU: Unknown TMU state\n");
75*4882a593Smuzhiyun }
76*4882a593Smuzhiyun }
77*4882a593Smuzhiyun #endif
78*4882a593Smuzhiyun
board_init(void)79*4882a593Smuzhiyun int board_init(void)
80*4882a593Smuzhiyun {
81*4882a593Smuzhiyun gd->bd->bi_boot_params = (PHYS_SDRAM_1 + 0x100UL);
82*4882a593Smuzhiyun #if defined CONFIG_EXYNOS_TMU
83*4882a593Smuzhiyun if (tmu_init(gd->fdt_blob) != TMU_STATUS_NORMAL) {
84*4882a593Smuzhiyun debug("%s: Failed to init TMU\n", __func__);
85*4882a593Smuzhiyun return -1;
86*4882a593Smuzhiyun }
87*4882a593Smuzhiyun boot_temp_check();
88*4882a593Smuzhiyun #endif
89*4882a593Smuzhiyun #ifdef CONFIG_TZSW_RESERVED_DRAM_SIZE
90*4882a593Smuzhiyun /* The last few MB of memory can be reserved for secure firmware */
91*4882a593Smuzhiyun ulong size = CONFIG_TZSW_RESERVED_DRAM_SIZE;
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun gd->ram_size -= size;
94*4882a593Smuzhiyun gd->bd->bi_dram[CONFIG_NR_DRAM_BANKS - 1].size -= size;
95*4882a593Smuzhiyun #endif
96*4882a593Smuzhiyun return exynos_init();
97*4882a593Smuzhiyun }
98*4882a593Smuzhiyun
dram_init(void)99*4882a593Smuzhiyun int dram_init(void)
100*4882a593Smuzhiyun {
101*4882a593Smuzhiyun unsigned int i;
102*4882a593Smuzhiyun unsigned long addr;
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
105*4882a593Smuzhiyun addr = CONFIG_SYS_SDRAM_BASE + (i * SDRAM_BANK_SIZE);
106*4882a593Smuzhiyun gd->ram_size += get_ram_size((long *)addr, SDRAM_BANK_SIZE);
107*4882a593Smuzhiyun }
108*4882a593Smuzhiyun return 0;
109*4882a593Smuzhiyun }
110*4882a593Smuzhiyun
dram_init_banksize(void)111*4882a593Smuzhiyun int dram_init_banksize(void)
112*4882a593Smuzhiyun {
113*4882a593Smuzhiyun unsigned int i;
114*4882a593Smuzhiyun unsigned long addr, size;
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
117*4882a593Smuzhiyun addr = CONFIG_SYS_SDRAM_BASE + (i * SDRAM_BANK_SIZE);
118*4882a593Smuzhiyun size = get_ram_size((long *)addr, SDRAM_BANK_SIZE);
119*4882a593Smuzhiyun
120*4882a593Smuzhiyun gd->bd->bi_dram[i].start = addr;
121*4882a593Smuzhiyun gd->bd->bi_dram[i].size = size;
122*4882a593Smuzhiyun }
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun return 0;
125*4882a593Smuzhiyun }
126*4882a593Smuzhiyun
board_uart_init(void)127*4882a593Smuzhiyun static int board_uart_init(void)
128*4882a593Smuzhiyun {
129*4882a593Smuzhiyun #ifndef CONFIG_PINCTRL_EXYNOS
130*4882a593Smuzhiyun int err, uart_id, ret = 0;
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun for (uart_id = PERIPH_ID_UART0; uart_id <= PERIPH_ID_UART3; uart_id++) {
133*4882a593Smuzhiyun err = exynos_pinmux_config(uart_id, PINMUX_FLAG_NONE);
134*4882a593Smuzhiyun if (err) {
135*4882a593Smuzhiyun debug("UART%d not configured\n",
136*4882a593Smuzhiyun (uart_id - PERIPH_ID_UART0));
137*4882a593Smuzhiyun ret |= err;
138*4882a593Smuzhiyun }
139*4882a593Smuzhiyun }
140*4882a593Smuzhiyun return ret;
141*4882a593Smuzhiyun #else
142*4882a593Smuzhiyun return 0;
143*4882a593Smuzhiyun #endif
144*4882a593Smuzhiyun }
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun #ifdef CONFIG_BOARD_EARLY_INIT_F
board_early_init_f(void)147*4882a593Smuzhiyun int board_early_init_f(void)
148*4882a593Smuzhiyun {
149*4882a593Smuzhiyun int err;
150*4882a593Smuzhiyun #ifdef CONFIG_BOARD_TYPES
151*4882a593Smuzhiyun set_board_type();
152*4882a593Smuzhiyun #endif
153*4882a593Smuzhiyun err = board_uart_init();
154*4882a593Smuzhiyun if (err) {
155*4882a593Smuzhiyun debug("UART init failed\n");
156*4882a593Smuzhiyun return err;
157*4882a593Smuzhiyun }
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun #ifdef CONFIG_SYS_I2C_INIT_BOARD
160*4882a593Smuzhiyun board_i2c_init(gd->fdt_blob);
161*4882a593Smuzhiyun #endif
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun return exynos_early_init_f();
164*4882a593Smuzhiyun }
165*4882a593Smuzhiyun #endif
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun #if defined(CONFIG_POWER) || defined(CONFIG_DM_PMIC)
power_init_board(void)168*4882a593Smuzhiyun int power_init_board(void)
169*4882a593Smuzhiyun {
170*4882a593Smuzhiyun set_ps_hold_ctrl();
171*4882a593Smuzhiyun
172*4882a593Smuzhiyun return exynos_power_init();
173*4882a593Smuzhiyun }
174*4882a593Smuzhiyun #endif
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun #ifdef CONFIG_SMC911X
decode_sromc(const void * blob,struct fdt_sromc * config)177*4882a593Smuzhiyun static int decode_sromc(const void *blob, struct fdt_sromc *config)
178*4882a593Smuzhiyun {
179*4882a593Smuzhiyun int err;
180*4882a593Smuzhiyun int node;
181*4882a593Smuzhiyun
182*4882a593Smuzhiyun node = fdtdec_next_compatible(blob, 0, COMPAT_SAMSUNG_EXYNOS5_SROMC);
183*4882a593Smuzhiyun if (node < 0) {
184*4882a593Smuzhiyun debug("Could not find SROMC node\n");
185*4882a593Smuzhiyun return node;
186*4882a593Smuzhiyun }
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun config->bank = fdtdec_get_int(blob, node, "bank", 0);
189*4882a593Smuzhiyun config->width = fdtdec_get_int(blob, node, "width", 2);
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun err = fdtdec_get_int_array(blob, node, "srom-timing", config->timing,
192*4882a593Smuzhiyun FDT_SROM_TIMING_COUNT);
193*4882a593Smuzhiyun if (err < 0) {
194*4882a593Smuzhiyun debug("Could not decode SROMC configuration Error: %s\n",
195*4882a593Smuzhiyun fdt_strerror(err));
196*4882a593Smuzhiyun return -FDT_ERR_NOTFOUND;
197*4882a593Smuzhiyun }
198*4882a593Smuzhiyun return 0;
199*4882a593Smuzhiyun }
200*4882a593Smuzhiyun #endif
201*4882a593Smuzhiyun
board_eth_init(bd_t * bis)202*4882a593Smuzhiyun int board_eth_init(bd_t *bis)
203*4882a593Smuzhiyun {
204*4882a593Smuzhiyun #ifdef CONFIG_SMC911X
205*4882a593Smuzhiyun u32 smc_bw_conf, smc_bc_conf;
206*4882a593Smuzhiyun struct fdt_sromc config;
207*4882a593Smuzhiyun fdt_addr_t base_addr;
208*4882a593Smuzhiyun int node;
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun node = decode_sromc(gd->fdt_blob, &config);
211*4882a593Smuzhiyun if (node < 0) {
212*4882a593Smuzhiyun debug("%s: Could not find sromc configuration\n", __func__);
213*4882a593Smuzhiyun return 0;
214*4882a593Smuzhiyun }
215*4882a593Smuzhiyun node = fdtdec_next_compatible(gd->fdt_blob, node, COMPAT_SMSC_LAN9215);
216*4882a593Smuzhiyun if (node < 0) {
217*4882a593Smuzhiyun debug("%s: Could not find lan9215 configuration\n", __func__);
218*4882a593Smuzhiyun return 0;
219*4882a593Smuzhiyun }
220*4882a593Smuzhiyun
221*4882a593Smuzhiyun /* We now have a node, so any problems from now on are errors */
222*4882a593Smuzhiyun base_addr = fdtdec_get_addr(gd->fdt_blob, node, "reg");
223*4882a593Smuzhiyun if (base_addr == FDT_ADDR_T_NONE) {
224*4882a593Smuzhiyun debug("%s: Could not find lan9215 address\n", __func__);
225*4882a593Smuzhiyun return -1;
226*4882a593Smuzhiyun }
227*4882a593Smuzhiyun
228*4882a593Smuzhiyun /* Ethernet needs data bus width of 16 bits */
229*4882a593Smuzhiyun if (config.width != 2) {
230*4882a593Smuzhiyun debug("%s: Unsupported bus width %d\n", __func__,
231*4882a593Smuzhiyun config.width);
232*4882a593Smuzhiyun return -1;
233*4882a593Smuzhiyun }
234*4882a593Smuzhiyun smc_bw_conf = SROMC_DATA16_WIDTH(config.bank)
235*4882a593Smuzhiyun | SROMC_BYTE_ENABLE(config.bank);
236*4882a593Smuzhiyun
237*4882a593Smuzhiyun smc_bc_conf = SROMC_BC_TACS(config.timing[FDT_SROM_TACS]) |
238*4882a593Smuzhiyun SROMC_BC_TCOS(config.timing[FDT_SROM_TCOS]) |
239*4882a593Smuzhiyun SROMC_BC_TACC(config.timing[FDT_SROM_TACC]) |
240*4882a593Smuzhiyun SROMC_BC_TCOH(config.timing[FDT_SROM_TCOH]) |
241*4882a593Smuzhiyun SROMC_BC_TAH(config.timing[FDT_SROM_TAH]) |
242*4882a593Smuzhiyun SROMC_BC_TACP(config.timing[FDT_SROM_TACP]) |
243*4882a593Smuzhiyun SROMC_BC_PMC(config.timing[FDT_SROM_PMC]);
244*4882a593Smuzhiyun
245*4882a593Smuzhiyun /* Select and configure the SROMC bank */
246*4882a593Smuzhiyun exynos_pinmux_config(PERIPH_ID_SROMC, config.bank);
247*4882a593Smuzhiyun s5p_config_sromc(config.bank, smc_bw_conf, smc_bc_conf);
248*4882a593Smuzhiyun return smc911x_initialize(0, base_addr);
249*4882a593Smuzhiyun #endif
250*4882a593Smuzhiyun return 0;
251*4882a593Smuzhiyun }
252*4882a593Smuzhiyun
253*4882a593Smuzhiyun #ifdef CONFIG_MMC
init_mmc(void)254*4882a593Smuzhiyun static int init_mmc(void)
255*4882a593Smuzhiyun {
256*4882a593Smuzhiyun #ifdef CONFIG_MMC_SDHCI
257*4882a593Smuzhiyun return exynos_mmc_init(gd->fdt_blob);
258*4882a593Smuzhiyun #else
259*4882a593Smuzhiyun return 0;
260*4882a593Smuzhiyun #endif
261*4882a593Smuzhiyun }
262*4882a593Smuzhiyun
init_dwmmc(void)263*4882a593Smuzhiyun static int init_dwmmc(void)
264*4882a593Smuzhiyun {
265*4882a593Smuzhiyun #ifdef CONFIG_MMC_DW
266*4882a593Smuzhiyun return exynos_dwmmc_init(gd->fdt_blob);
267*4882a593Smuzhiyun #else
268*4882a593Smuzhiyun return 0;
269*4882a593Smuzhiyun #endif
270*4882a593Smuzhiyun }
271*4882a593Smuzhiyun
board_mmc_init(bd_t * bis)272*4882a593Smuzhiyun int board_mmc_init(bd_t *bis)
273*4882a593Smuzhiyun {
274*4882a593Smuzhiyun int ret;
275*4882a593Smuzhiyun
276*4882a593Smuzhiyun if (get_boot_mode() == BOOT_MODE_SD) {
277*4882a593Smuzhiyun ret = init_mmc();
278*4882a593Smuzhiyun ret |= init_dwmmc();
279*4882a593Smuzhiyun } else {
280*4882a593Smuzhiyun ret = init_dwmmc();
281*4882a593Smuzhiyun ret |= init_mmc();
282*4882a593Smuzhiyun }
283*4882a593Smuzhiyun
284*4882a593Smuzhiyun if (ret)
285*4882a593Smuzhiyun debug("mmc init failed\n");
286*4882a593Smuzhiyun
287*4882a593Smuzhiyun return ret;
288*4882a593Smuzhiyun }
289*4882a593Smuzhiyun #endif
290*4882a593Smuzhiyun
291*4882a593Smuzhiyun #ifdef CONFIG_DISPLAY_BOARDINFO
checkboard(void)292*4882a593Smuzhiyun int checkboard(void)
293*4882a593Smuzhiyun {
294*4882a593Smuzhiyun const char *board_info;
295*4882a593Smuzhiyun
296*4882a593Smuzhiyun board_info = fdt_getprop(gd->fdt_blob, 0, "model", NULL);
297*4882a593Smuzhiyun printf("Board: %s\n", board_info ? board_info : "unknown");
298*4882a593Smuzhiyun #ifdef CONFIG_BOARD_TYPES
299*4882a593Smuzhiyun board_info = get_board_type();
300*4882a593Smuzhiyun if (board_info)
301*4882a593Smuzhiyun printf("Type: %s\n", board_info);
302*4882a593Smuzhiyun #endif
303*4882a593Smuzhiyun return 0;
304*4882a593Smuzhiyun }
305*4882a593Smuzhiyun #endif
306*4882a593Smuzhiyun
307*4882a593Smuzhiyun #ifdef CONFIG_BOARD_LATE_INIT
board_late_init(void)308*4882a593Smuzhiyun int board_late_init(void)
309*4882a593Smuzhiyun {
310*4882a593Smuzhiyun stdio_print_current_devices();
311*4882a593Smuzhiyun
312*4882a593Smuzhiyun if (cros_ec_get_error()) {
313*4882a593Smuzhiyun /* Force console on */
314*4882a593Smuzhiyun gd->flags &= ~GD_FLG_SILENT;
315*4882a593Smuzhiyun
316*4882a593Smuzhiyun printf("cros-ec communications failure %d\n",
317*4882a593Smuzhiyun cros_ec_get_error());
318*4882a593Smuzhiyun puts("\nPlease reset with Power+Refresh\n\n");
319*4882a593Smuzhiyun panic("Cannot init cros-ec device");
320*4882a593Smuzhiyun return -1;
321*4882a593Smuzhiyun }
322*4882a593Smuzhiyun return 0;
323*4882a593Smuzhiyun }
324*4882a593Smuzhiyun #endif
325*4882a593Smuzhiyun
326*4882a593Smuzhiyun #ifdef CONFIG_MISC_INIT_R
misc_init_r(void)327*4882a593Smuzhiyun int misc_init_r(void)
328*4882a593Smuzhiyun {
329*4882a593Smuzhiyun #ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
330*4882a593Smuzhiyun set_board_info();
331*4882a593Smuzhiyun #endif
332*4882a593Smuzhiyun #ifdef CONFIG_LCD_MENU
333*4882a593Smuzhiyun keys_init();
334*4882a593Smuzhiyun check_boot_mode();
335*4882a593Smuzhiyun #endif
336*4882a593Smuzhiyun #ifdef CONFIG_CMD_BMP
337*4882a593Smuzhiyun if (panel_info.logo_on)
338*4882a593Smuzhiyun draw_logo();
339*4882a593Smuzhiyun #endif
340*4882a593Smuzhiyun return 0;
341*4882a593Smuzhiyun }
342*4882a593Smuzhiyun #endif
343*4882a593Smuzhiyun
reset_misc(void)344*4882a593Smuzhiyun void reset_misc(void)
345*4882a593Smuzhiyun {
346*4882a593Smuzhiyun struct gpio_desc gpio = {};
347*4882a593Smuzhiyun int node;
348*4882a593Smuzhiyun
349*4882a593Smuzhiyun node = fdt_node_offset_by_compatible(gd->fdt_blob, 0,
350*4882a593Smuzhiyun "samsung,emmc-reset");
351*4882a593Smuzhiyun if (node < 0)
352*4882a593Smuzhiyun return;
353*4882a593Smuzhiyun
354*4882a593Smuzhiyun gpio_request_by_name_nodev(offset_to_ofnode(node), "reset-gpio", 0,
355*4882a593Smuzhiyun &gpio, GPIOD_IS_OUT);
356*4882a593Smuzhiyun
357*4882a593Smuzhiyun if (dm_gpio_is_valid(&gpio)) {
358*4882a593Smuzhiyun /*
359*4882a593Smuzhiyun * Reset eMMC
360*4882a593Smuzhiyun *
361*4882a593Smuzhiyun * FIXME: Need to optimize delay time. Minimum 1usec pulse is
362*4882a593Smuzhiyun * required by 'JEDEC Standard No.84-A441' (eMMC)
363*4882a593Smuzhiyun * document but real delay time is expected to greater
364*4882a593Smuzhiyun * than 1usec.
365*4882a593Smuzhiyun */
366*4882a593Smuzhiyun dm_gpio_set_value(&gpio, 0);
367*4882a593Smuzhiyun mdelay(10);
368*4882a593Smuzhiyun dm_gpio_set_value(&gpio, 1);
369*4882a593Smuzhiyun }
370*4882a593Smuzhiyun }
371*4882a593Smuzhiyun
board_usb_cleanup(int index,enum usb_init_type init)372*4882a593Smuzhiyun int board_usb_cleanup(int index, enum usb_init_type init)
373*4882a593Smuzhiyun {
374*4882a593Smuzhiyun #ifdef CONFIG_USB_DWC3
375*4882a593Smuzhiyun dwc3_uboot_exit(index);
376*4882a593Smuzhiyun #endif
377*4882a593Smuzhiyun return 0;
378*4882a593Smuzhiyun }
379