1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright (C) 2010-2011 Freescale Semiconductor, Inc.
3*4882a593Smuzhiyun * Based on mx6qsabrelite.c file
4*4882a593Smuzhiyun * Copyright (C) 2013, Adeneo Embedded <www.adeneo-embedded.com>
5*4882a593Smuzhiyun * Leo Sartre, <lsartre@adeneo-embedded.com>
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * SPDX-License-Identifier: GPL-2.0+
8*4882a593Smuzhiyun */
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #include <common.h>
11*4882a593Smuzhiyun #include <asm/io.h>
12*4882a593Smuzhiyun #include <asm/arch/clock.h>
13*4882a593Smuzhiyun #include <asm/arch/imx-regs.h>
14*4882a593Smuzhiyun #include <asm/arch/iomux.h>
15*4882a593Smuzhiyun #include <asm/arch/mx6-pins.h>
16*4882a593Smuzhiyun #include <asm/gpio.h>
17*4882a593Smuzhiyun #include <asm/mach-imx/iomux-v3.h>
18*4882a593Smuzhiyun #include <asm/mach-imx/sata.h>
19*4882a593Smuzhiyun #include <asm/mach-imx/boot_mode.h>
20*4882a593Smuzhiyun #include <asm/mach-imx/mxc_i2c.h>
21*4882a593Smuzhiyun #include <asm/arch/sys_proto.h>
22*4882a593Smuzhiyun #include <asm/arch/mxc_hdmi.h>
23*4882a593Smuzhiyun #include <asm/arch/crm_regs.h>
24*4882a593Smuzhiyun #include <mmc.h>
25*4882a593Smuzhiyun #include <fsl_esdhc.h>
26*4882a593Smuzhiyun #include <i2c.h>
27*4882a593Smuzhiyun #include <power/pmic.h>
28*4882a593Smuzhiyun #include <power/pfuze100_pmic.h>
29*4882a593Smuzhiyun #include <linux/fb.h>
30*4882a593Smuzhiyun #include <ipu_pixfmt.h>
31*4882a593Smuzhiyun #include <malloc.h>
32*4882a593Smuzhiyun #include <miiphy.h>
33*4882a593Smuzhiyun #include <netdev.h>
34*4882a593Smuzhiyun #include <micrel.h>
35*4882a593Smuzhiyun #include <spi_flash.h>
36*4882a593Smuzhiyun #include <spi.h>
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun DECLARE_GLOBAL_DATA_PTR;
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun #define UART_PAD_CTRL (PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED |\
41*4882a593Smuzhiyun PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST | PAD_CTL_HYS)
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun #define USDHC_PAD_CTRL (PAD_CTL_PUS_47K_UP | PAD_CTL_SPEED_LOW |\
44*4882a593Smuzhiyun PAD_CTL_DSE_80ohm | PAD_CTL_SRE_FAST | PAD_CTL_HYS)
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun #define I2C_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_PUE | \
47*4882a593Smuzhiyun PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | \
48*4882a593Smuzhiyun PAD_CTL_DSE_40ohm | PAD_CTL_HYS | \
49*4882a593Smuzhiyun PAD_CTL_ODE | PAD_CTL_SRE_FAST)
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun #define SPI_PAD_CTRL (PAD_CTL_HYS | \
52*4882a593Smuzhiyun PAD_CTL_SPEED_MED | \
53*4882a593Smuzhiyun PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST)
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun #define MX6Q_QMX6_PFUZE_MUX IMX_GPIO_NR(6, 9)
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun #define ENET_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_PUE | \
59*4882a593Smuzhiyun PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | \
60*4882a593Smuzhiyun PAD_CTL_DSE_40ohm | PAD_CTL_HYS)
61*4882a593Smuzhiyun
dram_init(void)62*4882a593Smuzhiyun int dram_init(void)
63*4882a593Smuzhiyun {
64*4882a593Smuzhiyun gd->ram_size = imx_ddr_size();
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun return 0;
67*4882a593Smuzhiyun }
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun static iomux_v3_cfg_t const uart2_pads[] = {
70*4882a593Smuzhiyun IOMUX_PADS(PAD_EIM_D26__UART2_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL)),
71*4882a593Smuzhiyun IOMUX_PADS(PAD_EIM_D27__UART2_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL)),
72*4882a593Smuzhiyun };
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun #ifndef CONFIG_SPL_BUILD
75*4882a593Smuzhiyun static iomux_v3_cfg_t const usdhc2_pads[] = {
76*4882a593Smuzhiyun IOMUX_PADS(PAD_SD2_CLK__SD2_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
77*4882a593Smuzhiyun IOMUX_PADS(PAD_SD2_CMD__SD2_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
78*4882a593Smuzhiyun IOMUX_PADS(PAD_SD2_DAT0__SD2_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
79*4882a593Smuzhiyun IOMUX_PADS(PAD_SD2_DAT1__SD2_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
80*4882a593Smuzhiyun IOMUX_PADS(PAD_SD2_DAT2__SD2_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
81*4882a593Smuzhiyun IOMUX_PADS(PAD_SD2_DAT3__SD2_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
82*4882a593Smuzhiyun IOMUX_PADS(PAD_GPIO_4__GPIO1_IO04 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
83*4882a593Smuzhiyun };
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun static iomux_v3_cfg_t const usdhc3_pads[] = {
86*4882a593Smuzhiyun IOMUX_PADS(PAD_SD3_CLK__SD3_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
87*4882a593Smuzhiyun IOMUX_PADS(PAD_SD3_CMD__SD3_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
88*4882a593Smuzhiyun IOMUX_PADS(PAD_SD3_DAT0__SD3_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
89*4882a593Smuzhiyun IOMUX_PADS(PAD_SD3_DAT1__SD3_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
90*4882a593Smuzhiyun IOMUX_PADS(PAD_SD3_DAT2__SD3_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
91*4882a593Smuzhiyun IOMUX_PADS(PAD_SD3_DAT3__SD3_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
92*4882a593Smuzhiyun IOMUX_PADS(PAD_SD3_DAT4__SD3_DATA4 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
93*4882a593Smuzhiyun IOMUX_PADS(PAD_SD3_DAT5__SD3_DATA5 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
94*4882a593Smuzhiyun IOMUX_PADS(PAD_SD3_DAT6__SD3_DATA6 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
95*4882a593Smuzhiyun IOMUX_PADS(PAD_SD3_DAT7__SD3_DATA7 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
96*4882a593Smuzhiyun IOMUX_PADS(PAD_SD3_RST__SD3_RESET | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
97*4882a593Smuzhiyun };
98*4882a593Smuzhiyun #endif
99*4882a593Smuzhiyun
100*4882a593Smuzhiyun static iomux_v3_cfg_t const usdhc4_pads[] = {
101*4882a593Smuzhiyun IOMUX_PADS(PAD_SD4_CLK__SD4_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
102*4882a593Smuzhiyun IOMUX_PADS(PAD_SD4_CMD__SD4_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
103*4882a593Smuzhiyun IOMUX_PADS(PAD_SD4_DAT0__SD4_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
104*4882a593Smuzhiyun IOMUX_PADS(PAD_SD4_DAT1__SD4_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
105*4882a593Smuzhiyun IOMUX_PADS(PAD_SD4_DAT2__SD4_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
106*4882a593Smuzhiyun IOMUX_PADS(PAD_SD4_DAT3__SD4_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
107*4882a593Smuzhiyun IOMUX_PADS(PAD_SD4_DAT4__SD4_DATA4 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
108*4882a593Smuzhiyun IOMUX_PADS(PAD_SD4_DAT5__SD4_DATA5 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
109*4882a593Smuzhiyun IOMUX_PADS(PAD_SD4_DAT6__SD4_DATA6 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
110*4882a593Smuzhiyun IOMUX_PADS(PAD_SD4_DAT7__SD4_DATA7 | MUX_PAD_CTRL(USDHC_PAD_CTRL)),
111*4882a593Smuzhiyun IOMUX_PADS(PAD_NANDF_D6__GPIO2_IO06 | MUX_PAD_CTRL(NO_PAD_CTRL)),
112*4882a593Smuzhiyun };
113*4882a593Smuzhiyun
114*4882a593Smuzhiyun static iomux_v3_cfg_t const usb_otg_pads[] = {
115*4882a593Smuzhiyun IOMUX_PADS(PAD_EIM_D22__USB_OTG_PWR | MUX_PAD_CTRL(NO_PAD_CTRL)),
116*4882a593Smuzhiyun IOMUX_PADS(PAD_GPIO_1__USB_OTG_ID | MUX_PAD_CTRL(NO_PAD_CTRL)),
117*4882a593Smuzhiyun };
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun static iomux_v3_cfg_t enet_pads_ksz9031[] = {
120*4882a593Smuzhiyun IOMUX_PADS(PAD_ENET_MDIO__ENET_MDIO | MUX_PAD_CTRL(ENET_PAD_CTRL)),
121*4882a593Smuzhiyun IOMUX_PADS(PAD_ENET_MDC__ENET_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL)),
122*4882a593Smuzhiyun IOMUX_PADS(PAD_RGMII_TXC__RGMII_TXC | MUX_PAD_CTRL(ENET_PAD_CTRL)),
123*4882a593Smuzhiyun IOMUX_PADS(PAD_RGMII_TD0__RGMII_TD0 | MUX_PAD_CTRL(ENET_PAD_CTRL)),
124*4882a593Smuzhiyun IOMUX_PADS(PAD_RGMII_TD1__RGMII_TD1 | MUX_PAD_CTRL(ENET_PAD_CTRL)),
125*4882a593Smuzhiyun IOMUX_PADS(PAD_RGMII_TD2__RGMII_TD2 | MUX_PAD_CTRL(ENET_PAD_CTRL)),
126*4882a593Smuzhiyun IOMUX_PADS(PAD_RGMII_TD3__RGMII_TD3 | MUX_PAD_CTRL(ENET_PAD_CTRL)),
127*4882a593Smuzhiyun IOMUX_PADS(PAD_RGMII_TX_CTL__RGMII_TX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL)),
128*4882a593Smuzhiyun IOMUX_PADS(PAD_ENET_REF_CLK__ENET_TX_CLK | MUX_PAD_CTRL(ENET_PAD_CTRL)),
129*4882a593Smuzhiyun IOMUX_PADS(PAD_RGMII_RXC__GPIO6_IO30 | MUX_PAD_CTRL(NO_PAD_CTRL)),
130*4882a593Smuzhiyun IOMUX_PADS(PAD_RGMII_RD0__GPIO6_IO25 | MUX_PAD_CTRL(NO_PAD_CTRL)),
131*4882a593Smuzhiyun IOMUX_PADS(PAD_RGMII_RD1__GPIO6_IO27 | MUX_PAD_CTRL(NO_PAD_CTRL)),
132*4882a593Smuzhiyun IOMUX_PADS(PAD_RGMII_RD2__GPIO6_IO28 | MUX_PAD_CTRL(NO_PAD_CTRL)),
133*4882a593Smuzhiyun IOMUX_PADS(PAD_RGMII_RD3__GPIO6_IO29 | MUX_PAD_CTRL(NO_PAD_CTRL)),
134*4882a593Smuzhiyun IOMUX_PADS(PAD_RGMII_RX_CTL__GPIO6_IO24 | MUX_PAD_CTRL(NO_PAD_CTRL)),
135*4882a593Smuzhiyun };
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun static iomux_v3_cfg_t enet_pads_final_ksz9031[] = {
138*4882a593Smuzhiyun IOMUX_PADS(PAD_RGMII_RXC__RGMII_RXC | MUX_PAD_CTRL(ENET_PAD_CTRL)),
139*4882a593Smuzhiyun IOMUX_PADS(PAD_RGMII_RD0__RGMII_RD0 | MUX_PAD_CTRL(ENET_PAD_CTRL)),
140*4882a593Smuzhiyun IOMUX_PADS(PAD_RGMII_RD1__RGMII_RD1 | MUX_PAD_CTRL(ENET_PAD_CTRL)),
141*4882a593Smuzhiyun IOMUX_PADS(PAD_RGMII_RD2__RGMII_RD2 | MUX_PAD_CTRL(ENET_PAD_CTRL)),
142*4882a593Smuzhiyun IOMUX_PADS(PAD_RGMII_RD3__RGMII_RD3 | MUX_PAD_CTRL(ENET_PAD_CTRL)),
143*4882a593Smuzhiyun IOMUX_PADS(PAD_RGMII_RX_CTL__RGMII_RX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL)),
144*4882a593Smuzhiyun };
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun static iomux_v3_cfg_t enet_pads_ar8035[] = {
147*4882a593Smuzhiyun IOMUX_PADS(PAD_ENET_MDIO__ENET_MDIO | MUX_PAD_CTRL(ENET_PAD_CTRL)),
148*4882a593Smuzhiyun IOMUX_PADS(PAD_ENET_MDC__ENET_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL)),
149*4882a593Smuzhiyun IOMUX_PADS(PAD_RGMII_TXC__RGMII_TXC | MUX_PAD_CTRL(ENET_PAD_CTRL)),
150*4882a593Smuzhiyun IOMUX_PADS(PAD_RGMII_TD0__RGMII_TD0 | MUX_PAD_CTRL(ENET_PAD_CTRL)),
151*4882a593Smuzhiyun IOMUX_PADS(PAD_RGMII_TD1__RGMII_TD1 | MUX_PAD_CTRL(ENET_PAD_CTRL)),
152*4882a593Smuzhiyun IOMUX_PADS(PAD_RGMII_TD2__RGMII_TD2 | MUX_PAD_CTRL(ENET_PAD_CTRL)),
153*4882a593Smuzhiyun IOMUX_PADS(PAD_RGMII_TD3__RGMII_TD3 | MUX_PAD_CTRL(ENET_PAD_CTRL)),
154*4882a593Smuzhiyun IOMUX_PADS(PAD_RGMII_TX_CTL__RGMII_TX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL)),
155*4882a593Smuzhiyun IOMUX_PADS(PAD_ENET_REF_CLK__ENET_TX_CLK | MUX_PAD_CTRL(ENET_PAD_CTRL)),
156*4882a593Smuzhiyun IOMUX_PADS(PAD_RGMII_RXC__RGMII_RXC | MUX_PAD_CTRL(ENET_PAD_CTRL)),
157*4882a593Smuzhiyun IOMUX_PADS(PAD_RGMII_RD0__RGMII_RD0 | MUX_PAD_CTRL(ENET_PAD_CTRL)),
158*4882a593Smuzhiyun IOMUX_PADS(PAD_RGMII_RD1__RGMII_RD1 | MUX_PAD_CTRL(ENET_PAD_CTRL)),
159*4882a593Smuzhiyun IOMUX_PADS(PAD_RGMII_RD2__RGMII_RD2 | MUX_PAD_CTRL(ENET_PAD_CTRL)),
160*4882a593Smuzhiyun IOMUX_PADS(PAD_RGMII_RD3__RGMII_RD3 | MUX_PAD_CTRL(ENET_PAD_CTRL)),
161*4882a593Smuzhiyun IOMUX_PADS(PAD_RGMII_RX_CTL__RGMII_RX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL)),
162*4882a593Smuzhiyun };
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun static iomux_v3_cfg_t const ecspi1_pads[] = {
165*4882a593Smuzhiyun IOMUX_PADS(PAD_EIM_D16__ECSPI1_SCLK | MUX_PAD_CTRL(SPI_PAD_CTRL)),
166*4882a593Smuzhiyun IOMUX_PADS(PAD_EIM_D17__ECSPI1_MISO | MUX_PAD_CTRL(SPI_PAD_CTRL)),
167*4882a593Smuzhiyun IOMUX_PADS(PAD_EIM_D18__ECSPI1_MOSI | MUX_PAD_CTRL(SPI_PAD_CTRL)),
168*4882a593Smuzhiyun IOMUX_PADS(PAD_EIM_D19__GPIO3_IO19 | MUX_PAD_CTRL(NO_PAD_CTRL)),
169*4882a593Smuzhiyun };
170*4882a593Smuzhiyun
171*4882a593Smuzhiyun #define PC MUX_PAD_CTRL(I2C_PAD_CTRL)
172*4882a593Smuzhiyun struct i2c_pads_info mx6q_i2c_pad_info1 = {
173*4882a593Smuzhiyun .scl = {
174*4882a593Smuzhiyun .i2c_mode = MX6Q_PAD_KEY_COL3__I2C2_SCL | PC,
175*4882a593Smuzhiyun .gpio_mode = MX6Q_PAD_KEY_COL3__GPIO4_IO12 | PC,
176*4882a593Smuzhiyun .gp = IMX_GPIO_NR(4, 12)
177*4882a593Smuzhiyun },
178*4882a593Smuzhiyun .sda = {
179*4882a593Smuzhiyun .i2c_mode = MX6Q_PAD_KEY_ROW3__I2C2_SDA | PC,
180*4882a593Smuzhiyun .gpio_mode = MX6Q_PAD_KEY_ROW3__GPIO4_IO13 | PC,
181*4882a593Smuzhiyun .gp = IMX_GPIO_NR(4, 13)
182*4882a593Smuzhiyun }
183*4882a593Smuzhiyun };
184*4882a593Smuzhiyun
185*4882a593Smuzhiyun struct i2c_pads_info mx6dl_i2c_pad_info1 = {
186*4882a593Smuzhiyun .scl = {
187*4882a593Smuzhiyun .i2c_mode = MX6DL_PAD_KEY_COL3__I2C2_SCL | PC,
188*4882a593Smuzhiyun .gpio_mode = MX6DL_PAD_KEY_COL3__GPIO4_IO12 | PC,
189*4882a593Smuzhiyun .gp = IMX_GPIO_NR(4, 12)
190*4882a593Smuzhiyun },
191*4882a593Smuzhiyun .sda = {
192*4882a593Smuzhiyun .i2c_mode = MX6DL_PAD_KEY_ROW3__I2C2_SDA | PC,
193*4882a593Smuzhiyun .gpio_mode = MX6DL_PAD_KEY_ROW3__GPIO4_IO13 | PC,
194*4882a593Smuzhiyun .gp = IMX_GPIO_NR(4, 13)
195*4882a593Smuzhiyun }
196*4882a593Smuzhiyun };
197*4882a593Smuzhiyun
198*4882a593Smuzhiyun #define I2C_PMIC 1 /* I2C2 port is used to connect to the PMIC */
199*4882a593Smuzhiyun
200*4882a593Smuzhiyun struct interface_level {
201*4882a593Smuzhiyun char *name;
202*4882a593Smuzhiyun uchar value;
203*4882a593Smuzhiyun };
204*4882a593Smuzhiyun
205*4882a593Smuzhiyun static struct interface_level mipi_levels[] = {
206*4882a593Smuzhiyun {"0V0", 0x00},
207*4882a593Smuzhiyun {"2V5", 0x17},
208*4882a593Smuzhiyun };
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun /* setup board specific PMIC */
power_init_board(void)211*4882a593Smuzhiyun int power_init_board(void)
212*4882a593Smuzhiyun {
213*4882a593Smuzhiyun struct pmic *p;
214*4882a593Smuzhiyun u32 id1, id2, i;
215*4882a593Smuzhiyun int ret;
216*4882a593Smuzhiyun char const *lv_mipi;
217*4882a593Smuzhiyun
218*4882a593Smuzhiyun /* configure I2C multiplexer */
219*4882a593Smuzhiyun gpio_direction_output(MX6Q_QMX6_PFUZE_MUX, 1);
220*4882a593Smuzhiyun
221*4882a593Smuzhiyun power_pfuze100_init(I2C_PMIC);
222*4882a593Smuzhiyun p = pmic_get("PFUZE100");
223*4882a593Smuzhiyun if (!p)
224*4882a593Smuzhiyun return -EINVAL;
225*4882a593Smuzhiyun
226*4882a593Smuzhiyun ret = pmic_probe(p);
227*4882a593Smuzhiyun if (ret)
228*4882a593Smuzhiyun return ret;
229*4882a593Smuzhiyun
230*4882a593Smuzhiyun pmic_reg_read(p, PFUZE100_DEVICEID, &id1);
231*4882a593Smuzhiyun pmic_reg_read(p, PFUZE100_REVID, &id2);
232*4882a593Smuzhiyun printf("PFUZE100 Rev. [%02x/%02x] detected\n", id1, id2);
233*4882a593Smuzhiyun
234*4882a593Smuzhiyun if (id2 >= 0x20)
235*4882a593Smuzhiyun return 0;
236*4882a593Smuzhiyun
237*4882a593Smuzhiyun /* set level of MIPI if specified */
238*4882a593Smuzhiyun lv_mipi = env_get("lv_mipi");
239*4882a593Smuzhiyun if (lv_mipi)
240*4882a593Smuzhiyun return 0;
241*4882a593Smuzhiyun
242*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(mipi_levels); i++) {
243*4882a593Smuzhiyun if (!strcmp(mipi_levels[i].name, lv_mipi)) {
244*4882a593Smuzhiyun printf("set MIPI level %s\n", mipi_levels[i].name);
245*4882a593Smuzhiyun ret = pmic_reg_write(p, PFUZE100_VGEN4VOL,
246*4882a593Smuzhiyun mipi_levels[i].value);
247*4882a593Smuzhiyun if (ret)
248*4882a593Smuzhiyun return ret;
249*4882a593Smuzhiyun }
250*4882a593Smuzhiyun }
251*4882a593Smuzhiyun
252*4882a593Smuzhiyun return 0;
253*4882a593Smuzhiyun }
254*4882a593Smuzhiyun
board_eth_init(bd_t * bis)255*4882a593Smuzhiyun int board_eth_init(bd_t *bis)
256*4882a593Smuzhiyun {
257*4882a593Smuzhiyun struct phy_device *phydev;
258*4882a593Smuzhiyun struct mii_dev *bus;
259*4882a593Smuzhiyun unsigned short id1, id2;
260*4882a593Smuzhiyun int ret;
261*4882a593Smuzhiyun
262*4882a593Smuzhiyun /* check whether KSZ9031 or AR8035 has to be configured */
263*4882a593Smuzhiyun SETUP_IOMUX_PADS(enet_pads_ar8035);
264*4882a593Smuzhiyun
265*4882a593Smuzhiyun /* phy reset */
266*4882a593Smuzhiyun gpio_direction_output(IMX_GPIO_NR(3, 23), 0);
267*4882a593Smuzhiyun udelay(2000);
268*4882a593Smuzhiyun gpio_set_value(IMX_GPIO_NR(3, 23), 1);
269*4882a593Smuzhiyun udelay(500);
270*4882a593Smuzhiyun
271*4882a593Smuzhiyun bus = fec_get_miibus(IMX_FEC_BASE, -1);
272*4882a593Smuzhiyun if (!bus)
273*4882a593Smuzhiyun return -EINVAL;
274*4882a593Smuzhiyun phydev = phy_find_by_mask(bus, (0xf << 4), PHY_INTERFACE_MODE_RGMII);
275*4882a593Smuzhiyun if (!phydev) {
276*4882a593Smuzhiyun printf("Error: phy device not found.\n");
277*4882a593Smuzhiyun ret = -ENODEV;
278*4882a593Smuzhiyun goto free_bus;
279*4882a593Smuzhiyun }
280*4882a593Smuzhiyun
281*4882a593Smuzhiyun /* get the PHY id */
282*4882a593Smuzhiyun id1 = phy_read(phydev, MDIO_DEVAD_NONE, 2);
283*4882a593Smuzhiyun id2 = phy_read(phydev, MDIO_DEVAD_NONE, 3);
284*4882a593Smuzhiyun
285*4882a593Smuzhiyun if ((id1 == 0x22) && ((id2 & 0xFFF0) == 0x1620)) {
286*4882a593Smuzhiyun /* re-configure for Micrel KSZ9031 */
287*4882a593Smuzhiyun printf("configure Micrel KSZ9031 Ethernet Phy at address %d\n",
288*4882a593Smuzhiyun phydev->addr);
289*4882a593Smuzhiyun
290*4882a593Smuzhiyun /* phy reset: gpio3-23 */
291*4882a593Smuzhiyun gpio_set_value(IMX_GPIO_NR(3, 23), 0);
292*4882a593Smuzhiyun gpio_set_value(IMX_GPIO_NR(6, 30), (phydev->addr >> 2));
293*4882a593Smuzhiyun gpio_set_value(IMX_GPIO_NR(6, 25), 1);
294*4882a593Smuzhiyun gpio_set_value(IMX_GPIO_NR(6, 27), 1);
295*4882a593Smuzhiyun gpio_set_value(IMX_GPIO_NR(6, 28), 1);
296*4882a593Smuzhiyun gpio_set_value(IMX_GPIO_NR(6, 29), 1);
297*4882a593Smuzhiyun SETUP_IOMUX_PADS(enet_pads_ksz9031);
298*4882a593Smuzhiyun gpio_set_value(IMX_GPIO_NR(6, 24), 1);
299*4882a593Smuzhiyun udelay(500);
300*4882a593Smuzhiyun gpio_set_value(IMX_GPIO_NR(3, 23), 1);
301*4882a593Smuzhiyun SETUP_IOMUX_PADS(enet_pads_final_ksz9031);
302*4882a593Smuzhiyun } else if ((id1 == 0x004d) && (id2 == 0xd072)) {
303*4882a593Smuzhiyun /* configure Atheros AR8035 - actually nothing to do */
304*4882a593Smuzhiyun printf("configure Atheros AR8035 Ethernet Phy at address %d\n",
305*4882a593Smuzhiyun phydev->addr);
306*4882a593Smuzhiyun } else {
307*4882a593Smuzhiyun printf("Unknown Ethernet-Phy: 0x%04x 0x%04x\n", id1, id2);
308*4882a593Smuzhiyun ret = -EINVAL;
309*4882a593Smuzhiyun goto free_phydev;
310*4882a593Smuzhiyun }
311*4882a593Smuzhiyun
312*4882a593Smuzhiyun ret = fec_probe(bis, -1, IMX_FEC_BASE, bus, phydev);
313*4882a593Smuzhiyun if (ret)
314*4882a593Smuzhiyun goto free_phydev;
315*4882a593Smuzhiyun
316*4882a593Smuzhiyun return 0;
317*4882a593Smuzhiyun
318*4882a593Smuzhiyun free_phydev:
319*4882a593Smuzhiyun free(phydev);
320*4882a593Smuzhiyun free_bus:
321*4882a593Smuzhiyun free(bus);
322*4882a593Smuzhiyun return ret;
323*4882a593Smuzhiyun }
324*4882a593Smuzhiyun
mx6_rgmii_rework(struct phy_device * phydev)325*4882a593Smuzhiyun int mx6_rgmii_rework(struct phy_device *phydev)
326*4882a593Smuzhiyun {
327*4882a593Smuzhiyun unsigned short id1, id2;
328*4882a593Smuzhiyun unsigned short val;
329*4882a593Smuzhiyun
330*4882a593Smuzhiyun /* check whether KSZ9031 or AR8035 has to be configured */
331*4882a593Smuzhiyun id1 = phy_read(phydev, MDIO_DEVAD_NONE, 2);
332*4882a593Smuzhiyun id2 = phy_read(phydev, MDIO_DEVAD_NONE, 3);
333*4882a593Smuzhiyun
334*4882a593Smuzhiyun if ((id1 == 0x22) && ((id2 & 0xFFF0) == 0x1620)) {
335*4882a593Smuzhiyun /* finalize phy configuration for Micrel KSZ9031 */
336*4882a593Smuzhiyun phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_CONTROL, 2);
337*4882a593Smuzhiyun phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_REG_DATA, 4);
338*4882a593Smuzhiyun phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_CONTROL, MII_KSZ9031_MOD_DATA_POST_INC_W | 0x2);
339*4882a593Smuzhiyun phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_REG_DATA, 0x0000);
340*4882a593Smuzhiyun
341*4882a593Smuzhiyun phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_CONTROL, 2);
342*4882a593Smuzhiyun phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_REG_DATA, 5);
343*4882a593Smuzhiyun phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_CONTROL, MII_KSZ9031_MOD_DATA_POST_INC_W | 0x2);
344*4882a593Smuzhiyun phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_REG_DATA, MII_KSZ9031_MOD_REG);
345*4882a593Smuzhiyun
346*4882a593Smuzhiyun phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_CONTROL, 2);
347*4882a593Smuzhiyun phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_REG_DATA, 6);
348*4882a593Smuzhiyun phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_CONTROL, MII_KSZ9031_MOD_DATA_POST_INC_W | 0x2);
349*4882a593Smuzhiyun phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_REG_DATA, 0xFFFF);
350*4882a593Smuzhiyun
351*4882a593Smuzhiyun phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_CONTROL, 2);
352*4882a593Smuzhiyun phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_REG_DATA, 8);
353*4882a593Smuzhiyun phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_CONTROL, MII_KSZ9031_MOD_DATA_POST_INC_W | 0x2);
354*4882a593Smuzhiyun phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_REG_DATA, 0x3FFF);
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun /* fix KSZ9031 link up issue */
357*4882a593Smuzhiyun phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_CONTROL, 0x0);
358*4882a593Smuzhiyun phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_REG_DATA, 0x4);
359*4882a593Smuzhiyun phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_CONTROL, MII_KSZ9031_MOD_DATA_NO_POST_INC);
360*4882a593Smuzhiyun phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_REG_DATA, 0x6);
361*4882a593Smuzhiyun phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_CONTROL, MII_KSZ9031_MOD_REG);
362*4882a593Smuzhiyun phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_REG_DATA, 0x3);
363*4882a593Smuzhiyun phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_CONTROL, MII_KSZ9031_MOD_DATA_NO_POST_INC);
364*4882a593Smuzhiyun phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_REG_DATA, 0x1A80);
365*4882a593Smuzhiyun }
366*4882a593Smuzhiyun
367*4882a593Smuzhiyun if ((id1 == 0x004d) && (id2 == 0xd072)) {
368*4882a593Smuzhiyun /* enable AR8035 ouput a 125MHz clk from CLK_25M */
369*4882a593Smuzhiyun phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_CONTROL, 0x7);
370*4882a593Smuzhiyun phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_REG_DATA, MII_KSZ9031_MOD_DATA_POST_INC_RW | 0x16);
371*4882a593Smuzhiyun phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_CONTROL, MII_KSZ9031_MOD_DATA_NO_POST_INC | 0x7);
372*4882a593Smuzhiyun val = phy_read(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_REG_DATA);
373*4882a593Smuzhiyun val &= 0xfe63;
374*4882a593Smuzhiyun val |= 0x18;
375*4882a593Smuzhiyun phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_REG_DATA, val);
376*4882a593Smuzhiyun
377*4882a593Smuzhiyun /* introduce tx clock delay */
378*4882a593Smuzhiyun phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x5);
379*4882a593Smuzhiyun val = phy_read(phydev, MDIO_DEVAD_NONE, 0x1e);
380*4882a593Smuzhiyun val |= 0x0100;
381*4882a593Smuzhiyun phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, val);
382*4882a593Smuzhiyun
383*4882a593Smuzhiyun /* disable hibernation */
384*4882a593Smuzhiyun phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0xb);
385*4882a593Smuzhiyun val = phy_read(phydev, MDIO_DEVAD_NONE, 0x1e);
386*4882a593Smuzhiyun phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x3c40);
387*4882a593Smuzhiyun }
388*4882a593Smuzhiyun return 0;
389*4882a593Smuzhiyun }
390*4882a593Smuzhiyun
board_phy_config(struct phy_device * phydev)391*4882a593Smuzhiyun int board_phy_config(struct phy_device *phydev)
392*4882a593Smuzhiyun {
393*4882a593Smuzhiyun mx6_rgmii_rework(phydev);
394*4882a593Smuzhiyun
395*4882a593Smuzhiyun if (phydev->drv->config)
396*4882a593Smuzhiyun phydev->drv->config(phydev);
397*4882a593Smuzhiyun
398*4882a593Smuzhiyun return 0;
399*4882a593Smuzhiyun }
400*4882a593Smuzhiyun
setup_iomux_uart(void)401*4882a593Smuzhiyun static void setup_iomux_uart(void)
402*4882a593Smuzhiyun {
403*4882a593Smuzhiyun SETUP_IOMUX_PADS(uart2_pads);
404*4882a593Smuzhiyun }
405*4882a593Smuzhiyun
406*4882a593Smuzhiyun #ifdef CONFIG_MXC_SPI
setup_spi(void)407*4882a593Smuzhiyun static void setup_spi(void)
408*4882a593Smuzhiyun {
409*4882a593Smuzhiyun SETUP_IOMUX_PADS(ecspi1_pads);
410*4882a593Smuzhiyun gpio_direction_output(IMX_GPIO_NR(3, 19), 0);
411*4882a593Smuzhiyun }
412*4882a593Smuzhiyun #endif
413*4882a593Smuzhiyun
414*4882a593Smuzhiyun #ifdef CONFIG_FSL_ESDHC
415*4882a593Smuzhiyun static struct fsl_esdhc_cfg usdhc_cfg[] = {
416*4882a593Smuzhiyun {USDHC2_BASE_ADDR},
417*4882a593Smuzhiyun {USDHC3_BASE_ADDR},
418*4882a593Smuzhiyun {USDHC4_BASE_ADDR},
419*4882a593Smuzhiyun };
420*4882a593Smuzhiyun
board_mmc_getcd(struct mmc * mmc)421*4882a593Smuzhiyun int board_mmc_getcd(struct mmc *mmc)
422*4882a593Smuzhiyun {
423*4882a593Smuzhiyun struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
424*4882a593Smuzhiyun int ret = 0;
425*4882a593Smuzhiyun
426*4882a593Smuzhiyun switch (cfg->esdhc_base) {
427*4882a593Smuzhiyun case USDHC2_BASE_ADDR:
428*4882a593Smuzhiyun gpio_direction_input(IMX_GPIO_NR(1, 4));
429*4882a593Smuzhiyun ret = !gpio_get_value(IMX_GPIO_NR(1, 4));
430*4882a593Smuzhiyun break;
431*4882a593Smuzhiyun case USDHC3_BASE_ADDR:
432*4882a593Smuzhiyun ret = 1; /* eMMC is always present */
433*4882a593Smuzhiyun break;
434*4882a593Smuzhiyun case USDHC4_BASE_ADDR:
435*4882a593Smuzhiyun gpio_direction_input(IMX_GPIO_NR(2, 6));
436*4882a593Smuzhiyun ret = !gpio_get_value(IMX_GPIO_NR(2, 6));
437*4882a593Smuzhiyun break;
438*4882a593Smuzhiyun default:
439*4882a593Smuzhiyun printf("Bad USDHC interface\n");
440*4882a593Smuzhiyun }
441*4882a593Smuzhiyun
442*4882a593Smuzhiyun return ret;
443*4882a593Smuzhiyun }
444*4882a593Smuzhiyun
board_mmc_init(bd_t * bis)445*4882a593Smuzhiyun int board_mmc_init(bd_t *bis)
446*4882a593Smuzhiyun {
447*4882a593Smuzhiyun #ifndef CONFIG_SPL_BUILD
448*4882a593Smuzhiyun s32 status = 0;
449*4882a593Smuzhiyun int i;
450*4882a593Smuzhiyun
451*4882a593Smuzhiyun usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK);
452*4882a593Smuzhiyun usdhc_cfg[1].sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK);
453*4882a593Smuzhiyun usdhc_cfg[2].sdhc_clk = mxc_get_clock(MXC_ESDHC4_CLK);
454*4882a593Smuzhiyun
455*4882a593Smuzhiyun SETUP_IOMUX_PADS(usdhc2_pads);
456*4882a593Smuzhiyun SETUP_IOMUX_PADS(usdhc3_pads);
457*4882a593Smuzhiyun SETUP_IOMUX_PADS(usdhc4_pads);
458*4882a593Smuzhiyun
459*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(usdhc_cfg); i++) {
460*4882a593Smuzhiyun status = fsl_esdhc_initialize(bis, &usdhc_cfg[i]);
461*4882a593Smuzhiyun if (status)
462*4882a593Smuzhiyun return status;
463*4882a593Smuzhiyun }
464*4882a593Smuzhiyun
465*4882a593Smuzhiyun return 0;
466*4882a593Smuzhiyun #else
467*4882a593Smuzhiyun SETUP_IOMUX_PADS(usdhc4_pads);
468*4882a593Smuzhiyun usdhc_cfg[0].esdhc_base = USDHC4_BASE_ADDR;
469*4882a593Smuzhiyun usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC4_CLK);
470*4882a593Smuzhiyun gd->arch.sdhc_clk = usdhc_cfg[0].sdhc_clk;
471*4882a593Smuzhiyun
472*4882a593Smuzhiyun return fsl_esdhc_initialize(bis, &usdhc_cfg[0]);
473*4882a593Smuzhiyun #endif
474*4882a593Smuzhiyun }
475*4882a593Smuzhiyun #endif
476*4882a593Smuzhiyun
board_ehci_hcd_init(int port)477*4882a593Smuzhiyun int board_ehci_hcd_init(int port)
478*4882a593Smuzhiyun {
479*4882a593Smuzhiyun switch (port) {
480*4882a593Smuzhiyun case 0:
481*4882a593Smuzhiyun SETUP_IOMUX_PADS(usb_otg_pads);
482*4882a593Smuzhiyun /*
483*4882a593Smuzhiyun * set daisy chain for otg_pin_id on 6q.
484*4882a593Smuzhiyun * for 6dl, this bit is reserved
485*4882a593Smuzhiyun */
486*4882a593Smuzhiyun imx_iomux_set_gpr_register(1, 13, 1, 1);
487*4882a593Smuzhiyun break;
488*4882a593Smuzhiyun case 1:
489*4882a593Smuzhiyun /* nothing to do */
490*4882a593Smuzhiyun break;
491*4882a593Smuzhiyun default:
492*4882a593Smuzhiyun printf("Invalid USB port: %d\n", port);
493*4882a593Smuzhiyun return -EINVAL;
494*4882a593Smuzhiyun }
495*4882a593Smuzhiyun
496*4882a593Smuzhiyun return 0;
497*4882a593Smuzhiyun }
498*4882a593Smuzhiyun
board_ehci_power(int port,int on)499*4882a593Smuzhiyun int board_ehci_power(int port, int on)
500*4882a593Smuzhiyun {
501*4882a593Smuzhiyun switch (port) {
502*4882a593Smuzhiyun case 0:
503*4882a593Smuzhiyun break;
504*4882a593Smuzhiyun case 1:
505*4882a593Smuzhiyun gpio_direction_output(IMX_GPIO_NR(5, 5), on);
506*4882a593Smuzhiyun break;
507*4882a593Smuzhiyun default:
508*4882a593Smuzhiyun printf("Invalid USB port: %d\n", port);
509*4882a593Smuzhiyun return -EINVAL;
510*4882a593Smuzhiyun }
511*4882a593Smuzhiyun
512*4882a593Smuzhiyun return 0;
513*4882a593Smuzhiyun }
514*4882a593Smuzhiyun
515*4882a593Smuzhiyun struct display_info_t {
516*4882a593Smuzhiyun int bus;
517*4882a593Smuzhiyun int addr;
518*4882a593Smuzhiyun int pixfmt;
519*4882a593Smuzhiyun int (*detect)(struct display_info_t const *dev);
520*4882a593Smuzhiyun void (*enable)(struct display_info_t const *dev);
521*4882a593Smuzhiyun struct fb_videomode mode;
522*4882a593Smuzhiyun };
523*4882a593Smuzhiyun
disable_lvds(struct display_info_t const * dev)524*4882a593Smuzhiyun static void disable_lvds(struct display_info_t const *dev)
525*4882a593Smuzhiyun {
526*4882a593Smuzhiyun struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR;
527*4882a593Smuzhiyun
528*4882a593Smuzhiyun clrbits_le32(&iomux->gpr[2], IOMUXC_GPR2_LVDS_CH0_MODE_MASK |
529*4882a593Smuzhiyun IOMUXC_GPR2_LVDS_CH1_MODE_MASK);
530*4882a593Smuzhiyun }
531*4882a593Smuzhiyun
do_enable_hdmi(struct display_info_t const * dev)532*4882a593Smuzhiyun static void do_enable_hdmi(struct display_info_t const *dev)
533*4882a593Smuzhiyun {
534*4882a593Smuzhiyun disable_lvds(dev);
535*4882a593Smuzhiyun imx_enable_hdmi_phy();
536*4882a593Smuzhiyun }
537*4882a593Smuzhiyun
538*4882a593Smuzhiyun static struct display_info_t const displays[] = {
539*4882a593Smuzhiyun {
540*4882a593Smuzhiyun .bus = -1,
541*4882a593Smuzhiyun .addr = 0,
542*4882a593Smuzhiyun .pixfmt = IPU_PIX_FMT_RGB666,
543*4882a593Smuzhiyun .detect = NULL,
544*4882a593Smuzhiyun .enable = NULL,
545*4882a593Smuzhiyun .mode = {
546*4882a593Smuzhiyun .name =
547*4882a593Smuzhiyun "Hannstar-XGA",
548*4882a593Smuzhiyun .refresh = 60,
549*4882a593Smuzhiyun .xres = 1024,
550*4882a593Smuzhiyun .yres = 768,
551*4882a593Smuzhiyun .pixclock = 15385,
552*4882a593Smuzhiyun .left_margin = 220,
553*4882a593Smuzhiyun .right_margin = 40,
554*4882a593Smuzhiyun .upper_margin = 21,
555*4882a593Smuzhiyun .lower_margin = 7,
556*4882a593Smuzhiyun .hsync_len = 60,
557*4882a593Smuzhiyun .vsync_len = 10,
558*4882a593Smuzhiyun .sync = FB_SYNC_EXT,
559*4882a593Smuzhiyun .vmode = FB_VMODE_NONINTERLACED } },
560*4882a593Smuzhiyun {
561*4882a593Smuzhiyun .bus = -1,
562*4882a593Smuzhiyun .addr = 0,
563*4882a593Smuzhiyun .pixfmt = IPU_PIX_FMT_RGB24,
564*4882a593Smuzhiyun .detect = NULL,
565*4882a593Smuzhiyun .enable = do_enable_hdmi,
566*4882a593Smuzhiyun .mode = {
567*4882a593Smuzhiyun .name = "HDMI",
568*4882a593Smuzhiyun .refresh = 60,
569*4882a593Smuzhiyun .xres = 1024,
570*4882a593Smuzhiyun .yres = 768,
571*4882a593Smuzhiyun .pixclock = 15385,
572*4882a593Smuzhiyun .left_margin = 220,
573*4882a593Smuzhiyun .right_margin = 40,
574*4882a593Smuzhiyun .upper_margin = 21,
575*4882a593Smuzhiyun .lower_margin = 7,
576*4882a593Smuzhiyun .hsync_len = 60,
577*4882a593Smuzhiyun .vsync_len = 10,
578*4882a593Smuzhiyun .sync = FB_SYNC_EXT,
579*4882a593Smuzhiyun .vmode = FB_VMODE_NONINTERLACED } }
580*4882a593Smuzhiyun };
581*4882a593Smuzhiyun
board_video_skip(void)582*4882a593Smuzhiyun int board_video_skip(void)
583*4882a593Smuzhiyun {
584*4882a593Smuzhiyun int i;
585*4882a593Smuzhiyun int ret;
586*4882a593Smuzhiyun char const *panel = env_get("panel");
587*4882a593Smuzhiyun if (!panel) {
588*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(displays); i++) {
589*4882a593Smuzhiyun struct display_info_t const *dev = displays + i;
590*4882a593Smuzhiyun if (dev->detect && dev->detect(dev)) {
591*4882a593Smuzhiyun panel = dev->mode.name;
592*4882a593Smuzhiyun printf("auto-detected panel %s\n", panel);
593*4882a593Smuzhiyun break;
594*4882a593Smuzhiyun }
595*4882a593Smuzhiyun }
596*4882a593Smuzhiyun if (!panel) {
597*4882a593Smuzhiyun panel = displays[0].mode.name;
598*4882a593Smuzhiyun printf("No panel detected: default to %s\n", panel);
599*4882a593Smuzhiyun i = 0;
600*4882a593Smuzhiyun }
601*4882a593Smuzhiyun } else {
602*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(displays); i++) {
603*4882a593Smuzhiyun if (!strcmp(panel, displays[i].mode.name))
604*4882a593Smuzhiyun break;
605*4882a593Smuzhiyun }
606*4882a593Smuzhiyun }
607*4882a593Smuzhiyun if (i < ARRAY_SIZE(displays)) {
608*4882a593Smuzhiyun ret = ipuv3_fb_init(&displays[i].mode, 0, displays[i].pixfmt);
609*4882a593Smuzhiyun if (!ret) {
610*4882a593Smuzhiyun if (displays[i].enable)
611*4882a593Smuzhiyun displays[i].enable(displays + i);
612*4882a593Smuzhiyun printf("Display: %s (%ux%u)\n",
613*4882a593Smuzhiyun displays[i].mode.name, displays[i].mode.xres,
614*4882a593Smuzhiyun displays[i].mode.yres);
615*4882a593Smuzhiyun } else
616*4882a593Smuzhiyun printf("LCD %s cannot be configured: %d\n",
617*4882a593Smuzhiyun displays[i].mode.name, ret);
618*4882a593Smuzhiyun } else {
619*4882a593Smuzhiyun printf("unsupported panel %s\n", panel);
620*4882a593Smuzhiyun return -EINVAL;
621*4882a593Smuzhiyun }
622*4882a593Smuzhiyun
623*4882a593Smuzhiyun return 0;
624*4882a593Smuzhiyun }
625*4882a593Smuzhiyun
setup_display(void)626*4882a593Smuzhiyun static void setup_display(void)
627*4882a593Smuzhiyun {
628*4882a593Smuzhiyun struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
629*4882a593Smuzhiyun struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR;
630*4882a593Smuzhiyun int reg;
631*4882a593Smuzhiyun
632*4882a593Smuzhiyun enable_ipu_clock();
633*4882a593Smuzhiyun imx_setup_hdmi();
634*4882a593Smuzhiyun
635*4882a593Smuzhiyun /* Turn on LDB0, LDB1, IPU,IPU DI0 clocks */
636*4882a593Smuzhiyun setbits_le32(&mxc_ccm->CCGR3, MXC_CCM_CCGR3_LDB_DI0_MASK |
637*4882a593Smuzhiyun MXC_CCM_CCGR3_LDB_DI1_MASK);
638*4882a593Smuzhiyun
639*4882a593Smuzhiyun /* set LDB0, LDB1 clk select to 011/011 */
640*4882a593Smuzhiyun reg = readl(&mxc_ccm->cs2cdr);
641*4882a593Smuzhiyun reg &= ~(MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_MASK |
642*4882a593Smuzhiyun MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_MASK);
643*4882a593Smuzhiyun reg |= (3 << MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_OFFSET) |
644*4882a593Smuzhiyun (3 << MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_OFFSET);
645*4882a593Smuzhiyun writel(reg, &mxc_ccm->cs2cdr);
646*4882a593Smuzhiyun
647*4882a593Smuzhiyun setbits_le32(&mxc_ccm->cscmr2, MXC_CCM_CSCMR2_LDB_DI0_IPU_DIV |
648*4882a593Smuzhiyun MXC_CCM_CSCMR2_LDB_DI1_IPU_DIV);
649*4882a593Smuzhiyun
650*4882a593Smuzhiyun setbits_le32(&mxc_ccm->chsccdr, CHSCCDR_CLK_SEL_LDB_DI0 <<
651*4882a593Smuzhiyun MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET |
652*4882a593Smuzhiyun CHSCCDR_CLK_SEL_LDB_DI0 <<
653*4882a593Smuzhiyun MXC_CCM_CHSCCDR_IPU1_DI1_CLK_SEL_OFFSET);
654*4882a593Smuzhiyun
655*4882a593Smuzhiyun reg = IOMUXC_GPR2_BGREF_RRMODE_EXTERNAL_RES
656*4882a593Smuzhiyun | IOMUXC_GPR2_DI1_VS_POLARITY_ACTIVE_LOW
657*4882a593Smuzhiyun | IOMUXC_GPR2_DI0_VS_POLARITY_ACTIVE_LOW
658*4882a593Smuzhiyun | IOMUXC_GPR2_BIT_MAPPING_CH1_SPWG
659*4882a593Smuzhiyun | IOMUXC_GPR2_DATA_WIDTH_CH1_18BIT
660*4882a593Smuzhiyun | IOMUXC_GPR2_BIT_MAPPING_CH0_SPWG
661*4882a593Smuzhiyun | IOMUXC_GPR2_DATA_WIDTH_CH0_18BIT
662*4882a593Smuzhiyun | IOMUXC_GPR2_LVDS_CH0_MODE_DISABLED
663*4882a593Smuzhiyun | IOMUXC_GPR2_LVDS_CH1_MODE_ENABLED_DI0;
664*4882a593Smuzhiyun writel(reg, &iomux->gpr[2]);
665*4882a593Smuzhiyun
666*4882a593Smuzhiyun reg = readl(&iomux->gpr[3]);
667*4882a593Smuzhiyun reg = (reg & ~(IOMUXC_GPR3_LVDS1_MUX_CTL_MASK |
668*4882a593Smuzhiyun IOMUXC_GPR3_HDMI_MUX_CTL_MASK)) |
669*4882a593Smuzhiyun (IOMUXC_GPR3_MUX_SRC_IPU1_DI0 <<
670*4882a593Smuzhiyun IOMUXC_GPR3_LVDS1_MUX_CTL_OFFSET);
671*4882a593Smuzhiyun writel(reg, &iomux->gpr[3]);
672*4882a593Smuzhiyun }
673*4882a593Smuzhiyun
674*4882a593Smuzhiyun /*
675*4882a593Smuzhiyun * Do not overwrite the console
676*4882a593Smuzhiyun * Use always serial for U-Boot console
677*4882a593Smuzhiyun */
overwrite_console(void)678*4882a593Smuzhiyun int overwrite_console(void)
679*4882a593Smuzhiyun {
680*4882a593Smuzhiyun return 1;
681*4882a593Smuzhiyun }
682*4882a593Smuzhiyun
board_early_init_f(void)683*4882a593Smuzhiyun int board_early_init_f(void)
684*4882a593Smuzhiyun {
685*4882a593Smuzhiyun setup_iomux_uart();
686*4882a593Smuzhiyun setup_display();
687*4882a593Smuzhiyun
688*4882a593Smuzhiyun #ifdef CONFIG_MXC_SPI
689*4882a593Smuzhiyun setup_spi();
690*4882a593Smuzhiyun #endif
691*4882a593Smuzhiyun return 0;
692*4882a593Smuzhiyun }
693*4882a593Smuzhiyun
board_init(void)694*4882a593Smuzhiyun int board_init(void)
695*4882a593Smuzhiyun {
696*4882a593Smuzhiyun /* address of boot parameters */
697*4882a593Smuzhiyun gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
698*4882a593Smuzhiyun
699*4882a593Smuzhiyun
700*4882a593Smuzhiyun if (is_mx6dq())
701*4882a593Smuzhiyun setup_i2c(1, CONFIG_SYS_I2C_SPEED, 0x7f, &mx6q_i2c_pad_info1);
702*4882a593Smuzhiyun else
703*4882a593Smuzhiyun setup_i2c(1, CONFIG_SYS_I2C_SPEED, 0x7f, &mx6dl_i2c_pad_info1);
704*4882a593Smuzhiyun
705*4882a593Smuzhiyun #ifdef CONFIG_SATA
706*4882a593Smuzhiyun setup_sata();
707*4882a593Smuzhiyun #endif
708*4882a593Smuzhiyun
709*4882a593Smuzhiyun return 0;
710*4882a593Smuzhiyun }
711*4882a593Smuzhiyun
checkboard(void)712*4882a593Smuzhiyun int checkboard(void)
713*4882a593Smuzhiyun {
714*4882a593Smuzhiyun char *type = "unknown";
715*4882a593Smuzhiyun
716*4882a593Smuzhiyun if (is_cpu_type(MXC_CPU_MX6Q))
717*4882a593Smuzhiyun type = "Quad";
718*4882a593Smuzhiyun else if (is_cpu_type(MXC_CPU_MX6D))
719*4882a593Smuzhiyun type = "Dual";
720*4882a593Smuzhiyun else if (is_cpu_type(MXC_CPU_MX6DL))
721*4882a593Smuzhiyun type = "Dual-Lite";
722*4882a593Smuzhiyun else if (is_cpu_type(MXC_CPU_MX6SOLO))
723*4882a593Smuzhiyun type = "Solo";
724*4882a593Smuzhiyun
725*4882a593Smuzhiyun printf("Board: conga-QMX6 %s\n", type);
726*4882a593Smuzhiyun
727*4882a593Smuzhiyun return 0;
728*4882a593Smuzhiyun }
729*4882a593Smuzhiyun
730*4882a593Smuzhiyun #ifdef CONFIG_MXC_SPI
board_spi_cs_gpio(unsigned bus,unsigned cs)731*4882a593Smuzhiyun int board_spi_cs_gpio(unsigned bus, unsigned cs)
732*4882a593Smuzhiyun {
733*4882a593Smuzhiyun return (bus == 0 && cs == 0) ? (IMX_GPIO_NR(3, 19)) : -EINVAL;
734*4882a593Smuzhiyun }
735*4882a593Smuzhiyun #endif
736*4882a593Smuzhiyun
737*4882a593Smuzhiyun #ifdef CONFIG_CMD_BMODE
738*4882a593Smuzhiyun static const struct boot_mode board_boot_modes[] = {
739*4882a593Smuzhiyun /* 4 bit bus width */
740*4882a593Smuzhiyun {"mmc0", MAKE_CFGVAL(0x50, 0x20, 0x00, 0x00)},
741*4882a593Smuzhiyun {"mmc1", MAKE_CFGVAL(0x50, 0x38, 0x00, 0x00)},
742*4882a593Smuzhiyun {NULL, 0},
743*4882a593Smuzhiyun };
744*4882a593Smuzhiyun #endif
745*4882a593Smuzhiyun
misc_init_r(void)746*4882a593Smuzhiyun int misc_init_r(void)
747*4882a593Smuzhiyun {
748*4882a593Smuzhiyun #ifdef CONFIG_CMD_BMODE
749*4882a593Smuzhiyun add_board_boot_modes(board_boot_modes);
750*4882a593Smuzhiyun #endif
751*4882a593Smuzhiyun return 0;
752*4882a593Smuzhiyun }
753*4882a593Smuzhiyun
board_late_init(void)754*4882a593Smuzhiyun int board_late_init(void)
755*4882a593Smuzhiyun {
756*4882a593Smuzhiyun #ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
757*4882a593Smuzhiyun if (is_mx6dq())
758*4882a593Smuzhiyun env_set("board_rev", "MX6Q");
759*4882a593Smuzhiyun else
760*4882a593Smuzhiyun env_set("board_rev", "MX6DL");
761*4882a593Smuzhiyun #endif
762*4882a593Smuzhiyun
763*4882a593Smuzhiyun return 0;
764*4882a593Smuzhiyun }
765*4882a593Smuzhiyun
766*4882a593Smuzhiyun #ifdef CONFIG_SPL_BUILD
767*4882a593Smuzhiyun #include <asm/arch/mx6-ddr.h>
768*4882a593Smuzhiyun #include <spl.h>
769*4882a593Smuzhiyun #include <linux/libfdt.h>
770*4882a593Smuzhiyun #include <spi_flash.h>
771*4882a593Smuzhiyun #include <spi.h>
772*4882a593Smuzhiyun
773*4882a593Smuzhiyun const struct mx6dq_iomux_ddr_regs mx6q_ddr_ioregs = {
774*4882a593Smuzhiyun .dram_sdclk_0 = 0x00000030,
775*4882a593Smuzhiyun .dram_sdclk_1 = 0x00000030,
776*4882a593Smuzhiyun .dram_cas = 0x00000030,
777*4882a593Smuzhiyun .dram_ras = 0x00000030,
778*4882a593Smuzhiyun .dram_reset = 0x00000030,
779*4882a593Smuzhiyun .dram_sdcke0 = 0x00003000,
780*4882a593Smuzhiyun .dram_sdcke1 = 0x00003000,
781*4882a593Smuzhiyun .dram_sdba2 = 0x00000000,
782*4882a593Smuzhiyun .dram_sdodt0 = 0x00000030,
783*4882a593Smuzhiyun .dram_sdodt1 = 0x00000030,
784*4882a593Smuzhiyun .dram_sdqs0 = 0x00000030,
785*4882a593Smuzhiyun .dram_sdqs1 = 0x00000030,
786*4882a593Smuzhiyun .dram_sdqs2 = 0x00000030,
787*4882a593Smuzhiyun .dram_sdqs3 = 0x00000030,
788*4882a593Smuzhiyun .dram_sdqs4 = 0x00000030,
789*4882a593Smuzhiyun .dram_sdqs5 = 0x00000030,
790*4882a593Smuzhiyun .dram_sdqs6 = 0x00000030,
791*4882a593Smuzhiyun .dram_sdqs7 = 0x00000030,
792*4882a593Smuzhiyun .dram_dqm0 = 0x00000030,
793*4882a593Smuzhiyun .dram_dqm1 = 0x00000030,
794*4882a593Smuzhiyun .dram_dqm2 = 0x00000030,
795*4882a593Smuzhiyun .dram_dqm3 = 0x00000030,
796*4882a593Smuzhiyun .dram_dqm4 = 0x00000030,
797*4882a593Smuzhiyun .dram_dqm5 = 0x00000030,
798*4882a593Smuzhiyun .dram_dqm6 = 0x00000030,
799*4882a593Smuzhiyun .dram_dqm7 = 0x00000030,
800*4882a593Smuzhiyun };
801*4882a593Smuzhiyun
802*4882a593Smuzhiyun static const struct mx6sdl_iomux_ddr_regs mx6dl_ddr_ioregs = {
803*4882a593Smuzhiyun .dram_sdclk_0 = 0x00000030,
804*4882a593Smuzhiyun .dram_sdclk_1 = 0x00000030,
805*4882a593Smuzhiyun .dram_cas = 0x00000030,
806*4882a593Smuzhiyun .dram_ras = 0x00000030,
807*4882a593Smuzhiyun .dram_reset = 0x00000030,
808*4882a593Smuzhiyun .dram_sdcke0 = 0x00003000,
809*4882a593Smuzhiyun .dram_sdcke1 = 0x00003000,
810*4882a593Smuzhiyun .dram_sdba2 = 0x00000000,
811*4882a593Smuzhiyun .dram_sdodt0 = 0x00000030,
812*4882a593Smuzhiyun .dram_sdodt1 = 0x00000030,
813*4882a593Smuzhiyun .dram_sdqs0 = 0x00000030,
814*4882a593Smuzhiyun .dram_sdqs1 = 0x00000030,
815*4882a593Smuzhiyun .dram_sdqs2 = 0x00000030,
816*4882a593Smuzhiyun .dram_sdqs3 = 0x00000030,
817*4882a593Smuzhiyun .dram_sdqs4 = 0x00000030,
818*4882a593Smuzhiyun .dram_sdqs5 = 0x00000030,
819*4882a593Smuzhiyun .dram_sdqs6 = 0x00000030,
820*4882a593Smuzhiyun .dram_sdqs7 = 0x00000030,
821*4882a593Smuzhiyun .dram_dqm0 = 0x00000030,
822*4882a593Smuzhiyun .dram_dqm1 = 0x00000030,
823*4882a593Smuzhiyun .dram_dqm2 = 0x00000030,
824*4882a593Smuzhiyun .dram_dqm3 = 0x00000030,
825*4882a593Smuzhiyun .dram_dqm4 = 0x00000030,
826*4882a593Smuzhiyun .dram_dqm5 = 0x00000030,
827*4882a593Smuzhiyun .dram_dqm6 = 0x00000030,
828*4882a593Smuzhiyun .dram_dqm7 = 0x00000030,
829*4882a593Smuzhiyun };
830*4882a593Smuzhiyun
831*4882a593Smuzhiyun const struct mx6dq_iomux_grp_regs mx6q_grp_ioregs = {
832*4882a593Smuzhiyun .grp_ddr_type = 0x000C0000,
833*4882a593Smuzhiyun .grp_ddrmode_ctl = 0x00020000,
834*4882a593Smuzhiyun .grp_ddrpke = 0x00000000,
835*4882a593Smuzhiyun .grp_addds = 0x00000030,
836*4882a593Smuzhiyun .grp_ctlds = 0x00000030,
837*4882a593Smuzhiyun .grp_ddrmode = 0x00020000,
838*4882a593Smuzhiyun .grp_b0ds = 0x00000030,
839*4882a593Smuzhiyun .grp_b1ds = 0x00000030,
840*4882a593Smuzhiyun .grp_b2ds = 0x00000030,
841*4882a593Smuzhiyun .grp_b3ds = 0x00000030,
842*4882a593Smuzhiyun .grp_b4ds = 0x00000030,
843*4882a593Smuzhiyun .grp_b5ds = 0x00000030,
844*4882a593Smuzhiyun .grp_b6ds = 0x00000030,
845*4882a593Smuzhiyun .grp_b7ds = 0x00000030,
846*4882a593Smuzhiyun };
847*4882a593Smuzhiyun
848*4882a593Smuzhiyun static const struct mx6sdl_iomux_grp_regs mx6sdl_grp_ioregs = {
849*4882a593Smuzhiyun .grp_ddr_type = 0x000c0000,
850*4882a593Smuzhiyun .grp_ddrmode_ctl = 0x00020000,
851*4882a593Smuzhiyun .grp_ddrpke = 0x00000000,
852*4882a593Smuzhiyun .grp_addds = 0x00000030,
853*4882a593Smuzhiyun .grp_ctlds = 0x00000030,
854*4882a593Smuzhiyun .grp_ddrmode = 0x00020000,
855*4882a593Smuzhiyun .grp_b0ds = 0x00000030,
856*4882a593Smuzhiyun .grp_b1ds = 0x00000030,
857*4882a593Smuzhiyun .grp_b2ds = 0x00000030,
858*4882a593Smuzhiyun .grp_b3ds = 0x00000030,
859*4882a593Smuzhiyun .grp_b4ds = 0x00000030,
860*4882a593Smuzhiyun .grp_b5ds = 0x00000030,
861*4882a593Smuzhiyun .grp_b6ds = 0x00000030,
862*4882a593Smuzhiyun .grp_b7ds = 0x00000030,
863*4882a593Smuzhiyun };
864*4882a593Smuzhiyun
865*4882a593Smuzhiyun const struct mx6_mmdc_calibration mx6q_mmcd_calib = {
866*4882a593Smuzhiyun .p0_mpwldectrl0 = 0x0016001A,
867*4882a593Smuzhiyun .p0_mpwldectrl1 = 0x0023001C,
868*4882a593Smuzhiyun .p1_mpwldectrl0 = 0x0028003A,
869*4882a593Smuzhiyun .p1_mpwldectrl1 = 0x001F002C,
870*4882a593Smuzhiyun .p0_mpdgctrl0 = 0x43440354,
871*4882a593Smuzhiyun .p0_mpdgctrl1 = 0x033C033C,
872*4882a593Smuzhiyun .p1_mpdgctrl0 = 0x43300368,
873*4882a593Smuzhiyun .p1_mpdgctrl1 = 0x03500330,
874*4882a593Smuzhiyun .p0_mprddlctl = 0x3228242E,
875*4882a593Smuzhiyun .p1_mprddlctl = 0x2C2C2636,
876*4882a593Smuzhiyun .p0_mpwrdlctl = 0x36323A38,
877*4882a593Smuzhiyun .p1_mpwrdlctl = 0x42324440,
878*4882a593Smuzhiyun };
879*4882a593Smuzhiyun
880*4882a593Smuzhiyun const struct mx6_mmdc_calibration mx6q_2g_mmcd_calib = {
881*4882a593Smuzhiyun .p0_mpwldectrl0 = 0x00080016,
882*4882a593Smuzhiyun .p0_mpwldectrl1 = 0x001D0016,
883*4882a593Smuzhiyun .p1_mpwldectrl0 = 0x0018002C,
884*4882a593Smuzhiyun .p1_mpwldectrl1 = 0x000D001D,
885*4882a593Smuzhiyun .p0_mpdgctrl0 = 0x43200334,
886*4882a593Smuzhiyun .p0_mpdgctrl1 = 0x0320031C,
887*4882a593Smuzhiyun .p1_mpdgctrl0 = 0x0344034C,
888*4882a593Smuzhiyun .p1_mpdgctrl1 = 0x03380314,
889*4882a593Smuzhiyun .p0_mprddlctl = 0x3E36383A,
890*4882a593Smuzhiyun .p1_mprddlctl = 0x38363240,
891*4882a593Smuzhiyun .p0_mpwrdlctl = 0x36364238,
892*4882a593Smuzhiyun .p1_mpwrdlctl = 0x4230423E,
893*4882a593Smuzhiyun };
894*4882a593Smuzhiyun
895*4882a593Smuzhiyun static const struct mx6_mmdc_calibration mx6s_mmcd_calib = {
896*4882a593Smuzhiyun .p0_mpwldectrl0 = 0x00480049,
897*4882a593Smuzhiyun .p0_mpwldectrl1 = 0x00410044,
898*4882a593Smuzhiyun .p0_mpdgctrl0 = 0x42480248,
899*4882a593Smuzhiyun .p0_mpdgctrl1 = 0x023C023C,
900*4882a593Smuzhiyun .p0_mprddlctl = 0x40424644,
901*4882a593Smuzhiyun .p0_mpwrdlctl = 0x34323034,
902*4882a593Smuzhiyun };
903*4882a593Smuzhiyun
904*4882a593Smuzhiyun const struct mx6_mmdc_calibration mx6dl_mmcd_calib = {
905*4882a593Smuzhiyun .p0_mpwldectrl0 = 0x0043004B,
906*4882a593Smuzhiyun .p0_mpwldectrl1 = 0x003A003E,
907*4882a593Smuzhiyun .p1_mpwldectrl0 = 0x0047004F,
908*4882a593Smuzhiyun .p1_mpwldectrl1 = 0x004E0061,
909*4882a593Smuzhiyun .p0_mpdgctrl0 = 0x42500250,
910*4882a593Smuzhiyun .p0_mpdgctrl1 = 0x0238023C,
911*4882a593Smuzhiyun .p1_mpdgctrl0 = 0x42640264,
912*4882a593Smuzhiyun .p1_mpdgctrl1 = 0x02500258,
913*4882a593Smuzhiyun .p0_mprddlctl = 0x40424846,
914*4882a593Smuzhiyun .p1_mprddlctl = 0x46484842,
915*4882a593Smuzhiyun .p0_mpwrdlctl = 0x38382C30,
916*4882a593Smuzhiyun .p1_mpwrdlctl = 0x34343430,
917*4882a593Smuzhiyun };
918*4882a593Smuzhiyun
919*4882a593Smuzhiyun static struct mx6_ddr3_cfg mem_ddr_2g = {
920*4882a593Smuzhiyun .mem_speed = 1600,
921*4882a593Smuzhiyun .density = 2,
922*4882a593Smuzhiyun .width = 16,
923*4882a593Smuzhiyun .banks = 8,
924*4882a593Smuzhiyun .rowaddr = 14,
925*4882a593Smuzhiyun .coladdr = 10,
926*4882a593Smuzhiyun .pagesz = 2,
927*4882a593Smuzhiyun .trcd = 1310,
928*4882a593Smuzhiyun .trcmin = 4875,
929*4882a593Smuzhiyun .trasmin = 3500,
930*4882a593Smuzhiyun };
931*4882a593Smuzhiyun
932*4882a593Smuzhiyun static struct mx6_ddr3_cfg mem_ddr_4g = {
933*4882a593Smuzhiyun .mem_speed = 1600,
934*4882a593Smuzhiyun .density = 4,
935*4882a593Smuzhiyun .width = 16,
936*4882a593Smuzhiyun .banks = 8,
937*4882a593Smuzhiyun .rowaddr = 15,
938*4882a593Smuzhiyun .coladdr = 10,
939*4882a593Smuzhiyun .pagesz = 2,
940*4882a593Smuzhiyun .trcd = 1310,
941*4882a593Smuzhiyun .trcmin = 4875,
942*4882a593Smuzhiyun .trasmin = 3500,
943*4882a593Smuzhiyun };
944*4882a593Smuzhiyun
ccgr_init(void)945*4882a593Smuzhiyun static void ccgr_init(void)
946*4882a593Smuzhiyun {
947*4882a593Smuzhiyun struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
948*4882a593Smuzhiyun
949*4882a593Smuzhiyun writel(0x00C03F3F, &ccm->CCGR0);
950*4882a593Smuzhiyun writel(0x0030FC03, &ccm->CCGR1);
951*4882a593Smuzhiyun writel(0x0FFFC000, &ccm->CCGR2);
952*4882a593Smuzhiyun writel(0x3FF00000, &ccm->CCGR3);
953*4882a593Smuzhiyun writel(0x00FFF300, &ccm->CCGR4);
954*4882a593Smuzhiyun writel(0x0F0000C3, &ccm->CCGR5);
955*4882a593Smuzhiyun writel(0x000003FF, &ccm->CCGR6);
956*4882a593Smuzhiyun }
957*4882a593Smuzhiyun
958*4882a593Smuzhiyun /* Define a minimal structure so that the part number can be read via SPL */
959*4882a593Smuzhiyun struct mfgdata {
960*4882a593Smuzhiyun unsigned char tsize;
961*4882a593Smuzhiyun /* size of checksummed part in bytes */
962*4882a593Smuzhiyun unsigned char ckcnt;
963*4882a593Smuzhiyun /* checksum corrected byte */
964*4882a593Smuzhiyun unsigned char cksum;
965*4882a593Smuzhiyun /* decimal serial number, packed BCD */
966*4882a593Smuzhiyun unsigned char serial[6];
967*4882a593Smuzhiyun /* part number, right justified, ASCII */
968*4882a593Smuzhiyun unsigned char pn[16];
969*4882a593Smuzhiyun };
970*4882a593Smuzhiyun
conv_ascii(unsigned char * dst,unsigned char * src,int len)971*4882a593Smuzhiyun static void conv_ascii(unsigned char *dst, unsigned char *src, int len)
972*4882a593Smuzhiyun {
973*4882a593Smuzhiyun int remain = len;
974*4882a593Smuzhiyun unsigned char *sptr = src;
975*4882a593Smuzhiyun unsigned char *dptr = dst;
976*4882a593Smuzhiyun
977*4882a593Smuzhiyun while (remain) {
978*4882a593Smuzhiyun if (*sptr) {
979*4882a593Smuzhiyun *dptr = *sptr;
980*4882a593Smuzhiyun dptr++;
981*4882a593Smuzhiyun }
982*4882a593Smuzhiyun sptr++;
983*4882a593Smuzhiyun remain--;
984*4882a593Smuzhiyun }
985*4882a593Smuzhiyun *dptr = 0x0;
986*4882a593Smuzhiyun }
987*4882a593Smuzhiyun
988*4882a593Smuzhiyun #define CFG_MFG_ADDR_OFFSET (spi->size - SZ_16K)
is_2gb(void)989*4882a593Smuzhiyun static bool is_2gb(void)
990*4882a593Smuzhiyun {
991*4882a593Smuzhiyun struct spi_flash *spi;
992*4882a593Smuzhiyun int ret;
993*4882a593Smuzhiyun char buf[sizeof(struct mfgdata)];
994*4882a593Smuzhiyun struct mfgdata *data = (struct mfgdata *)buf;
995*4882a593Smuzhiyun unsigned char outbuf[32];
996*4882a593Smuzhiyun
997*4882a593Smuzhiyun spi = spi_flash_probe(CONFIG_ENV_SPI_BUS,
998*4882a593Smuzhiyun CONFIG_ENV_SPI_CS,
999*4882a593Smuzhiyun CONFIG_ENV_SPI_MAX_HZ, CONFIG_ENV_SPI_MODE);
1000*4882a593Smuzhiyun ret = spi_flash_read(spi, CFG_MFG_ADDR_OFFSET, sizeof(struct mfgdata),
1001*4882a593Smuzhiyun buf);
1002*4882a593Smuzhiyun if (ret)
1003*4882a593Smuzhiyun return false;
1004*4882a593Smuzhiyun
1005*4882a593Smuzhiyun /* Congatec Part Numbers 104 and 105 have 2GiB of RAM */
1006*4882a593Smuzhiyun conv_ascii(outbuf, data->pn, sizeof(data->pn));
1007*4882a593Smuzhiyun if (!memcmp(outbuf, "016104", 6) || !memcmp(outbuf, "016105", 6))
1008*4882a593Smuzhiyun return true;
1009*4882a593Smuzhiyun else
1010*4882a593Smuzhiyun return false;
1011*4882a593Smuzhiyun }
1012*4882a593Smuzhiyun
spl_dram_init(int width)1013*4882a593Smuzhiyun static void spl_dram_init(int width)
1014*4882a593Smuzhiyun {
1015*4882a593Smuzhiyun struct mx6_ddr_sysinfo sysinfo = {
1016*4882a593Smuzhiyun /* width of data bus:0=16,1=32,2=64 */
1017*4882a593Smuzhiyun .dsize = width / 32,
1018*4882a593Smuzhiyun /* config for full 4GB range so that get_mem_size() works */
1019*4882a593Smuzhiyun .cs_density = 32, /* 32Gb per CS */
1020*4882a593Smuzhiyun /* single chip select */
1021*4882a593Smuzhiyun .ncs = 1,
1022*4882a593Smuzhiyun .cs1_mirror = 0,
1023*4882a593Smuzhiyun .rtt_wr = 2,
1024*4882a593Smuzhiyun .rtt_nom = 2,
1025*4882a593Smuzhiyun .walat = 0,
1026*4882a593Smuzhiyun .ralat = 5,
1027*4882a593Smuzhiyun .mif3_mode = 3,
1028*4882a593Smuzhiyun .bi_on = 1,
1029*4882a593Smuzhiyun .sde_to_rst = 0x0d,
1030*4882a593Smuzhiyun .rst_to_cke = 0x20,
1031*4882a593Smuzhiyun .refsel = 1, /* Refresh cycles at 32KHz */
1032*4882a593Smuzhiyun .refr = 7, /* 8 refresh commands per refresh cycle */
1033*4882a593Smuzhiyun };
1034*4882a593Smuzhiyun
1035*4882a593Smuzhiyun if (is_cpu_type(MXC_CPU_MX6Q) && is_2gb()) {
1036*4882a593Smuzhiyun mx6dq_dram_iocfg(width, &mx6q_ddr_ioregs, &mx6q_grp_ioregs);
1037*4882a593Smuzhiyun mx6_dram_cfg(&sysinfo, &mx6q_2g_mmcd_calib, &mem_ddr_4g);
1038*4882a593Smuzhiyun return;
1039*4882a593Smuzhiyun }
1040*4882a593Smuzhiyun
1041*4882a593Smuzhiyun if (is_mx6dq()) {
1042*4882a593Smuzhiyun mx6dq_dram_iocfg(width, &mx6q_ddr_ioregs, &mx6q_grp_ioregs);
1043*4882a593Smuzhiyun mx6_dram_cfg(&sysinfo, &mx6q_mmcd_calib, &mem_ddr_2g);
1044*4882a593Smuzhiyun } else if (is_cpu_type(MXC_CPU_MX6SOLO)) {
1045*4882a593Smuzhiyun sysinfo.walat = 1;
1046*4882a593Smuzhiyun mx6sdl_dram_iocfg(width, &mx6dl_ddr_ioregs, &mx6sdl_grp_ioregs);
1047*4882a593Smuzhiyun mx6_dram_cfg(&sysinfo, &mx6s_mmcd_calib, &mem_ddr_4g);
1048*4882a593Smuzhiyun } else if (is_cpu_type(MXC_CPU_MX6DL)) {
1049*4882a593Smuzhiyun sysinfo.walat = 1;
1050*4882a593Smuzhiyun mx6sdl_dram_iocfg(width, &mx6dl_ddr_ioregs, &mx6sdl_grp_ioregs);
1051*4882a593Smuzhiyun mx6_dram_cfg(&sysinfo, &mx6dl_mmcd_calib, &mem_ddr_2g);
1052*4882a593Smuzhiyun }
1053*4882a593Smuzhiyun }
1054*4882a593Smuzhiyun
board_init_f(ulong dummy)1055*4882a593Smuzhiyun void board_init_f(ulong dummy)
1056*4882a593Smuzhiyun {
1057*4882a593Smuzhiyun /* setup AIPS and disable watchdog */
1058*4882a593Smuzhiyun arch_cpu_init();
1059*4882a593Smuzhiyun
1060*4882a593Smuzhiyun ccgr_init();
1061*4882a593Smuzhiyun gpr_init();
1062*4882a593Smuzhiyun
1063*4882a593Smuzhiyun /* iomux and setup of i2c */
1064*4882a593Smuzhiyun board_early_init_f();
1065*4882a593Smuzhiyun
1066*4882a593Smuzhiyun /* setup GP timer */
1067*4882a593Smuzhiyun timer_init();
1068*4882a593Smuzhiyun
1069*4882a593Smuzhiyun /* UART clocks enabled and gd valid - init serial console */
1070*4882a593Smuzhiyun preloader_console_init();
1071*4882a593Smuzhiyun
1072*4882a593Smuzhiyun /* Needed for malloc() to work in SPL prior to board_init_r() */
1073*4882a593Smuzhiyun spl_init();
1074*4882a593Smuzhiyun
1075*4882a593Smuzhiyun /* DDR initialization */
1076*4882a593Smuzhiyun if (is_cpu_type(MXC_CPU_MX6SOLO))
1077*4882a593Smuzhiyun spl_dram_init(32);
1078*4882a593Smuzhiyun else
1079*4882a593Smuzhiyun spl_dram_init(64);
1080*4882a593Smuzhiyun
1081*4882a593Smuzhiyun /* Clear the BSS. */
1082*4882a593Smuzhiyun memset(__bss_start, 0, __bss_end - __bss_start);
1083*4882a593Smuzhiyun
1084*4882a593Smuzhiyun /* load/boot image from boot device */
1085*4882a593Smuzhiyun board_init_r(NULL, 0);
1086*4882a593Smuzhiyun }
1087*4882a593Smuzhiyun #endif
1088