1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2022 Kontron Electronics GmbH
4 */
5
6#include <asm/arch/clock.h>
7#include <asm/arch/mx6-pins.h>
8#include <asm/arch/sys_proto.h>
9#include <asm/arch/crm_regs.h>
10#include <asm/mach-imx/iomux-v3.h>
11#include <asm/sections.h>
12#include <init.h>
13#include <spl.h>
14#include <fsl_esdhc_imx.h>
15#include <mmc.h>
16
17#define SPI_PAD_CTRL (PAD_CTL_HYS | PAD_CTL_SPEED_MED | 	\
18	PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST)
19
20#define UART_PAD_CTRL  (PAD_CTL_PUS_100K_UP |			\
21	PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm |			\
22	PAD_CTL_SRE_FAST | PAD_CTL_HYS)
23
24#define USDHC_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_PUE |		\
25	PAD_CTL_PUS_22K_UP | PAD_CTL_SPEED_LOW |		\
26	PAD_CTL_DSE_80ohm | PAD_CTL_SRE_FAST | PAD_CTL_HYS)
27
28#define GPIO_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_PUE |		\
29	PAD_CTL_PUS_100K_DOWN | PAD_CTL_SPEED_LOW |		\
30	PAD_CTL_DSE_80ohm | PAD_CTL_SRE_FAST | PAD_CTL_HYS)
31
32static const iomux_v3_cfg_t ecspi2_pads[] = {
33	MX6_PAD_CSI0_DAT10__ECSPI2_MISO | MUX_PAD_CTRL(SPI_PAD_CTRL),
34	MX6_PAD_CSI0_DAT9__ECSPI2_MOSI | MUX_PAD_CTRL(SPI_PAD_CTRL),
35	MX6_PAD_CSI0_DAT8__ECSPI2_SCLK | MUX_PAD_CTRL(SPI_PAD_CTRL),
36	MX6_PAD_CSI0_DAT11__GPIO5_IO29  | MUX_PAD_CTRL(NO_PAD_CTRL),
37};
38
39static const iomux_v3_cfg_t uart2_pads[] = {
40	MX6_PAD_SD4_DAT7__UART2_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
41	MX6_PAD_SD4_DAT4__UART2_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
42};
43
44static const iomux_v3_cfg_t usdhc3_pads[] = {
45	MX6_PAD_SD3_CLK__SD3_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
46	MX6_PAD_SD3_CMD__SD3_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
47	MX6_PAD_SD3_DAT0__SD3_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
48	MX6_PAD_SD3_DAT1__SD3_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
49	MX6_PAD_SD3_DAT2__SD3_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
50	MX6_PAD_SD3_DAT3__SD3_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
51
52	/* CD */
53	MX6_PAD_GPIO_4__GPIO1_IO04 | MUX_PAD_CTRL(GPIO_PAD_CTRL),
54};
55
56#define USDHC3_CD_GPIO	IMX_GPIO_NR(1, 4)
57#define SPI2_CS_GPIO	IMX_GPIO_NR(5, 29)
58
59static struct fsl_esdhc_cfg usdhc_cfg[1] = {
60	{USDHC3_BASE_ADDR, 0, 4},
61};
62
63int board_mmc_getcd(struct mmc *mmc)
64{
65	struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
66	int ret = 0;
67
68	switch (cfg->esdhc_base) {
69	case USDHC3_BASE_ADDR:
70		ret = !gpio_get_value(USDHC3_CD_GPIO);
71		break;
72	}
73
74	return ret;
75}
76
77int board_mmc_init(struct bd_info *bis)
78{
79	int i, ret;
80
81	/*
82	 * According to the board_mmc_init() the following map is done:
83	 * (U-boot device node)    (Physical Port)
84	 * mmc0                    USDHC1
85	 * mmc1                    USDHC2
86	 */
87	for (i = 0; i < CFG_SYS_FSL_USDHC_NUM; i++) {
88		switch (i) {
89		case 0:
90			imx_iomux_v3_setup_multiple_pads(usdhc3_pads,
91							 ARRAY_SIZE(usdhc3_pads));
92			gpio_direction_input(USDHC3_CD_GPIO);
93			usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK);
94			break;
95		default:
96			printf("Warning: you configured more USDHC controllers (%d) than supported by the board\n",
97			       i + 1);
98			return -EINVAL;
99		}
100
101		ret = fsl_esdhc_initialize(bis, &usdhc_cfg[i]);
102		if (ret) {
103			printf("Warning: failed to initialize mmc dev %d\n", i);
104			return ret;
105		}
106	}
107	return 0;
108}
109
110static void ccgr_init(void)
111{
112	struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
113
114	writel(0x00C03F3F, &ccm->CCGR0);
115	writel(0x0030FC03, &ccm->CCGR1);
116	writel(0x0FFFC000, &ccm->CCGR2);
117	writel(0x3FF00000, &ccm->CCGR3);
118	writel(0x00FFF300, &ccm->CCGR4);
119	writel(0x0F0000C3, &ccm->CCGR5);
120	writel(0x000003FF, &ccm->CCGR6);
121}
122
123static int mx6ssielaff_dcd_table[] = {
124	0x020e0774, 0x000C0000,
125	0x020e0754, 0x00000000,
126	0x020e04ac, 0x00000030,
127	0x020e04b0, 0x00000030,
128	0x020e0464, 0x00000030,
129	0x020e0490, 0x00000030,
130	0x020e074c, 0x00000030,
131	0x020e0494, 0x00000030,
132	0x020e04a0, 0x00000000,
133	0x020e04b4, 0x00000030,
134	0x020e04b8, 0x00000030,
135	0x020e076c, 0x00000030,
136	0x020e0750, 0x00020000,
137	0x020e04bc, 0x00000030,
138	0x020e04c0, 0x00000030,
139	0x020e04c4, 0x00000030,
140	0x020e04c8, 0x00000030,
141	0x020e0760, 0x00020000,
142	0x020e0764, 0x00000030,
143	0x020e0770, 0x00000030,
144	0x020e0778, 0x00000030,
145	0x020e077c, 0x00000030,
146	0x020e0470, 0x00000030,
147	0x020e0474, 0x00000030,
148	0x020e0478, 0x00000030,
149	0x020e047c, 0x00000030,
150	0x021b001c, 0x00008000,
151	0x021b0800, 0xA1390003,
152	0x021b080c, 0x00350035,
153	0x021b0810, 0x002A0032,
154	0x021b083c, 0x02340234,
155	0x021b0840, 0x02200220,
156	0x021b0848, 0x4650504E,
157	0x021b0850, 0x3A342E34,
158	0x021b081c, 0x33333333,
159	0x021b0820, 0x33333333,
160	0x021b0824, 0x33333333,
161	0x021b0828, 0x33333333,
162	0x021b08b8, 0x00000800,
163	0x021b0004, 0x0002002D,
164	0x021b0008, 0x00333040,
165	0x021b000c, 0x676B52F3,
166	0x021b0010, 0xB66D8B63,
167	0x021b0014, 0x01FF00DB,
168	0x021b0018, 0x00011740,
169	0x021b001c, 0x00008000,
170	0x021b002c, 0x000026D2,
171	0x021b0030, 0x006B1023,
172	0x021b0040, 0x00000027,
173	0x021b0000, 0x84190000,
174	0x021b001c, 0x02008032,
175	0x021b001c, 0x00008033,
176	0x021b001c, 0x00048031,
177	0x021b001c, 0x15208030,
178	0x021b001c, 0x04008040,
179	0x021b0020, 0x00007800,
180	0x021b0818, 0x00022227,
181	0x021b0004, 0x0002556D,
182	0x021b0404, 0x00011006,
183	0x021b001c, 0x00000000,
184	0x020c4068, 0x00C03F3F,
185	0x020c406c, 0x0030FC03,
186	0x020c4070, 0x0FFFC000,
187	0x020c4074, 0x3FF00000,
188	0x020c4078, 0xFFFFF300,
189	0x020c407c, 0x0F0000C3,
190	0x020c4080, 0x000003FF,
191	0x020e0010, 0xF00000CF,
192	0x020e0018, 0x007F007F,
193	0x020e001c, 0x007F007F,
194};
195
196static void ddr_init(int *table, int size)
197{
198	int i;
199
200	for (i = 0; i < size / 2 ; i++)
201		writel(table[2 * i + 1], table[2 * i]);
202}
203
204static void spl_dram_init(void)
205{
206	ddr_init(mx6ssielaff_dcd_table, ARRAY_SIZE(mx6ssielaff_dcd_table));
207}
208
209int board_spi_cs_gpio(unsigned int bus, unsigned int cs)
210{
211	return (bus == CONFIG_SF_DEFAULT_BUS && cs == CONFIG_SF_DEFAULT_CS)
212		? SPI2_CS_GPIO : -1;
213}
214
215static void setup_spi(void)
216{
217	imx_iomux_v3_setup_multiple_pads(ecspi2_pads, ARRAY_SIZE(ecspi2_pads));
218	gpio_request(SPI2_CS_GPIO, "spi2_cs0");
219	gpio_direction_output(SPI2_CS_GPIO, 1);
220	enable_spi_clk(true, 1);
221}
222
223void board_init_f(ulong dummy)
224{
225	/* setup AIPS and disable watchdog */
226	arch_cpu_init();
227
228	ccgr_init();
229	gpr_init();
230
231	/* IOMUX UART */
232	imx_iomux_v3_setup_multiple_pads(uart2_pads, ARRAY_SIZE(uart2_pads));
233
234	/* setup GP timer */
235	timer_init();
236
237	/* UART clocks enabled and gd valid - init serial console */
238	preloader_console_init();
239
240	/* DDR initialization */
241	spl_dram_init();
242
243	/* Clear the BSS. */
244	memset(__bss_start, 0, __bss_end - __bss_start);
245
246	/* SPI */
247	setup_spi();
248
249	/* load/boot image from boot device */
250	board_init_r(NULL, 0);
251}
252
253void board_boot_order(u32 *spl_boot_list)
254{
255	u32 bootdev = spl_boot_device();
256
257	/*
258	 * The default boot fuse settings use the SD card (MMC1) as primary
259	 * boot device, but allow SPI NOR as a fallback boot device.
260	 * We can't detect the fallback case and spl_boot_device() will return
261	 * BOOT_DEVICE_MMC1 despite the actual boot device being SPI NOR.
262	 * Therefore we try to load U-Boot proper vom SPI NOR after loading
263	 * from MMC has failed.
264	 */
265	spl_boot_list[0] = bootdev;
266
267	switch (bootdev) {
268	case BOOT_DEVICE_MMC1:
269	case BOOT_DEVICE_MMC2:
270		spl_boot_list[1] = BOOT_DEVICE_SPI;
271		break;
272	}
273}
274