1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2012 Freescale Semiconductor, Inc.
4 *
5 * Author: Fabio Estevam <fabio.estevam@freescale.com>
6 */
7
8#include <common.h>
9#include <image.h>
10#include <init.h>
11#include <net.h>
12#include <asm/global_data.h>
13#include <asm/io.h>
14#include <asm/arch/clock.h>
15#include <asm/arch/imx-regs.h>
16#include <asm/arch/iomux.h>
17#include <asm/arch/mx6-pins.h>
18#include <asm/sections.h>
19#include <env.h>
20#include <linux/errno.h>
21#include <asm/gpio.h>
22#include <asm/mach-imx/iomux-v3.h>
23#include <asm/mach-imx/boot_mode.h>
24#include <asm/mach-imx/spi.h>
25#include <mmc.h>
26#include <fsl_esdhc_imx.h>
27#include <miiphy.h>
28#include <asm/arch/sys_proto.h>
29#include <input.h>
30#include <asm/arch/mxc_hdmi.h>
31#include <asm/mach-imx/video.h>
32#include <asm/arch/crm_regs.h>
33#include <pca953x.h>
34#include <power/pmic.h>
35#include <power/pfuze100_pmic.h>
36#include "../common/pfuze.h"
37
38DECLARE_GLOBAL_DATA_PTR;
39
40#define UART_PAD_CTRL  (PAD_CTL_PUS_100K_UP |			\
41	PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm |			\
42	PAD_CTL_SRE_FAST  | PAD_CTL_HYS)
43
44#define USDHC_PAD_CTRL (PAD_CTL_PUS_47K_UP |			\
45	PAD_CTL_SPEED_LOW | PAD_CTL_DSE_80ohm |			\
46	PAD_CTL_SRE_FAST  | PAD_CTL_HYS)
47
48#define ENET_PAD_CTRL  (PAD_CTL_PUS_100K_UP |			\
49	PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_HYS)
50
51#define GPMI_PAD_CTRL0 (PAD_CTL_PKE | PAD_CTL_PUE | PAD_CTL_PUS_100K_UP)
52#define GPMI_PAD_CTRL1 (PAD_CTL_DSE_40ohm | PAD_CTL_SPEED_MED | \
53			PAD_CTL_SRE_FAST)
54#define GPMI_PAD_CTRL2 (GPMI_PAD_CTRL0 | GPMI_PAD_CTRL1)
55
56#define WEIM_NOR_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_PUE |          \
57	PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED |               \
58	PAD_CTL_DSE_40ohm   | PAD_CTL_SRE_FAST)
59
60int dram_init(void)
61{
62	gd->ram_size = imx_ddr_size();
63
64	return 0;
65}
66
67static iomux_v3_cfg_t const uart4_pads[] = {
68	IOMUX_PADS(PAD_KEY_COL0__UART4_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL)),
69	IOMUX_PADS(PAD_KEY_ROW0__UART4_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL)),
70};
71
72static iomux_v3_cfg_t const port_exp[] = {
73	IOMUX_PADS(PAD_SD2_DAT0__GPIO1_IO15	| MUX_PAD_CTRL(NO_PAD_CTRL)),
74};
75
76#ifdef CONFIG_MTD_NOR_FLASH
77static iomux_v3_cfg_t const eimnor_pads[] = {
78	IOMUX_PADS(PAD_EIM_D16__EIM_DATA16	| MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL)),
79	IOMUX_PADS(PAD_EIM_D17__EIM_DATA17	| MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL)),
80	IOMUX_PADS(PAD_EIM_D18__EIM_DATA18	| MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL)),
81	IOMUX_PADS(PAD_EIM_D19__EIM_DATA19	| MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL)),
82	IOMUX_PADS(PAD_EIM_D20__EIM_DATA20	| MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL)),
83	IOMUX_PADS(PAD_EIM_D21__EIM_DATA21	| MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL)),
84	IOMUX_PADS(PAD_EIM_D22__EIM_DATA22	| MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL)),
85	IOMUX_PADS(PAD_EIM_D23__EIM_DATA23	| MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL)),
86	IOMUX_PADS(PAD_EIM_D24__EIM_DATA24	| MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL)),
87	IOMUX_PADS(PAD_EIM_D25__EIM_DATA25	| MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL)),
88	IOMUX_PADS(PAD_EIM_D26__EIM_DATA26	| MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL)),
89	IOMUX_PADS(PAD_EIM_D27__EIM_DATA27	| MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL)),
90	IOMUX_PADS(PAD_EIM_D28__EIM_DATA28	| MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL)),
91	IOMUX_PADS(PAD_EIM_D29__EIM_DATA29	| MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL)),
92	IOMUX_PADS(PAD_EIM_D30__EIM_DATA30	| MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL)),
93	IOMUX_PADS(PAD_EIM_D31__EIM_DATA31	| MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL)),
94	IOMUX_PADS(PAD_EIM_DA0__EIM_AD00	| MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL)),
95	IOMUX_PADS(PAD_EIM_DA1__EIM_AD01	| MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL)),
96	IOMUX_PADS(PAD_EIM_DA2__EIM_AD02	| MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL)),
97	IOMUX_PADS(PAD_EIM_DA3__EIM_AD03	| MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL)),
98	IOMUX_PADS(PAD_EIM_DA4__EIM_AD04	| MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL)),
99	IOMUX_PADS(PAD_EIM_DA5__EIM_AD05	| MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL)),
100	IOMUX_PADS(PAD_EIM_DA6__EIM_AD06	| MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL)),
101	IOMUX_PADS(PAD_EIM_DA7__EIM_AD07	| MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL)),
102	IOMUX_PADS(PAD_EIM_DA8__EIM_AD08	| MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL)),
103	IOMUX_PADS(PAD_EIM_DA9__EIM_AD09	| MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL)),
104	IOMUX_PADS(PAD_EIM_DA10__EIM_AD10	| MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL)),
105	IOMUX_PADS(PAD_EIM_DA11__EIM_AD11	| MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL)),
106	IOMUX_PADS(PAD_EIM_DA12__EIM_AD12	| MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL)),
107	IOMUX_PADS(PAD_EIM_DA13__EIM_AD13	| MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL)),
108	IOMUX_PADS(PAD_EIM_DA14__EIM_AD14	| MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL)),
109	IOMUX_PADS(PAD_EIM_DA15__EIM_AD15	| MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL)),
110	IOMUX_PADS(PAD_EIM_A16__EIM_ADDR16	| MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL)),
111	IOMUX_PADS(PAD_EIM_A17__EIM_ADDR17	| MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL)),
112	IOMUX_PADS(PAD_EIM_A18__EIM_ADDR18	| MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL)),
113	IOMUX_PADS(PAD_EIM_A19__EIM_ADDR19	| MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL)),
114	IOMUX_PADS(PAD_EIM_A20__EIM_ADDR20	| MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL)),
115	IOMUX_PADS(PAD_EIM_A21__EIM_ADDR21	| MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL)),
116	IOMUX_PADS(PAD_EIM_A22__EIM_ADDR22	| MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL)),
117	IOMUX_PADS(PAD_EIM_A23__EIM_ADDR23	| MUX_PAD_CTRL(WEIM_NOR_PAD_CTRL)),
118	IOMUX_PADS(PAD_EIM_OE__EIM_OE_B		| MUX_PAD_CTRL(NO_PAD_CTRL)),
119	IOMUX_PADS(PAD_EIM_RW__EIM_RW		| MUX_PAD_CTRL(NO_PAD_CTRL)),
120	IOMUX_PADS(PAD_EIM_CS0__EIM_CS0_B	| MUX_PAD_CTRL(NO_PAD_CTRL)),
121};
122
123static void eimnor_cs_setup(void)
124{
125	struct weim *weim_regs = (struct weim *)WEIM_BASE_ADDR;
126
127	writel(0x00020181, &weim_regs->cs0gcr1);
128	writel(0x00000001, &weim_regs->cs0gcr2);
129	writel(0x0a020000, &weim_regs->cs0rcr1);
130	writel(0x0000c000, &weim_regs->cs0rcr2);
131	writel(0x0804a240, &weim_regs->cs0wcr1);
132	writel(0x00000120, &weim_regs->wcr);
133
134	set_chipselect_size(CS0_128);
135}
136
137static void eim_clk_setup(void)
138{
139	struct mxc_ccm_reg *imx_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
140	int cscmr1, ccgr6;
141
142
143	/* Turn off EIM clock */
144	ccgr6 = readl(&imx_ccm->CCGR6);
145	ccgr6 &= ~(0x3 << 10);
146	writel(ccgr6, &imx_ccm->CCGR6);
147
148	/*
149	 * Configure clk_eim_slow_sel = 00 --> derive clock from AXI clk root
150	 * and aclk_eim_slow_podf = 01 --> divide by 2
151	 * so that we can have EIM at the maximum clock of 132MHz
152	 */
153	cscmr1 = readl(&imx_ccm->cscmr1);
154	cscmr1 &= ~(MXC_CCM_CSCMR1_ACLK_EMI_SLOW_MASK |
155		    MXC_CCM_CSCMR1_ACLK_EMI_SLOW_PODF_MASK);
156	cscmr1 |= (1 << MXC_CCM_CSCMR1_ACLK_EMI_SLOW_PODF_OFFSET);
157	writel(cscmr1, &imx_ccm->cscmr1);
158
159	/* Turn on EIM clock */
160	ccgr6 |= (0x3 << 10);
161	writel(ccgr6, &imx_ccm->CCGR6);
162}
163
164static void setup_iomux_eimnor(void)
165{
166	SETUP_IOMUX_PADS(eimnor_pads);
167
168	gpio_direction_output(IMX_GPIO_NR(5, 4), 0);
169
170	eimnor_cs_setup();
171}
172#endif
173
174
175static iomux_v3_cfg_t const usdhc3_pads[] = {
176	IOMUX_PADS(PAD_SD3_CLK__SD3_CLK		| MUX_PAD_CTRL(USDHC_PAD_CTRL)),
177	IOMUX_PADS(PAD_SD3_CMD__SD3_CMD		| MUX_PAD_CTRL(USDHC_PAD_CTRL)),
178	IOMUX_PADS(PAD_SD3_DAT0__SD3_DATA0	| MUX_PAD_CTRL(USDHC_PAD_CTRL)),
179	IOMUX_PADS(PAD_SD3_DAT1__SD3_DATA1	| MUX_PAD_CTRL(USDHC_PAD_CTRL)),
180	IOMUX_PADS(PAD_SD3_DAT2__SD3_DATA2	| MUX_PAD_CTRL(USDHC_PAD_CTRL)),
181	IOMUX_PADS(PAD_SD3_DAT3__SD3_DATA3	| MUX_PAD_CTRL(USDHC_PAD_CTRL)),
182	IOMUX_PADS(PAD_SD3_DAT4__SD3_DATA4	| MUX_PAD_CTRL(USDHC_PAD_CTRL)),
183	IOMUX_PADS(PAD_SD3_DAT5__SD3_DATA5	| MUX_PAD_CTRL(USDHC_PAD_CTRL)),
184	IOMUX_PADS(PAD_SD3_DAT6__SD3_DATA6	| MUX_PAD_CTRL(USDHC_PAD_CTRL)),
185	IOMUX_PADS(PAD_SD3_DAT7__SD3_DATA7	| MUX_PAD_CTRL(USDHC_PAD_CTRL)),
186	IOMUX_PADS(PAD_GPIO_18__SD3_VSELECT	| MUX_PAD_CTRL(USDHC_PAD_CTRL)),
187	IOMUX_PADS(PAD_NANDF_CS2__GPIO6_IO15	| MUX_PAD_CTRL(NO_PAD_CTRL)),
188};
189
190static void setup_iomux_uart(void)
191{
192	SETUP_IOMUX_PADS(uart4_pads);
193}
194
195#ifdef CONFIG_FSL_ESDHC_IMX
196static struct fsl_esdhc_cfg usdhc_cfg[1] = {
197	{USDHC3_BASE_ADDR},
198};
199
200int board_mmc_getcd(struct mmc *mmc)
201{
202	gpio_direction_input(IMX_GPIO_NR(6, 15));
203	return !gpio_get_value(IMX_GPIO_NR(6, 15));
204}
205
206int board_mmc_init(struct bd_info *bis)
207{
208	SETUP_IOMUX_PADS(usdhc3_pads);
209
210	usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK);
211	return fsl_esdhc_initialize(bis, &usdhc_cfg[0]);
212}
213#endif
214
215#ifdef CONFIG_NAND_MXS
216static iomux_v3_cfg_t gpmi_pads[] = {
217	IOMUX_PADS(PAD_NANDF_CLE__NAND_CLE	| MUX_PAD_CTRL(GPMI_PAD_CTRL2)),
218	IOMUX_PADS(PAD_NANDF_ALE__NAND_ALE	| MUX_PAD_CTRL(GPMI_PAD_CTRL2)),
219	IOMUX_PADS(PAD_NANDF_WP_B__NAND_WP_B	| MUX_PAD_CTRL(GPMI_PAD_CTRL2)),
220	IOMUX_PADS(PAD_NANDF_RB0__NAND_READY_B	| MUX_PAD_CTRL(GPMI_PAD_CTRL0)),
221	IOMUX_PADS(PAD_NANDF_CS0__NAND_CE0_B	| MUX_PAD_CTRL(GPMI_PAD_CTRL2)),
222	IOMUX_PADS(PAD_SD4_CMD__NAND_RE_B	| MUX_PAD_CTRL(GPMI_PAD_CTRL2)),
223	IOMUX_PADS(PAD_SD4_CLK__NAND_WE_B	| MUX_PAD_CTRL(GPMI_PAD_CTRL2)),
224	IOMUX_PADS(PAD_NANDF_D0__NAND_DATA00	| MUX_PAD_CTRL(GPMI_PAD_CTRL2)),
225	IOMUX_PADS(PAD_NANDF_D1__NAND_DATA01	| MUX_PAD_CTRL(GPMI_PAD_CTRL2)),
226	IOMUX_PADS(PAD_NANDF_D2__NAND_DATA02	| MUX_PAD_CTRL(GPMI_PAD_CTRL2)),
227	IOMUX_PADS(PAD_NANDF_D3__NAND_DATA03	| MUX_PAD_CTRL(GPMI_PAD_CTRL2)),
228	IOMUX_PADS(PAD_NANDF_D4__NAND_DATA04	| MUX_PAD_CTRL(GPMI_PAD_CTRL2)),
229	IOMUX_PADS(PAD_NANDF_D5__NAND_DATA05	| MUX_PAD_CTRL(GPMI_PAD_CTRL2)),
230	IOMUX_PADS(PAD_NANDF_D6__NAND_DATA06	| MUX_PAD_CTRL(GPMI_PAD_CTRL2)),
231	IOMUX_PADS(PAD_NANDF_D7__NAND_DATA07	| MUX_PAD_CTRL(GPMI_PAD_CTRL2)),
232	IOMUX_PADS(PAD_SD4_DAT0__NAND_DQS	| MUX_PAD_CTRL(GPMI_PAD_CTRL1)),
233};
234
235static void setup_gpmi_nand(void)
236{
237	struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
238
239	/* config gpmi nand iomux */
240	SETUP_IOMUX_PADS(gpmi_pads);
241
242	setup_gpmi_io_clk((MXC_CCM_CS2CDR_ENFC_CLK_PODF(0) |
243			MXC_CCM_CS2CDR_ENFC_CLK_PRED(3) |
244			MXC_CCM_CS2CDR_ENFC_CLK_SEL(3)));
245
246	/* enable apbh clock gating */
247	setbits_le32(&mxc_ccm->CCGR0, MXC_CCM_CCGR0_APBHDMA_MASK);
248}
249#endif
250
251#ifdef CONFIG_REVISION_TAG
252u32 get_board_rev(void)
253{
254	int rev = nxp_board_rev();
255
256	return (get_cpu_rev() & ~(0xF << 8)) | rev;
257}
258#endif
259
260static int ar8031_phy_fixup(struct phy_device *phydev)
261{
262	unsigned short val;
263
264	/* To enable AR8031 ouput a 125MHz clk from CLK_25M */
265	phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x7);
266	phy_write(phydev, MDIO_DEVAD_NONE, 0xe, 0x8016);
267	phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x4007);
268
269	val = phy_read(phydev, MDIO_DEVAD_NONE, 0xe);
270	val &= 0xffe3;
271	val |= 0x18;
272	phy_write(phydev, MDIO_DEVAD_NONE, 0xe, val);
273
274	/* introduce tx clock delay */
275	phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x5);
276	val = phy_read(phydev, MDIO_DEVAD_NONE, 0x1e);
277	val |= 0x0100;
278	phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, val);
279
280	return 0;
281}
282
283int board_phy_config(struct phy_device *phydev)
284{
285	ar8031_phy_fixup(phydev);
286
287	if (phydev->drv->config)
288		phydev->drv->config(phydev);
289
290	return 0;
291}
292
293#if defined(CONFIG_VIDEO_IPUV3)
294static void disable_lvds(struct display_info_t const *dev)
295{
296	struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR;
297
298	clrbits_le32(&iomux->gpr[2],
299		     IOMUXC_GPR2_LVDS_CH0_MODE_MASK |
300		     IOMUXC_GPR2_LVDS_CH1_MODE_MASK);
301}
302
303static void do_enable_hdmi(struct display_info_t const *dev)
304{
305	disable_lvds(dev);
306	imx_enable_hdmi_phy();
307}
308
309struct display_info_t const displays[] = {{
310	.bus	= -1,
311	.addr	= 0,
312	.pixfmt	= IPU_PIX_FMT_RGB666,
313	.detect	= NULL,
314	.enable	= NULL,
315	.mode	= {
316		.name           = "Hannstar-XGA",
317		.refresh        = 60,
318		.xres           = 1024,
319		.yres           = 768,
320		.pixclock       = 15385,
321		.left_margin    = 220,
322		.right_margin   = 40,
323		.upper_margin   = 21,
324		.lower_margin   = 7,
325		.hsync_len      = 60,
326		.vsync_len      = 10,
327		.sync           = FB_SYNC_EXT,
328		.vmode          = FB_VMODE_NONINTERLACED
329} }, {
330	.bus	= -1,
331	.addr	= 0,
332	.pixfmt	= IPU_PIX_FMT_RGB24,
333	.detect	= detect_hdmi,
334	.enable	= do_enable_hdmi,
335	.mode	= {
336		.name           = "HDMI",
337		.refresh        = 60,
338		.xres           = 1024,
339		.yres           = 768,
340		.pixclock       = 15385,
341		.left_margin    = 220,
342		.right_margin   = 40,
343		.upper_margin   = 21,
344		.lower_margin   = 7,
345		.hsync_len      = 60,
346		.vsync_len      = 10,
347		.sync           = FB_SYNC_EXT,
348		.vmode          = FB_VMODE_NONINTERLACED,
349} } };
350size_t display_count = ARRAY_SIZE(displays);
351
352iomux_v3_cfg_t const backlight_pads[] = {
353	IOMUX_PADS(PAD_SD4_DAT1__GPIO2_IO09 | MUX_PAD_CTRL(ENET_PAD_CTRL)),
354};
355
356static void setup_iomux_backlight(void)
357{
358	gpio_request(IMX_GPIO_NR(2, 9), "backlight");
359	gpio_direction_output(IMX_GPIO_NR(2, 9), 1);
360	SETUP_IOMUX_PADS(backlight_pads);
361}
362
363static void setup_display(void)
364{
365	struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
366	struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR;
367	int reg;
368
369	setup_iomux_backlight();
370	enable_ipu_clock();
371	imx_setup_hdmi();
372
373	/* Turn on LDB_DI0 and LDB_DI1 clocks */
374	reg = readl(&mxc_ccm->CCGR3);
375	reg |= MXC_CCM_CCGR3_LDB_DI0_MASK | MXC_CCM_CCGR3_LDB_DI1_MASK;
376	writel(reg, &mxc_ccm->CCGR3);
377
378	/* Set LDB_DI0 and LDB_DI1 clk select to 3b'011 */
379	reg = readl(&mxc_ccm->cs2cdr);
380	reg &= ~(MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_MASK |
381		 MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_MASK);
382	reg |= (3 << MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_OFFSET) |
383	       (3 << MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_OFFSET);
384	writel(reg, &mxc_ccm->cs2cdr);
385
386	reg = readl(&mxc_ccm->cscmr2);
387	reg |= MXC_CCM_CSCMR2_LDB_DI0_IPU_DIV | MXC_CCM_CSCMR2_LDB_DI1_IPU_DIV;
388	writel(reg, &mxc_ccm->cscmr2);
389
390	reg = readl(&mxc_ccm->chsccdr);
391	reg |= (CHSCCDR_CLK_SEL_LDB_DI0
392		<< MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET);
393	reg |= (CHSCCDR_CLK_SEL_LDB_DI0 <<
394		MXC_CCM_CHSCCDR_IPU1_DI1_CLK_SEL_OFFSET);
395	writel(reg, &mxc_ccm->chsccdr);
396
397	reg = IOMUXC_GPR2_DI1_VS_POLARITY_ACTIVE_LOW |
398	      IOMUXC_GPR2_DI0_VS_POLARITY_ACTIVE_LOW |
399	      IOMUXC_GPR2_BIT_MAPPING_CH1_SPWG |
400	      IOMUXC_GPR2_DATA_WIDTH_CH1_18BIT |
401	      IOMUXC_GPR2_BIT_MAPPING_CH0_SPWG |
402	      IOMUXC_GPR2_DATA_WIDTH_CH0_18BIT |
403	      IOMUXC_GPR2_LVDS_CH0_MODE_ENABLED_DI0 |
404	      IOMUXC_GPR2_LVDS_CH1_MODE_DISABLED;
405	writel(reg, &iomux->gpr[2]);
406
407	reg = readl(&iomux->gpr[3]);
408	reg &= ~(IOMUXC_GPR3_LVDS0_MUX_CTL_MASK |
409		 IOMUXC_GPR3_HDMI_MUX_CTL_MASK);
410	reg |= (IOMUXC_GPR3_MUX_SRC_IPU1_DI0 <<
411		IOMUXC_GPR3_LVDS0_MUX_CTL_OFFSET) |
412	       (IOMUXC_GPR3_MUX_SRC_IPU1_DI0 <<
413		IOMUXC_GPR3_HDMI_MUX_CTL_OFFSET);
414	writel(reg, &iomux->gpr[3]);
415}
416#endif /* CONFIG_VIDEO_IPUV3 */
417
418/*
419 * Do not overwrite the console
420 * Use always serial for U-Boot console
421 */
422int overwrite_console(void)
423{
424	return 1;
425}
426
427int board_early_init_f(void)
428{
429	setup_iomux_uart();
430
431#ifdef CONFIG_NAND_MXS
432	setup_gpmi_nand();
433#endif
434
435#ifdef CONFIG_MTD_NOR_FLASH
436	eim_clk_setup();
437#endif
438	return 0;
439}
440
441int board_init(void)
442{
443	/* address of boot parameters */
444	gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
445
446	/* I2C 3 Steer */
447	gpio_request(IMX_GPIO_NR(5, 4), "steer logic");
448	gpio_direction_output(IMX_GPIO_NR(5, 4), 1);
449
450	gpio_request(IMX_GPIO_NR(1, 15), "expander en");
451	gpio_direction_output(IMX_GPIO_NR(1, 15), 1);
452	SETUP_IOMUX_PADS(port_exp);
453
454#ifdef CONFIG_VIDEO_IPUV3
455	setup_display();
456#endif
457
458#ifdef CONFIG_MTD_NOR_FLASH
459	setup_iomux_eimnor();
460#endif
461	return 0;
462}
463
464#ifdef CONFIG_MXC_SPI
465int board_spi_cs_gpio(unsigned bus, unsigned cs)
466{
467	return (bus == 0 && cs == 0) ? (IMX_GPIO_NR(4, 9)) : -1;
468}
469#endif
470
471int power_init_board(void)
472{
473	struct udevice *dev;
474	unsigned int value;
475	int ret;
476
477	ret = pmic_get("pfuze100@8", &dev);
478	if (ret == -ENODEV)
479		return 0;
480
481	if (ret != 0)
482		return ret;
483
484
485	if (is_mx6dqp()) {
486		/* set SW2 staby volatage 0.975V*/
487		value = pmic_reg_read(dev, PFUZE100_SW2STBY);
488		value &= ~0x3f;
489		value |= 0x17;
490		pmic_reg_write(dev, PFUZE100_SW2STBY, value);
491	}
492
493	return pfuze_mode_init(dev, APS_PFM);
494}
495
496#ifdef CONFIG_CMD_BMODE
497static const struct boot_mode board_boot_modes[] = {
498	/* 4 bit bus width */
499	{"mmc0", MAKE_CFGVAL(0x40, 0x30, 0x00, 0x00)},
500	{NULL,   0},
501};
502#endif
503
504int board_late_init(void)
505{
506#ifdef CONFIG_CMD_BMODE
507	add_board_boot_modes(board_boot_modes);
508#endif
509
510#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
511	env_set("board_name", "SABREAUTO");
512
513	if (is_mx6dqp())
514		env_set("board_rev", "MX6QP");
515	else if (is_mx6dq())
516		env_set("board_rev", "MX6Q");
517	else if (is_mx6sdl())
518		env_set("board_rev", "MX6DL");
519#endif
520
521	return 0;
522}
523
524int checkboard(void)
525{
526	printf("Board: MX6Q-Sabreauto rev%c\n", nxp_board_rev_string());
527
528	return 0;
529}
530
531#ifdef CONFIG_USB_EHCI_MX6
532int board_ehci_hcd_init(int port)
533{
534	switch (port) {
535	case 0:
536		/*
537		  * Set daisy chain for otg_pin_id on 6q.
538		 *  For 6dl, this bit is reserved.
539		 */
540		imx_iomux_set_gpr_register(1, 13, 1, 0);
541		break;
542	case 1:
543		break;
544	default:
545		printf("MXC USB port %d not yet supported\n", port);
546		return -EINVAL;
547	}
548	return 0;
549}
550#endif
551
552#ifdef CONFIG_SPL_BUILD
553#include <asm/arch/mx6-ddr.h>
554#include <spl.h>
555#include <linux/libfdt.h>
556
557#ifdef CONFIG_SPL_OS_BOOT
558int spl_start_uboot(void)
559{
560	return 0;
561}
562#endif
563
564static void ccgr_init(void)
565{
566	struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
567
568	writel(0x00C03F3F, &ccm->CCGR0);
569	writel(0x0030FC03, &ccm->CCGR1);
570	writel(0x0FFFC000, &ccm->CCGR2);
571	writel(0x3FF00000, &ccm->CCGR3);
572	writel(0x00FFF300, &ccm->CCGR4);
573	writel(0x0F0000C3, &ccm->CCGR5);
574	writel(0x000003FF, &ccm->CCGR6);
575}
576
577static int mx6q_dcd_table[] = {
578	0x020e0798, 0x000C0000,
579	0x020e0758, 0x00000000,
580	0x020e0588, 0x00000030,
581	0x020e0594, 0x00000030,
582	0x020e056c, 0x00000030,
583	0x020e0578, 0x00000030,
584	0x020e074c, 0x00000030,
585	0x020e057c, 0x00000030,
586	0x020e058c, 0x00000000,
587	0x020e059c, 0x00000030,
588	0x020e05a0, 0x00000030,
589	0x020e078c, 0x00000030,
590	0x020e0750, 0x00020000,
591	0x020e05a8, 0x00000028,
592	0x020e05b0, 0x00000028,
593	0x020e0524, 0x00000028,
594	0x020e051c, 0x00000028,
595	0x020e0518, 0x00000028,
596	0x020e050c, 0x00000028,
597	0x020e05b8, 0x00000028,
598	0x020e05c0, 0x00000028,
599	0x020e0774, 0x00020000,
600	0x020e0784, 0x00000028,
601	0x020e0788, 0x00000028,
602	0x020e0794, 0x00000028,
603	0x020e079c, 0x00000028,
604	0x020e07a0, 0x00000028,
605	0x020e07a4, 0x00000028,
606	0x020e07a8, 0x00000028,
607	0x020e0748, 0x00000028,
608	0x020e05ac, 0x00000028,
609	0x020e05b4, 0x00000028,
610	0x020e0528, 0x00000028,
611	0x020e0520, 0x00000028,
612	0x020e0514, 0x00000028,
613	0x020e0510, 0x00000028,
614	0x020e05bc, 0x00000028,
615	0x020e05c4, 0x00000028,
616	0x021b0800, 0xa1390003,
617	0x021b080c, 0x001F001F,
618	0x021b0810, 0x001F001F,
619	0x021b480c, 0x001F001F,
620	0x021b4810, 0x001F001F,
621	0x021b083c, 0x43260335,
622	0x021b0840, 0x031A030B,
623	0x021b483c, 0x4323033B,
624	0x021b4840, 0x0323026F,
625	0x021b0848, 0x483D4545,
626	0x021b4848, 0x44433E48,
627	0x021b0850, 0x41444840,
628	0x021b4850, 0x4835483E,
629	0x021b081c, 0x33333333,
630	0x021b0820, 0x33333333,
631	0x021b0824, 0x33333333,
632	0x021b0828, 0x33333333,
633	0x021b481c, 0x33333333,
634	0x021b4820, 0x33333333,
635	0x021b4824, 0x33333333,
636	0x021b4828, 0x33333333,
637	0x021b08b8, 0x00000800,
638	0x021b48b8, 0x00000800,
639	0x021b0004, 0x00020036,
640	0x021b0008, 0x09444040,
641	0x021b000c, 0x8A8F7955,
642	0x021b0010, 0xFF328F64,
643	0x021b0014, 0x01FF00DB,
644	0x021b0018, 0x00001740,
645	0x021b001c, 0x00008000,
646	0x021b002c, 0x000026d2,
647	0x021b0030, 0x008F1023,
648	0x021b0040, 0x00000047,
649	0x021b0000, 0x841A0000,
650	0x021b001c, 0x04088032,
651	0x021b001c, 0x00008033,
652	0x021b001c, 0x00048031,
653	0x021b001c, 0x09408030,
654	0x021b001c, 0x04008040,
655	0x021b0020, 0x00005800,
656	0x021b0818, 0x00011117,
657	0x021b4818, 0x00011117,
658	0x021b0004, 0x00025576,
659	0x021b0404, 0x00011006,
660	0x021b001c, 0x00000000,
661	0x020c4068, 0x00C03F3F,
662	0x020c406c, 0x0030FC03,
663	0x020c4070, 0x0FFFC000,
664	0x020c4074, 0x3FF00000,
665	0x020c4078, 0xFFFFF300,
666	0x020c407c, 0x0F0000F3,
667	0x020c4080, 0x00000FFF,
668	0x020e0010, 0xF00000CF,
669	0x020e0018, 0x007F007F,
670	0x020e001c, 0x007F007F,
671};
672
673static int mx6qp_dcd_table[] = {
674	0x020e0798, 0x000C0000,
675	0x020e0758, 0x00000000,
676	0x020e0588, 0x00000030,
677	0x020e0594, 0x00000030,
678	0x020e056c, 0x00000030,
679	0x020e0578, 0x00000030,
680	0x020e074c, 0x00000030,
681	0x020e057c, 0x00000030,
682	0x020e058c, 0x00000000,
683	0x020e059c, 0x00000030,
684	0x020e05a0, 0x00000030,
685	0x020e078c, 0x00000030,
686	0x020e0750, 0x00020000,
687	0x020e05a8, 0x00000030,
688	0x020e05b0, 0x00000030,
689	0x020e0524, 0x00000030,
690	0x020e051c, 0x00000030,
691	0x020e0518, 0x00000030,
692	0x020e050c, 0x00000030,
693	0x020e05b8, 0x00000030,
694	0x020e05c0, 0x00000030,
695	0x020e0774, 0x00020000,
696	0x020e0784, 0x00000030,
697	0x020e0788, 0x00000030,
698	0x020e0794, 0x00000030,
699	0x020e079c, 0x00000030,
700	0x020e07a0, 0x00000030,
701	0x020e07a4, 0x00000030,
702	0x020e07a8, 0x00000030,
703	0x020e0748, 0x00000030,
704	0x020e05ac, 0x00000030,
705	0x020e05b4, 0x00000030,
706	0x020e0528, 0x00000030,
707	0x020e0520, 0x00000030,
708	0x020e0514, 0x00000030,
709	0x020e0510, 0x00000030,
710	0x020e05bc, 0x00000030,
711	0x020e05c4, 0x00000030,
712	0x021b0800, 0xa1390003,
713	0x021b080c, 0x001b001e,
714	0x021b0810, 0x002e0029,
715	0x021b480c, 0x001b002a,
716	0x021b4810, 0x0019002c,
717	0x021b083c, 0x43240334,
718	0x021b0840, 0x0324031a,
719	0x021b483c, 0x43340344,
720	0x021b4840, 0x03280276,
721	0x021b0848, 0x44383A3E,
722	0x021b4848, 0x3C3C3846,
723	0x021b0850, 0x2e303230,
724	0x021b4850, 0x38283E34,
725	0x021b081c, 0x33333333,
726	0x021b0820, 0x33333333,
727	0x021b0824, 0x33333333,
728	0x021b0828, 0x33333333,
729	0x021b481c, 0x33333333,
730	0x021b4820, 0x33333333,
731	0x021b4824, 0x33333333,
732	0x021b4828, 0x33333333,
733	0x021b08c0, 0x24912492,
734	0x021b48c0, 0x24912492,
735	0x021b08b8, 0x00000800,
736	0x021b48b8, 0x00000800,
737	0x021b0004, 0x00020036,
738	0x021b0008, 0x09444040,
739	0x021b000c, 0x898E7955,
740	0x021b0010, 0xFF328F64,
741	0x021b0014, 0x01FF00DB,
742	0x021b0018, 0x00001740,
743	0x021b001c, 0x00008000,
744	0x021b002c, 0x000026d2,
745	0x021b0030, 0x008E1023,
746	0x021b0040, 0x00000047,
747	0x021b0400, 0x14420000,
748	0x021b0000, 0x841A0000,
749	0x00bb0008, 0x00000004,
750	0x00bb000c, 0x2891E41A,
751	0x00bb0038, 0x00000564,
752	0x00bb0014, 0x00000040,
753	0x00bb0028, 0x00000020,
754	0x00bb002c, 0x00000020,
755	0x021b001c, 0x04088032,
756	0x021b001c, 0x00008033,
757	0x021b001c, 0x00048031,
758	0x021b001c, 0x09408030,
759	0x021b001c, 0x04008040,
760	0x021b0020, 0x00005800,
761	0x021b0818, 0x00011117,
762	0x021b4818, 0x00011117,
763	0x021b0004, 0x00025576,
764	0x021b0404, 0x00011006,
765	0x021b001c, 0x00000000,
766	0x020c4068, 0x00C03F3F,
767	0x020c406c, 0x0030FC03,
768	0x020c4070, 0x0FFFC000,
769	0x020c4074, 0x3FF00000,
770	0x020c4078, 0xFFFFF300,
771	0x020c407c, 0x0F0000F3,
772	0x020c4080, 0x00000FFF,
773	0x020e0010, 0xF00000CF,
774	0x020e0018, 0x77177717,
775	0x020e001c, 0x77177717,
776};
777
778static int mx6dl_dcd_table[] = {
779	0x020e0774, 0x000C0000,
780	0x020e0754, 0x00000000,
781	0x020e04ac, 0x00000030,
782	0x020e04b0, 0x00000030,
783	0x020e0464, 0x00000030,
784	0x020e0490, 0x00000030,
785	0x020e074c, 0x00000030,
786	0x020e0494, 0x00000030,
787	0x020e04a0, 0x00000000,
788	0x020e04b4, 0x00000030,
789	0x020e04b8, 0x00000030,
790	0x020e076c, 0x00000030,
791	0x020e0750, 0x00020000,
792	0x020e04bc, 0x00000028,
793	0x020e04c0, 0x00000028,
794	0x020e04c4, 0x00000028,
795	0x020e04c8, 0x00000028,
796	0x020e04cc, 0x00000028,
797	0x020e04d0, 0x00000028,
798	0x020e04d4, 0x00000028,
799	0x020e04d8, 0x00000028,
800	0x020e0760, 0x00020000,
801	0x020e0764, 0x00000028,
802	0x020e0770, 0x00000028,
803	0x020e0778, 0x00000028,
804	0x020e077c, 0x00000028,
805	0x020e0780, 0x00000028,
806	0x020e0784, 0x00000028,
807	0x020e078c, 0x00000028,
808	0x020e0748, 0x00000028,
809	0x020e0470, 0x00000028,
810	0x020e0474, 0x00000028,
811	0x020e0478, 0x00000028,
812	0x020e047c, 0x00000028,
813	0x020e0480, 0x00000028,
814	0x020e0484, 0x00000028,
815	0x020e0488, 0x00000028,
816	0x020e048c, 0x00000028,
817	0x021b0800, 0xa1390003,
818	0x021b080c, 0x001F001F,
819	0x021b0810, 0x001F001F,
820	0x021b480c, 0x001F001F,
821	0x021b4810, 0x001F001F,
822	0x021b083c, 0x42190217,
823	0x021b0840, 0x017B017B,
824	0x021b483c, 0x4176017B,
825	0x021b4840, 0x015F016C,
826	0x021b0848, 0x4C4C4D4C,
827	0x021b4848, 0x4A4D4C48,
828	0x021b0850, 0x3F3F3F40,
829	0x021b4850, 0x3538382E,
830	0x021b081c, 0x33333333,
831	0x021b0820, 0x33333333,
832	0x021b0824, 0x33333333,
833	0x021b0828, 0x33333333,
834	0x021b481c, 0x33333333,
835	0x021b4820, 0x33333333,
836	0x021b4824, 0x33333333,
837	0x021b4828, 0x33333333,
838	0x021b08b8, 0x00000800,
839	0x021b48b8, 0x00000800,
840	0x021b0004, 0x00020025,
841	0x021b0008, 0x00333030,
842	0x021b000c, 0x676B5313,
843	0x021b0010, 0xB66E8B63,
844	0x021b0014, 0x01FF00DB,
845	0x021b0018, 0x00001740,
846	0x021b001c, 0x00008000,
847	0x021b002c, 0x000026d2,
848	0x021b0030, 0x006B1023,
849	0x021b0040, 0x00000047,
850	0x021b0000, 0x841A0000,
851	0x021b001c, 0x04008032,
852	0x021b001c, 0x00008033,
853	0x021b001c, 0x00048031,
854	0x021b001c, 0x05208030,
855	0x021b001c, 0x04008040,
856	0x021b0020, 0x00005800,
857	0x021b0818, 0x00011117,
858	0x021b4818, 0x00011117,
859	0x021b0004, 0x00025565,
860	0x021b0404, 0x00011006,
861	0x021b001c, 0x00000000,
862	0x020c4068, 0x00C03F3F,
863	0x020c406c, 0x0030FC03,
864	0x020c4070, 0x0FFFC000,
865	0x020c4074, 0x3FF00000,
866	0x020c4078, 0xFFFFF300,
867	0x020c407c, 0x0F0000C3,
868	0x020c4080, 0x00000FFF,
869	0x020e0010, 0xF00000CF,
870	0x020e0018, 0x007F007F,
871	0x020e001c, 0x007F007F,
872};
873
874static void ddr_init(int *table, int size)
875{
876	int i;
877
878	for (i = 0; i < size / 2 ; i++)
879		writel(table[2 * i + 1], table[2 * i]);
880}
881
882static void spl_dram_init(void)
883{
884	if (is_mx6dq())
885		ddr_init(mx6q_dcd_table, ARRAY_SIZE(mx6q_dcd_table));
886	else if (is_mx6dqp())
887		ddr_init(mx6qp_dcd_table, ARRAY_SIZE(mx6qp_dcd_table));
888	else if (is_mx6sdl())
889		ddr_init(mx6dl_dcd_table, ARRAY_SIZE(mx6dl_dcd_table));
890}
891
892void board_init_f(ulong dummy)
893{
894	/* DDR initialization */
895	spl_dram_init();
896
897	/* setup AIPS and disable watchdog */
898	arch_cpu_init();
899
900	ccgr_init();
901	gpr_init();
902
903	board_early_init_f();
904
905	/* setup GP timer */
906	timer_init();
907
908	/* UART clocks enabled and gd valid - init serial console */
909	preloader_console_init();
910
911	/* Clear the BSS. */
912	memset(__bss_start, 0, __bss_end - __bss_start);
913
914	/* load/boot image from boot device */
915	board_init_r(NULL, 0);
916}
917#endif
918
919#ifdef CONFIG_SPL_LOAD_FIT
920int board_fit_config_name_match(const char *name)
921{
922	if (is_mx6dq()) {
923		if (!strcmp(name, "imx6q-sabreauto"))
924			return 0;
925	} else if (is_mx6dqp()) {
926		if (!strcmp(name, "imx6qp-sabreauto"))
927			return 0;
928	} else if (is_mx6dl()) {
929		if (!strcmp(name, "imx6dl-sabreauto"))
930			return 0;
931	}
932
933	return -1;
934}
935#endif
936