uboot/board/beckhoff/mx53cx9020/mx53cx9020.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2015  Beckhoff Automation GmbH & Co. KG
   3 * Patrick Bruenn <p.bruenn@beckhoff.com>
   4 *
   5 * Based on <u-boot>/board/freescale/mx53loco/mx53loco.c
   6 * Copyright (C) 2011 Freescale Semiconductor, Inc.
   7 *
   8 * SPDX-License-Identifier:     GPL-2.0+
   9 */
  10
  11#include <common.h>
  12#include <dm.h>
  13#include <asm/io.h>
  14#include <asm/arch/imx-regs.h>
  15#include <asm/arch/sys_proto.h>
  16#include <asm/arch/crm_regs.h>
  17#include <asm/arch/clock.h>
  18#include <asm/arch/iomux-mx53.h>
  19#include <asm/arch/clock.h>
  20#include <asm/mach-imx/mx5_video.h>
  21#include <ACEX1K.h>
  22#include <netdev.h>
  23#include <i2c.h>
  24#include <mmc.h>
  25#include <fsl_esdhc.h>
  26#include <asm/gpio.h>
  27#include <linux/fb.h>
  28#include <ipu_pixfmt.h>
  29#include <input.h>
  30#include <fs.h>
  31#include <dm/platform_data/serial_mxc.h>
  32
  33enum LED_GPIOS {
  34        GPIO_SD1_CD = IMX_GPIO_NR(1, 1),
  35        GPIO_SD2_CD = IMX_GPIO_NR(1, 4),
  36        GPIO_LED_SD2_R = IMX_GPIO_NR(3, 16),
  37        GPIO_LED_SD2_B = IMX_GPIO_NR(3, 17),
  38        GPIO_LED_SD2_G = IMX_GPIO_NR(3, 18),
  39        GPIO_LED_SD1_R = IMX_GPIO_NR(3, 19),
  40        GPIO_LED_SD1_B = IMX_GPIO_NR(3, 20),
  41        GPIO_LED_SD1_G = IMX_GPIO_NR(3, 21),
  42        GPIO_LED_PWR_R = IMX_GPIO_NR(3, 22),
  43        GPIO_LED_PWR_B = IMX_GPIO_NR(3, 23),
  44        GPIO_LED_PWR_G = IMX_GPIO_NR(3, 24),
  45        GPIO_SUPS_INT = IMX_GPIO_NR(3, 31),
  46        GPIO_C3_CONFIG = IMX_GPIO_NR(6, 8),
  47        GPIO_C3_STATUS = IMX_GPIO_NR(6, 7),
  48        GPIO_C3_DONE = IMX_GPIO_NR(6, 9),
  49};
  50
  51#define CCAT_BASE_ADDR ((void *)0xf0000000)
  52#define CCAT_END_ADDR (CCAT_BASE_ADDR + (1024 * 1024 * 32))
  53#define CCAT_SIZE 1191788
  54#define CCAT_SIGN_ADDR (CCAT_BASE_ADDR + 12)
  55static const char CCAT_SIGNATURE[] = "CCAT";
  56
  57static const u32 CCAT_MODE_CONFIG = 0x0024DC81;
  58static const u32 CCAT_MODE_RUN = 0x0033DC8F;
  59
  60DECLARE_GLOBAL_DATA_PTR;
  61
  62static uint32_t mx53_dram_size[2];
  63
  64phys_size_t get_effective_memsize(void)
  65{
  66        /*
  67         * WARNING: We must override get_effective_memsize() function here
  68         * to report only the size of the first DRAM bank. This is to make
  69         * U-Boot relocator place U-Boot into valid memory, that is, at the
  70         * end of the first DRAM bank. If we did not override this function
  71         * like so, U-Boot would be placed at the address of the first DRAM
  72         * bank + total DRAM size - sizeof(uboot), which in the setup where
  73         * each DRAM bank contains 512MiB of DRAM would result in placing
  74         * U-Boot into invalid memory area close to the end of the first
  75         * DRAM bank.
  76         */
  77        return mx53_dram_size[0];
  78}
  79
  80int dram_init(void)
  81{
  82        mx53_dram_size[0] = get_ram_size((void *)PHYS_SDRAM_1, 1 << 30);
  83        mx53_dram_size[1] = get_ram_size((void *)PHYS_SDRAM_2, 1 << 30);
  84
  85        gd->ram_size = mx53_dram_size[0] + mx53_dram_size[1];
  86
  87        return 0;
  88}
  89
  90int dram_init_banksize(void)
  91{
  92        gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
  93        gd->bd->bi_dram[0].size = mx53_dram_size[0];
  94
  95        gd->bd->bi_dram[1].start = PHYS_SDRAM_2;
  96        gd->bd->bi_dram[1].size = mx53_dram_size[1];
  97
  98        return 0;
  99}
 100
 101u32 get_board_rev(void)
 102{
 103        struct iim_regs *iim = (struct iim_regs *)IMX_IIM_BASE;
 104        struct fuse_bank *bank = &iim->bank[0];
 105        struct fuse_bank0_regs *fuse =
 106            (struct fuse_bank0_regs *)bank->fuse_regs;
 107
 108        int rev = readl(&fuse->gp[6]);
 109
 110        return (get_cpu_rev() & ~(0xF << 8)) | (rev & 0xF) << 8;
 111}
 112
 113/*
 114 * Set CCAT mode
 115 * @mode: use CCAT_MODE_CONFIG or CCAT_MODE_RUN
 116 */
 117void weim_cs0_settings(u32 mode)
 118{
 119        struct weim *weim_regs = (struct weim *)WEIM_BASE_ADDR;
 120
 121        writel(0x0, &weim_regs->cs0gcr1);
 122        writel(mode, &weim_regs->cs0gcr1);
 123        writel(0x00001002, &weim_regs->cs0gcr2);
 124
 125        writel(0x04000000, &weim_regs->cs0rcr1);
 126        writel(0x00000000, &weim_regs->cs0rcr2);
 127
 128        writel(0x04000000, &weim_regs->cs0wcr1);
 129        writel(0x00000000, &weim_regs->cs0wcr2);
 130}
 131
 132static void setup_gpio_eim(void)
 133{
 134        gpio_direction_input(GPIO_C3_STATUS);
 135        gpio_direction_input(GPIO_C3_DONE);
 136        gpio_direction_output(GPIO_C3_CONFIG, 1);
 137
 138        weim_cs0_settings(CCAT_MODE_RUN);
 139}
 140
 141static void setup_gpio_sups(void)
 142{
 143        gpio_direction_input(GPIO_SUPS_INT);
 144
 145        static const int BLINK_INTERVALL = 50000;
 146        int status = 1;
 147        while (gpio_get_value(GPIO_SUPS_INT)) {
 148                /* signal "CX SUPS power fail" */
 149                gpio_set_value(GPIO_LED_PWR_R,
 150                               (++status / BLINK_INTERVALL) % 2);
 151        }
 152
 153        /* signal "CX power up" */
 154        gpio_set_value(GPIO_LED_PWR_R, 1);
 155}
 156
 157static void setup_gpio_leds(void)
 158{
 159        gpio_direction_output(GPIO_LED_SD2_R, 0);
 160        gpio_direction_output(GPIO_LED_SD2_B, 0);
 161        gpio_direction_output(GPIO_LED_SD2_G, 0);
 162        gpio_direction_output(GPIO_LED_SD1_R, 0);
 163        gpio_direction_output(GPIO_LED_SD1_B, 0);
 164        gpio_direction_output(GPIO_LED_SD1_G, 0);
 165        gpio_direction_output(GPIO_LED_PWR_R, 0);
 166        gpio_direction_output(GPIO_LED_PWR_B, 0);
 167        gpio_direction_output(GPIO_LED_PWR_G, 0);
 168}
 169
 170#ifdef CONFIG_USB_EHCI_MX5
 171int board_ehci_hcd_init(int port)
 172{
 173        /* request VBUS power enable pin, GPIO7_8 */
 174        gpio_direction_output(IMX_GPIO_NR(7, 8), 1);
 175        return 0;
 176}
 177#endif
 178
 179#ifdef CONFIG_FSL_ESDHC
 180struct fsl_esdhc_cfg esdhc_cfg[2] = {
 181        {MMC_SDHC1_BASE_ADDR},
 182        {MMC_SDHC2_BASE_ADDR},
 183};
 184
 185int board_mmc_getcd(struct mmc *mmc)
 186{
 187        struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
 188        int ret;
 189
 190        gpio_direction_input(GPIO_SD1_CD);
 191        gpio_direction_input(GPIO_SD2_CD);
 192
 193        if (cfg->esdhc_base == MMC_SDHC1_BASE_ADDR)
 194                ret = !gpio_get_value(GPIO_SD1_CD);
 195        else
 196                ret = !gpio_get_value(GPIO_SD2_CD);
 197
 198        return ret;
 199}
 200
 201int board_mmc_init(bd_t *bis)
 202{
 203        u32 index;
 204        int ret;
 205
 206        esdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC_CLK);
 207        esdhc_cfg[1].sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK);
 208
 209        for (index = 0; index < CONFIG_SYS_FSL_ESDHC_NUM; index++) {
 210                switch (index) {
 211                case 0:
 212                        break;
 213                case 1:
 214                        break;
 215                default:
 216                        printf("Warning: you configured more ESDHC controller(%d) as supported by the board(2)\n",
 217                               CONFIG_SYS_FSL_ESDHC_NUM);
 218                        return -EINVAL;
 219                }
 220                ret = fsl_esdhc_initialize(bis, &esdhc_cfg[index]);
 221                if (ret)
 222                        return ret;
 223        }
 224
 225        return 0;
 226}
 227#endif
 228
 229static int power_init(void)
 230{
 231        /* nothing to do on CX9020 */
 232        return 0;
 233}
 234
 235static void clock_1GHz(void)
 236{
 237        int ret;
 238        u32 ref_clk = MXC_HCLK;
 239        /*
 240         * After increasing voltage to 1.25V, we can switch
 241         * CPU clock to 1GHz and DDR to 400MHz safely
 242         */
 243        ret = mxc_set_clock(ref_clk, 1000, MXC_ARM_CLK);
 244        if (ret)
 245                printf("CPU:   Switch CPU clock to 1GHZ failed\n");
 246
 247        ret = mxc_set_clock(ref_clk, 400, MXC_PERIPH_CLK);
 248        ret |= mxc_set_clock(ref_clk, 400, MXC_DDR_CLK);
 249        if (ret)
 250                printf("CPU:   Switch DDR clock to 400MHz failed\n");
 251}
 252
 253int board_early_init_f(void)
 254{
 255        setup_gpio_leds();
 256        setup_gpio_sups();
 257        setup_gpio_eim();
 258        setup_iomux_lcd();
 259
 260        return 0;
 261}
 262
 263/*
 264 * Do not overwrite the console
 265 * Use always serial for U-Boot console
 266 */
 267int overwrite_console(void)
 268{
 269        return 1;
 270}
 271
 272int board_init(void)
 273{
 274        gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100;
 275
 276        mxc_set_sata_internal_clock();
 277
 278        return 0;
 279}
 280
 281int checkboard(void)
 282{
 283        puts("Board: Beckhoff CX9020\n");
 284
 285        return 0;
 286}
 287
 288static int ccat_config_fn(int assert_config, int flush, int cookie)
 289{
 290        /* prepare FPGA for programming */
 291        weim_cs0_settings(CCAT_MODE_CONFIG);
 292        gpio_set_value(GPIO_C3_CONFIG, 0);
 293        udelay(1);
 294        gpio_set_value(GPIO_C3_CONFIG, 1);
 295        udelay(230);
 296
 297        return FPGA_SUCCESS;
 298}
 299
 300static int ccat_status_fn(int cookie)
 301{
 302        return FPGA_FAIL;
 303}
 304
 305static int ccat_write_fn(const void *buf, size_t buf_len, int flush, int cookie)
 306{
 307        const uint8_t *const buffer = buf;
 308
 309        /* program CCAT */
 310        int i;
 311        for (i = 0; i < buf_len; ++i)
 312                writeb(buffer[i], CCAT_BASE_ADDR);
 313
 314        writeb(0xff, CCAT_BASE_ADDR);
 315        writeb(0xff, CCAT_BASE_ADDR);
 316
 317        return FPGA_SUCCESS;
 318}
 319
 320static int ccat_done_fn(int cookie)
 321{
 322        /* programming complete? */
 323        return gpio_get_value(GPIO_C3_DONE);
 324}
 325
 326static int ccat_post_fn(int cookie)
 327{
 328        /* switch to FPGA run mode */
 329        weim_cs0_settings(CCAT_MODE_RUN);
 330        invalidate_dcache_range((ulong) CCAT_BASE_ADDR, (ulong) CCAT_END_ADDR);
 331
 332        if (memcmp(CCAT_SIGN_ADDR, CCAT_SIGNATURE, sizeof(CCAT_SIGNATURE))) {
 333                printf("Verifing CCAT firmware failed, signature not found\n");
 334                return FPGA_FAIL;
 335        }
 336
 337        /* signal "CX booting OS" */
 338        gpio_set_value(GPIO_LED_PWR_R, 1);
 339        gpio_set_value(GPIO_LED_PWR_G, 1);
 340        gpio_set_value(GPIO_LED_PWR_B, 0);
 341        return FPGA_SUCCESS;
 342}
 343
 344static Altera_CYC2_Passive_Serial_fns ccat_fns = {
 345        .config = ccat_config_fn,
 346        .status = ccat_status_fn,
 347        .done = ccat_done_fn,
 348        .write = ccat_write_fn,
 349        .abort = ccat_post_fn,
 350        .post = ccat_post_fn,
 351};
 352
 353static Altera_desc ccat_fpga = {
 354        .family = Altera_CYC2,
 355        .iface = passive_serial,
 356        .size = CCAT_SIZE,
 357        .iface_fns = &ccat_fns,
 358        .base = CCAT_BASE_ADDR,
 359};
 360
 361int board_late_init(void)
 362{
 363        if (!power_init())
 364                clock_1GHz();
 365
 366        fpga_init();
 367        fpga_add(fpga_altera, &ccat_fpga);
 368
 369        return 0;
 370}
 371