xref: /OK3568_Linux_fs/u-boot/board/congatec/cgtqmx6eval/cgtqmx6eval.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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