1eae4988bSStefano Babic /* 2eae4988bSStefano Babic * Copyright (C) 2007, Guennadi Liakhovetski <lg@denx.de> 3eae4988bSStefano Babic * 4eae4988bSStefano Babic * (C) Copyright 2008-2010 Freescale Semiconductor, Inc. 5eae4988bSStefano Babic * 61a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+ 7eae4988bSStefano Babic */ 8eae4988bSStefano Babic 9eae4988bSStefano Babic #include <common.h> 10eae4988bSStefano Babic #include <asm/io.h> 11eae4988bSStefano Babic #include <asm/errno.h> 12eae4988bSStefano Babic #include <asm/arch/imx-regs.h> 13eae4988bSStefano Babic #include <asm/arch/crm_regs.h> 14a2ac1b3aSBenoît Thébaudeau #include <asm/arch/clock.h> 15105c9eafSBenoît Thébaudeau #include <asm/arch/iomux-mx35.h> 16eae4988bSStefano Babic #include <i2c.h> 17c7336815SŁukasz Majewski #include <power/pmic.h> 18eae4988bSStefano Babic #include <fsl_pmic.h> 193292539eSStefano Babic #include <mmc.h> 203292539eSStefano Babic #include <fsl_esdhc.h> 21eae4988bSStefano Babic #include <mc9sdz60.h> 22eae4988bSStefano Babic #include <mc13892.h> 23eae4988bSStefano Babic #include <linux/types.h> 24a4adedd4SStefano Babic #include <asm/gpio.h> 25eae4988bSStefano Babic #include <asm/arch/sys_proto.h> 26eae4988bSStefano Babic #include <netdev.h> 27eae4988bSStefano Babic 289660e442SHelmut Raiger #ifndef CONFIG_BOARD_LATE_INIT 299660e442SHelmut Raiger #error "CONFIG_BOARD_LATE_INIT must be set for this board" 30eae4988bSStefano Babic #endif 31eae4988bSStefano Babic 32eae4988bSStefano Babic #ifndef CONFIG_BOARD_EARLY_INIT_F 33eae4988bSStefano Babic #error "CONFIG_BOARD_EARLY_INIT_F must be set for this board" 34eae4988bSStefano Babic #endif 35eae4988bSStefano Babic 36eae4988bSStefano Babic DECLARE_GLOBAL_DATA_PTR; 37eae4988bSStefano Babic 38eae4988bSStefano Babic int dram_init(void) 39eae4988bSStefano Babic { 406b5acfc1SStefano Babic u32 size1, size2; 416b5acfc1SStefano Babic 426b5acfc1SStefano Babic size1 = get_ram_size((void *)PHYS_SDRAM_1, PHYS_SDRAM_1_SIZE); 436b5acfc1SStefano Babic size2 = get_ram_size((void *)PHYS_SDRAM_2, PHYS_SDRAM_2_SIZE); 446b5acfc1SStefano Babic 456b5acfc1SStefano Babic gd->ram_size = size1 + size2; 46eae4988bSStefano Babic 47eae4988bSStefano Babic return 0; 48eae4988bSStefano Babic } 49eae4988bSStefano Babic 506b5acfc1SStefano Babic void dram_init_banksize(void) 516b5acfc1SStefano Babic { 526b5acfc1SStefano Babic gd->bd->bi_dram[0].start = PHYS_SDRAM_1; 536b5acfc1SStefano Babic gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE; 546b5acfc1SStefano Babic 556b5acfc1SStefano Babic gd->bd->bi_dram[1].start = PHYS_SDRAM_2; 566b5acfc1SStefano Babic gd->bd->bi_dram[1].size = PHYS_SDRAM_2_SIZE; 576b5acfc1SStefano Babic } 586b5acfc1SStefano Babic 59105c9eafSBenoît Thébaudeau #define I2C_PAD_CTRL (PAD_CTL_HYS | PAD_CTL_PUS_100K_DOWN | PAD_CTL_ODE) 60105c9eafSBenoît Thébaudeau 61eae4988bSStefano Babic static void setup_iomux_i2c(void) 62eae4988bSStefano Babic { 63105c9eafSBenoît Thébaudeau static const iomux_v3_cfg_t i2c1_pads[] = { 64105c9eafSBenoît Thébaudeau NEW_PAD_CTRL(MX35_PAD_I2C1_CLK__I2C1_SCL, I2C_PAD_CTRL), 65105c9eafSBenoît Thébaudeau NEW_PAD_CTRL(MX35_PAD_I2C1_DAT__I2C1_SDA, I2C_PAD_CTRL), 66105c9eafSBenoît Thébaudeau }; 67eae4988bSStefano Babic 68eae4988bSStefano Babic /* setup pins for I2C1 */ 69105c9eafSBenoît Thébaudeau imx_iomux_v3_setup_multiple_pads(i2c1_pads, ARRAY_SIZE(i2c1_pads)); 70eae4988bSStefano Babic } 71eae4988bSStefano Babic 72eae4988bSStefano Babic 73eae4988bSStefano Babic static void setup_iomux_spi(void) 74eae4988bSStefano Babic { 75105c9eafSBenoît Thébaudeau static const iomux_v3_cfg_t spi_pads[] = { 76105c9eafSBenoît Thébaudeau MX35_PAD_CSPI1_MOSI__CSPI1_MOSI, 77105c9eafSBenoît Thébaudeau MX35_PAD_CSPI1_MISO__CSPI1_MISO, 78105c9eafSBenoît Thébaudeau MX35_PAD_CSPI1_SS0__CSPI1_SS0, 79105c9eafSBenoît Thébaudeau MX35_PAD_CSPI1_SS1__CSPI1_SS1, 80105c9eafSBenoît Thébaudeau MX35_PAD_CSPI1_SCLK__CSPI1_SCLK, 81105c9eafSBenoît Thébaudeau }; 82105c9eafSBenoît Thébaudeau 83105c9eafSBenoît Thébaudeau imx_iomux_v3_setup_multiple_pads(spi_pads, ARRAY_SIZE(spi_pads)); 84eae4988bSStefano Babic } 85eae4988bSStefano Babic 86105c9eafSBenoît Thébaudeau #define USBOTG_IN_PAD_CTRL (PAD_CTL_HYS | PAD_CTL_PUS_100K_DOWN | \ 87105c9eafSBenoît Thébaudeau PAD_CTL_DSE_LOW | PAD_CTL_SRE_SLOW) 88105c9eafSBenoît Thébaudeau #define USBOTG_OUT_PAD_CTRL (PAD_CTL_DSE_LOW | PAD_CTL_SRE_SLOW) 89105c9eafSBenoît Thébaudeau 90961a7628SBenoît Thébaudeau static void setup_iomux_usbotg(void) 91961a7628SBenoît Thébaudeau { 92105c9eafSBenoît Thébaudeau static const iomux_v3_cfg_t usbotg_pads[] = { 93105c9eafSBenoît Thébaudeau NEW_PAD_CTRL(MX35_PAD_USBOTG_PWR__USB_TOP_USBOTG_PWR, 94105c9eafSBenoît Thébaudeau USBOTG_OUT_PAD_CTRL), 95105c9eafSBenoît Thébaudeau NEW_PAD_CTRL(MX35_PAD_USBOTG_OC__USB_TOP_USBOTG_OC, 96105c9eafSBenoît Thébaudeau USBOTG_IN_PAD_CTRL), 97105c9eafSBenoît Thébaudeau }; 98961a7628SBenoît Thébaudeau 99961a7628SBenoît Thébaudeau /* Set up pins for USBOTG. */ 100105c9eafSBenoît Thébaudeau imx_iomux_v3_setup_multiple_pads(usbotg_pads, ARRAY_SIZE(usbotg_pads)); 101961a7628SBenoît Thébaudeau } 102961a7628SBenoît Thébaudeau 103105c9eafSBenoît Thébaudeau #define FEC_PAD_CTRL (PAD_CTL_DSE_LOW | PAD_CTL_SRE_SLOW) 104105c9eafSBenoît Thébaudeau 105eae4988bSStefano Babic static void setup_iomux_fec(void) 106eae4988bSStefano Babic { 107105c9eafSBenoît Thébaudeau static const iomux_v3_cfg_t fec_pads[] = { 108105c9eafSBenoît Thébaudeau NEW_PAD_CTRL(MX35_PAD_FEC_TX_CLK__FEC_TX_CLK, FEC_PAD_CTRL | 109105c9eafSBenoît Thébaudeau PAD_CTL_HYS | PAD_CTL_PUS_100K_DOWN), 110105c9eafSBenoît Thébaudeau NEW_PAD_CTRL(MX35_PAD_FEC_RX_CLK__FEC_RX_CLK, FEC_PAD_CTRL | 111105c9eafSBenoît Thébaudeau PAD_CTL_HYS | PAD_CTL_PUS_100K_DOWN), 112105c9eafSBenoît Thébaudeau NEW_PAD_CTRL(MX35_PAD_FEC_RX_DV__FEC_RX_DV, FEC_PAD_CTRL | 113105c9eafSBenoît Thébaudeau PAD_CTL_HYS | PAD_CTL_PUS_100K_DOWN), 114105c9eafSBenoît Thébaudeau NEW_PAD_CTRL(MX35_PAD_FEC_COL__FEC_COL, FEC_PAD_CTRL | 115105c9eafSBenoît Thébaudeau PAD_CTL_HYS | PAD_CTL_PUS_100K_DOWN), 116105c9eafSBenoît Thébaudeau NEW_PAD_CTRL(MX35_PAD_FEC_RDATA0__FEC_RDATA_0, FEC_PAD_CTRL | 117105c9eafSBenoît Thébaudeau PAD_CTL_HYS | PAD_CTL_PUS_100K_DOWN), 118105c9eafSBenoît Thébaudeau NEW_PAD_CTRL(MX35_PAD_FEC_TDATA0__FEC_TDATA_0, FEC_PAD_CTRL), 119105c9eafSBenoît Thébaudeau NEW_PAD_CTRL(MX35_PAD_FEC_TX_EN__FEC_TX_EN, FEC_PAD_CTRL), 120105c9eafSBenoît Thébaudeau NEW_PAD_CTRL(MX35_PAD_FEC_MDC__FEC_MDC, FEC_PAD_CTRL), 121105c9eafSBenoît Thébaudeau NEW_PAD_CTRL(MX35_PAD_FEC_MDIO__FEC_MDIO, FEC_PAD_CTRL | 122105c9eafSBenoît Thébaudeau PAD_CTL_HYS | PAD_CTL_PUS_22K_UP), 123105c9eafSBenoît Thébaudeau NEW_PAD_CTRL(MX35_PAD_FEC_TX_ERR__FEC_TX_ERR, FEC_PAD_CTRL), 124105c9eafSBenoît Thébaudeau NEW_PAD_CTRL(MX35_PAD_FEC_RX_ERR__FEC_RX_ERR, FEC_PAD_CTRL | 125105c9eafSBenoît Thébaudeau PAD_CTL_HYS | PAD_CTL_PUS_100K_DOWN), 126105c9eafSBenoît Thébaudeau NEW_PAD_CTRL(MX35_PAD_FEC_CRS__FEC_CRS, FEC_PAD_CTRL | 127105c9eafSBenoît Thébaudeau PAD_CTL_HYS | PAD_CTL_PUS_100K_DOWN), 128105c9eafSBenoît Thébaudeau NEW_PAD_CTRL(MX35_PAD_FEC_RDATA1__FEC_RDATA_1, FEC_PAD_CTRL | 129105c9eafSBenoît Thébaudeau PAD_CTL_HYS | PAD_CTL_PUS_100K_DOWN), 130105c9eafSBenoît Thébaudeau NEW_PAD_CTRL(MX35_PAD_FEC_TDATA1__FEC_TDATA_1, FEC_PAD_CTRL), 131105c9eafSBenoît Thébaudeau NEW_PAD_CTRL(MX35_PAD_FEC_RDATA2__FEC_RDATA_2, FEC_PAD_CTRL | 132105c9eafSBenoît Thébaudeau PAD_CTL_HYS | PAD_CTL_PUS_100K_DOWN), 133105c9eafSBenoît Thébaudeau NEW_PAD_CTRL(MX35_PAD_FEC_TDATA2__FEC_TDATA_2, FEC_PAD_CTRL), 134105c9eafSBenoît Thébaudeau NEW_PAD_CTRL(MX35_PAD_FEC_RDATA3__FEC_RDATA_3, FEC_PAD_CTRL | 135105c9eafSBenoît Thébaudeau PAD_CTL_HYS | PAD_CTL_PUS_100K_DOWN), 136105c9eafSBenoît Thébaudeau NEW_PAD_CTRL(MX35_PAD_FEC_TDATA3__FEC_TDATA_3, FEC_PAD_CTRL), 137105c9eafSBenoît Thébaudeau }; 138eae4988bSStefano Babic 139eae4988bSStefano Babic /* setup pins for FEC */ 140105c9eafSBenoît Thébaudeau imx_iomux_v3_setup_multiple_pads(fec_pads, ARRAY_SIZE(fec_pads)); 141eae4988bSStefano Babic } 142eae4988bSStefano Babic 143eae4988bSStefano Babic int board_early_init_f(void) 144eae4988bSStefano Babic { 145eae4988bSStefano Babic struct ccm_regs *ccm = 146eae4988bSStefano Babic (struct ccm_regs *)IMX_CCM_BASE; 147eae4988bSStefano Babic 148eae4988bSStefano Babic /* enable clocks */ 149eae4988bSStefano Babic writel(readl(&ccm->cgr0) | 150eae4988bSStefano Babic MXC_CCM_CGR0_EMI_MASK | 15134a31bf5SBenoît Thébaudeau MXC_CCM_CGR0_EDIO_MASK | 152eae4988bSStefano Babic MXC_CCM_CGR0_EPIT1_MASK, 153eae4988bSStefano Babic &ccm->cgr0); 154eae4988bSStefano Babic 155eae4988bSStefano Babic writel(readl(&ccm->cgr1) | 156eae4988bSStefano Babic MXC_CCM_CGR1_FEC_MASK | 157eae4988bSStefano Babic MXC_CCM_CGR1_GPIO1_MASK | 158eae4988bSStefano Babic MXC_CCM_CGR1_GPIO2_MASK | 159eae4988bSStefano Babic MXC_CCM_CGR1_GPIO3_MASK | 160eae4988bSStefano Babic MXC_CCM_CGR1_I2C1_MASK | 161eae4988bSStefano Babic MXC_CCM_CGR1_I2C2_MASK | 162eae4988bSStefano Babic MXC_CCM_CGR1_IPU_MASK, 163eae4988bSStefano Babic &ccm->cgr1); 164eae4988bSStefano Babic 165eae4988bSStefano Babic /* Setup NAND */ 166eae4988bSStefano Babic __raw_writel(readl(&ccm->rcsr) | MXC_CCM_RCSR_NFC_FMS, &ccm->rcsr); 167eae4988bSStefano Babic 168eae4988bSStefano Babic setup_iomux_i2c(); 169961a7628SBenoît Thébaudeau setup_iomux_usbotg(); 170eae4988bSStefano Babic setup_iomux_fec(); 171eae4988bSStefano Babic setup_iomux_spi(); 172eae4988bSStefano Babic 173eae4988bSStefano Babic return 0; 174eae4988bSStefano Babic } 175eae4988bSStefano Babic 176eae4988bSStefano Babic int board_init(void) 177eae4988bSStefano Babic { 178eae4988bSStefano Babic gd->bd->bi_arch_number = MACH_TYPE_MX35_3DS; /* board id for linux */ 179eae4988bSStefano Babic /* address of boot parameters */ 180eae4988bSStefano Babic gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100; 181eae4988bSStefano Babic 182eae4988bSStefano Babic return 0; 183eae4988bSStefano Babic } 184eae4988bSStefano Babic 185eae4988bSStefano Babic static inline int pmic_detect(void) 186eae4988bSStefano Babic { 1875213d6e4SStefano Babic unsigned int id; 188c7336815SŁukasz Majewski struct pmic *p = pmic_get("FSL_PMIC"); 189c7336815SŁukasz Majewski if (!p) 190c7336815SŁukasz Majewski return -ENODEV; 191eae4988bSStefano Babic 1925213d6e4SStefano Babic pmic_reg_read(p, REG_IDENTIFICATION, &id); 193eae4988bSStefano Babic 194eae4988bSStefano Babic id = (id >> 6) & 0x7; 195eae4988bSStefano Babic if (id == 0x7) 196eae4988bSStefano Babic return 1; 197eae4988bSStefano Babic return 0; 198eae4988bSStefano Babic } 199eae4988bSStefano Babic 200eae4988bSStefano Babic u32 get_board_rev(void) 201eae4988bSStefano Babic { 202eae4988bSStefano Babic int rev; 203eae4988bSStefano Babic 204eae4988bSStefano Babic rev = pmic_detect(); 205eae4988bSStefano Babic 206eae4988bSStefano Babic return (get_cpu_rev() & ~(0xF << 8)) | (rev & 0xF) << 8; 207eae4988bSStefano Babic } 208eae4988bSStefano Babic 209eae4988bSStefano Babic int board_late_init(void) 210eae4988bSStefano Babic { 211eae4988bSStefano Babic u8 val; 212eae4988bSStefano Babic u32 pmic_val; 2135213d6e4SStefano Babic struct pmic *p; 214c7336815SŁukasz Majewski int ret; 215eae4988bSStefano Babic 216c7336815SŁukasz Majewski ret = pmic_init(I2C_PMIC); 217c7336815SŁukasz Majewski if (ret) 218c7336815SŁukasz Majewski return ret; 219c7336815SŁukasz Majewski 220eae4988bSStefano Babic if (pmic_detect()) { 221c7336815SŁukasz Majewski p = pmic_get("FSL_PMIC"); 222105c9eafSBenoît Thébaudeau imx_iomux_v3_setup_pad(MX35_PAD_WDOG_RST__WDOG_WDOG_B); 223eae4988bSStefano Babic 2245213d6e4SStefano Babic pmic_reg_read(p, REG_SETTING_0, &pmic_val); 2255213d6e4SStefano Babic pmic_reg_write(p, REG_SETTING_0, 2265213d6e4SStefano Babic pmic_val | VO_1_30V | VO_1_50V); 2275213d6e4SStefano Babic pmic_reg_read(p, REG_MODE_0, &pmic_val); 2285213d6e4SStefano Babic pmic_reg_write(p, REG_MODE_0, pmic_val | VGEN3EN); 229eae4988bSStefano Babic 230105c9eafSBenoît Thébaudeau imx_iomux_v3_setup_pad(MX35_PAD_COMPARE__GPIO1_5); 231eae4988bSStefano Babic 23268088ceeSBenoît Thébaudeau gpio_direction_output(IMX_GPIO_NR(1, 5), 1); 233eae4988bSStefano Babic } 234eae4988bSStefano Babic 235eae4988bSStefano Babic val = mc9sdz60_reg_read(MC9SDZ60_REG_GPIO_1) | 0x04; 236eae4988bSStefano Babic mc9sdz60_reg_write(MC9SDZ60_REG_GPIO_1, val); 237eae4988bSStefano Babic mdelay(200); 238eae4988bSStefano Babic 239eae4988bSStefano Babic val = mc9sdz60_reg_read(MC9SDZ60_REG_RESET_1) & 0x7F; 240eae4988bSStefano Babic mc9sdz60_reg_write(MC9SDZ60_REG_RESET_1, val); 241eae4988bSStefano Babic mdelay(200); 242eae4988bSStefano Babic 243eae4988bSStefano Babic val |= 0x80; 244eae4988bSStefano Babic mc9sdz60_reg_write(MC9SDZ60_REG_RESET_1, val); 245eae4988bSStefano Babic 246eae4988bSStefano Babic /* Print board revision */ 247ba901df4SFabio Estevam printf("Board: MX35 PDK %d.0\n", ((get_board_rev() >> 8) + 1) & 0x0F); 248eae4988bSStefano Babic 249eae4988bSStefano Babic return 0; 250eae4988bSStefano Babic } 251eae4988bSStefano Babic 252eae4988bSStefano Babic int board_eth_init(bd_t *bis) 253eae4988bSStefano Babic { 254eae4988bSStefano Babic #if defined(CONFIG_SMC911X) 255*a05f4ab6SFabio Estevam int rc = smc911x_initialize(0, CONFIG_SMC911X_BASE); 256*a05f4ab6SFabio Estevam if (rc) 257eae4988bSStefano Babic return rc; 258*a05f4ab6SFabio Estevam #endif 259*a05f4ab6SFabio Estevam return cpu_eth_init(bis); 260eae4988bSStefano Babic } 2613292539eSStefano Babic 2623292539eSStefano Babic #if defined(CONFIG_FSL_ESDHC) 2633292539eSStefano Babic 2643292539eSStefano Babic struct fsl_esdhc_cfg esdhc_cfg = {MMC_SDHC1_BASE_ADDR}; 2653292539eSStefano Babic 2663292539eSStefano Babic int board_mmc_init(bd_t *bis) 2673292539eSStefano Babic { 268105c9eafSBenoît Thébaudeau static const iomux_v3_cfg_t sdhc1_pads[] = { 269105c9eafSBenoît Thébaudeau MX35_PAD_SD1_CMD__ESDHC1_CMD, 270105c9eafSBenoît Thébaudeau MX35_PAD_SD1_CLK__ESDHC1_CLK, 271105c9eafSBenoît Thébaudeau MX35_PAD_SD1_DATA0__ESDHC1_DAT0, 272105c9eafSBenoît Thébaudeau MX35_PAD_SD1_DATA1__ESDHC1_DAT1, 273105c9eafSBenoît Thébaudeau MX35_PAD_SD1_DATA2__ESDHC1_DAT2, 274105c9eafSBenoît Thébaudeau MX35_PAD_SD1_DATA3__ESDHC1_DAT3, 275105c9eafSBenoît Thébaudeau }; 276105c9eafSBenoît Thébaudeau 2773292539eSStefano Babic /* configure pins for SDHC1 only */ 278105c9eafSBenoît Thébaudeau imx_iomux_v3_setup_multiple_pads(sdhc1_pads, ARRAY_SIZE(sdhc1_pads)); 2793292539eSStefano Babic 280a2ac1b3aSBenoît Thébaudeau esdhc_cfg.sdhc_clk = mxc_get_clock(MXC_ESDHC1_CLK); 2813292539eSStefano Babic return fsl_esdhc_initialize(bis, &esdhc_cfg); 2823292539eSStefano Babic } 2833292539eSStefano Babic 2843292539eSStefano Babic int board_mmc_getcd(struct mmc *mmc) 2853292539eSStefano Babic { 2863292539eSStefano Babic return !(mc9sdz60_reg_read(MC9SDZ60_REG_DES_FLAG) & 0x4); 2873292539eSStefano Babic } 2883292539eSStefano Babic #endif 289