Booting mx25 based device from SD and NOR

Roberto Nibali rnibali at gmail.com
Tue May 29 05:26:34 EDT 2012


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 <common.h>
#include <asm/io.h>
#include <asm/errno.h>
#include <asm/arch/mx25.h>
#include <asm/arch/mx25-regs.h>
#include <asm/arch/mx25_pins.h>
#include <asm/arch/iomux.h>
#include <asm/arch/gpio.h>
#include <imx_spi.h>

#ifdef CONFIG_CMD_MMC
#include <mmc.h>
#include <fsl_esdhc.h>
#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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.infradead.org/pipermail/barebox/attachments/20120529/7de01a63/attachment-0001.html>


More information about the barebox mailing list