]>
Commit | Line | Data |
---|---|---|
b8ce6fe2 FE |
1 | /* |
2 | * Copyright (C) 2015 Freescale Semiconductor, Inc. | |
3 | * | |
4 | * Author: Fabio Estevam <fabio.estevam@freescale.com> | |
5 | * | |
6 | * Copyright (C) 2013 Jon Nettleton <jon.nettleton@gmail.com> | |
7 | * | |
8 | * Based on SPL code from Solidrun tree, which is: | |
9 | * Author: Tungyi Lin <tungyilin1127@gmail.com> | |
10 | * | |
11 | * Derived from EDM_CF_IMX6 code by TechNexion,Inc | |
12 | * Ported to SolidRun microSOM by Rabeeh Khoury <rabeeh@solid-run.com> | |
13 | * | |
14 | * SPDX-License-Identifier: GPL-2.0+ | |
15 | */ | |
16 | ||
17 | #include <asm/arch/clock.h> | |
18 | #include <asm/arch/imx-regs.h> | |
19 | #include <asm/arch/iomux.h> | |
20 | #include <asm/arch/mx6-pins.h> | |
21 | #include <asm/errno.h> | |
22 | #include <asm/gpio.h> | |
23 | #include <asm/imx-common/iomux-v3.h> | |
24 | #include <mmc.h> | |
25 | #include <fsl_esdhc.h> | |
26 | #include <miiphy.h> | |
27 | #include <netdev.h> | |
28 | #include <asm/arch/crm_regs.h> | |
29 | #include <asm/io.h> | |
30 | #include <asm/arch/sys_proto.h> | |
31 | #include <asm/arch/mx6-ddr.h> | |
32 | #include <spl.h> | |
33 | ||
34 | DECLARE_GLOBAL_DATA_PTR; | |
35 | ||
36 | #define UART_PAD_CTRL (PAD_CTL_PUS_100K_UP | \ | |
37 | PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | \ | |
38 | PAD_CTL_SRE_FAST | PAD_CTL_HYS) | |
39 | ||
40 | #define USDHC_PAD_CTRL (PAD_CTL_PUS_47K_UP | \ | |
41 | PAD_CTL_SPEED_LOW | PAD_CTL_DSE_80ohm | \ | |
42 | PAD_CTL_SRE_FAST | PAD_CTL_HYS) | |
43 | ||
44 | #define ENET_PAD_CTRL (PAD_CTL_PUS_100K_UP | \ | |
45 | PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_HYS) | |
46 | ||
47 | #define ENET_PAD_CTRL_PD (PAD_CTL_PUS_100K_DOWN | \ | |
48 | PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_HYS) | |
49 | ||
50 | #define ENET_PAD_CTRL_CLK ((PAD_CTL_PUS_100K_UP & ~PAD_CTL_PKE) | \ | |
51 | PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST) | |
52 | ||
53 | #define ETH_PHY_RESET IMX_GPIO_NR(4, 15) | |
54 | ||
55 | int dram_init(void) | |
56 | { | |
57 | gd->ram_size = imx_ddr_size(); | |
58 | return 0; | |
59 | } | |
60 | ||
61 | static iomux_v3_cfg_t const uart1_pads[] = { | |
62 | MX6_PAD_CSI0_DAT10__UART1_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL), | |
63 | MX6_PAD_CSI0_DAT11__UART1_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL), | |
64 | }; | |
65 | ||
66 | static iomux_v3_cfg_t const usdhc2_pads[] = { | |
67 | MX6_PAD_SD2_CLK__SD2_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL), | |
68 | MX6_PAD_SD2_CMD__SD2_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL), | |
69 | MX6_PAD_SD2_DAT0__SD2_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL), | |
70 | MX6_PAD_SD2_DAT1__SD2_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL), | |
71 | MX6_PAD_SD2_DAT2__SD2_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL), | |
72 | MX6_PAD_SD2_DAT3__SD2_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL), | |
73 | }; | |
74 | ||
75 | static void setup_iomux_uart(void) | |
76 | { | |
77 | imx_iomux_v3_setup_multiple_pads(uart1_pads, ARRAY_SIZE(uart1_pads)); | |
78 | } | |
79 | ||
80 | static struct fsl_esdhc_cfg usdhc_cfg[1] = { | |
81 | {USDHC2_BASE_ADDR}, | |
82 | }; | |
83 | ||
84 | int board_mmc_getcd(struct mmc *mmc) | |
85 | { | |
86 | return 1; /* uSDHC2 is always present */ | |
87 | } | |
88 | ||
89 | int board_mmc_init(bd_t *bis) | |
90 | { | |
91 | imx_iomux_v3_setup_multiple_pads(usdhc2_pads, ARRAY_SIZE(usdhc2_pads)); | |
92 | usdhc_cfg[0].esdhc_base = USDHC2_BASE_ADDR; | |
93 | usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK); | |
94 | gd->arch.sdhc_clk = usdhc_cfg[0].sdhc_clk; | |
95 | ||
96 | return fsl_esdhc_initialize(bis, &usdhc_cfg[0]); | |
97 | } | |
98 | ||
99 | static iomux_v3_cfg_t const enet_pads[] = { | |
100 | MX6_PAD_ENET_MDIO__ENET_MDIO | MUX_PAD_CTRL(ENET_PAD_CTRL), | |
101 | MX6_PAD_ENET_MDC__ENET_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL), | |
102 | /* AR8035 reset */ | |
103 | MX6_PAD_KEY_ROW4__GPIO4_IO15 | MUX_PAD_CTRL(ENET_PAD_CTRL_PD), | |
104 | /* AR8035 interrupt */ | |
105 | MX6_PAD_DI0_PIN2__GPIO4_IO18 | MUX_PAD_CTRL(NO_PAD_CTRL), | |
106 | /* GPIO16 -> AR8035 25MHz */ | |
107 | MX6_PAD_GPIO_16__ENET_REF_CLK | MUX_PAD_CTRL(NO_PAD_CTRL), | |
108 | MX6_PAD_RGMII_TXC__RGMII_TXC | MUX_PAD_CTRL(NO_PAD_CTRL), | |
109 | MX6_PAD_RGMII_TD0__RGMII_TD0 | MUX_PAD_CTRL(ENET_PAD_CTRL), | |
110 | MX6_PAD_RGMII_TD1__RGMII_TD1 | MUX_PAD_CTRL(ENET_PAD_CTRL), | |
111 | MX6_PAD_RGMII_TD2__RGMII_TD2 | MUX_PAD_CTRL(ENET_PAD_CTRL), | |
112 | MX6_PAD_RGMII_TD3__RGMII_TD3 | MUX_PAD_CTRL(ENET_PAD_CTRL), | |
113 | MX6_PAD_RGMII_TX_CTL__RGMII_TX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL), | |
114 | /* AR8035 CLK_25M --> ENET_REF_CLK (V22) */ | |
115 | MX6_PAD_ENET_REF_CLK__ENET_TX_CLK | MUX_PAD_CTRL(ENET_PAD_CTRL_CLK), | |
116 | MX6_PAD_RGMII_RXC__RGMII_RXC | MUX_PAD_CTRL(ENET_PAD_CTRL), | |
117 | MX6_PAD_RGMII_RD0__RGMII_RD0 | MUX_PAD_CTRL(ENET_PAD_CTRL_PD), | |
118 | MX6_PAD_RGMII_RD1__RGMII_RD1 | MUX_PAD_CTRL(ENET_PAD_CTRL_PD), | |
119 | MX6_PAD_RGMII_RD2__RGMII_RD2 | MUX_PAD_CTRL(ENET_PAD_CTRL), | |
120 | MX6_PAD_RGMII_RD3__RGMII_RD3 | MUX_PAD_CTRL(ENET_PAD_CTRL), | |
121 | MX6_PAD_RGMII_RX_CTL__RGMII_RX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL_PD), | |
122 | }; | |
123 | ||
124 | static void setup_iomux_enet(void) | |
125 | { | |
126 | imx_iomux_v3_setup_multiple_pads(enet_pads, ARRAY_SIZE(enet_pads)); | |
127 | ||
128 | gpio_direction_output(ETH_PHY_RESET, 0); | |
129 | mdelay(2); | |
130 | gpio_set_value(ETH_PHY_RESET, 1); | |
131 | } | |
132 | ||
133 | int board_phy_config(struct phy_device *phydev) | |
134 | { | |
135 | if (phydev->drv->config) | |
136 | phydev->drv->config(phydev); | |
137 | ||
138 | return 0; | |
139 | } | |
140 | ||
141 | int board_eth_init(bd_t *bis) | |
142 | { | |
143 | struct iomuxc *const iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR; | |
144 | ||
145 | int ret = enable_fec_anatop_clock(ENET_25MHZ); | |
146 | if (ret) | |
147 | return ret; | |
148 | ||
149 | /* set gpr1[ENET_CLK_SEL] */ | |
150 | setbits_le32(&iomuxc_regs->gpr[1], IOMUXC_GPR1_ENET_CLK_SEL_MASK); | |
151 | ||
152 | setup_iomux_enet(); | |
153 | ||
154 | return cpu_eth_init(bis); | |
155 | } | |
156 | ||
157 | int board_early_init_f(void) | |
158 | { | |
159 | setup_iomux_uart(); | |
160 | return 0; | |
161 | } | |
162 | ||
163 | int board_init(void) | |
164 | { | |
165 | /* address of boot parameters */ | |
166 | gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100; | |
167 | ||
168 | return 0; | |
169 | } | |
170 | ||
171 | int checkboard(void) | |
172 | { | |
173 | puts("Board: MX6 Hummingboard\n"); | |
174 | return 0; | |
175 | } | |
176 | ||
177 | #ifdef CONFIG_SPL_BUILD | |
178 | static const struct mx6dq_iomux_ddr_regs mx6_ddr_ioregs = { | |
179 | .dram_sdclk_0 = 0x00020030, | |
180 | .dram_sdclk_1 = 0x00020030, | |
181 | .dram_cas = 0x00020030, | |
182 | .dram_ras = 0x00020030, | |
183 | .dram_reset = 0x00020030, | |
184 | .dram_sdcke0 = 0x00003000, | |
185 | .dram_sdcke1 = 0x00003000, | |
186 | .dram_sdba2 = 0x00000000, | |
187 | .dram_sdodt0 = 0x00003030, | |
188 | .dram_sdodt1 = 0x00003030, | |
189 | .dram_sdqs0 = 0x00000030, | |
190 | .dram_sdqs1 = 0x00000030, | |
191 | .dram_sdqs2 = 0x00000030, | |
192 | .dram_sdqs3 = 0x00000030, | |
193 | .dram_sdqs4 = 0x00000030, | |
194 | .dram_sdqs5 = 0x00000030, | |
195 | .dram_sdqs6 = 0x00000030, | |
196 | .dram_sdqs7 = 0x00000030, | |
197 | .dram_dqm0 = 0x00020030, | |
198 | .dram_dqm1 = 0x00020030, | |
199 | .dram_dqm2 = 0x00020030, | |
200 | .dram_dqm3 = 0x00020030, | |
201 | .dram_dqm4 = 0x00020030, | |
202 | .dram_dqm5 = 0x00020030, | |
203 | .dram_dqm6 = 0x00020030, | |
204 | .dram_dqm7 = 0x00020030, | |
205 | }; | |
206 | ||
207 | static const struct mx6dq_iomux_grp_regs mx6_grp_ioregs = { | |
208 | .grp_ddr_type = 0x000C0000, | |
209 | .grp_ddrmode_ctl = 0x00020000, | |
210 | .grp_ddrpke = 0x00000000, | |
211 | .grp_addds = 0x00000030, | |
212 | .grp_ctlds = 0x00000030, | |
213 | .grp_ddrmode = 0x00020000, | |
214 | .grp_b0ds = 0x00000030, | |
215 | .grp_b1ds = 0x00000030, | |
216 | .grp_b2ds = 0x00000030, | |
217 | .grp_b3ds = 0x00000030, | |
218 | .grp_b4ds = 0x00000030, | |
219 | .grp_b5ds = 0x00000030, | |
220 | .grp_b6ds = 0x00000030, | |
221 | .grp_b7ds = 0x00000030, | |
222 | }; | |
223 | ||
224 | static const struct mx6_mmdc_calibration mx6_mmcd_calib = { | |
225 | .p0_mpwldectrl0 = 0x00000000, | |
226 | .p0_mpwldectrl1 = 0x00000000, | |
227 | .p1_mpwldectrl0 = 0x00000000, | |
228 | .p1_mpwldectrl1 = 0x00000000, | |
229 | .p0_mpdgctrl0 = 0x0314031c, | |
230 | .p0_mpdgctrl1 = 0x023e0304, | |
231 | .p1_mpdgctrl0 = 0x03240330, | |
232 | .p1_mpdgctrl1 = 0x03180260, | |
233 | .p0_mprddlctl = 0x3630323c, | |
234 | .p1_mprddlctl = 0x3436283a, | |
235 | .p0_mpwrdlctl = 0x36344038, | |
236 | .p1_mpwrdlctl = 0x422a423c, | |
237 | }; | |
238 | ||
239 | static struct mx6_ddr3_cfg mem_ddr = { | |
240 | .mem_speed = 1600, | |
241 | .density = 2, | |
242 | .width = 16, | |
243 | .banks = 8, | |
244 | .rowaddr = 14, | |
245 | .coladdr = 10, | |
246 | .pagesz = 2, | |
247 | .trcd = 1375, | |
248 | .trcmin = 4875, | |
249 | .trasmin = 3500, | |
250 | .SRT = 1, | |
251 | }; | |
252 | ||
253 | static void ccgr_init(void) | |
254 | { | |
255 | struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; | |
256 | ||
257 | writel(0x00C03F3F, &ccm->CCGR0); | |
258 | writel(0x0030FC03, &ccm->CCGR1); | |
259 | writel(0x0FFFC000, &ccm->CCGR2); | |
260 | writel(0x3FF00000, &ccm->CCGR3); | |
261 | writel(0x00FFF300, &ccm->CCGR4); | |
262 | writel(0x0F0000C3, &ccm->CCGR5); | |
263 | writel(0x000003FF, &ccm->CCGR6); | |
264 | } | |
265 | ||
266 | static void gpr_init(void) | |
267 | { | |
268 | struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR; | |
269 | ||
270 | /* enable AXI cache for VDOA/VPU/IPU */ | |
271 | writel(0xF00000CF, &iomux->gpr[4]); | |
272 | /* set IPU AXI-id0 Qos=0xf(bypass) AXI-id1 Qos=0x7 */ | |
273 | writel(0x007F007F, &iomux->gpr[6]); | |
274 | writel(0x007F007F, &iomux->gpr[7]); | |
275 | } | |
276 | ||
277 | /* | |
278 | * This section requires the differentiation between Solidrun mx6 boards, but | |
279 | * for now, it will configure only for the mx6dual hummingboard version. | |
280 | */ | |
281 | static void spl_dram_init(void) | |
282 | { | |
283 | struct mx6_ddr_sysinfo sysinfo = { | |
284 | /* width of data bus: 0=16, 1=32, 2=64 */ | |
285 | .dsize = 2, | |
286 | /* config for full 4GB range so that get_mem_size() works */ | |
287 | .cs_density = 32, /* 32Gb per CS */ | |
288 | .ncs = 1, /* single chip select */ | |
289 | .cs1_mirror = 0, | |
290 | .rtt_wr = 1 /*DDR3_RTT_60_OHM*/, /* RTT_Wr = RZQ/4 */ | |
291 | .rtt_nom = 1 /*DDR3_RTT_60_OHM*/, /* RTT_Nom = RZQ/4 */ | |
292 | .walat = 1, /* Write additional latency */ | |
293 | .ralat = 5, /* Read additional latency */ | |
294 | .mif3_mode = 3, /* Command prediction working mode */ | |
295 | .bi_on = 1, /* Bank interleaving enabled */ | |
296 | .sde_to_rst = 0x10, /* 14 cycles, 200us (JEDEC default) */ | |
297 | .rst_to_cke = 0x23, /* 33 cycles, 500us (JEDEC default) */ | |
298 | }; | |
299 | ||
300 | mx6dq_dram_iocfg(64, &mx6_ddr_ioregs, &mx6_grp_ioregs); | |
301 | mx6_dram_cfg(&sysinfo, &mx6_mmcd_calib, &mem_ddr); | |
302 | } | |
303 | ||
304 | void board_init_f(ulong dummy) | |
305 | { | |
306 | /* setup AIPS and disable watchdog */ | |
307 | arch_cpu_init(); | |
308 | ||
309 | ccgr_init(); | |
310 | gpr_init(); | |
311 | ||
312 | /* iomux and setup of i2c */ | |
313 | board_early_init_f(); | |
314 | ||
315 | /* setup GP timer */ | |
316 | timer_init(); | |
317 | ||
318 | /* UART clocks enabled and gd valid - init serial console */ | |
319 | preloader_console_init(); | |
320 | ||
321 | /* DDR initialization */ | |
322 | spl_dram_init(); | |
323 | ||
324 | /* Clear the BSS. */ | |
325 | memset(__bss_start, 0, __bss_end - __bss_start); | |
326 | ||
327 | /* load/boot image from boot device */ | |
328 | board_init_r(NULL, 0); | |
329 | } | |
330 | #endif |