arm: imx: add i.MX53 Beckhoff CX9020 Embedded PC
Add CX9020 board based on mx53loco.
Add simplified imx53 base device tree from kernel v4.8-rc8, to reuse
serial_mxc with DTE and prepare for device tree migration of other
functions and imx53 devices.
The CX9020 differs from i.MX53 Quick Start Board by:
- use uart2 instead of uart1
- DVI-D connector instead of VGA
- no audio
- CCAT FPGA connected to emi
- enable rtc
Signed-off-by: Patrick Bruenn <p.bruenn@beckhoff.com>
diff --git a/board/beckhoff/mx53cx9020/Kconfig b/board/beckhoff/mx53cx9020/Kconfig
new file mode 100644
index 0000000..dcdafb6
--- /dev/null
+++ b/board/beckhoff/mx53cx9020/Kconfig
@@ -0,0 +1,12 @@
+if TARGET_MX53CX9020
+
+config SYS_BOARD
+ default "mx53cx9020"
+
+config SYS_VENDOR
+ default "beckhoff"
+
+config SYS_CONFIG_NAME
+ default "mx53cx9020"
+
+endif
diff --git a/board/beckhoff/mx53cx9020/MAINTAINERS b/board/beckhoff/mx53cx9020/MAINTAINERS
new file mode 100644
index 0000000..f84413e
--- /dev/null
+++ b/board/beckhoff/mx53cx9020/MAINTAINERS
@@ -0,0 +1,6 @@
+MX53 CX9020
+M: Patrick Bruenn <p.bruenn@beckhoff.com>
+S: Maintained
+F: board/beckhoff/mx53cx9020/
+F: include/configs/mx53cx9020.h
+F: configs/mx53cx9020_defconfig
diff --git a/board/beckhoff/mx53cx9020/Makefile b/board/beckhoff/mx53cx9020/Makefile
new file mode 100644
index 0000000..a01c0f1
--- /dev/null
+++ b/board/beckhoff/mx53cx9020/Makefile
@@ -0,0 +1,9 @@
+#
+# Copyright (C) 2015 Beckhoff Automation GmbH & Co. KG
+# Patrick Bruenn <p.bruenn@beckhoff.com>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+obj-y += mx53cx9020.o
+obj-$(CONFIG_VIDEO) += mx53cx9020_video.o
diff --git a/board/beckhoff/mx53cx9020/imximage.cfg b/board/beckhoff/mx53cx9020/imximage.cfg
new file mode 100644
index 0000000..a11d04c
--- /dev/null
+++ b/board/beckhoff/mx53cx9020/imximage.cfg
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2015 Beckhoff Automation GmbH
+ * Patrick Bruenn <p.bruenn@beckhoff.com>
+ *
+ * Based on <u-boot>/board/freescale/mx53loco/imximage.cfg
+ * Copyright (C) 2011 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/* image version */
+IMAGE_VERSION 2
+
+/*
+ * Boot Device : one of
+ * spi, sd (the board has no nand neither onenand)
+ */
+BOOT_FROM sd
+
+/*
+ * Device Configuration Data (DCD)
+ *
+ * Each entry must have the format:
+ * Addr-type Address Value
+ *
+ * where:
+ * Addr-type register length (1,2 or 4 bytes)
+ * Address absolute address of the register
+ * value value to be stored in the register
+ */
+DATA 4 0x53fa8554 0x00300000
+DATA 4 0x53fa8558 0x00300040
+DATA 4 0x53fa8560 0x00300000
+DATA 4 0x53fa8564 0x00300040
+DATA 4 0x53fa8568 0x00300040
+DATA 4 0x53fa8570 0x00300000
+DATA 4 0x53fa8574 0x00300000
+DATA 4 0x53fa8578 0x00300000
+DATA 4 0x53fa857c 0x00300040
+DATA 4 0x53fa8580 0x00300040
+DATA 4 0x53fa8584 0x00300000
+DATA 4 0x53fa8588 0x00300000
+DATA 4 0x53fa8590 0x00300040
+DATA 4 0x53fa8594 0x00300000
+DATA 4 0x53fa86f0 0x00300000
+DATA 4 0x53fa86f4 0x00000000
+DATA 4 0x53fa86fc 0x00000000
+DATA 4 0x53fa8714 0x00000000
+DATA 4 0x53fa8718 0x00300000
+DATA 4 0x53fa871c 0x00300000
+DATA 4 0x53fa8720 0x00300000
+DATA 4 0x53fa8724 0x00000000
+DATA 4 0x53fa8728 0x00300000
+DATA 4 0x53fa872c 0x00300000
+DATA 4 0x63fd9088 0x35343535
+DATA 4 0x63fd9090 0x4d444c44
+DATA 4 0x63fd907c 0x01370138
+DATA 4 0x63fd9080 0x013b013c
+DATA 4 0x63fd9018 0x00011740
+DATA 4 0x63fd9000 0x83190000
+DATA 4 0x63fd900c 0x40425333
+DATA 4 0x63fd9010 0xb68e8a63
+DATA 4 0x63fd9014 0x01ff00db
+DATA 4 0x63fd902c 0x000026d2
+DATA 4 0x63fd9030 0x009f0e21
+DATA 4 0x63fd9008 0x12273030
+DATA 4 0x63fd9004 0x0002002d
+DATA 4 0x63fd901c 0x00008032
+DATA 4 0x63fd901c 0x00008033
+DATA 4 0x63fd901c 0x00028031
+DATA 4 0x63fd901c 0x052080b0
+DATA 4 0x63fd901c 0x04008040
+DATA 4 0x63fd9000 0xc3190000
+DATA 4 0x63fd901c 0x0000803a
+DATA 4 0x63fd901c 0x0000803b
+DATA 4 0x63fd901c 0x00028039
+DATA 4 0x63fd901c 0x05208138
+DATA 4 0x63fd901c 0x04008048
+DATA 4 0x63fd9020 0x00005800
+DATA 4 0x63fd9040 0x05380003
+DATA 4 0x63fd9058 0x00022227
+DATA 4 0x63fd901c 0x00000000
diff --git a/board/beckhoff/mx53cx9020/mx53cx9020.c b/board/beckhoff/mx53cx9020/mx53cx9020.c
new file mode 100644
index 0000000..9b3ac22
--- /dev/null
+++ b/board/beckhoff/mx53cx9020/mx53cx9020.c
@@ -0,0 +1,367 @@
+/*
+ * Copyright (C) 2015 Beckhoff Automation GmbH & Co. KG
+ * Patrick Bruenn <p.bruenn@beckhoff.com>
+ *
+ * Based on <u-boot>/board/freescale/mx53loco/mx53loco.c
+ * Copyright (C) 2011 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/arch/crm_regs.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/iomux-mx53.h>
+#include <asm/arch/clock.h>
+#include <asm/imx-common/mx5_video.h>
+#include <ACEX1K.h>
+#include <netdev.h>
+#include <i2c.h>
+#include <mmc.h>
+#include <fsl_esdhc.h>
+#include <asm/gpio.h>
+#include <linux/fb.h>
+#include <ipu_pixfmt.h>
+#include <fs.h>
+#include <dm/platdata.h>
+#include <dm/platform_data/serial_mxc.h>
+
+enum LED_GPIOS {
+ GPIO_SD1_CD = IMX_GPIO_NR(1, 1),
+ GPIO_SD2_CD = IMX_GPIO_NR(1, 4),
+ GPIO_LED_SD2_R = IMX_GPIO_NR(3, 16),
+ GPIO_LED_SD2_B = IMX_GPIO_NR(3, 17),
+ GPIO_LED_SD2_G = IMX_GPIO_NR(3, 18),
+ GPIO_LED_SD1_R = IMX_GPIO_NR(3, 19),
+ GPIO_LED_SD1_B = IMX_GPIO_NR(3, 20),
+ GPIO_LED_SD1_G = IMX_GPIO_NR(3, 21),
+ GPIO_LED_PWR_R = IMX_GPIO_NR(3, 22),
+ GPIO_LED_PWR_B = IMX_GPIO_NR(3, 23),
+ GPIO_LED_PWR_G = IMX_GPIO_NR(3, 24),
+ GPIO_SUPS_INT = IMX_GPIO_NR(3, 31),
+ GPIO_C3_CONFIG = IMX_GPIO_NR(6, 8),
+ GPIO_C3_STATUS = IMX_GPIO_NR(6, 7),
+ GPIO_C3_DONE = IMX_GPIO_NR(6, 9),
+};
+
+#define CCAT_BASE_ADDR ((void *)0xf0000000)
+#define CCAT_END_ADDR (CCAT_BASE_ADDR + (1024 * 1024 * 32))
+#define CCAT_SIZE 1191788
+#define CCAT_SIGN_ADDR (CCAT_BASE_ADDR + 12)
+static const char CCAT_SIGNATURE[] = "CCAT";
+
+static const u32 CCAT_MODE_CONFIG = 0x0024DC81;
+static const u32 CCAT_MODE_RUN = 0x0033DC8F;
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static uint32_t mx53_dram_size[2];
+
+phys_size_t get_effective_memsize(void)
+{
+ /*
+ * WARNING: We must override get_effective_memsize() function here
+ * to report only the size of the first DRAM bank. This is to make
+ * U-Boot relocator place U-Boot into valid memory, that is, at the
+ * end of the first DRAM bank. If we did not override this function
+ * like so, U-Boot would be placed at the address of the first DRAM
+ * bank + total DRAM size - sizeof(uboot), which in the setup where
+ * each DRAM bank contains 512MiB of DRAM would result in placing
+ * U-Boot into invalid memory area close to the end of the first
+ * DRAM bank.
+ */
+ return mx53_dram_size[0];
+}
+
+int dram_init(void)
+{
+ mx53_dram_size[0] = get_ram_size((void *)PHYS_SDRAM_1, 1 << 30);
+ mx53_dram_size[1] = get_ram_size((void *)PHYS_SDRAM_2, 1 << 30);
+
+ gd->ram_size = mx53_dram_size[0] + mx53_dram_size[1];
+
+ return 0;
+}
+
+void dram_init_banksize(void)
+{
+ gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
+ gd->bd->bi_dram[0].size = mx53_dram_size[0];
+
+ gd->bd->bi_dram[1].start = PHYS_SDRAM_2;
+ gd->bd->bi_dram[1].size = mx53_dram_size[1];
+}
+
+u32 get_board_rev(void)
+{
+ struct iim_regs *iim = (struct iim_regs *)IMX_IIM_BASE;
+ struct fuse_bank *bank = &iim->bank[0];
+ struct fuse_bank0_regs *fuse =
+ (struct fuse_bank0_regs *)bank->fuse_regs;
+
+ int rev = readl(&fuse->gp[6]);
+
+ return (get_cpu_rev() & ~(0xF << 8)) | (rev & 0xF) << 8;
+}
+
+/*
+ * Set CCAT mode
+ * @mode: use CCAT_MODE_CONFIG or CCAT_MODE_RUN
+ */
+void weim_cs0_settings(u32 mode)
+{
+ struct weim *weim_regs = (struct weim *)WEIM_BASE_ADDR;
+
+ writel(0x0, &weim_regs->cs0gcr1);
+ writel(mode, &weim_regs->cs0gcr1);
+ writel(0x00001002, &weim_regs->cs0gcr2);
+
+ writel(0x04000000, &weim_regs->cs0rcr1);
+ writel(0x00000000, &weim_regs->cs0rcr2);
+
+ writel(0x04000000, &weim_regs->cs0wcr1);
+ writel(0x00000000, &weim_regs->cs0wcr2);
+}
+
+static void setup_gpio_eim(void)
+{
+ gpio_direction_input(GPIO_C3_STATUS);
+ gpio_direction_input(GPIO_C3_DONE);
+ gpio_direction_output(GPIO_C3_CONFIG, 1);
+
+ weim_cs0_settings(CCAT_MODE_RUN);
+}
+
+static void setup_gpio_sups(void)
+{
+ gpio_direction_input(GPIO_SUPS_INT);
+
+ static const int BLINK_INTERVALL = 50000;
+ int status = 1;
+ while (gpio_get_value(GPIO_SUPS_INT)) {
+ /* signal "CX SUPS power fail" */
+ gpio_set_value(GPIO_LED_PWR_R,
+ (++status / BLINK_INTERVALL) % 2);
+ }
+
+ /* signal "CX power up" */
+ gpio_set_value(GPIO_LED_PWR_R, 1);
+}
+
+static void setup_gpio_leds(void)
+{
+ gpio_direction_output(GPIO_LED_SD2_R, 0);
+ gpio_direction_output(GPIO_LED_SD2_B, 0);
+ gpio_direction_output(GPIO_LED_SD2_G, 0);
+ gpio_direction_output(GPIO_LED_SD1_R, 0);
+ gpio_direction_output(GPIO_LED_SD1_B, 0);
+ gpio_direction_output(GPIO_LED_SD1_G, 0);
+ gpio_direction_output(GPIO_LED_PWR_R, 0);
+ gpio_direction_output(GPIO_LED_PWR_B, 0);
+ gpio_direction_output(GPIO_LED_PWR_G, 0);
+}
+
+#ifdef CONFIG_USB_EHCI_MX5
+int board_ehci_hcd_init(int port)
+{
+ /* request VBUS power enable pin, GPIO7_8 */
+ gpio_direction_output(IMX_GPIO_NR(7, 8), 1);
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_FSL_ESDHC
+struct fsl_esdhc_cfg esdhc_cfg[2] = {
+ {MMC_SDHC1_BASE_ADDR},
+ {MMC_SDHC2_BASE_ADDR},
+};
+
+int board_mmc_getcd(struct mmc *mmc)
+{
+ struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
+ int ret;
+
+ gpio_direction_input(GPIO_SD1_CD);
+ gpio_direction_input(GPIO_SD2_CD);
+
+ if (cfg->esdhc_base == MMC_SDHC1_BASE_ADDR)
+ ret = !gpio_get_value(GPIO_SD1_CD);
+ else
+ ret = !gpio_get_value(GPIO_SD2_CD);
+
+ return ret;
+}
+
+int board_mmc_init(bd_t *bis)
+{
+ u32 index;
+ int ret;
+
+ esdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC_CLK);
+ esdhc_cfg[1].sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK);
+
+ for (index = 0; index < CONFIG_SYS_FSL_ESDHC_NUM; index++) {
+ switch (index) {
+ case 0:
+ break;
+ case 1:
+ break;
+ default:
+ printf("Warning: you configured more ESDHC controller(%d) as supported by the board(2)\n",
+ CONFIG_SYS_FSL_ESDHC_NUM);
+ return -EINVAL;
+ }
+ ret = fsl_esdhc_initialize(bis, &esdhc_cfg[index]);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+#endif
+
+static int power_init(void)
+{
+ /* nothing to do on CX9020 */
+ return 0;
+}
+
+static void clock_1GHz(void)
+{
+ int ret;
+ u32 ref_clk = MXC_HCLK;
+ /*
+ * After increasing voltage to 1.25V, we can switch
+ * CPU clock to 1GHz and DDR to 400MHz safely
+ */
+ ret = mxc_set_clock(ref_clk, 1000, MXC_ARM_CLK);
+ if (ret)
+ printf("CPU: Switch CPU clock to 1GHZ failed\n");
+
+ ret = mxc_set_clock(ref_clk, 400, MXC_PERIPH_CLK);
+ ret |= mxc_set_clock(ref_clk, 400, MXC_DDR_CLK);
+ if (ret)
+ printf("CPU: Switch DDR clock to 400MHz failed\n");
+}
+
+int board_early_init_f(void)
+{
+ setup_gpio_leds();
+ setup_gpio_sups();
+ setup_gpio_eim();
+ setup_iomux_lcd();
+
+ return 0;
+}
+
+/*
+ * Do not overwrite the console
+ * Use always serial for U-Boot console
+ */
+int overwrite_console(void)
+{
+ return 1;
+}
+
+int board_init(void)
+{
+ gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100;
+
+ mxc_set_sata_internal_clock();
+
+ return 0;
+}
+
+int checkboard(void)
+{
+ puts("Board: Beckhoff CX9020\n");
+
+ return 0;
+}
+
+static int ccat_config_fn(int assert_config, int flush, int cookie)
+{
+ /* prepare FPGA for programming */
+ weim_cs0_settings(CCAT_MODE_CONFIG);
+ gpio_set_value(GPIO_C3_CONFIG, 0);
+ udelay(1);
+ gpio_set_value(GPIO_C3_CONFIG, 1);
+ udelay(230);
+
+ return FPGA_SUCCESS;
+}
+
+static int ccat_status_fn(int cookie)
+{
+ return FPGA_FAIL;
+}
+
+static int ccat_write_fn(const void *buf, size_t buf_len, int flush, int cookie)
+{
+ const uint8_t *const buffer = buf;
+
+ /* program CCAT */
+ int i;
+ for (i = 0; i < buf_len; ++i)
+ writeb(buffer[i], CCAT_BASE_ADDR);
+
+ writeb(0xff, CCAT_BASE_ADDR);
+ writeb(0xff, CCAT_BASE_ADDR);
+
+ return FPGA_SUCCESS;
+}
+
+static int ccat_done_fn(int cookie)
+{
+ /* programming complete? */
+ return gpio_get_value(GPIO_C3_DONE);
+}
+
+static int ccat_post_fn(int cookie)
+{
+ /* switch to FPGA run mode */
+ weim_cs0_settings(CCAT_MODE_RUN);
+ invalidate_dcache_range((ulong) CCAT_BASE_ADDR, (ulong) CCAT_END_ADDR);
+
+ if (memcmp(CCAT_SIGN_ADDR, CCAT_SIGNATURE, sizeof(CCAT_SIGNATURE))) {
+ printf("Verifing CCAT firmware failed, signature not found\n");
+ return FPGA_FAIL;
+ }
+
+ /* signal "CX booting OS" */
+ gpio_set_value(GPIO_LED_PWR_R, 1);
+ gpio_set_value(GPIO_LED_PWR_G, 1);
+ gpio_set_value(GPIO_LED_PWR_B, 0);
+ return FPGA_SUCCESS;
+}
+
+static Altera_CYC2_Passive_Serial_fns ccat_fns = {
+ .config = ccat_config_fn,
+ .status = ccat_status_fn,
+ .done = ccat_done_fn,
+ .write = ccat_write_fn,
+ .abort = ccat_post_fn,
+ .post = ccat_post_fn,
+};
+
+static Altera_desc ccat_fpga = {
+ .family = Altera_CYC2,
+ .iface = passive_serial,
+ .size = CCAT_SIZE,
+ .iface_fns = &ccat_fns,
+ .base = CCAT_BASE_ADDR,
+};
+
+int board_late_init(void)
+{
+ if (!power_init())
+ clock_1GHz();
+
+ fpga_init();
+ fpga_add(fpga_altera, &ccat_fpga);
+
+ return 0;
+}
diff --git a/board/beckhoff/mx53cx9020/mx53cx9020_video.c b/board/beckhoff/mx53cx9020/mx53cx9020_video.c
new file mode 100644
index 0000000..4da83da
--- /dev/null
+++ b/board/beckhoff/mx53cx9020/mx53cx9020_video.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2015 Beckhoff Automation GmbH & Co. KG
+ * Patrick Bruenn <p.bruenn@beckhoff.com>
+ *
+ * Based on <u-boot>/board/freescale/mx53loco/mx53loco_video.c
+ * Copyright (C) 2012 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <linux/list.h>
+#include <asm/gpio.h>
+#include <asm/arch/iomux-mx53.h>
+#include <linux/fb.h>
+#include <ipu_pixfmt.h>
+
+#define CX9020_DVI_PWD IMX_GPIO_NR(6, 1)
+
+static struct fb_videomode const vga_640x480 = {
+ .name = "VESA_VGA_640x480",
+ .refresh = 60,
+ .xres = 640,
+ .yres = 480,
+ .pixclock = 39721, /* picosecond (25.175 MHz) */
+ .left_margin = 40,
+ .right_margin = 60,
+ .upper_margin = 10,
+ .lower_margin = 10,
+ .hsync_len = 20,
+ .vsync_len = 10,
+ .sync = 0,
+ .vmode = FB_VMODE_NONINTERLACED
+};
+
+void setup_iomux_lcd(void)
+{
+ /* Turn on DVI_PWD */
+ imx_iomux_v3_setup_pad(MX53_PAD_CSI0_DAT15__GPIO6_1);
+ gpio_direction_output(CX9020_DVI_PWD, 1);
+}
+
+int board_video_skip(void)
+{
+ const int ret = ipuv3_fb_init(&vga_640x480, 0, IPU_PIX_FMT_RGB24);
+ if (ret)
+ printf("VESA VG 640x480 cannot be configured: %d\n", ret);
+ return ret;
+}