1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright 2018 NXP
4 *
5 */
6
7#include <common.h>
8#include <hang.h>
9#include <init.h>
10#include <asm/arch/ddr.h>
11#include <asm/arch/imx8mq_pins.h>
12#include <asm/arch/sys_proto.h>
13#include <asm/arch/clock.h>
14#include <asm/mach-imx/gpio.h>
15#include <asm/mach-imx/mxc_i2c.h>
16#include <asm/sections.h>
17#include <fsl_esdhc_imx.h>
18#include <linux/delay.h>
19#include <spl.h>
20
21DECLARE_GLOBAL_DATA_PTR;
22
23static void spl_dram_init(void)
24{
25	/* ddr init */
26	ddr_init(&dram_timing);
27}
28
29#define USDHC2_CD_GPIO	IMX_GPIO_NR(2, 12)
30#define USDHC1_PWR_GPIO IMX_GPIO_NR(2, 10)
31#define USDHC2_PWR_GPIO IMX_GPIO_NR(2, 19)
32
33int board_mmc_getcd(struct mmc *mmc)
34{
35	struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
36	int ret = 0;
37
38	switch (cfg->esdhc_base) {
39	case USDHC1_BASE_ADDR:
40		ret = 1;
41		break;
42	case USDHC2_BASE_ADDR:
43		ret = gpio_get_value(USDHC2_CD_GPIO);
44		return ret;
45	}
46
47	return 1;
48}
49
50#define USDHC_PAD_CTRL	(PAD_CTL_DSE6 | PAD_CTL_HYS | PAD_CTL_PUE | \
51			 PAD_CTL_FSEL2)
52#define USDHC_GPIO_PAD_CTRL (PAD_CTL_PUE | PAD_CTL_DSE1)
53
54static iomux_v3_cfg_t const usdhc1_pads[] = {
55	IMX8MQ_PAD_SD1_CLK__USDHC1_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
56	IMX8MQ_PAD_SD1_CMD__USDHC1_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
57	IMX8MQ_PAD_SD1_DATA0__USDHC1_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
58	IMX8MQ_PAD_SD1_DATA1__USDHC1_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
59	IMX8MQ_PAD_SD1_DATA2__USDHC1_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
60	IMX8MQ_PAD_SD1_DATA3__USDHC1_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
61	IMX8MQ_PAD_SD1_DATA4__USDHC1_DATA4 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
62	IMX8MQ_PAD_SD1_DATA5__USDHC1_DATA5 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
63	IMX8MQ_PAD_SD1_DATA6__USDHC1_DATA6 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
64	IMX8MQ_PAD_SD1_DATA7__USDHC1_DATA7 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
65	IMX8MQ_PAD_SD1_RESET_B__GPIO2_IO10 | MUX_PAD_CTRL(NO_PAD_CTRL),
66};
67
68static iomux_v3_cfg_t const usdhc2_pads[] = {
69	IMX8MQ_PAD_SD2_CLK__USDHC2_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
70	IMX8MQ_PAD_SD2_CMD__USDHC2_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
71	IMX8MQ_PAD_SD2_DATA0__USDHC2_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
72	IMX8MQ_PAD_SD2_DATA1__USDHC2_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
73	IMX8MQ_PAD_SD2_DATA2__USDHC2_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
74	IMX8MQ_PAD_SD2_DATA3__USDHC2_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
75	IMX8MQ_PAD_SD2_CD_B__GPIO2_IO12 | MUX_PAD_CTRL(USDHC_GPIO_PAD_CTRL),
76	IMX8MQ_PAD_SD2_RESET_B__GPIO2_IO19 | MUX_PAD_CTRL(USDHC_GPIO_PAD_CTRL),
77};
78
79static struct fsl_esdhc_cfg usdhc_cfg[2] = {
80	{USDHC1_BASE_ADDR, 0, 8},
81	{USDHC2_BASE_ADDR, 0, 4},
82};
83
84int board_mmc_init(struct bd_info *bis)
85{
86	int i, ret;
87	/*
88	 * According to the board_mmc_init() the following map is done:
89	 * (U-Boot device node)    (Physical Port)
90	 * mmc0                    USDHC1
91	 * mmc1                    USDHC2
92	 */
93	for (i = 0; i < CFG_SYS_FSL_USDHC_NUM; i++) {
94		switch (i) {
95		case 0:
96			init_clk_usdhc(0);
97			usdhc_cfg[0].sdhc_clk = mxc_get_clock(USDHC1_CLK_ROOT);
98			imx_iomux_v3_setup_multiple_pads(usdhc1_pads,
99							 ARRAY_SIZE(usdhc1_pads));
100			gpio_request(USDHC1_PWR_GPIO, "usdhc1_reset");
101			gpio_direction_output(USDHC1_PWR_GPIO, 0);
102			udelay(500);
103			gpio_direction_output(USDHC1_PWR_GPIO, 1);
104			break;
105		case 1:
106			init_clk_usdhc(1);
107			usdhc_cfg[1].sdhc_clk = mxc_get_clock(USDHC2_CLK_ROOT);
108			imx_iomux_v3_setup_multiple_pads(usdhc2_pads,
109							 ARRAY_SIZE(usdhc2_pads));
110			gpio_request(USDHC2_PWR_GPIO, "usdhc2_reset");
111			gpio_direction_output(USDHC2_PWR_GPIO, 0);
112			udelay(500);
113			gpio_direction_output(USDHC2_PWR_GPIO, 1);
114			break;
115		default:
116			printf("Warning: you configured more USDHC controllers(%d)"
117					" than supported by the board\n", i + 1);
118			return -EINVAL;
119		}
120
121		ret = fsl_esdhc_initialize(bis, &usdhc_cfg[i]);
122		if (ret)
123			return ret;
124	}
125
126	return 0;
127}
128
129void spl_board_init(void)
130{
131	puts("Normal Boot\n");
132}
133
134void board_init_f(ulong dummy)
135{
136	int ret;
137
138	/* Clear global data */
139	memset((void *)gd, 0, sizeof(gd_t));
140
141	arch_cpu_init();
142
143	init_uart_clk(0);
144
145	board_early_init_f();
146
147	timer_init();
148
149	preloader_console_init();
150
151	/* Clear the BSS. */
152	memset(__bss_start, 0, __bss_end - __bss_start);
153
154	ret = spl_init();
155	if (ret) {
156		debug("spl_init() failed: %d\n", ret);
157		hang();
158	}
159
160	enable_tzc380();
161
162	/* DDR initialization */
163	spl_dram_init();
164
165	board_init_r(NULL, 0);
166}
167