blob: 6815952c0fbb80ded7ea072039c69383e850416b [file] [log] [blame]
Frieder Schrempf9569c932024-02-15 15:00:35 +01001// 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:
Frieder Schrempffe4b99b2024-02-20 10:01:00 +010096 printf("Warning: you configured more USDHC controllers (%d) than supported by the board\n",
97 i + 1);
Frieder Schrempf9569c932024-02-15 15:00:35 +010098 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}