Hi Sascha Thank you so much for taking your time explaining things the way you did. It certainly cleared things up a lot, albeit it still does not work; comment below. > > I read the different board initialization routines over and over again, > > but can't find a common pattern. From what I see the lowlevel_init (which > > has been converted nicely into a C file), only AIPS, MAX, MPLL core > clock, > > all clocks, SDRAM are initialized, but I have seen AIPS and MAX setups in > > core_init functions (eukrea_cpuimx35.c), as well as clock setups in > > console_init and other places. So, what's the bare minimum in lowlevel to > > set up? SDRAM/MDDR? What's the order of things? > > > > I am merely asking because I have come a long way trying to debug an > issue > > with weird I/O and clock behaviour on the ESDHC and other parts of my > mx25 > > device. > > - MAX setup is not needed for barebox > - AIPS can most probably be done later aswell > - I'm unsure with the MPLL, that depends on whether the SDRAM clock > depends on it. > In my case I am fairly certain that SDRAM clock does not depend on MPLL. I will be moving MAX and AIPS setup out of lowlevel init, so as to keep it tiny. > You should only setup all dependencies for SDRAM and the SDRAM itself. > Everything else can be done later. What that is for the i.MX25 you > can see in the dcd, here from the Eukrea mx25: > > struct imx_dcd_entry __dcd_entry_section dcd_entry[] = { > { .ptr_type = 4, .addr = 0xb8001010, .val = 0x00000004, }, > { .ptr_type = 4, .addr = 0xb8001000, .val = 0x92100000, }, > { .ptr_type = 1, .addr = 0x80000400, .val = 0x12344321, }, > { .ptr_type = 4, .addr = 0xb8001000, .val = 0xa2100000, }, > { .ptr_type = 4, .addr = 0x80000000, .val = 0x12344321, }, > { .ptr_type = 4, .addr = 0x80000000, .val = 0x12344321, }, > { .ptr_type = 4, .addr = 0xb8001000, .val = 0xb2100000, }, > { .ptr_type = 1, .addr = 0x80000033, .val = 0xda, }, > { .ptr_type = 1, .addr = 0x81000000, .val = 0xff, }, > { .ptr_type = 4, .addr = 0xb8001000, .val = 0x82216080, }, > { .ptr_type = 4, .addr = 0xb8001004, .val = 0x00295729, }, > { .ptr_type = 4, .addr = 0x53f80008, .val = 0x20034000, }, > }; > > So basically this means that the SDRAM does not seem to have any > dependencies. > This is the first time I have realized that the DCD actually represents more or less what should be done in the lowlevel init. After carefully reading what you explained and cross-checking with the old uboot, I have come up with the following DCD: struct imx_dcd_entry __dcd_entry_section dcd_entry[] = { /* NOR flash, CS0_CSCRU, CS0_CSCRL, CS0_CSCRA */ { .ptr_type = 4, .addr = 0xB8002000, .val = 0x0000D003, }, { .ptr_type = 4, .addr = 0xB8002004, .val = 0x00330D01, }, { .ptr_type = 4, .addr = 0xB8002008, .val = 0x00220800, }, /* DDR2 init */ { .ptr_type = 4, .addr = 0xb8001004, .val = 0x0076e83a, }, /* initial value for ESDCFG0 */ { .ptr_type = 4, .addr = 0xb8001010, .val = 0x00000204, }, /* ESD_MISC */ { .ptr_type = 4, .addr = 0xb8001000, .val = 0x92210000, }, /* CS0 precharge command */ { .ptr_type = 4, .addr = 0x80000f00, .val = 0x12344321, }, /* precharge all dummy write */ { .ptr_type = 4, .addr = 0xb8001000, .val = 0xb2210000, }, /* Load Mode Register command */ { .ptr_type = 1, .addr = 0x82000000, .val = 0xda, }, /* dummy write Load EMR2 */ { .ptr_type = 1, .addr = 0x83000000, .val = 0xda, }, /* dummy write Load EMR3 */ { .ptr_type = 1, .addr = 0x81000400, .val = 0xda, }, /* dummy write Load EMR1; enable DLL */ { .ptr_type = 1, .addr = 0x80000333, .val = 0xda, }, /* dummy write Load MR; reset DLL */ { .ptr_type = 4, .addr = 0xb8001000, .val = 0x92210000, }, /* CS0 precharge command */ { .ptr_type = 4, .addr = 0x80000400, .val = 0x12345678, }, /* precharge all dummy write */ { .ptr_type = 4, .addr = 0xb8001000, .val = 0xA2210000, }, /* select manual refresh mode */ { .ptr_type = 4, .addr = 0x80000000, .val = 0x87654321, }, /* manual refresh */ { .ptr_type = 4, .addr = 0x80000000, .val = 0x87654321, }, /* manual refresh twice */ { .ptr_type = 4, .addr = 0xb8001000, .val = 0xb2210000, }, /* Load Mode Register command */ { .ptr_type = 1, .addr = 0x80000233, .val = 0xda, }, /* Load MR; CL=3, BL=8, end DLL reset */ { .ptr_type = 1, .addr = 0x81000780, .val = 0xda, }, /* Load EMR1; OCD default */ { .ptr_type = 1, .addr = 0x81000400, .val = 0xda, }, /* Load EMR1; OCD exit */ { .ptr_type = 4, .addr = 0xb8001000, .val = 0x82216080, }, /* normal mode */ /* IOMUX_SW_PAD setup */ { .ptr_type = 4, .addr = 0x43FAC454, .val = 0x00001000, }, /* IOMUXC_SW_PAD_CTL_GRP_DDRTYPE(1-5) */ { .ptr_type = 4, .addr = 0x43FAC448, .val = 0x00002000, }, /* IOMUXC_SW_PAD NFC voltage 1.8 */ /* CLKCTL */ { .ptr_type = 4, .addr = 0x53f80008, .val = 0x20034000, }, /* CLKCTL ARM=399 AHB=133 */ }; > All the things in lowlevel_init are then done when running from SDRAM > anyway (at least when doing a dcd based boot), so they can safely be > done later. > > The next thing is that the clocks are correctly initialized before the > corresponding devices are registered. > I have seen that some devices simply enable all clocks in lowlevel and some enable the necessary ones at a later stage. To be sure, I have included both versions in my setup, so I can assure that all the necessary clocks are running on boot init. > So let's analyze Eukreas lowlevel init: > > > > void __bare_init __naked board_init_lowlevel(void) > > { > > uint32_t r; > > #ifdef CONFIG_NAND_IMX_BOOT > > unsigned int *trg, *src; > > int i; > > #endif > > register uint32_t loops = 0x20000; > > > > /* restart the MPLL and wait until it's stable */ > > writel(readl(IMX_CCM_BASE + CCM_CCTL) | (1 << 27), > > IMX_CCM_BASE + CCM_CCTL); > > while (readl(IMX_CCM_BASE + CCM_CCTL) & (1 << 27)) {}; > > > > /* Configure dividers and ARM clock source > > * ARM @ 400 MHz > > * AHB @ 133 MHz > > */ > > writel(0x20034000, IMX_CCM_BASE + CCM_CCTL); > > This may influence the timer clock, so it can be here. > I have copied this, since it was also done in the old uboot version that works. > > > > /* Enable UART1 / FEC / */ > > /* writel(0x1FFFFFFF, IMX_CCM_BASE + CCM_CGCR0); > > writel(0xFFFFFFFF, IMX_CCM_BASE + CCM_CGCR1); > > writel(0x000FDFFF, IMX_CCM_BASE + CCM_CGCR2);*/ > > This brings the Clock gate registers to reset default. This may be a > good idea, but can be done later. > Ok, I have copied this. > > > > > /* AIPS setup - Only setup MPROTx registers. The PACR default > values are good. > > * Set all MPROTx to be non-bufferable, trusted for R/W, > > * not forced to user-mode. > > */ > > writel(0x77777777, 0x43f00000); > > writel(0x77777777, 0x43f00004); > > writel(0x77777777, 0x53f00000); > > writel(0x77777777, 0x53f00004); > > This can be done later. This is duplicated in many boards and is always > the same. Look for example at the i.MX53 code, there we have > imx53_init_lowlevel() which sets up the AIPS. This is common for all > i.MX53 and is called from an initcall. Similar could be done for i.MX25 > aswell, if somebody is willing to implement it. > I like the imx53_init_lowlevel() approach a lot, it's very clean and helps avoiding redundancy and maintenance costs. If I get my device to boot from NOR, I might be inclined to give it a shot. > > > > /* MAX (Multi-Layer AHB Crossbar Switch) setup > > * MPR - priority for MX25 is (SDHC2/SDMA)>USBOTG>RTIC>IAHB>DAHB > > */ > > writel(0x00002143, 0x43f04000); > > writel(0x00002143, 0x43f04100); > > writel(0x00002143, 0x43f04200); > > writel(0x00002143, 0x43f04300); > > writel(0x00002143, 0x43f04400); > > /* SGPCR - always park on last master */ > > writel(0x10, 0x43f04010); > > writel(0x10, 0x43f04110); > > writel(0x10, 0x43f04210); > > writel(0x10, 0x43f04310); > > writel(0x10, 0x43f04410); > > /* MGPCR - restore default values */ > > writel(0x0, 0x43f04800); > > writel(0x0, 0x43f04900); > > writel(0x0, 0x43f04a00); > > writel(0x0, 0x43f04b00); > > writel(0x0, 0x43f04c00); > > > > /* Configure M3IF registers > > * M3IF Control Register (M3IFCTL) for MX25 > > * MRRP[0] = LCDC on priority list (1 << 0) = 0x00000001 > > * MRRP[1] = MAX1 not on priority list (0 << 1) = 0x00000000 > > * MRRP[2] = MAX0 not on priority list (0 << 2) = 0x00000000 > > * MRRP[3] = USB HOST not on priority list (0 << 3) = 0x00000000 > > * MRRP[4] = SDMA not on priority list (0 << 4) = 0x00000000 > > * MRRP[5] = SD/ATA/FEC not on priority list (0 << 5) = 0x00000000 > > * MRRP[6] = SCMFBC not on priority list (0 << 6) = 0x00000000 > > * MRRP[7] = CSI not on priority list (0 << 7) = 0x00000000 > > * ---------- > > * 0x00000001 > > */ > > writel(0x1, 0xb8003000); > > Same as above. > > > > > /* Speed up NAND controller by adjusting the NFC divider */ > > r = readl(IMX_CCM_BASE + CCM_PCDR2); > > r &= ~0xf; > > r |= 0x1; > > writel(r, IMX_CCM_BASE + CCM_PCDR2); > > This is necessary for external NAND boot. The NAND controller comes up > with a low speed which makes the copying of the image > (CONFIG_NAND_IMX_BOOT below) slow. This is optional but has to be done > here to get a faster boot. > > Ok, I reckon there is nothing comparable which should be done in the NOR case. > > > > /* Skip SDRAM initialization if we run from RAM */ > > r = get_pc(); > > if (r > 0x80000000 && r < 0x90000000) > > board_init_lowlevel_return(); > > Here we bail out for second stage boots (and also internal bootmode > where we are already running from SDRAM > It's this place where I wanted to put a printf() to see where the code is actually branching and if my setting of the corresponding WEIM CS0 registers upset the processor already. However, it seems as if printf()'s here is a no-go. > > > > /* Init Mobile DDR */ > > writel(0x0000000E, ESDMISC); > > writel(0x00000004, ESDMISC); > > __asm__ volatile ("1:\n" > > "subs %0, %1, #1\n" > > "bne 1b":"=r" (loops):"0" (loops)); > > > > writel(0x0029572B, ESDCFG0); > > writel(0x92210000, ESDCTL0); > > writeb(0xda, IMX_SDRAM_CS0 + 0x400); > > writel(0xA2210000, ESDCTL0); > > writeb(0xda, IMX_SDRAM_CS0); > > writeb(0xda, IMX_SDRAM_CS0); > > writel(0xB2210000, ESDCTL0); > > writeb(0xda, IMX_SDRAM_CS0 + 0x33); > > writeb(0xda, IMX_SDRAM_CS0 + 0x1000000); > > writel(0x82216080, ESDCTL0); > > RAM init for external bootmode, has to be done here. > I left it there. > > > > > #ifdef CONFIG_NAND_IMX_BOOT > > /* skip NAND boot if not running from NFC space */ > > r = get_pc(); > > if (r < IMX_NFC_BASE || r > IMX_NFC_BASE + 0x800) > > board_init_lowlevel_return(); > > > > src = (unsigned int *)IMX_NFC_BASE; > > trg = (unsigned int *)TEXT_BASE; > > > > /* Move ourselves out of NFC SRAM */ > > for (i = 0; i < 0x800 / sizeof(int); i++) > > *trg++ = *src++; > > > > /* Jump to SDRAM */ > > r = (unsigned int)&insdram; > > __asm__ __volatile__("mov pc, %0" : : "r"(r)); > > #else > > board_init_lowlevel_return(); > > #endif > > Finally copy the image from NAND SRAM to SDRAM, only needed for external > NAND boot. > > And since I am trying to perform an internal MMC or NOR boot, this does not affect me at all. > Often the whole lowlevel stuff is setup in early assembly code. This has > mostly historical reasons and 'hey, this is hardcore stuff we configure > here, we must do it early and we must do it in assembly'. Much of the > lowlevel stuff we have in barebox is just copied from a working U-Boot > or redboot setup and never touched again, hence the slightly chaotic > situation. > This is what I have slowly come to understand while reading more source code over the weekend. I have also found the old uboot init part for this device from 2009.08 and have adapted my lowlevel and device part code accordingly. I wonder if someone could write a quick and dirty perl/shell script to auto-port devices from uboot to barebox, at least the basic booting facility. In my case, there is one peculiarity in the u-boot sources, which I haven't been able to map to barebox yet and it's best described by the corresponding code: #include #include #include #include #include #include #include #include #include #ifdef CONFIG_CMD_MMC #include #include #endif DECLARE_GLOBAL_DATA_PTR; static u32 system_rev; u32 get_board_rev(void) { return system_rev; } static inline void setup_soc_rev(void) { int reg; reg = __REG(IIM_BASE + IIM_SREV); if (!reg) { reg = __REG(ROMPATCH_REV); reg <<= 4; } else reg += CHIP_REV_1_0; system_rev = 0x25000 + (reg & 0xFF); } inline int is_soc_rev(int rev) { return (system_rev & 0xFF) - rev; } int dram_init(void) { gd->bd->bi_dram[0].start = PHYS_SDRAM_1; gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE; return 0; } #ifdef CONFIG_CMD_MMC u32 *imx_esdhc_base_addr; int esdhc_gpio_init(void) { u32 interface_esdhc = 0, val = 0; interface_esdhc = (readl(CCM_RCSR) & (0x00300000)) >> 20; switch (interface_esdhc) { case 0: imx_esdhc_base_addr = (u32 *)MMC_SDHC1_BASE; /* Pins */ writel(0x10, IOMUXC_BASE + 0x190); /* SD1_CMD */ writel(0x10, IOMUXC_BASE + 0x194); /* SD1_CLK */ writel(0x00, IOMUXC_BASE + 0x198); /* SD1_DATA0 */ writel(0x00, IOMUXC_BASE + 0x19c); /* SD1_DATA1 */ writel(0x00, IOMUXC_BASE + 0x1a0); /* SD1_DATA2 */ writel(0x00, IOMUXC_BASE + 0x1a4); /* SD1_DATA3 */ /*ENABLE NOR writel(0x06, IOMUXC_BASE + 0x094); // D12 (SD1_DATA4) writel(0x06, IOMUXC_BASE + 0x090); // D13 (SD1_DATA5) writel(0x06, IOMUXC_BASE + 0x08c); // D14 (SD1_DATA6) writel(0x06, IOMUXC_BASE + 0x088); // D15 (SD1_DATA7) writel(0x05, IOMUXC_BASE + 0x010); // A14 (SD1_WP) writel(0x05, IOMUXC_BASE + 0x014); // A15 (SD1_DET) */ /* Pads */ writel(0xD1, IOMUXC_BASE + 0x388); /* SD1_CMD */ writel(0xD1, IOMUXC_BASE + 0x38c); /* SD1_CLK */ writel(0xD1, IOMUXC_BASE + 0x390); /* SD1_DATA0 */ writel(0xD1, IOMUXC_BASE + 0x394); /* SD1_DATA1 */ writel(0xD1, IOMUXC_BASE + 0x398); /* SD1_DATA2 */ writel(0xD1, IOMUXC_BASE + 0x39c); /* SD1_DATA3 */ /* ENABLE NOR writel(0xD1, IOMUXC_BASE + 0x28c); // D12 (SD1_DATA4) writel(0xD1, IOMUXC_BASE + 0x288); // D13 (SD1_DATA5) writel(0xD1, IOMUXC_BASE + 0x284); // D14 (SD1_DATA6) writel(0xD1, IOMUXC_BASE + 0x280); // D15 (SD1_DATA7) writel(0xD1, IOMUXC_BASE + 0x230); // A14 (SD1_WP) writel(0xD1, IOMUXC_BASE + 0x234); // A15 (SD1_DET) */ /* * Set write protect and card detect gpio as inputs * A14 (SD1_WP) and A15 (SD1_DET) */ val = ~(3 << 0) & readl(GPIO1_BASE + GPIO_GDIR); writel(val, GPIO1_BASE + GPIO_GDIR); break; case 1: imx_esdhc_base_addr = (u32 *)MMC_SDHC2_BASE; /* Pins */ writel(0x16, IOMUXC_BASE + 0x0e8); /* LD8 (SD1_CMD) */ writel(0x16, IOMUXC_BASE + 0x0ec); /* LD9 (SD1_CLK) */ writel(0x06, IOMUXC_BASE + 0x0f0); /* LD10 (SD1_DATA0) */ writel(0x06, IOMUXC_BASE + 0x0f4); /* LD11 (SD1_DATA1) */ writel(0x06, IOMUXC_BASE + 0x0f8); /* LD12 (SD1_DATA2) */ writel(0x06, IOMUXC_BASE + 0x0fc); /* LD13 (SD1_DATA3) */ writel(0x02, IOMUXC_BASE + 0x120); /* CSI_D2 (SD1_DATA4) */ writel(0x02, IOMUXC_BASE + 0x124); /* CSI_D3 (SD1_DATA5) */ writel(0x02, IOMUXC_BASE + 0x128); /* CSI_D4 (SD1_DATA6) */ writel(0x02, IOMUXC_BASE + 0x12c); /* CSI_D5 (SD1_DATA7) */ /* Pads */ writel(0xD1, IOMUXC_BASE + 0x2e0); /* LD8 (SD1_CMD) */ writel(0xD1, IOMUXC_BASE + 0x2e4); /* LD9 (SD1_CLK) */ writel(0xD1, IOMUXC_BASE + 0x2e8); /* LD10 (SD1_DATA0) */ writel(0xD1, IOMUXC_BASE + 0x2ec); /* LD11 (SD1_DATA1) */ writel(0xD1, IOMUXC_BASE + 0x2f0); /* LD12 (SD1_DATA2) */ writel(0xD1, IOMUXC_BASE + 0x2f4); /* LD13 (SD1_DATA3) */ writel(0xD1, IOMUXC_BASE + 0x318); /* CSI_D2 (SD1_DATA4) */ writel(0xD1, IOMUXC_BASE + 0x31c); /* CSI_D3 (SD1_DATA5) */ writel(0xD1, IOMUXC_BASE + 0x320); /* CSI_D4 (SD1_DATA6) */ writel(0xD1, IOMUXC_BASE + 0x324); /* CSI_D5 (SD1_DATA7) */ break; default: break; } return 0; } int board_mmc_init(void) { if (!esdhc_gpio_init()) return fsl_esdhc_mmc_init(gd->bd); else return -1; } #endif void spi_io_init(struct imx_spi_dev_t *dev) { switch (dev->base) { case CSPI1_BASE: writel(0, IOMUXC_BASE + 0x180); /* CSPI1 SCLK */ writel(0x1C0, IOMUXC_BASE + 0x5c4); writel(0, IOMUXC_BASE + 0x184); /* SPI_RDY */ writel(0x1E0, IOMUXC_BASE + 0x5c8); writel(0, IOMUXC_BASE + 0x170); /* MOSI */ writel(0x1C0, IOMUXC_BASE + 0x5b4); writel(0, IOMUXC_BASE + 0x174); /* MISO */ writel(0x1C0, IOMUXC_BASE + 0x5b8); writel(0, IOMUXC_BASE + 0x17C); /* SS1 */ writel(0x1E0, IOMUXC_BASE + 0x5C0); break; default: break; } } int board_init(void) { setup_soc_rev(); /* setup pins for UART1 */ /* UART 1 IOMUX Configs */ mxc_request_iomux(MX25_PIN_UART1_RXD, MUX_CONFIG_FUNC); mxc_request_iomux(MX25_PIN_UART1_TXD, MUX_CONFIG_FUNC); mxc_request_iomux(MX25_PIN_UART1_RTS, MUX_CONFIG_FUNC); mxc_request_iomux(MX25_PIN_UART1_CTS, MUX_CONFIG_FUNC); mxc_iomux_set_pad(MX25_PIN_UART1_RXD, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PUD | PAD_CTL_100K_PU); mxc_iomux_set_pad(MX25_PIN_UART1_TXD, PAD_CTL_PUE_PUD | PAD_CTL_100K_PD); mxc_iomux_set_pad(MX25_PIN_UART1_RTS, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PUD | PAD_CTL_100K_PU); mxc_iomux_set_pad(MX25_PIN_UART1_CTS, PAD_CTL_PUE_PUD | PAD_CTL_100K_PD); /* setup pins for FEC */ mxc_request_iomux(MX25_PIN_FEC_TX_CLK, MUX_CONFIG_FUNC); mxc_request_iomux(MX25_PIN_FEC_RX_DV, MUX_CONFIG_FUNC); mxc_request_iomux(MX25_PIN_FEC_RDATA0, MUX_CONFIG_FUNC); mxc_request_iomux(MX25_PIN_FEC_TDATA0, MUX_CONFIG_FUNC); mxc_request_iomux(MX25_PIN_FEC_TX_EN, MUX_CONFIG_FUNC); mxc_request_iomux(MX25_PIN_FEC_MDC, MUX_CONFIG_FUNC); mxc_request_iomux(MX25_PIN_FEC_MDIO, MUX_CONFIG_FUNC); mxc_request_iomux(MX25_PIN_FEC_RDATA1, MUX_CONFIG_FUNC); mxc_request_iomux(MX25_PIN_FEC_TDATA1, MUX_CONFIG_FUNC); mxc_request_iomux(MX25_PIN_POWER_FAIL, MUX_CONFIG_FUNC); /* PHY INT */ #define FEC_PAD_CTL1 (PAD_CTL_HYS_SCHMITZ | PAD_CTL_PUE_PUD | \ PAD_CTL_PKE_ENABLE) #define FEC_PAD_CTL2 (PAD_CTL_PUE_PUD) mxc_iomux_set_pad(MX25_PIN_FEC_TX_CLK, FEC_PAD_CTL1); mxc_iomux_set_pad(MX25_PIN_FEC_RX_DV, FEC_PAD_CTL1); mxc_iomux_set_pad(MX25_PIN_FEC_RDATA0, FEC_PAD_CTL1); mxc_iomux_set_pad(MX25_PIN_FEC_TDATA0, FEC_PAD_CTL2); mxc_iomux_set_pad(MX25_PIN_FEC_TX_EN, FEC_PAD_CTL2); mxc_iomux_set_pad(MX25_PIN_FEC_MDC, FEC_PAD_CTL2); mxc_iomux_set_pad(MX25_PIN_FEC_MDIO, FEC_PAD_CTL1 | PAD_CTL_22K_PU); mxc_iomux_set_pad(MX25_PIN_FEC_RDATA1, FEC_PAD_CTL1); mxc_iomux_set_pad(MX25_PIN_FEC_TDATA1, FEC_PAD_CTL2); mxc_iomux_set_pad(MX25_PIN_POWER_FAIL, FEC_PAD_CTL1); /* * Set up the FEC_RESET_B and FEC_ENABLE GPIO pins. * Assert FEC_RESET_B, then power up the PHY by asserting * FEC_ENABLE, at the same time lifting FEC_RESET_B. * * FEC_RESET_B: gpio2[3] is ALT 5 mode of pin D12 * FEC_ENABLE_B: gpio4[8] is ALT 5 mode of pin A17 */ /*FQ FOR ENABLE NOR mxc_request_iomux(MX25_PIN_A17, MUX_CONFIG_ALT5); // FEC_EN mxc_request_iomux(MX25_PIN_D12, MUX_CONFIG_ALT5); // FEC_RESET_B mxc_iomux_set_pad(MX25_PIN_A17, PAD_CTL_ODE_OpenDrain); mxc_iomux_set_pad(MX25_PIN_D12, 0); mxc_set_gpio_direction(MX25_PIN_A17, 0); // FEC_EN mxc_set_gpio_direction(MX25_PIN_D12, 0); // FEC_RESET_B /* drop PHY power mxc_set_gpio_dataout(MX25_PIN_A17, 0); // FEC_EN // assert reset mxc_set_gpio_dataout(MX25_PIN_D12, 0); // FEC_RESET_B udelay(2); // spec says 1us min // turn on PHY power and lift reset mxc_set_gpio_dataout(MX25_PIN_A17, 1); // FEC_EN mxc_set_gpio_dataout(MX25_PIN_D12, 1); // FEC_RESET_B */ #define I2C_PAD_CTL (PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | \ PAD_CTL_PUE_PUD | PAD_CTL_100K_PU | PAD_CTL_ODE_OpenDrain) mxc_request_iomux(MX25_PIN_I2C1_CLK, MUX_CONFIG_SION); mxc_request_iomux(MX25_PIN_I2C1_DAT, MUX_CONFIG_SION); mxc_iomux_set_pad(MX25_PIN_I2C1_CLK, 0x1E8); mxc_iomux_set_pad(MX25_PIN_I2C1_DAT, 0x1E8); gd->bd->bi_arch_number = MACH_TYPE_MX25_3DS; /* board id for linux */ gd->bd->bi_boot_params = 0x80000100; /* address of boot parameters */ return 0; #undef FEC_PAD_CTL1 #undef FEC_PAD_CTL2 #undef I2C_PAD_CTL } #ifdef BOARD_LATE_INIT int board_late_init(void) { u8 reg[4]; /* Turn PMIC On*/ reg[0] = 0x09; i2c_write(0x54, 0x02, 1, reg, 1); #ifdef CONFIG_IMX_SPI_CPLD mxc_cpld_spi_init(); #endif return 0; } #endif int checkboard(void) { printf("Boot Device: SD Card \n"); printf("Board: SID1 i.MX25 \n"); return 0; } int board_eth_init(bd_t *bis) { int rc = -ENODEV; #if defined(CONFIG_SMC911X) rc = smc911x_initialize(0, CONFIG_SMC911X_BASE); #endif return rc; } It seems as if in order to support NOR upon boot, the following PADs and PINs have to be disabled: writel(0x06, IOMUXC_BASE + 0x094); // D12 (SD1_DATA4) writel(0x06, IOMUXC_BASE + 0x090); // D13 (SD1_DATA5) writel(0x06, IOMUXC_BASE + 0x08c); // D14 (SD1_DATA6) writel(0x06, IOMUXC_BASE + 0x088); // D15 (SD1_DATA7) writel(0x05, IOMUXC_BASE + 0x010); // A14 (SD1_WP) writel(0x05, IOMUXC_BASE + 0x014); // A15 (SD1_DET) Why, and how could I find the corresponding barebox mappings? I recall that last week someone wanted to synchronize the IOMUX settings with the kernel ones. But still, why this change and could this affect my issue I am seeing with barebox? I still cannot initialize the NOR upon MMC internal boot on my device. Hope I could help you a bit. > > A lot, let me know where I can send the beers or any beverage to as soon as I get the bloody thing booting from NOR and showing up my NOR :). Take care Roberto