blob: 0dc0160e19fe9e70510d66668bc2cdef1b341090 [file] [log] [blame]
Fabio Estevam7dd65452012-09-24 08:09:33 +00001/*
2 * Copyright (C) 2012 Freescale Semiconductor, Inc.
3 *
4 * Author: Fabio Estevam <fabio.estevam@freescale.com>
5 *
Wolfgang Denk1a459662013-07-08 09:37:19 +02006 * SPDX-License-Identifier: GPL-2.0+
Fabio Estevam7dd65452012-09-24 08:09:33 +00007 */
8
9#include <common.h>
10#include <asm/io.h>
11#include <asm/arch/clock.h>
12#include <asm/arch/imx-regs.h>
13#include <asm/arch/iomux.h>
Eric Nelsonb47abc32013-11-13 16:36:19 -070014#include <asm/arch/mx6-pins.h>
Fabio Estevam7dd65452012-09-24 08:09:33 +000015#include <asm/errno.h>
16#include <asm/gpio.h>
17#include <asm/imx-common/iomux-v3.h>
Renato Frias19578162013-05-13 18:01:12 +000018#include <asm/imx-common/mxc_i2c.h>
Otavio Salvador85449db2013-03-16 08:05:07 +000019#include <asm/imx-common/boot_mode.h>
Eric Nelson3acb0112014-09-30 15:40:03 -070020#include <asm/imx-common/spi.h>
Fabio Estevam7dd65452012-09-24 08:09:33 +000021#include <mmc.h>
22#include <fsl_esdhc.h>
Fabio Estevamfe5ebe92012-09-25 08:43:57 +000023#include <miiphy.h>
24#include <netdev.h>
Fabio Estevamdce67bd2012-10-02 11:20:12 +000025#include <asm/arch/sys_proto.h>
Renato Frias19578162013-05-13 18:01:12 +000026#include <i2c.h>
Fabio Estevam510922a2014-09-22 13:55:52 -030027#include <asm/arch/mxc_hdmi.h>
28#include <asm/imx-common/video.h>
29#include <asm/arch/crm_regs.h>
Fabio Estevamdce67bd2012-10-02 11:20:12 +000030
Fabio Estevam7dd65452012-09-24 08:09:33 +000031DECLARE_GLOBAL_DATA_PTR;
32
Benoît Thébaudeau7e2173c2013-04-26 01:34:47 +000033#define UART_PAD_CTRL (PAD_CTL_PUS_100K_UP | \
34 PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | \
35 PAD_CTL_SRE_FAST | PAD_CTL_HYS)
Fabio Estevam7dd65452012-09-24 08:09:33 +000036
Benoît Thébaudeau7e2173c2013-04-26 01:34:47 +000037#define USDHC_PAD_CTRL (PAD_CTL_PUS_47K_UP | \
38 PAD_CTL_SPEED_LOW | PAD_CTL_DSE_80ohm | \
39 PAD_CTL_SRE_FAST | PAD_CTL_HYS)
Fabio Estevam7dd65452012-09-24 08:09:33 +000040
Benoît Thébaudeau7e2173c2013-04-26 01:34:47 +000041#define ENET_PAD_CTRL (PAD_CTL_PUS_100K_UP | \
42 PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_HYS)
Fabio Estevamfe5ebe92012-09-25 08:43:57 +000043
Renato Frias19578162013-05-13 18:01:12 +000044#define I2C_PAD_CTRL (PAD_CTL_PUS_100K_UP | \
45 PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_HYS | \
46 PAD_CTL_ODE | PAD_CTL_SRE_FAST)
47
48#define PC MUX_PAD_CTRL(I2C_PAD_CTRL)
49
Fabio Estevam7dd65452012-09-24 08:09:33 +000050int dram_init(void)
51{
52 gd->ram_size = get_ram_size((void *)PHYS_SDRAM, PHYS_SDRAM_SIZE);
53
54 return 0;
55}
56
Fabio Estevam067a6592014-09-13 18:21:36 -030057static iomux_v3_cfg_t const uart4_pads[] = {
Eric Nelson10fda482013-11-04 17:00:51 -070058 MX6_PAD_KEY_COL0__UART4_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
59 MX6_PAD_KEY_ROW0__UART4_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
Fabio Estevam7dd65452012-09-24 08:09:33 +000060};
61
Fabio Estevam067a6592014-09-13 18:21:36 -030062static iomux_v3_cfg_t const enet_pads[] = {
Eric Nelsoncfb8b9d2013-02-19 10:07:01 +000063 MX6_PAD_KEY_COL1__ENET_MDIO | MUX_PAD_CTRL(ENET_PAD_CTRL),
64 MX6_PAD_KEY_COL2__ENET_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL),
Eric Nelson10fda482013-11-04 17:00:51 -070065 MX6_PAD_RGMII_TXC__RGMII_TXC | MUX_PAD_CTRL(ENET_PAD_CTRL),
66 MX6_PAD_RGMII_TD0__RGMII_TD0 | MUX_PAD_CTRL(ENET_PAD_CTRL),
67 MX6_PAD_RGMII_TD1__RGMII_TD1 | MUX_PAD_CTRL(ENET_PAD_CTRL),
68 MX6_PAD_RGMII_TD2__RGMII_TD2 | MUX_PAD_CTRL(ENET_PAD_CTRL),
69 MX6_PAD_RGMII_TD3__RGMII_TD3 | MUX_PAD_CTRL(ENET_PAD_CTRL),
Eric Nelsoncfb8b9d2013-02-19 10:07:01 +000070 MX6_PAD_RGMII_TX_CTL__RGMII_TX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL),
71 MX6_PAD_ENET_REF_CLK__ENET_TX_CLK | MUX_PAD_CTRL(ENET_PAD_CTRL),
Eric Nelson10fda482013-11-04 17:00:51 -070072 MX6_PAD_RGMII_RXC__RGMII_RXC | MUX_PAD_CTRL(ENET_PAD_CTRL),
73 MX6_PAD_RGMII_RD0__RGMII_RD0 | MUX_PAD_CTRL(ENET_PAD_CTRL),
74 MX6_PAD_RGMII_RD1__RGMII_RD1 | MUX_PAD_CTRL(ENET_PAD_CTRL),
75 MX6_PAD_RGMII_RD2__RGMII_RD2 | MUX_PAD_CTRL(ENET_PAD_CTRL),
76 MX6_PAD_RGMII_RD3__RGMII_RD3 | MUX_PAD_CTRL(ENET_PAD_CTRL),
Eric Nelsoncfb8b9d2013-02-19 10:07:01 +000077 MX6_PAD_RGMII_RX_CTL__RGMII_RX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL),
Fabio Estevamfe5ebe92012-09-25 08:43:57 +000078};
79
Renato Frias19578162013-05-13 18:01:12 +000080/* I2C2 PMIC, iPod, Tuner, Codec, Touch, HDMI EDID, MIPI CSI2 card */
Fabio Estevam067a6592014-09-13 18:21:36 -030081static struct i2c_pads_info i2c_pad_info1 = {
Renato Frias19578162013-05-13 18:01:12 +000082 .scl = {
83 .i2c_mode = MX6_PAD_EIM_EB2__I2C2_SCL | PC,
Eric Nelson10fda482013-11-04 17:00:51 -070084 .gpio_mode = MX6_PAD_EIM_EB2__GPIO2_IO30 | PC,
Renato Frias19578162013-05-13 18:01:12 +000085 .gp = IMX_GPIO_NR(2, 30)
86 },
87 .sda = {
88 .i2c_mode = MX6_PAD_KEY_ROW3__I2C2_SDA | PC,
Eric Nelson10fda482013-11-04 17:00:51 -070089 .gpio_mode = MX6_PAD_KEY_ROW3__GPIO4_IO13 | PC,
Renato Frias19578162013-05-13 18:01:12 +000090 .gp = IMX_GPIO_NR(4, 13)
91 }
92};
93
94/*
95 * I2C3 MLB, Port Expanders (A, B, C), Video ADC, Light Sensor,
96 * Compass Sensor, Accelerometer, Res Touch
97 */
Fabio Estevam067a6592014-09-13 18:21:36 -030098static struct i2c_pads_info i2c_pad_info2 = {
Renato Frias19578162013-05-13 18:01:12 +000099 .scl = {
100 .i2c_mode = MX6_PAD_GPIO_3__I2C3_SCL | PC,
Eric Nelson10fda482013-11-04 17:00:51 -0700101 .gpio_mode = MX6_PAD_GPIO_3__GPIO1_IO03 | PC,
Renato Frias19578162013-05-13 18:01:12 +0000102 .gp = IMX_GPIO_NR(1, 3)
103 },
104 .sda = {
105 .i2c_mode = MX6_PAD_EIM_D18__I2C3_SDA | PC,
Eric Nelson10fda482013-11-04 17:00:51 -0700106 .gpio_mode = MX6_PAD_EIM_D18__GPIO3_IO18 | PC,
Renato Frias19578162013-05-13 18:01:12 +0000107 .gp = IMX_GPIO_NR(3, 18)
108 }
109};
110
Fabio Estevam067a6592014-09-13 18:21:36 -0300111static iomux_v3_cfg_t const i2c3_pads[] = {
Eric Nelson10fda482013-11-04 17:00:51 -0700112 MX6_PAD_EIM_A24__GPIO5_IO04 | MUX_PAD_CTRL(NO_PAD_CTRL),
Renato Frias19578162013-05-13 18:01:12 +0000113};
114
Fabio Estevam067a6592014-09-13 18:21:36 -0300115static iomux_v3_cfg_t const port_exp[] = {
Eric Nelson10fda482013-11-04 17:00:51 -0700116 MX6_PAD_SD2_DAT0__GPIO1_IO15 | MUX_PAD_CTRL(NO_PAD_CTRL),
Renato Friasa1f67802013-05-13 18:01:13 +0000117};
118
Fabio Estevamfe5ebe92012-09-25 08:43:57 +0000119static void setup_iomux_enet(void)
120{
121 imx_iomux_v3_setup_multiple_pads(enet_pads, ARRAY_SIZE(enet_pads));
122}
123
Fabio Estevam067a6592014-09-13 18:21:36 -0300124static iomux_v3_cfg_t const usdhc3_pads[] = {
Eric Nelson10fda482013-11-04 17:00:51 -0700125 MX6_PAD_SD3_CLK__SD3_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
126 MX6_PAD_SD3_CMD__SD3_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
127 MX6_PAD_SD3_DAT0__SD3_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
128 MX6_PAD_SD3_DAT1__SD3_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
129 MX6_PAD_SD3_DAT2__SD3_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
130 MX6_PAD_SD3_DAT3__SD3_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
131 MX6_PAD_SD3_DAT4__SD3_DATA4 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
132 MX6_PAD_SD3_DAT5__SD3_DATA5 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
133 MX6_PAD_SD3_DAT6__SD3_DATA6 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
134 MX6_PAD_SD3_DAT7__SD3_DATA7 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
135 MX6_PAD_GPIO_18__SD3_VSELECT | MUX_PAD_CTRL(USDHC_PAD_CTRL),
136 MX6_PAD_NANDF_CS2__GPIO6_IO15 | MUX_PAD_CTRL(NO_PAD_CTRL),
Fabio Estevam7dd65452012-09-24 08:09:33 +0000137};
138
139static void setup_iomux_uart(void)
140{
141 imx_iomux_v3_setup_multiple_pads(uart4_pads, ARRAY_SIZE(uart4_pads));
142}
143
144#ifdef CONFIG_FSL_ESDHC
Fabio Estevam067a6592014-09-13 18:21:36 -0300145static struct fsl_esdhc_cfg usdhc_cfg[1] = {
Fabio Estevam7dd65452012-09-24 08:09:33 +0000146 {USDHC3_BASE_ADDR},
147};
148
149int board_mmc_getcd(struct mmc *mmc)
150{
151 gpio_direction_input(IMX_GPIO_NR(6, 15));
152 return !gpio_get_value(IMX_GPIO_NR(6, 15));
153}
154
155int board_mmc_init(bd_t *bis)
156{
157 imx_iomux_v3_setup_multiple_pads(usdhc3_pads, ARRAY_SIZE(usdhc3_pads));
158
Benoît Thébaudeaua2ac1b32012-10-01 08:36:25 +0000159 usdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK);
Fabio Estevam7dd65452012-09-24 08:09:33 +0000160 return fsl_esdhc_initialize(bis, &usdhc_cfg[0]);
161}
162#endif
163
Fabio Estevamfe5ebe92012-09-25 08:43:57 +0000164int mx6_rgmii_rework(struct phy_device *phydev)
165{
166 unsigned short val;
167
168 /* To enable AR8031 ouput a 125MHz clk from CLK_25M */
169 phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x7);
170 phy_write(phydev, MDIO_DEVAD_NONE, 0xe, 0x8016);
171 phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x4007);
172
173 val = phy_read(phydev, MDIO_DEVAD_NONE, 0xe);
174 val &= 0xffe3;
175 val |= 0x18;
176 phy_write(phydev, MDIO_DEVAD_NONE, 0xe, val);
177
178 /* introduce tx clock delay */
179 phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x5);
180 val = phy_read(phydev, MDIO_DEVAD_NONE, 0x1e);
181 val |= 0x0100;
182 phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, val);
183
184 return 0;
185}
186
187int board_phy_config(struct phy_device *phydev)
188{
189 mx6_rgmii_rework(phydev);
190
191 if (phydev->drv->config)
192 phydev->drv->config(phydev);
193
194 return 0;
195}
196
197int board_eth_init(bd_t *bis)
198{
Fabio Estevamfe5ebe92012-09-25 08:43:57 +0000199 setup_iomux_enet();
200
Fabio Estevam579be2f2014-01-04 17:36:31 -0200201 return cpu_eth_init(bis);
Fabio Estevamfe5ebe92012-09-25 08:43:57 +0000202}
203
Fabio Estevamdce67bd2012-10-02 11:20:12 +0000204#define BOARD_REV_B 0x200
205#define BOARD_REV_A 0x100
206
207static int mx6sabre_rev(void)
208{
209 /*
210 * Get Board ID information from OCOTP_GP1[15:8]
211 * i.MX6Q ARD RevA: 0x01
212 * i.MX6Q ARD RevB: 0x02
213 */
214 struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
Benoît Thébaudeau8f3ff112013-04-23 10:17:38 +0000215 struct fuse_bank *bank = &ocotp->bank[4];
216 struct fuse_bank4_regs *fuse =
217 (struct fuse_bank4_regs *)bank->fuse_regs;
218 int reg = readl(&fuse->gp1);
Fabio Estevamdce67bd2012-10-02 11:20:12 +0000219 int ret;
220
221 switch (reg >> 8 & 0x0F) {
222 case 0x02:
223 ret = BOARD_REV_B;
224 break;
225 case 0x01:
226 default:
227 ret = BOARD_REV_A;
228 break;
229 }
230
231 return ret;
232}
233
Fabio Estevam7dd65452012-09-24 08:09:33 +0000234u32 get_board_rev(void)
235{
Fabio Estevamdce67bd2012-10-02 11:20:12 +0000236 int rev = mx6sabre_rev();
237
238 return (get_cpu_rev() & ~(0xF << 8)) | rev;
Fabio Estevam7dd65452012-09-24 08:09:33 +0000239}
240
Fabio Estevam510922a2014-09-22 13:55:52 -0300241#if defined(CONFIG_VIDEO_IPUV3)
242static void do_enable_hdmi(struct display_info_t const *dev)
243{
244 imx_enable_hdmi_phy();
245}
246
247struct display_info_t const displays[] = {{
248 .bus = -1,
249 .addr = 0,
250 .pixfmt = IPU_PIX_FMT_RGB24,
251 .detect = detect_hdmi,
252 .enable = do_enable_hdmi,
253 .mode = {
254 .name = "HDMI",
255 .refresh = 60,
256 .xres = 1024,
257 .yres = 768,
258 .pixclock = 15385,
259 .left_margin = 220,
260 .right_margin = 40,
261 .upper_margin = 21,
262 .lower_margin = 7,
263 .hsync_len = 60,
264 .vsync_len = 10,
265 .sync = FB_SYNC_EXT,
266 .vmode = FB_VMODE_NONINTERLACED,
267} } };
268size_t display_count = ARRAY_SIZE(displays);
269
270static void setup_display(void)
271{
272 struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
273 int reg;
274
275 enable_ipu_clock();
276 imx_setup_hdmi();
277
278 reg = readl(&mxc_ccm->chsccdr);
279 reg |= (CHSCCDR_CLK_SEL_LDB_DI0
280 << MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET);
281 writel(reg, &mxc_ccm->chsccdr);
282}
283#endif /* CONFIG_VIDEO_IPUV3 */
284
285/*
286 * Do not overwrite the console
287 * Use always serial for U-Boot console
288 */
289int overwrite_console(void)
290{
291 return 1;
292}
293
Fabio Estevam7dd65452012-09-24 08:09:33 +0000294int board_early_init_f(void)
295{
296 setup_iomux_uart();
Fabio Estevam510922a2014-09-22 13:55:52 -0300297#ifdef CONFIG_VIDEO_IPUV3
298 setup_display();
299#endif
Fabio Estevam7dd65452012-09-24 08:09:33 +0000300 return 0;
301}
302
303int board_init(void)
304{
305 /* address of boot parameters */
306 gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
307
Renato Frias19578162013-05-13 18:01:12 +0000308 /* I2C 2 and 3 setup - I2C 3 hw mux with EIM */
309 setup_i2c(1, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info1);
310 /* I2C 3 Steer */
311 gpio_direction_output(IMX_GPIO_NR(5, 4), 1);
312 imx_iomux_v3_setup_multiple_pads(i2c3_pads, ARRAY_SIZE(i2c3_pads));
313 setup_i2c(2, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info2);
314
Renato Friasa1f67802013-05-13 18:01:13 +0000315 gpio_direction_output(IMX_GPIO_NR(1, 15), 1);
316 imx_iomux_v3_setup_multiple_pads(port_exp, ARRAY_SIZE(port_exp));
317
Fabio Estevam7dd65452012-09-24 08:09:33 +0000318 return 0;
319}
320
Nikita Kiryanov155fa9a2014-08-20 15:08:50 +0300321#ifdef CONFIG_MXC_SPI
322int board_spi_cs_gpio(unsigned bus, unsigned cs)
323{
324 return (bus == 0 && cs == 0) ? (IMX_GPIO_NR(4, 9)) : -1;
325}
326#endif
327
Otavio Salvador85449db2013-03-16 08:05:07 +0000328#ifdef CONFIG_CMD_BMODE
329static const struct boot_mode board_boot_modes[] = {
330 /* 4 bit bus width */
331 {"mmc0", MAKE_CFGVAL(0x40, 0x30, 0x00, 0x00)},
332 {NULL, 0},
333};
334#endif
335
336int board_late_init(void)
337{
338#ifdef CONFIG_CMD_BMODE
339 add_board_boot_modes(board_boot_modes);
340#endif
341
342 return 0;
343}
344
Fabio Estevam7dd65452012-09-24 08:09:33 +0000345int checkboard(void)
346{
Fabio Estevamdce67bd2012-10-02 11:20:12 +0000347 int rev = mx6sabre_rev();
348 char *revname;
349
350 switch (rev) {
351 case BOARD_REV_B:
352 revname = "B";
353 break;
354 case BOARD_REV_A:
355 default:
356 revname = "A";
357 break;
358 }
359
360 printf("Board: MX6Q-Sabreauto rev%s\n", revname);
Fabio Estevam7dd65452012-09-24 08:09:33 +0000361
362 return 0;
363}