Re: Booting mx25 based device from SD and NOR

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]


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 = "" 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 
_______________________________________________
barebox mailing list
barebox@xxxxxxxxxxxxxxxxxxx
http://lists.infradead.org/mailman/listinfo/barebox

[Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Photo]     [Yosemite News]    [Yosemite Photos]    [Free Online Dating]     [Linux Kernel]     [Linux SCSI]     [XFree86]

Add to Google Powered by Linux