blob: 896350140d61c64cab5db1eb71092d94975d6c1e [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Eric Benard2e66f3b2014-04-04 19:05:55 +02002/*
3 * Copyright (C) 2014 Eukréa Electromatique
4 * Author: Eric Bénard <eric@eukrea.com>
5 * Fabio Estevam <fabio.estevam@freescale.com>
6 * Jon Nettleton <jon.nettleton@gmail.com>
7 *
8 * based on sabresd.c which is :
9 * Copyright (C) 2012 Freescale Semiconductor, Inc.
10 * and on hummingboard.c which is :
11 * Copyright (C) 2013 SolidRun ltd.
12 * Copyright (C) 2013 Jon Nettleton <jon.nettleton@gmail.com>.
Eric Benard2e66f3b2014-04-04 19:05:55 +020013 */
14
Simon Glassa7b51302019-11-14 12:57:46 -070015#include <init.h>
Simon Glass274e0b02020-05-10 11:39:56 -060016#include <net.h>
Eric Benard2e66f3b2014-04-04 19:05:55 +020017#include <asm/arch/clock.h>
18#include <asm/arch/sys_proto.h>
19#include <asm/arch/imx-regs.h>
20#include <asm/arch/iomux.h>
21#include <asm/arch/mx6-pins.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060022#include <asm/global_data.h>
Simon Glassdbd79542020-05-10 11:40:11 -060023#include <linux/delay.h>
Masahiro Yamada56a931c2016-09-21 11:28:55 +090024#include <linux/errno.h>
Eric Benard2e66f3b2014-04-04 19:05:55 +020025#include <asm/gpio.h>
Stefano Babic33731bc2017-06-29 10:16:06 +020026#include <asm/mach-imx/iomux-v3.h>
27#include <asm/mach-imx/boot_mode.h>
28#include <asm/mach-imx/mxc_i2c.h>
29#include <asm/mach-imx/spi.h>
30#include <asm/mach-imx/video.h>
Eric Benard2e66f3b2014-04-04 19:05:55 +020031#include <i2c.h>
Diego Dorta2661c9c2017-09-22 12:12:18 -030032#include <input.h>
Eric Benard2e66f3b2014-04-04 19:05:55 +020033#include <miiphy.h>
34#include <netdev.h>
35#include <asm/arch/mxc_hdmi.h>
36#include <asm/arch/crm_regs.h>
37#include <linux/fb.h>
38#include <ipu_pixfmt.h>
39#include <asm/io.h>
Lukasz Majewskiadd95732017-11-07 11:10:29 +010040
Eric Benard2e66f3b2014-04-04 19:05:55 +020041DECLARE_GLOBAL_DATA_PTR;
42
43#define UART_PAD_CTRL (PAD_CTL_PUS_100K_UP | \
44 PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | \
45 PAD_CTL_SRE_FAST | PAD_CTL_HYS)
46
47#define USDHC_PAD_CTRL (PAD_CTL_PUS_47K_UP | \
48 PAD_CTL_SPEED_LOW | PAD_CTL_DSE_80ohm | \
49 PAD_CTL_SRE_FAST | PAD_CTL_HYS)
50
51#define USDHC_PAD_CLK_CTRL (PAD_CTL_SPEED_LOW | \
52 PAD_CTL_DSE_80ohm | PAD_CTL_SRE_FAST | \
53 PAD_CTL_HYS)
54
55#define ENET_PAD_CTRL (PAD_CTL_PUS_100K_UP | \
56 PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_HYS)
57
58#define ENET_PAD_CTRL_PD (PAD_CTL_PUS_100K_DOWN | \
59 PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_HYS)
60
61#define ENET_PAD_CTRL_CLK ((PAD_CTL_PUS_100K_UP & ~PAD_CTL_PKE) | \
62 PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST)
63
64#define I2C_PAD_CTRL (PAD_CTL_PUS_100K_UP | \
65 PAD_CTL_SPEED_MED | PAD_CTL_DSE_40ohm | PAD_CTL_HYS | \
66 PAD_CTL_ODE | PAD_CTL_SRE_FAST)
67
68#define SPI_PAD_CTRL (PAD_CTL_HYS | PAD_CTL_SPEED_MED | \
69 PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST)
70
71static int board_type = -1;
72#define BOARD_IS_MARSBOARD 0
73#define BOARD_IS_RIOTBOARD 1
74
75int dram_init(void)
76{
77 gd->ram_size = get_ram_size((void *)PHYS_SDRAM, PHYS_SDRAM_SIZE);
78
79 return 0;
80}
81
82static iomux_v3_cfg_t const uart2_pads[] = {
83 MX6_PAD_EIM_D26__UART2_TX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
84 MX6_PAD_EIM_D27__UART2_RX_DATA | MUX_PAD_CTRL(UART_PAD_CTRL),
85};
86
87static void setup_iomux_uart(void)
88{
89 imx_iomux_v3_setup_multiple_pads(uart2_pads, ARRAY_SIZE(uart2_pads));
90}
91
92iomux_v3_cfg_t const enet_pads[] = {
Eric Benard2e66f3b2014-04-04 19:05:55 +020093 /* AR8035 PHY Reset */
94 MX6_PAD_EIM_D31__GPIO3_IO31 | MUX_PAD_CTRL(ENET_PAD_CTRL_PD),
95 /* AR8035 PHY Interrupt */
96 MX6_PAD_ENET_TX_EN__GPIO1_IO28 | MUX_PAD_CTRL(ENET_PAD_CTRL),
97};
98
99static void setup_iomux_enet(void)
100{
101 imx_iomux_v3_setup_multiple_pads(enet_pads, ARRAY_SIZE(enet_pads));
102
103 /* Reset AR8035 PHY */
104 gpio_direction_output(IMX_GPIO_NR(3, 31) , 0);
105 mdelay(2);
106 gpio_set_value(IMX_GPIO_NR(3, 31), 1);
107}
108
109int mx6_rgmii_rework(struct phy_device *phydev)
110{
111 /* from linux/arch/arm/mach-imx/mach-imx6q.c :
112 * Ar803x phy SmartEEE feature cause link status generates glitch,
113 * which cause ethernet link down/up issue, so disable SmartEEE
114 */
115 phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x7);
116 phy_write(phydev, MDIO_DEVAD_NONE, 0xe, 0x805d);
117 phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x4003);
118
119 return 0;
120}
121
122int board_phy_config(struct phy_device *phydev)
123{
124 mx6_rgmii_rework(phydev);
125
126 if (phydev->drv->config)
127 phydev->drv->config(phydev);
128
129 return 0;
130}
131
Eric Benard2e66f3b2014-04-04 19:05:55 +0200132#ifdef CONFIG_MXC_SPI
133iomux_v3_cfg_t const ecspi1_pads[] = {
134 MX6_PAD_EIM_D16__ECSPI1_SCLK | MUX_PAD_CTRL(SPI_PAD_CTRL),
135 MX6_PAD_EIM_D17__ECSPI1_MISO | MUX_PAD_CTRL(SPI_PAD_CTRL),
136 MX6_PAD_EIM_D18__ECSPI1_MOSI | MUX_PAD_CTRL(SPI_PAD_CTRL),
137 MX6_PAD_EIM_EB2__GPIO2_IO30 | MUX_PAD_CTRL(NO_PAD_CTRL),
138};
139
Nikita Kiryanov00cd7382014-08-20 15:08:50 +0300140int board_spi_cs_gpio(unsigned bus, unsigned cs)
141{
142 return (bus == 0 && cs == 0) ? (IMX_GPIO_NR(2, 30)) : -1;
143}
144
Eric Benard2e66f3b2014-04-04 19:05:55 +0200145static void setup_spi(void)
146{
147 imx_iomux_v3_setup_multiple_pads(ecspi1_pads, ARRAY_SIZE(ecspi1_pads));
148}
149#endif
150
151struct i2c_pads_info i2c_pad_info1 = {
152 .scl = {
153 .i2c_mode = MX6_PAD_CSI0_DAT9__I2C1_SCL
154 | MUX_PAD_CTRL(I2C_PAD_CTRL),
155 .gpio_mode = MX6_PAD_CSI0_DAT9__GPIO5_IO27
156 | MUX_PAD_CTRL(I2C_PAD_CTRL),
157 .gp = IMX_GPIO_NR(5, 27)
158 },
159 .sda = {
160 .i2c_mode = MX6_PAD_CSI0_DAT8__I2C1_SDA
161 | MUX_PAD_CTRL(I2C_PAD_CTRL),
162 .gpio_mode = MX6_PAD_CSI0_DAT8__GPIO5_IO26
163 | MUX_PAD_CTRL(I2C_PAD_CTRL),
164 .gp = IMX_GPIO_NR(5, 26)
165 }
166};
167
168struct i2c_pads_info i2c_pad_info2 = {
169 .scl = {
170 .i2c_mode = MX6_PAD_KEY_COL3__I2C2_SCL
171 | MUX_PAD_CTRL(I2C_PAD_CTRL),
172 .gpio_mode = MX6_PAD_KEY_COL3__GPIO4_IO12
173 | MUX_PAD_CTRL(I2C_PAD_CTRL),
174 .gp = IMX_GPIO_NR(4, 12)
175 },
176 .sda = {
177 .i2c_mode = MX6_PAD_KEY_ROW3__I2C2_SDA
178 | MUX_PAD_CTRL(I2C_PAD_CTRL),
179 .gpio_mode = MX6_PAD_KEY_ROW3__GPIO4_IO13
180 | MUX_PAD_CTRL(I2C_PAD_CTRL),
181 .gp = IMX_GPIO_NR(4, 13)
182 }
183};
184
185struct i2c_pads_info i2c_pad_info3 = {
186 .scl = {
187 .i2c_mode = MX6_PAD_GPIO_5__I2C3_SCL
188 | MUX_PAD_CTRL(I2C_PAD_CTRL),
189 .gpio_mode = MX6_PAD_GPIO_5__GPIO1_IO05
190 | MUX_PAD_CTRL(I2C_PAD_CTRL),
191 .gp = IMX_GPIO_NR(1, 5)
192 },
193 .sda = {
194 .i2c_mode = MX6_PAD_GPIO_6__I2C3_SDA
195 | MUX_PAD_CTRL(I2C_PAD_CTRL),
196 .gpio_mode = MX6_PAD_GPIO_6__GPIO1_IO06
197 | MUX_PAD_CTRL(I2C_PAD_CTRL),
198 .gp = IMX_GPIO_NR(1, 6)
199 }
200};
201
202iomux_v3_cfg_t const tft_pads_riot[] = {
203 /* LCD_PWR_EN */
204 MX6_PAD_ENET_TXD1__GPIO1_IO29 | MUX_PAD_CTRL(NO_PAD_CTRL),
205 /* TOUCH_INT */
206 MX6_PAD_NANDF_CS1__GPIO6_IO14 | MUX_PAD_CTRL(NO_PAD_CTRL),
207 /* LED_PWR_EN */
208 MX6_PAD_NANDF_CS2__GPIO6_IO15 | MUX_PAD_CTRL(NO_PAD_CTRL),
209 /* BL LEVEL */
210 MX6_PAD_SD1_CMD__GPIO1_IO18 | MUX_PAD_CTRL(NO_PAD_CTRL),
211};
212
213iomux_v3_cfg_t const tft_pads_mars[] = {
214 /* LCD_PWR_EN */
215 MX6_PAD_ENET_TXD1__GPIO1_IO29 | MUX_PAD_CTRL(NO_PAD_CTRL),
216 /* TOUCH_INT */
217 MX6_PAD_NANDF_CS1__GPIO6_IO14 | MUX_PAD_CTRL(NO_PAD_CTRL),
218 /* LED_PWR_EN */
219 MX6_PAD_NANDF_CS2__GPIO6_IO15 | MUX_PAD_CTRL(NO_PAD_CTRL),
220 /* BL LEVEL (PWM4) */
221 MX6_PAD_SD4_DAT2__GPIO2_IO10 | MUX_PAD_CTRL(NO_PAD_CTRL),
222};
223
224#if defined(CONFIG_VIDEO_IPUV3)
225
226static void enable_lvds(struct display_info_t const *dev)
227{
228 struct iomuxc *iomux = (struct iomuxc *)
229 IOMUXC_BASE_ADDR;
230 setbits_le32(&iomux->gpr[2],
231 IOMUXC_GPR2_DATA_WIDTH_CH0_24BIT);
232 /* set backlight level to ON */
233 if (board_type == BOARD_IS_RIOTBOARD)
234 gpio_direction_output(IMX_GPIO_NR(1, 18) , 1);
235 else if (board_type == BOARD_IS_MARSBOARD)
236 gpio_direction_output(IMX_GPIO_NR(2, 10) , 1);
237}
238
239static void disable_lvds(struct display_info_t const *dev)
240{
241 struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR;
242
243 /* set backlight level to OFF */
244 if (board_type == BOARD_IS_RIOTBOARD)
245 gpio_direction_output(IMX_GPIO_NR(1, 18) , 0);
246 else if (board_type == BOARD_IS_MARSBOARD)
247 gpio_direction_output(IMX_GPIO_NR(2, 10) , 0);
248
249 clrbits_le32(&iomux->gpr[2],
250 IOMUXC_GPR2_LVDS_CH0_MODE_MASK);
251}
252
Eric Benard2e66f3b2014-04-04 19:05:55 +0200253static void do_enable_hdmi(struct display_info_t const *dev)
254{
255 disable_lvds(dev);
256 imx_enable_hdmi_phy();
257}
258
259static int detect_i2c(struct display_info_t const *dev)
260{
261 return (0 == i2c_set_bus_num(dev->bus)) &&
262 (0 == i2c_probe(dev->addr));
263}
264
265struct display_info_t const displays[] = {{
266 .bus = -1,
267 .addr = 0,
268 .pixfmt = IPU_PIX_FMT_RGB24,
269 .detect = detect_hdmi,
270 .enable = do_enable_hdmi,
271 .mode = {
272 .name = "HDMI",
273 .refresh = 60,
274 .xres = 1024,
275 .yres = 768,
276 .pixclock = 15385,
277 .left_margin = 220,
278 .right_margin = 40,
279 .upper_margin = 21,
280 .lower_margin = 7,
281 .hsync_len = 60,
282 .vsync_len = 10,
283 .sync = FB_SYNC_EXT,
284 .vmode = FB_VMODE_NONINTERLACED
285} }, {
286 .bus = 2,
287 .addr = 0x1,
288 .pixfmt = IPU_PIX_FMT_LVDS666,
289 .detect = detect_i2c,
290 .enable = enable_lvds,
291 .mode = {
292 .name = "LCD8000-97C",
293 .refresh = 60,
294 .xres = 1024,
295 .yres = 768,
296 .pixclock = 15385,
297 .left_margin = 100,
298 .right_margin = 200,
299 .upper_margin = 10,
300 .lower_margin = 20,
301 .hsync_len = 20,
302 .vsync_len = 8,
303 .sync = FB_SYNC_EXT,
304 .vmode = FB_VMODE_NONINTERLACED
305} } };
306size_t display_count = ARRAY_SIZE(displays);
307
308static void setup_display(void)
309{
310 struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
311 struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR;
312 int reg;
313
314 enable_ipu_clock();
315 imx_setup_hdmi();
316
317 /* Turn on LDB0, IPU,IPU DI0 clocks */
318 setbits_le32(&mxc_ccm->CCGR3,
319 MXC_CCM_CCGR3_LDB_DI0_MASK);
320
321 /* set LDB0 clk select to 011/011 */
322 clrsetbits_le32(&mxc_ccm->cs2cdr,
323 MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_MASK,
324 (3 << MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_OFFSET));
325
326 setbits_le32(&mxc_ccm->cscmr2,
327 MXC_CCM_CSCMR2_LDB_DI0_IPU_DIV);
328
329 setbits_le32(&mxc_ccm->chsccdr,
330 (CHSCCDR_CLK_SEL_LDB_DI0
331 << MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET));
332
333 reg = IOMUXC_GPR2_BGREF_RRMODE_EXTERNAL_RES
334 | IOMUXC_GPR2_DI0_VS_POLARITY_ACTIVE_LOW
335 | IOMUXC_GPR2_BIT_MAPPING_CH1_SPWG
336 | IOMUXC_GPR2_DATA_WIDTH_CH1_18BIT
337 | IOMUXC_GPR2_BIT_MAPPING_CH0_SPWG
338 | IOMUXC_GPR2_DATA_WIDTH_CH0_18BIT
339 | IOMUXC_GPR2_LVDS_CH1_MODE_DISABLED
340 | IOMUXC_GPR2_LVDS_CH0_MODE_ENABLED_DI0;
341 writel(reg, &iomux->gpr[2]);
342
343 clrsetbits_le32(&iomux->gpr[3],
344 IOMUXC_GPR3_LVDS0_MUX_CTL_MASK |
345 IOMUXC_GPR3_HDMI_MUX_CTL_MASK,
346 IOMUXC_GPR3_MUX_SRC_IPU1_DI0
347 << IOMUXC_GPR3_LVDS0_MUX_CTL_OFFSET);
348}
349#endif /* CONFIG_VIDEO_IPUV3 */
350
351/*
352 * Do not overwrite the console
353 * Use always serial for U-Boot console
354 */
355int overwrite_console(void)
356{
357 return 1;
358}
359
Eric Benard2e66f3b2014-04-04 19:05:55 +0200360int board_early_init_f(void)
361{
362 u32 cputype = cpu_type(get_cpu_rev());
363
364 switch (cputype) {
365 case MXC_CPU_MX6SOLO:
366 board_type = BOARD_IS_RIOTBOARD;
367 break;
368 case MXC_CPU_MX6D:
369 board_type = BOARD_IS_MARSBOARD;
370 break;
371 }
372
373 setup_iomux_uart();
374
375 if (board_type == BOARD_IS_RIOTBOARD)
376 imx_iomux_v3_setup_multiple_pads(
377 tft_pads_riot, ARRAY_SIZE(tft_pads_riot));
378 else if (board_type == BOARD_IS_MARSBOARD)
379 imx_iomux_v3_setup_multiple_pads(
380 tft_pads_mars, ARRAY_SIZE(tft_pads_mars));
381#if defined(CONFIG_VIDEO_IPUV3)
382 /* power ON LCD */
383 gpio_direction_output(IMX_GPIO_NR(1, 29) , 1);
384 /* touch interrupt is an input */
385 gpio_direction_input(IMX_GPIO_NR(6, 14));
386 /* power ON backlight */
387 gpio_direction_output(IMX_GPIO_NR(6, 15) , 1);
388 /* set backlight level to off */
389 if (board_type == BOARD_IS_RIOTBOARD)
390 gpio_direction_output(IMX_GPIO_NR(1, 18) , 0);
391 else if (board_type == BOARD_IS_MARSBOARD)
392 gpio_direction_output(IMX_GPIO_NR(2, 10) , 0);
393 setup_display();
394#endif
395
396 return 0;
397}
398
399int board_init(void)
400{
401 /* address of boot parameters */
402 gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
403 /* i2c1 : PMIC, Audio codec on RiOT, Expansion connector on MarS */
404 setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info1);
405 /* i2c2 : HDMI EDID */
406 setup_i2c(1, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info2);
407 /* i2c3 : LVDS, Expansion connector */
408 setup_i2c(2, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info3);
409#ifdef CONFIG_MXC_SPI
410 setup_spi();
411#endif
412 return 0;
413}
414
415#ifdef CONFIG_CMD_BMODE
416static const struct boot_mode riotboard_boot_modes[] = {
417 {"sd2", MAKE_CFGVAL(0x40, 0x28, 0x00, 0x00)},
418 {"sd3", MAKE_CFGVAL(0x40, 0x30, 0x00, 0x00)},
419 {"emmc", MAKE_CFGVAL(0x40, 0x38, 0x00, 0x00)},
420 {NULL, 0},
421};
422static const struct boot_mode marsboard_boot_modes[] = {
423 {"sd2", MAKE_CFGVAL(0x40, 0x28, 0x00, 0x00)},
424 {"emmc", MAKE_CFGVAL(0x40, 0x30, 0x00, 0x00)},
425 {NULL, 0},
426};
427#endif
428
429int board_late_init(void)
430{
431#ifdef CONFIG_CMD_BMODE
432 if (board_type == BOARD_IS_RIOTBOARD)
433 add_board_boot_modes(riotboard_boot_modes);
434 else if (board_type == BOARD_IS_RIOTBOARD)
435 add_board_boot_modes(marsboard_boot_modes);
436#endif
Peter Robinsonfa89e832021-04-02 15:52:32 +0100437 setup_iomux_enet();
Eric Benard2e66f3b2014-04-04 19:05:55 +0200438
439 return 0;
440}
441
442int checkboard(void)
443{
444 puts("Board: ");
445 if (board_type == BOARD_IS_MARSBOARD)
446 puts("MarSBoard\n");
447 else if (board_type == BOARD_IS_RIOTBOARD)
448 puts("RIoTboard\n");
449 else
450 printf("unknown - cputype : %02x\n", cpu_type(get_cpu_rev()));
451
452 return 0;
453}
Fabien Lahouderea47a6a12018-11-08 11:28:05 +0100454
455#ifdef CONFIG_SPL_BUILD
456#include <spl.h>
457
458void board_init_f(ulong dummy)
459{
460 u32 cputype = cpu_type(get_cpu_rev());
461
462 switch (cputype) {
463 case MXC_CPU_MX6SOLO:
464 board_type = BOARD_IS_RIOTBOARD;
465 break;
466 case MXC_CPU_MX6D:
467 board_type = BOARD_IS_MARSBOARD;
468 break;
469 }
470 arch_cpu_init();
471
472 /* setup GP timer */
473 timer_init();
474
Simon Glassf4d60392021-08-08 12:20:12 -0600475#ifdef CONFIG_SPL_SERIAL
Fabien Lahouderea47a6a12018-11-08 11:28:05 +0100476 setup_iomux_uart();
477 preloader_console_init();
478#endif
479}
480
481void board_boot_order(u32 *spl_boot_list)
482{
483 spl_boot_list[0] = BOOT_DEVICE_MMC1;
484}
485
486/*
487 * In order to jump to standard u-boot shell, you have to connect pin 5 of J13
488 * to pin 3 (ground).
489 */
490int spl_start_uboot(void)
491{
492 int gpio_key = IMX_GPIO_NR(4, 16);
493
494 gpio_direction_input(gpio_key);
495 if (gpio_get_value(gpio_key) == 0)
496 return 1;
497 else
498 return 0;
499}
500
501#endif