xref: /openbmc/u-boot/arch/arm/mach-imx/mx6/opos6ul.c (revision c5d548a9f881b2268f1d81dab9cd329ae336607e)
183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
2552a848eSStefano Babic /*
330754ef7SSébastien Szymanski  * Copyright (C) 2018 Armadeus Systems
4552a848eSStefano Babic  */
5552a848eSStefano Babic 
6552a848eSStefano Babic #include <asm/arch/clock.h>
7552a848eSStefano Babic #include <asm/arch/crm_regs.h>
8552a848eSStefano Babic #include <asm/arch/imx-regs.h>
9552a848eSStefano Babic #include <asm/arch/iomux.h>
10552a848eSStefano Babic #include <asm/arch/mx6-pins.h>
11552a848eSStefano Babic #include <asm/arch/sys_proto.h>
12552a848eSStefano Babic #include <asm/gpio.h>
13552a848eSStefano Babic #include <asm/mach-imx/iomux-v3.h>
14552a848eSStefano Babic #include <asm/io.h>
15552a848eSStefano Babic #include <common.h>
16552a848eSStefano Babic #include <environment.h>
17552a848eSStefano Babic 
18552a848eSStefano Babic DECLARE_GLOBAL_DATA_PTR;
19552a848eSStefano Babic 
20552a848eSStefano Babic #ifdef CONFIG_FEC_MXC
21552a848eSStefano Babic #include <miiphy.h>
22552a848eSStefano Babic 
23552a848eSStefano Babic #define MDIO_PAD_CTRL ( \
24552a848eSStefano Babic 	PAD_CTL_HYS | PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | \
25552a848eSStefano Babic 	PAD_CTL_DSE_40ohm \
26552a848eSStefano Babic )
27552a848eSStefano Babic 
28552a848eSStefano Babic #define ENET_PAD_CTRL_PU ( \
29552a848eSStefano Babic 	PAD_CTL_HYS | PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | \
30552a848eSStefano Babic 	PAD_CTL_DSE_40ohm \
31552a848eSStefano Babic )
32552a848eSStefano Babic 
33552a848eSStefano Babic #define ENET_PAD_CTRL_PD ( \
34552a848eSStefano Babic 	PAD_CTL_HYS | PAD_CTL_PUS_100K_DOWN | PAD_CTL_SPEED_MED | \
35552a848eSStefano Babic 	PAD_CTL_DSE_40ohm \
36552a848eSStefano Babic )
37552a848eSStefano Babic 
38552a848eSStefano Babic #define ENET_CLK_PAD_CTRL ( \
39552a848eSStefano Babic 	PAD_CTL_HYS | PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_LOW | \
40552a848eSStefano Babic 	PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST \
41552a848eSStefano Babic )
42552a848eSStefano Babic 
43552a848eSStefano Babic static iomux_v3_cfg_t const fec1_pads[] = {
44552a848eSStefano Babic 	MX6_PAD_GPIO1_IO06__ENET1_MDIO        | MUX_PAD_CTRL(MDIO_PAD_CTRL),
45552a848eSStefano Babic 	MX6_PAD_GPIO1_IO07__ENET1_MDC         | MUX_PAD_CTRL(MDIO_PAD_CTRL),
46552a848eSStefano Babic 	MX6_PAD_ENET1_RX_ER__ENET1_RX_ER      | MUX_PAD_CTRL(ENET_PAD_CTRL_PD),
47552a848eSStefano Babic 	MX6_PAD_ENET1_RX_EN__ENET1_RX_EN      | MUX_PAD_CTRL(ENET_PAD_CTRL_PD),
48552a848eSStefano Babic 	MX6_PAD_ENET1_RX_DATA1__ENET1_RDATA01 | MUX_PAD_CTRL(ENET_PAD_CTRL_PD),
49552a848eSStefano Babic 	MX6_PAD_ENET1_RX_DATA0__ENET1_RDATA00 | MUX_PAD_CTRL(ENET_PAD_CTRL_PD),
50552a848eSStefano Babic 	MX6_PAD_ENET1_TX_DATA0__ENET1_TDATA00 | MUX_PAD_CTRL(ENET_PAD_CTRL_PU),
51552a848eSStefano Babic 	MX6_PAD_ENET1_TX_DATA1__ENET1_TDATA01 | MUX_PAD_CTRL(ENET_PAD_CTRL_PU),
52552a848eSStefano Babic 	MX6_PAD_ENET1_TX_EN__ENET1_TX_EN      | MUX_PAD_CTRL(ENET_PAD_CTRL_PU),
53552a848eSStefano Babic 	/* PHY Int */
54552a848eSStefano Babic 	MX6_PAD_NAND_DQS__GPIO4_IO16          | MUX_PAD_CTRL(ENET_PAD_CTRL_PU),
55552a848eSStefano Babic 	/* PHY Reset */
56552a848eSStefano Babic 	MX6_PAD_NAND_DATA00__GPIO4_IO02       | MUX_PAD_CTRL(ENET_PAD_CTRL_PD),
57552a848eSStefano Babic 	MX6_PAD_ENET1_TX_CLK__ENET1_REF_CLK1  | MUX_PAD_CTRL(ENET_CLK_PAD_CTRL),
58552a848eSStefano Babic };
59552a848eSStefano Babic 
board_phy_config(struct phy_device * phydev)60552a848eSStefano Babic int board_phy_config(struct phy_device *phydev)
61552a848eSStefano Babic {
62552a848eSStefano Babic 	phy_write(phydev, MDIO_DEVAD_NONE, 0x1f, 0x8190);
63552a848eSStefano Babic 
64552a848eSStefano Babic 	if (phydev->drv->config)
65552a848eSStefano Babic 		phydev->drv->config(phydev);
66552a848eSStefano Babic 
67552a848eSStefano Babic 	return 0;
68552a848eSStefano Babic }
69552a848eSStefano Babic 
board_eth_init(bd_t * bis)70552a848eSStefano Babic int board_eth_init(bd_t *bis)
71552a848eSStefano Babic {
72552a848eSStefano Babic 	struct iomuxc *const iomuxc_regs = (struct iomuxc *)IOMUXC_BASE_ADDR;
73552a848eSStefano Babic 	struct gpio_desc rst;
74552a848eSStefano Babic 	int ret;
75552a848eSStefano Babic 
76552a848eSStefano Babic 	/* Use 50M anatop loopback REF_CLK1 for ENET1,
77552a848eSStefano Babic 	 * clear gpr1[13], set gpr1[17] */
78552a848eSStefano Babic 	clrsetbits_le32(&iomuxc_regs->gpr[1], IOMUX_GPR1_FEC1_MASK,
79552a848eSStefano Babic 			IOMUX_GPR1_FEC1_CLOCK_MUX1_SEL_MASK);
80552a848eSStefano Babic 
81552a848eSStefano Babic 	ret = enable_fec_anatop_clock(0, ENET_50MHZ);
82552a848eSStefano Babic 	if (ret)
83552a848eSStefano Babic 		return ret;
84552a848eSStefano Babic 
85552a848eSStefano Babic 	enable_enet_clk(1);
86552a848eSStefano Babic 
87552a848eSStefano Babic 	imx_iomux_v3_setup_multiple_pads(fec1_pads, ARRAY_SIZE(fec1_pads));
88552a848eSStefano Babic 
89552a848eSStefano Babic 	ret = dm_gpio_lookup_name("GPIO4_2", &rst);
90552a848eSStefano Babic 	if (ret) {
91552a848eSStefano Babic 		printf("Cannot get GPIO4_2\n");
92552a848eSStefano Babic 		return ret;
93552a848eSStefano Babic 	}
94552a848eSStefano Babic 
95552a848eSStefano Babic 	ret = dm_gpio_request(&rst, "phy-rst");
96552a848eSStefano Babic 	if (ret) {
97552a848eSStefano Babic 		printf("Cannot request GPIO4_2\n");
98552a848eSStefano Babic 		return ret;
99552a848eSStefano Babic 	}
100552a848eSStefano Babic 
101552a848eSStefano Babic 	dm_gpio_set_dir_flags(&rst, GPIOD_IS_OUT);
102552a848eSStefano Babic 	dm_gpio_set_value(&rst, 0);
103552a848eSStefano Babic 	udelay(1000);
104552a848eSStefano Babic 	dm_gpio_set_value(&rst, 1);
105552a848eSStefano Babic 
106552a848eSStefano Babic 	return fecmxc_initialize(bis);
107552a848eSStefano Babic }
108552a848eSStefano Babic #endif /* CONFIG_FEC_MXC */
109552a848eSStefano Babic 
board_init(void)110552a848eSStefano Babic int board_init(void)
111552a848eSStefano Babic {
112552a848eSStefano Babic 	/* Address of boot parameters */
113552a848eSStefano Babic 	gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;
114552a848eSStefano Babic 
115552a848eSStefano Babic 	return 0;
116552a848eSStefano Babic }
117552a848eSStefano Babic 
opos6ul_board_late_init(void)118552a848eSStefano Babic int __weak opos6ul_board_late_init(void)
119552a848eSStefano Babic {
120552a848eSStefano Babic 	return 0;
121552a848eSStefano Babic }
122552a848eSStefano Babic 
board_late_init(void)123552a848eSStefano Babic int board_late_init(void)
124552a848eSStefano Babic {
125552a848eSStefano Babic 	struct src *psrc = (struct src *)SRC_BASE_ADDR;
126552a848eSStefano Babic 	unsigned reg = readl(&psrc->sbmr2);
127552a848eSStefano Babic 
128552a848eSStefano Babic 	/* In bootstrap don't use the env vars */
129552a848eSStefano Babic 	if (((reg & 0x3000000) >> 24) == 0x1) {
130*c5d548a9SYaniv Levinsky 		set_default_env(NULL, 0);
131382bee57SSimon Glass 		env_set("preboot", "");
132552a848eSStefano Babic 	}
133552a848eSStefano Babic 
134552a848eSStefano Babic 	return opos6ul_board_late_init();
135552a848eSStefano Babic }
136552a848eSStefano Babic 
dram_init(void)137552a848eSStefano Babic int dram_init(void)
138552a848eSStefano Babic {
139552a848eSStefano Babic 	gd->ram_size = imx_ddr_size();
140552a848eSStefano Babic 
141552a848eSStefano Babic 	return 0;
142552a848eSStefano Babic }
143552a848eSStefano Babic 
144552a848eSStefano Babic #ifdef CONFIG_SPL_BUILD
145552a848eSStefano Babic #include <asm/arch/mx6-ddr.h>
146b08c8c48SMasahiro Yamada #include <linux/libfdt.h>
147552a848eSStefano Babic #include <spl.h>
148552a848eSStefano Babic 
149552a848eSStefano Babic static struct mx6ul_iomux_grp_regs mx6_grp_ioregs = {
150552a848eSStefano Babic 	.grp_addds = 0x00000030,
151552a848eSStefano Babic 	.grp_ddrmode_ctl = 0x00020000,
152552a848eSStefano Babic 	.grp_b0ds = 0x00000030,
153552a848eSStefano Babic 	.grp_ctlds = 0x00000030,
154552a848eSStefano Babic 	.grp_b1ds = 0x00000030,
155552a848eSStefano Babic 	.grp_ddrpke = 0x00000000,
156552a848eSStefano Babic 	.grp_ddrmode = 0x00020000,
157552a848eSStefano Babic 	.grp_ddr_type = 0x000c0000,
158552a848eSStefano Babic };
159552a848eSStefano Babic 
160552a848eSStefano Babic static struct mx6ul_iomux_ddr_regs mx6_ddr_ioregs = {
161552a848eSStefano Babic 	.dram_dqm0 = 0x00000030,
162552a848eSStefano Babic 	.dram_dqm1 = 0x00000030,
163552a848eSStefano Babic 	.dram_ras = 0x00000030,
164552a848eSStefano Babic 	.dram_cas = 0x00000030,
165552a848eSStefano Babic 	.dram_odt0 = 0x00000030,
166552a848eSStefano Babic 	.dram_odt1 = 0x00000030,
167552a848eSStefano Babic 	.dram_sdba2 = 0x00000000,
168552a848eSStefano Babic 	.dram_sdclk_0 = 0x00000008,
169552a848eSStefano Babic 	.dram_sdqs0 = 0x00000038,
170552a848eSStefano Babic 	.dram_sdqs1 = 0x00000030,
171552a848eSStefano Babic 	.dram_reset = 0x00000030,
172552a848eSStefano Babic };
173552a848eSStefano Babic 
174552a848eSStefano Babic static struct mx6_mmdc_calibration mx6_mmcd_calib = {
175552a848eSStefano Babic 	.p0_mpwldectrl0 = 0x00070007,
176552a848eSStefano Babic 	.p0_mpdgctrl0 = 0x41490145,
177552a848eSStefano Babic 	.p0_mprddlctl = 0x40404546,
178552a848eSStefano Babic 	.p0_mpwrdlctl = 0x4040524D,
179552a848eSStefano Babic };
180552a848eSStefano Babic 
181552a848eSStefano Babic struct mx6_ddr_sysinfo ddr_sysinfo = {
182552a848eSStefano Babic 	.dsize = 0,
183552a848eSStefano Babic 	.cs_density = 20,
184552a848eSStefano Babic 	.ncs = 1,
185552a848eSStefano Babic 	.cs1_mirror = 0,
186552a848eSStefano Babic 	.rtt_wr = 2,
187552a848eSStefano Babic 	.rtt_nom = 1,		/* RTT_Nom = RZQ/2 */
188552a848eSStefano Babic 	.walat = 1,		/* Write additional latency */
189552a848eSStefano Babic 	.ralat = 5,		/* Read additional latency */
190552a848eSStefano Babic 	.mif3_mode = 3,		/* Command prediction working mode */
191552a848eSStefano Babic 	.bi_on = 1,		/* Bank interleaving enabled */
192552a848eSStefano Babic 	.sde_to_rst = 0x10,	/* 14 cycles, 200us (JEDEC default) */
193552a848eSStefano Babic 	.rst_to_cke = 0x23,	/* 33 cycles, 500us (JEDEC default) */
194552a848eSStefano Babic 	.ddr_type = DDR_TYPE_DDR3,
195552a848eSStefano Babic };
196552a848eSStefano Babic 
197552a848eSStefano Babic static struct mx6_ddr3_cfg mem_ddr = {
198552a848eSStefano Babic 	.mem_speed = 800,
199552a848eSStefano Babic 	.density = 2,
200552a848eSStefano Babic 	.width = 16,
201552a848eSStefano Babic 	.banks = 8,
202552a848eSStefano Babic 	.rowaddr = 14,
203552a848eSStefano Babic 	.coladdr = 10,
204552a848eSStefano Babic 	.pagesz = 2,
205552a848eSStefano Babic 	.trcd = 1500,
206552a848eSStefano Babic 	.trcmin = 5250,
207552a848eSStefano Babic 	.trasmin = 3750,
208552a848eSStefano Babic };
209552a848eSStefano Babic 
board_boot_order(u32 * spl_boot_list)210ea772178SSébastien Szymanski void board_boot_order(u32 *spl_boot_list)
211ea772178SSébastien Szymanski {
212ea772178SSébastien Szymanski 	unsigned int bmode = readl(&src_base->sbmr2);
213ea772178SSébastien Szymanski 
214ea772178SSébastien Szymanski 	if (((bmode >> 24) & 0x03) == 0x01) /* Serial Downloader */
215ea772178SSébastien Szymanski 		spl_boot_list[0] = BOOT_DEVICE_UART;
216ea772178SSébastien Szymanski 	else
217ea772178SSébastien Szymanski 		spl_boot_list[0] = spl_boot_device();
218ea772178SSébastien Szymanski }
219ea772178SSébastien Szymanski 
ccgr_init(void)220552a848eSStefano Babic static void ccgr_init(void)
221552a848eSStefano Babic {
222552a848eSStefano Babic 	struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
223552a848eSStefano Babic 
224552a848eSStefano Babic 	writel(0xFFFFFFFF, &ccm->CCGR0);
225552a848eSStefano Babic 	writel(0xFFFFFFFF, &ccm->CCGR1);
226552a848eSStefano Babic 	writel(0xFFFFFFFF, &ccm->CCGR2);
227552a848eSStefano Babic 	writel(0xFFFFFFFF, &ccm->CCGR3);
228552a848eSStefano Babic 	writel(0xFFFFFFFF, &ccm->CCGR4);
229552a848eSStefano Babic 	writel(0xFFFFFFFF, &ccm->CCGR5);
230552a848eSStefano Babic 	writel(0xFFFFFFFF, &ccm->CCGR6);
231552a848eSStefano Babic 	writel(0xFFFFFFFF, &ccm->CCGR7);
232552a848eSStefano Babic }
233552a848eSStefano Babic 
spl_dram_init(void)234552a848eSStefano Babic static void spl_dram_init(void)
235552a848eSStefano Babic {
236552a848eSStefano Babic 	struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
237552a848eSStefano Babic 	struct fuse_bank *bank = &ocotp->bank[4];
238552a848eSStefano Babic 	struct fuse_bank4_regs *fuse =
239552a848eSStefano Babic 		(struct fuse_bank4_regs *)bank->fuse_regs;
240552a848eSStefano Babic 	int reg = readl(&fuse->gp1);
241552a848eSStefano Babic 
242552a848eSStefano Babic 	/* 512MB of RAM */
243552a848eSStefano Babic 	if (reg & 0x1) {
244552a848eSStefano Babic 		mem_ddr.density = 4;
245552a848eSStefano Babic 		mem_ddr.rowaddr = 15;
246552a848eSStefano Babic 		mem_ddr.trcd = 1375;
247552a848eSStefano Babic 		mem_ddr.trcmin = 4875;
248552a848eSStefano Babic 		mem_ddr.trasmin = 3500;
249552a848eSStefano Babic 	}
250552a848eSStefano Babic 
251552a848eSStefano Babic 	mx6ul_dram_iocfg(mem_ddr.width, &mx6_ddr_ioregs, &mx6_grp_ioregs);
252552a848eSStefano Babic 	mx6_dram_cfg(&ddr_sysinfo, &mx6_mmcd_calib, &mem_ddr);
253552a848eSStefano Babic }
254552a848eSStefano Babic 
spl_board_init(void)25530754ef7SSébastien Szymanski void spl_board_init(void)
25630754ef7SSébastien Szymanski {
25730754ef7SSébastien Szymanski 	preloader_console_init();
25830754ef7SSébastien Szymanski }
25930754ef7SSébastien Szymanski 
board_init_f(ulong dummy)260552a848eSStefano Babic void board_init_f(ulong dummy)
261552a848eSStefano Babic {
262552a848eSStefano Babic 	ccgr_init();
263552a848eSStefano Babic 
264552a848eSStefano Babic 	/* setup AIPS and disable watchdog */
265552a848eSStefano Babic 	arch_cpu_init();
266552a848eSStefano Babic 
267552a848eSStefano Babic 	/* setup GP timer */
268552a848eSStefano Babic 	timer_init();
269552a848eSStefano Babic 
270552a848eSStefano Babic 	/* DDR initialization */
271552a848eSStefano Babic 	spl_dram_init();
272552a848eSStefano Babic }
273552a848eSStefano Babic #endif /* CONFIG_SPL_BUILD */
274