From 3227c278048e6b13397d9d0793e77e703649d7de Mon Sep 17 00:00:00 2001 From: Fred Fan Date: Mon, 14 Sep 2009 16:40:37 +0800 Subject: ENGR00116472-1 U-BOOT upgrade to V2009.08 U-BOOT upgrade from V2009.01 to V2009.08 Initial version for i.MX51 BBG board. Support: FEC, SPI, spi Nor Flash Boot from spi nor flash and mmc/sd Signed-off-by:Fred Fan --- board/freescale/imx51/config.mk | 2 + common/cmd_nvedit.c | 8 - cpu/arm_cortexa8/config.mk | 17 +- cpu/arm_cortexa8/cpu.c | 1 - cpu/arm_cortexa8/mx51/Makefile | 2 +- cpu/arm_cortexa8/mx51/interrupts.c | 78 ----- cpu/arm_cortexa8/mx51/timer.c | 123 +++++++ drivers/mmc/fsl_esdhc.c | 648 ++++--------------------------------- drivers/net/mxc_fec.c | 4 +- include/configs/imx51.h | 34 +- 10 files changed, 202 insertions(+), 715 deletions(-) create mode 100644 cpu/arm_cortexa8/mx51/timer.c diff --git a/board/freescale/imx51/config.mk b/board/freescale/imx51/config.mk index ce7369d..705aa34 100644 --- a/board/freescale/imx51/config.mk +++ b/board/freescale/imx51/config.mk @@ -1 +1,3 @@ +LDSCRIPT := $(SRCTREE)/board/$(VENDOR)/$(BOARD)/u-boot.lds + TEXT_BASE = 0x97800000 diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c index cda14e8..e0ccd56 100644 --- a/common/cmd_nvedit.c +++ b/common/cmd_nvedit.c @@ -613,14 +613,6 @@ U_BOOT_CMD( " - delete environment variable 'name'" ); -#if defined(CONFIG_CMD_SAVEENV) && !defined(CONFIG_ENV_IS_NOWHERE) -U_BOOT_CMD( - saveenv, 1, 0, do_saveenv, - "saveenv - save environment variables to persistent storage\n", - NULL -); -#endif - #if defined(CONFIG_CMD_ASKENV) U_BOOT_CMD( diff --git a/cpu/arm_cortexa8/config.mk b/cpu/arm_cortexa8/config.mk index 954ad98..079bd5f 100644 --- a/cpu/arm_cortexa8/config.mk +++ b/cpu/arm_cortexa8/config.mk @@ -30,11 +30,14 @@ PLATFORM_CPPFLAGS += -march=armv5 # Supply options according to compiler version # # ========================================================================= -ifdef CONFIG_SYS_APCS_GNU -PLATFORM_CPPFLAGS +=$(call cc-option,-mapcs-32,-mabi=apcs-gnu) -else -PLATFORM_CPPFLAGS +=$(call cc-option) -endif -PLATFORM_CPPFLAGS +=$(call cc-option,-mno-thumb-interwork,) -PLATFORM_RELFLAGS +=$(call cc-option,-mshort-load-bytes,\ +#ifdef CONFIG_SYS_APCS_GNU +#PLATFORM_CPPFLAGS +=$(call cc-option,-mapcs-32,-mabi=apcs-gnu) +#else +#PLATFORM_CPPFLAGS +=$(call cc-option) +#endif +#PLATFORM_CPPFLAGS +=$(call cc-option,-mno-thumb-interwork,\ +# $(call cc-option,-mshort-load-bytes,\ +# $(call cc-option,-malignment-traps,))) + +PLATFORM_CPPFLAGS +=$(call cc-option,-mshort-load-bytes,\ $(call cc-option,-malignment-traps,)) diff --git a/cpu/arm_cortexa8/cpu.c b/cpu/arm_cortexa8/cpu.c index 79f04ea..df96804 100644 --- a/cpu/arm_cortexa8/cpu.c +++ b/cpu/arm_cortexa8/cpu.c @@ -35,7 +35,6 @@ #include #include #include -#include #ifndef CONFIG_L2_OFF #ifndef CONFIG_MXC diff --git a/cpu/arm_cortexa8/mx51/Makefile b/cpu/arm_cortexa8/mx51/Makefile index 6f10e3e..940b05c 100644 --- a/cpu/arm_cortexa8/mx51/Makefile +++ b/cpu/arm_cortexa8/mx51/Makefile @@ -27,7 +27,7 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(SOC).a -COBJS = interrupts.o serial.o generic.o iomux.o +COBJS = interrupts.o serial.o generic.o iomux.o timer.o SOBJS = mxc_nand_load.o SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) diff --git a/cpu/arm_cortexa8/mx51/interrupts.c b/cpu/arm_cortexa8/mx51/interrupts.c index 484b961..1b5a4d1 100644 --- a/cpu/arm_cortexa8/mx51/interrupts.c +++ b/cpu/arm_cortexa8/mx51/interrupts.c @@ -38,90 +38,12 @@ #define GPTCR_CLKSOURCE_32 (4<<6) /* Clock source */ #define GPTCR_TEN (1) /* Timer enable */ -static inline void setup_gpt() -{ - int i; - static int init_done; - - if (init_done) - return; - - init_done = 1; - - /* setup GP Timer 1 */ - GPTCR = GPTCR_SWR; - for (i = 0; i < 100; i++) - GPTCR = 0; /* We have no udelay by now */ - GPTPR = 0; /* 32Khz */ - /* Freerun Mode, PERCLK1 input */ - GPTCR |= GPTCR_CLKSOURCE_32 | GPTCR_TEN; -} - /* nothing really to do with interrupts, just starts up a counter. */ int interrupt_init(void) { - setup_gpt(); - return 0; } -void reset_timer(void) -{ - reset_timer_masked(); -} - -void reset_timer_masked(void) -{ - GPTCR = 0; - /* Freerun Mode, PERCLK1 input */ - GPTCR = GPTCR_CLKSOURCE_32 | GPTCR_TEN; -} - -ulong get_timer_masked(void) -{ - ulong val = GPTCNT; - return val; -} - -ulong get_timer(ulong base) -{ - return get_timer_masked() - base; -} - -void set_timer(ulong t) -{ -} - -/* delay x useconds AND perserve advance timstamp value */ -void udelay(unsigned long usec) -{ - ulong tmo, tmp; - - setup_gpt(); - - /* if "big" number, spread normalization to seconds */ - if (usec >= 1000) { - /* start to normalize for usec to ticks per sec */ - tmo = usec / 1000; - /* find number of "ticks" to wait to achieve target */ - tmo *= CONFIG_SYS_HZ; - tmo /= 1000; /* finish normalize. */ - } else {/* else small number, don't kill it prior to HZ multiply */ - tmo = usec * CONFIG_SYS_HZ; - tmo /= (1000 * 1000); - } - - tmp = get_timer(0); /* get current timestamp */ - /* if setting this forward will roll time stamp */ - if ((tmo + tmp + 1) < tmp) - /* reset "advancing" timestamp to 0, set lastinc value */ - reset_timer_masked(); - else /* else, set advancing stamp wake up time */ - tmo += tmp; - while (get_timer_masked() < tmo) /* loop till event */ - /*NOP*/; -} - void reset_cpu(ulong addr) { __REG16(WDOG1_BASE_ADDR) = 4; diff --git a/cpu/arm_cortexa8/mx51/timer.c b/cpu/arm_cortexa8/mx51/timer.c new file mode 100644 index 0000000..ff982be --- /dev/null +++ b/cpu/arm_cortexa8/mx51/timer.c @@ -0,0 +1,123 @@ +/* + * (C) Copyright 2007 + * Sascha Hauer, Pengutronix + * + * (C) Copyright 2009 Freescale Semiconductor, Inc. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include + +/* General purpose timers registers */ +#define GPTCR __REG(GPT1_BASE_ADDR) /* Control register */ +#define GPTPR __REG(GPT1_BASE_ADDR + 0x4) /* Prescaler register */ +#define GPTSR __REG(GPT1_BASE_ADDR + 0x8) /* Status register */ +#define GPTCNT __REG(GPT1_BASE_ADDR + 0x24) /* Counter register */ + +/* General purpose timers bitfields */ +#define GPTCR_SWR (1<<15) /* Software reset */ +#define GPTCR_FRR (1<<9) /* Freerun / restart */ +#define GPTCR_CLKSOURCE_32 (4<<6) /* Clock source */ +#define GPTCR_TEN (1) /* Timer enable */ + +static inline void setup_gpt() +{ + int i; + static int init_done; + + if (init_done) + return; + + init_done = 1; + + /* setup GP Timer 1 */ + GPTCR = GPTCR_SWR; + for (i = 0; i < 100; i++) + GPTCR = 0; /* We have no udelay by now */ + GPTPR = 0; /* 32Khz */ + /* Freerun Mode, PERCLK1 input */ + GPTCR |= GPTCR_CLKSOURCE_32 | GPTCR_TEN; +} + +/* nothing really to do with interrupts, just starts up a counter. */ +int timer_init(void) +{ + setup_gpt(); + + return 0; +} + +void reset_timer(void) +{ + reset_timer_masked(); +} + +void reset_timer_masked(void) +{ + GPTCR = 0; + /* Freerun Mode, PERCLK1 input */ + GPTCR = GPTCR_CLKSOURCE_32 | GPTCR_TEN; +} + +ulong get_timer_masked(void) +{ + ulong val = GPTCNT; + return val; +} + +ulong get_timer(ulong base) +{ + return get_timer_masked() - base; +} + +void set_timer(ulong t) +{ +} + +/* delay x useconds AND perserve advance timstamp value */ +void udelay(unsigned long usec) +{ + ulong tmo, tmp; + + setup_gpt(); + + /* if "big" number, spread normalization to seconds */ + if (usec >= 1000) { + /* start to normalize for usec to ticks per sec */ + tmo = usec / 1000; + /* find number of "ticks" to wait to achieve target */ + tmo *= CONFIG_SYS_HZ; + tmo /= 1000; /* finish normalize. */ + } else {/* else small number, don't kill it prior to HZ multiply */ + tmo = usec * CONFIG_SYS_HZ; + tmo /= (1000 * 1000); + } + + tmp = get_timer(0); /* get current timestamp */ + /* if setting this forward will roll time stamp */ + if ((tmo + tmp + 1) < tmp) + /* reset "advancing" timestamp to 0, set lastinc value */ + reset_timer_masked(); + else /* else, set advancing stamp wake up time */ + tmo += tmp; + while (get_timer_masked() < tmo) /* loop till event */ + /*NOP*/; +} diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c index fab39eb..c6e9e6e 100644 --- a/drivers/mmc/fsl_esdhc.c +++ b/drivers/mmc/fsl_esdhc.c @@ -1,5 +1,6 @@ /* - * Copyright 2008-2009 Freescale Semiconductor, Inc. + * Copyright 2007, Freescale Semiconductor, Inc + * Andy Fleming * * Based vaguely on the pxa mmc code: * (C) Copyright 2003 @@ -24,18 +25,7 @@ * MA 02111-1307 USA */ -/*! - * @file esdhc.c - * - * @brief source code for the mmc card operation - * - * @ingroup mmc - */ - #include -#include -#include -#include #include #include #include @@ -45,9 +35,9 @@ #include #include #include -#include #include + DECLARE_GLOBAL_DATA_PTR; struct fsl_esdhc { @@ -77,41 +67,6 @@ struct fsl_esdhc { uint scr; }; -#define RETRIES_TIMES 100 - -#define REG_WRITE_OR(val, reg) { \ - u32 temp = 0; \ - temp = readl(reg); \ - (temp) |= (val); \ - writel((temp), (reg)); \ - } - -#define REG_WRITE_AND(val, reg) { \ - u32 temp = 0; \ - temp = readl(reg); \ - (temp) &= (val); \ - writel((temp), (reg)); \ - } - -#define SDHC_DELAY_BY_100(x) { \ - u32 i; \ - for (i = 0; i < x; ++i) \ - udelay(100); \ - } - -extern volatile u32 esdhc_base_pointer; - -static void esdhc_cmd_config(esdhc_cmd_t *); -static u32 esdhc_check_response(void); -static u32 esdhc_wait_buf_rdy_intr(u32, u32); -static void esdhc_wait_op_done_intr(void); -static u32 esdhc_check_data(void); -static void esdhc_set_data_transfer_width(u32 data_transfer_width); -static u32 esdhc_poll_cihb_cdihb(data_present_select data_present); -static void esdhc_set_endianness(u32 endian_mode); -static void esdhc_clear_buf_rdy_intr(u32 mask); -static u32 esdhc_check_data_crc_status(void); - /* Return the XFERTYP flags for a given command and data packet */ uint esdhc_xfertyp(struct mmc_cmd *cmd, struct mmc_data *data) { @@ -119,9 +74,12 @@ uint esdhc_xfertyp(struct mmc_cmd *cmd, struct mmc_data *data) if (data) { xfertyp |= XFERTYP_DPSEL | XFERTYP_DMAEN; + if (data->blocks > 1) { xfertyp |= XFERTYP_MSBSEL; xfertyp |= XFERTYP_BCEN; + } + if (data->flags & MMC_DATA_READ) xfertyp |= XFERTYP_DTDSEL; } @@ -140,30 +98,20 @@ uint esdhc_xfertyp(struct mmc_cmd *cmd, struct mmc_data *data) return XFERTYP_CMD(cmd->cmdidx) | xfertyp; } -/*! - * Send 80 SD clock to card and wait for INITA bit to get cleared. - */ -void interface_initialization_active(void) -{ - /* Send 80 clock ticks for card to power up */ - REG_WRITE_OR(ESDHC_SYSCTL_INITA, \ - esdhc_base_pointer + SDHCI_SYSTEM_CONTROL); - - /* Start a general purpose timer */ - udelay(ESDHC_CARD_INIT_TIMEOUT); -} - static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data) { uint wml_value; int timeout; struct fsl_esdhc *regs = mmc->priv; + wml_value = data->blocksize/4; if (data->flags & MMC_DATA_READ) { if (wml_value > 0x10) wml_value = 0x10; + wml_value = 0x100000 | wml_value; + out_be32(®s->dsaddr, (u32)data->dest); } else { if (wml_value > 0x80) @@ -177,127 +125,24 @@ static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data) } out_be32(®s->wml, wml_value); + out_be32(®s->blkattr, data->blocks << 16 | data->blocksize); + /* Calculate the timeout period for data transactions */ timeout = __ilog2(mmc->tran_speed/10); timeout -= 13; + if (timeout > 14) timeout = 14; + if (timeout < 0) timeout = 0; - clrsetbits_be32(®s->sysctl, SYSCTL_TIMEOUT_MASK, timeout << 16); - return 0; -} - -/*! - * Execute a software reset and set data bus width for eSDHC. - */ -u32 interface_reset(void) -{ - u32 reset_status = 0; - u32 u32Retries = 0; - u32 u32Temp = 0; - - debug("Entry: interface_reset"); - - /* Reset the entire host controller by writing - 1 to RSTA bit of SYSCTRL Register */ - REG_WRITE_OR(ESDHC_SOFTWARE_RESET, \ - esdhc_base_pointer + SDHCI_SYSTEM_CONTROL); - - /* Start a general purpose timer (3 millsec delay) */ - /* udelay(ESDHC_OPER_TIMEOUT); */ - - /* Wait for clearance of CIHB and CDIHB Bits */ - for (u32Retries = RETRIES_TIMES; u32Retries > 0; --u32Retries) { - if (readl(esdhc_base_pointer + SDHCI_SYSTEM_CONTROL) \ - & ESDHC_SOFTWARE_RESET) { - reset_status = 1; - } else { - reset_status = 0; - break; - } - } - - /* Set data bus width of ESDCH */ - esdhc_set_data_transfer_width(0x00000000); - /* Set Endianness of ESDHC */ - esdhc_set_endianness(0x00000020); - - /* set data timeout delay to max */ - u32Temp = (readl(esdhc_base_pointer + SDHCI_SYSTEM_CONTROL) & \ - 0xfff0ffff) | 0x000e0000; - writel(u32Temp, esdhc_base_pointer + SDHCI_SYSTEM_CONTROL); - return reset_status; -} + clrsetbits_be32(®s->sysctl, SYSCTL_TIMEOUT_MASK, timeout << 16); -/*! - * Clear interrupts at eSDHC level. - */ -void interface_clear_interrupt(void) -{ - /* Clear Interrupt status register */ - writel(ESDHC_CLEAR_INTERRUPT, esdhc_base_pointer + SDHCI_INT_STATUS); + return 0; } -/*! - * Enable Clock and set operating frequency. - */ -void interface_configure_clock(sdhc_freq_t frequency) -{ - u32 ident_freq = 0; - u32 oper_freq = 0; - - /* Clear SDCLKEN bit */ - REG_WRITE_OR((~ESDHC_SYSCTL_SDCLKEN_MASK), \ - esdhc_base_pointer + SDHCI_SYSTEM_CONTROL); - - /* Clear DTOCV, SDCLKFS, DVFS bits */ - REG_WRITE_OR((~ESDHC_SYSCTL_FREQ_MASK), \ - esdhc_base_pointer + SDHCI_SYSTEM_CONTROL); - ident_freq = ESDHC_SYSCTL_IDENT_FREQ_TO2; - oper_freq = ESDHC_SYSCTL_OPERT_FREQ_TO2; - - /* Disable the PEREN, HCKEN and IPGEN */ - REG_WRITE_OR((~ESDHC_SYSCTL_INPUT_CLOCK_MASK), \ - esdhc_base_pointer + SDHCI_SYSTEM_CONTROL); - - if (frequency == IDENTIFICATION_FREQ) { - /* Input frequecy to eSDHC is 36 MHZ */ - /* PLL3 is the source of input frequency*/ - /*Set DTOCV and SDCLKFS bit to get SD_CLK - of frequency below 400 KHZ (70.31 KHZ) */ - REG_WRITE_OR(ident_freq, \ - esdhc_base_pointer + SDHCI_SYSTEM_CONTROL); - } else if (frequency == OPERATING_FREQ) { - /*Set DTOCV and SDCLKFS bit to get SD_CLK - of frequency around 25 MHz.(18 MHz)*/ - REG_WRITE_OR(oper_freq, \ - esdhc_base_pointer + SDHCI_SYSTEM_CONTROL); - } - - /* Start a general purpose timer */ - /* Wait for clock to be stable */ - SDHC_DELAY_BY_100(96); - - /* Set SDCLKEN bit to enable clock */ - REG_WRITE_OR(ESDHC_SYSCTL_SDCLKEN_MASK, \ - esdhc_base_pointer + SDHCI_SYSTEM_CONTROL); - - /* Mask Data Timeout Error Status Enable Interrupt (DTOESEN) */ - REG_WRITE_AND((~ESDHC_IRQSTATEN_DTOESEN), \ - esdhc_base_pointer + SDHCI_INT_ENABLE); - - /* Set the Data Timeout Counter Value(DTOCV) */ - REG_WRITE_OR(ESDHC_SYSCTL_DTOCV_VAL, \ - esdhc_base_pointer + SDHCI_SYSTEM_CONTROL); - - /* Enable Data Timeout Error Status - Enable Interrupt (DTOESEN) */ - REG_WRITE_OR(ESDHC_IRQSTATEN_DTOESEN, \ - esdhc_base_pointer + SDHCI_INT_ENABLE); -} /* * Sends a command out on the bus. Takes the mmc pointer, @@ -309,18 +154,24 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) uint xfertyp; uint irqstat; volatile struct fsl_esdhc *regs = mmc->priv; + out_be32(®s->irqstat, -1); + sync(); + /* Wait for the bus to be idle */ while ((in_be32(®s->prsstat) & PRSSTAT_CICHB) || (in_be32(®s->prsstat) & PRSSTAT_CIDHB)); + while (in_be32(®s->prsstat) & PRSSTAT_DLA); + /* Wait at least 8 SD clock cycles before the next command */ /* * Note: This is way more than 8 cycles, but 1ms seems to * resolve timing issues with some cards */ udelay(1000); + /* Set up for a data transfer if we have one */ if (data) { int err; @@ -329,23 +180,30 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) if(err) return err; } + /* Figure out the transfer arguments */ xfertyp = esdhc_xfertyp(cmd, data); + /* Send the command */ out_be32(®s->cmdarg, cmd->cmdarg); out_be32(®s->xfertyp, xfertyp); + /* Wait for the command to complete */ while (!(in_be32(®s->irqstat) & IRQSTAT_CC)); irqstat = in_be32(®s->irqstat); out_be32(®s->irqstat, irqstat); + if (irqstat & CMD_ERR) return COMM_ERR; + if (irqstat & IRQSTAT_CTOE) return TIMEOUT; + /* Copy the response to the response buffer */ if (cmd->resp_type & MMC_RSP_136) { u32 cmdrsp3, cmdrsp2, cmdrsp1, cmdrsp0; + cmdrsp3 = in_be32(®s->cmdrsp3); cmdrsp2 = in_be32(®s->cmdrsp2); cmdrsp1 = in_be32(®s->cmdrsp1); @@ -356,12 +214,15 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) cmd->response[3] = (cmdrsp0 << 8); } else cmd->response[0] = in_be32(®s->cmdrsp0); + /* Wait until all of the blocks are transferred */ if (data) { do { irqstat = in_be32(®s->irqstat); + if (irqstat & DATA_ERR) return COMM_ERR; + if (irqstat & IRQSTAT_DTOE) return TIMEOUT; } while (!(irqstat & IRQSTAT_TC) && @@ -369,128 +230,10 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) } out_be32(®s->irqstat, -1); - return 0; -} - -/*! - * Set data transfer width for e-SDHC. - */ -static void esdhc_set_data_transfer_width(u32 data_transfer_width) -{ - /* Set DWT bit of protocol control register according to bus_width */ - REG_WRITE_AND((~ESDHC_BUS_WIDTH_MASK), \ - esdhc_base_pointer + SDHCI_HOST_CONTROL); - - REG_WRITE_OR((data_transfer_width), \ - esdhc_base_pointer + SDHCI_HOST_CONTROL); -} - -/*! - * Set endianness mode for e-SDHC. - */ -static void esdhc_set_endianness(u32 endian_mode) -{ - REG_WRITE_AND((~ESDHC_ENDIAN_MODE_MASK), \ - esdhc_base_pointer + SDHCI_HOST_CONTROL); - /* Set DWT bit of protocol control register according to bus_width */ - REG_WRITE_OR((endian_mode), \ - esdhc_base_pointer + SDHCI_HOST_CONTROL); -} - -/*! - * Poll the CIHB & CDIHB bits of the present - * state register and wait until it goes low. - */ -static u32 esdhc_poll_cihb_cdihb(data_present_select data_present) -{ - u32 init_status = 0; - u32 u32Retries = 0; - - /* Start a general purpose timer */ - for (u32Retries = RETRIES_TIMES; u32Retries > 0; u32Retries--) { - if (!(readl(esdhc_base_pointer + SDHCI_PRESENT_STATE) & \ - ESDHC_PRESENT_STATE_CIHB)) { - init_status = 0; - break; - } - SDHC_DELAY_BY_100(10); - } - - /* - * Wait for the data line to be free (poll the CDIHB bit of - * the present state register). - */ - if ((0 == init_status) && (data_present == DATA_PRESENT)) { - /* Start a general purpose timer */ - SDHC_DELAY_BY_100(32); - - if (readl(esdhc_base_pointer + SDHCI_PRESENT_STATE) & \ - ESDHC_PRESENT_STATE_CDIHB) { - init_status = 1; - } - } - - return init_status; -} - -/*! - * Wait until the command and data lines are free. - */ -u32 interface_wait_cmd_data_lines(data_present_select data_present) -{ - u32 cmd_status = 0; - - cmd_status = esdhc_poll_cihb_cdihb(data_present); - - return cmd_status; -} - -u32 interface_set_bus_width(u32 bus_width) -{ - u32 tmp; - - tmp = readl(esdhc_base_pointer + SDHCI_HOST_CONTROL); - tmp &= ~SDHCI_CTRL_8BITBUS; - tmp |= SDHCI_CTRL_4BITBUS; - - writel(tmp, esdhc_base_pointer + SDHCI_HOST_CONTROL); return 0; } -/*! - * Execute a command and wait for the response. - */ -u32 interface_send_cmd_wait_resp(esdhc_cmd_t *cmd) -{ - u32 cmd_status = 0; - - /* Clear Interrupt status register */ - writel(ESDHC_CLEAR_INTERRUPT, \ - esdhc_base_pointer + SDHCI_INT_STATUS); - - /* Enable Interrupt */ - REG_WRITE_OR(ESDHC_INTERRUPT_ENABLE, \ - esdhc_base_pointer + SDHCI_INT_ENABLE); - - cmd_status = interface_wait_cmd_data_lines(cmd->data_present); - - if (cmd_status == 1) - return 1; - - /* Configure Command */ - esdhc_cmd_config(cmd); - - /* Wait for interrupt CTOE or CC */ - SDHC_DELAY_BY_100(96); - - /* Mask all interrupts */ - writel(0, esdhc_base_pointer + SDHCI_SIGNAL_ENABLE); - - /* Check if an error occured */ - return esdhc_check_response(); -} - void set_sysctl(struct mmc *mmc, uint clock) { int sdhc_clk = gd->sdhc_clk; @@ -504,176 +247,39 @@ void set_sysctl(struct mmc *mmc, uint clock) break; } else pre_div = 2; + for (div = 1; div <= 16; div++) if ((sdhc_clk / (div * pre_div)) <= clock) break; + pre_div >>= 1; div -= 1; - clk = (pre_div << 8) | (div << 4); - clrsetbits_be32(®s->sysctl, SYSCTL_CLOCK_MASK, clk); - udelay(10000); - setbits_be32(®s->sysctl, SYSCTL_PEREN); -} -/*! - * Configure ESDHC registers for sending a command to MMC. - */ -static void esdhc_cmd_config(esdhc_cmd_t *cmd) -{ - u32 u32Temp = 0; - - /* Write Command Argument in Command Argument Register */ - writel(cmd->arg, esdhc_base_pointer + SDHCI_ARGUMENT); - - /* - *Configure e-SDHC Register value according to Command - */ - u32Temp = \ - (((cmd->data_transfer)<response_format)<data_present)<crc_check) << ESDHC_CRC_CHECK_SHIFT) | - ((cmd->cmdindex_check) << ESDHC_CMD_INDEX_CHECK_SHIFT) | - ((cmd->command) << ESDHC_CMD_INDEX_SHIFT) | - ((cmd->block_count_enable_check) << \ - ESDHC_BLOCK_COUNT_ENABLE_SHIFT) | - ((cmd->multi_single_block) << \ - ESDHC_MULTI_SINGLE_BLOCK_SELECT_SHIFT)); - - writel(u32Temp, esdhc_base_pointer + SDHCI_TRANSFER_MODE); -} - -/*! - * Wait a END_CMD_RESP interrupt by interrupt status register. - * e-SDHC sets this bit after receving command response. - */ -static u32 esdhc_check_response(void) -{ - u32 status = 1; - - /* Check whether the interrupt is an END_CMD_RESP - * or a response time out or a CRC error - */ - if ((readl(esdhc_base_pointer + SDHCI_INT_STATUS) & \ - ESDHC_STATUS_END_CMD_RESP_MSK) && - !(readl(esdhc_base_pointer + SDHCI_INT_STATUS) & \ - ESDHC_STATUS_TIME_OUT_RESP_MSK) && - !(readl(esdhc_base_pointer + SDHCI_INT_STATUS) & \ - ESDHC_STATUS_RESP_CRC_ERR_MSK) && - !(readl(esdhc_base_pointer + SDHCI_INT_STATUS) & \ - ESDHC_STATUS_RESP_CMD_INDEX_ERR_MSK)) - status = 0; - - return status; -} - -/*! - * This function will read response from e-SDHC - * register according to reponse format. - */ -void interface_read_response(esdhc_resp_t *cmd_resp) -{ - /* get response values from e-SDHC CMDRSP registers.*/ - cmd_resp->cmd_rsp0 = (u32)readl(esdhc_base_pointer + SDHCI_RESPONSE); - cmd_resp->cmd_rsp1 = (u32)readl(esdhc_base_pointer + \ - SDHCI_RESPONSE + 4); - cmd_resp->cmd_rsp2 = (u32)readl(esdhc_base_pointer + \ - SDHCI_RESPONSE + 8); - cmd_resp->cmd_rsp3 = (u32)readl(esdhc_base_pointer + \ - SDHCI_RESPONSE + 12); -} - -/*! - * This function will read response from e-SDHC register - * according to reponse format. - */ -u32 interface_data_read(u32 *dest_ptr, u32 blk_len) -{ - u32 i = 0; - u32 j = 0; - u32 status = 1; - u32 *tmp_ptr = dest_ptr; - - debug("Entry: interface_data_read()\n"); - - /* Enable Interrupt */ - REG_WRITE_OR(ESDHC_INTERRUPT_ENABLE, \ - esdhc_base_pointer + SDHCI_INT_ENABLE); - - for (i = 0; i < (blk_len) / (ESDHC_FIFO_SIZE * 4); ++i) { - /* Wait for BRR bit to be set */ - status = esdhc_wait_buf_rdy_intr(ESDHC_STATUS_BUF_READ_RDY_MSK, - ESDHC_READ_DATA_TIME_OUT); - - debug("esdhc_wait_buf_rdy_intr: %d\n", status); - - if (!status) { - for (j = 0; j < ESDHC_FIFO_SIZE; ++j) { - *tmp_ptr++ = \ - readl(esdhc_base_pointer + SDHCI_BUFFER); - } - /* Clear the BRR */ - esdhc_clear_buf_rdy_intr(ESDHC_STATUS_BUF_READ_RDY_MSK); - } else { - debug("esdhc_wait_buf_rdy_intr failed\n"); - break; - } - } - - esdhc_wait_op_done_intr(); - - status = esdhc_check_data(); + clk = (pre_div << 8) | (div << 4); - if (!status) - status = 0; + clrsetbits_be32(®s->sysctl, SYSCTL_CLOCK_MASK, clk); - debug("esdhc_check_data: %d\n", status); - debug("Exit: interface_data_read()\n"); + udelay(10000); - return status; + setbits_be32(®s->sysctl, SYSCTL_PEREN); } static void esdhc_set_ios(struct mmc *mmc) { struct fsl_esdhc *regs = mmc->priv; + /* Set the clock speed */ set_sysctl(mmc, mmc->clock); + /* Set the bus width */ clrbits_be32(®s->proctl, PROCTL_DTW_4 | PROCTL_DTW_8); + if (mmc->bus_width == 4) setbits_be32(®s->proctl, PROCTL_DTW_4); else if (mmc->bus_width == 8) setbits_be32(®s->proctl, PROCTL_DTW_8); } -/*! - * Wait a BUF_READ_READY interrupt by pooling STATUS register. - */ -static u32 esdhc_wait_buf_rdy_intr(u32 mask, u32 multi_single_block) -{ - u32 status = 0; - u32 u32Retries = 0; - - /* Wait interrupt (BUF_READ_RDY) - */ - - for (u32Retries = RETRIES_TIMES; u32Retries > 0; --u32Retries) { - if (!(readl(esdhc_base_pointer + SDHCI_INT_STATUS) & mask)) { - status = 1; - } else { - status = 0; - break; - } - SDHC_DELAY_BY_100(10); - } - - if (multi_single_block == MULTIPLE && \ - readl(esdhc_base_pointer + SDHCI_INT_STATUS) & mask) - REG_WRITE_OR(mask, (esdhc_base_pointer + SDHCI_INT_STATUS)); - - return status; -} - static int esdhc_init(struct mmc *mmc) { struct fsl_esdhc *regs = mmc->priv; @@ -681,90 +287,25 @@ static int esdhc_init(struct mmc *mmc) /* Enable cache snooping */ out_be32(®s->scr, 0x00000040); + out_be32(®s->sysctl, SYSCTL_HCKEN | SYSCTL_IPGEN); + /* Set the initial clock speed */ set_sysctl(mmc, 400000); + /* Disable the BRR and BWR bits in IRQSTAT */ clrbits_be32(®s->irqstaten, IRQSTATEN_BRR | IRQSTATEN_BWR); + /* Put the PROCTL reg back to the default */ out_be32(®s->proctl, PROCTL_INIT); + while (!(in_be32(®s->prsstat) & PRSSTAT_CINS) && --timeout) udelay(1000); + if (timeout <= 0) return NO_CARD_ERR; - return 0; -} -/*! - * Clear BUF_READ_READY/BUF_WRITE_READY interrupt - * by writing 1 to STATUS register. - */ -static void esdhc_clear_buf_rdy_intr(u32 mask) -{ - writel(mask, (esdhc_base_pointer + SDHCI_INT_STATUS)); -} - -/*! - * Wait for TC, DEBE, DCE or DTOE by polling Interrupt STATUS register. - */ -static void esdhc_wait_op_done_intr(void) -{ - while (!(readl(esdhc_base_pointer + SDHCI_INT_STATUS) & \ - ESDHC_STATUS_TRANSFER_COMPLETE_MSK)) - ; -} - -/*! - * If READ_OP_DONE occured check ESDHC_STATUS_TIME_OUT_READ - * and RD_CRC_ERR_CODE and - * to determine if an error occured - */ -static u32 esdhc_check_data(void) -{ - u32 status = 1; - - debug("Entry: esdhc_check_data()\n"); - - /* Check whether the interrupt is an OP_DONE - * or a data time out or a CRC error - */ - if ((readl(esdhc_base_pointer + SDHCI_INT_STATUS) & \ - ESDHC_STATUS_TRANSFER_COMPLETE_MSK) && - !(readl(esdhc_base_pointer + SDHCI_INT_STATUS) & \ - ESDHC_STATUS_TIME_OUT_READ_MASK) && - !(readl(esdhc_base_pointer + SDHCI_INT_STATUS) & \ - ESDHC_STATUS_READ_CRC_ERR_MSK)) { - writel(ESDHC_STATUS_TRANSFER_COMPLETE_MSK, \ - (esdhc_base_pointer + SDHCI_INT_STATUS)); - status = 0; - } else { - status = 1; - } - - debug("Exit: esdhc_check_data()\n"); - return status; -} -/*! - * Check for Data timeout error, data CRC error and data end bit error - * to determine if an error occured. - */ -static u32 esdhc_check_data_crc_status(void) -{ - u32 status = 1; - - /* Check whether the interrupt is DTOE/DCE/DEBE */ - if (!(readl(esdhc_base_pointer + SDHCI_INT_STATUS) & \ - ESDHC_STATUS_TIME_OUT_READ_MASK) && - !(readl(esdhc_base_pointer + SDHCI_INT_STATUS) & \ - ESDHC_STATUS_READ_CRC_ERR_MSK) && - !(readl(esdhc_base_pointer + SDHCI_INT_STATUS) & \ - ESDHC_STATUS_RW_DATA_END_BIT_ERR_MSK)) { - status = 0; - } else { - status = 1; - } - - return status; + return 0; } static int esdhc_initialize(bd_t *bis) @@ -772,75 +313,35 @@ static int esdhc_initialize(bd_t *bis) struct fsl_esdhc *regs = (struct fsl_esdhc *)CONFIG_SYS_FSL_ESDHC_ADDR; struct mmc *mmc; u32 caps; + mmc = malloc(sizeof(struct mmc)); + sprintf(mmc->name, "FSL_ESDHC"); mmc->priv = regs; mmc->send_cmd = esdhc_send_cmd; mmc->set_ios = esdhc_set_ios; mmc->init = esdhc_init; + caps = regs->hostcapblt; + if (caps & ESDHC_HOSTCAPBLT_VS18) mmc->voltages |= MMC_VDD_165_195; if (caps & ESDHC_HOSTCAPBLT_VS30) mmc->voltages |= MMC_VDD_29_30 | MMC_VDD_30_31; if (caps & ESDHC_HOSTCAPBLT_VS33) mmc->voltages |= MMC_VDD_32_33 | MMC_VDD_33_34; + mmc->host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT; + if (caps & ESDHC_HOSTCAPBLT_HSS) mmc->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS; + mmc->f_min = 400000; mmc->f_max = MIN(gd->sdhc_clk, 50000000); - mmc_register(mmc); - return 0; -} - -/*! - * Set Block length. - */ -void interface_config_block_info(u32 blk_len, u32 nob, u32 wml) -{ - /* Configre block Attributes register */ - writel(((nob << ESDHC_BLOCK_SHIFT) | blk_len), \ - (esdhc_base_pointer + SDHCI_BLOCK_SIZE)); - /* Set Read Water MArk Level register */ - writel(wml, esdhc_base_pointer + SDHCI_WML_LEV); -} -/*! - * This function will write data to device attached to interface. - */ -u32 interface_data_write(u32 *dest_ptr, u32 blk_len) -{ - u32 i = 0; - u32 j = 0; - u32 status = 1; - u32 *tmp_ptr = dest_ptr; - - debug("Entry: interface_data_write()\n"); - - /* Enable Interrupt */ - REG_WRITE_OR(ESDHC_INTERRUPT_ENABLE, \ - (esdhc_base_pointer + SDHCI_INT_ENABLE)); - - for (i = 0; i < (blk_len) / (ESDHC_FIFO_SIZE * 4); ++i) { - /* Wait for BWR bit to be set */ - esdhc_wait_buf_rdy_intr(ESDHC_STATUS_BUF_WRITE_RDY_MSK, \ - SINGLE); - for (j = 0; j < ESDHC_FIFO_SIZE; ++j) { - writel((*tmp_ptr), esdhc_base_pointer + SDHCI_BUFFER); - ++tmp_ptr; - } - esdhc_clear_buf_rdy_intr(ESDHC_STATUS_BUF_WRITE_RDY_MSK); - } - - /* Wait for transfer complete operation interrupt */ - esdhc_wait_op_done_intr(); - - /* Check for status errors */ - status = esdhc_check_data(); + mmc_register(mmc); - debug("Exit: interface_data_write()\n"); - return status; + return 0; } int fsl_esdhc_mmc_init(bd_t *bis) @@ -852,48 +353,15 @@ void fdt_fixup_esdhc(void *blob, bd_t *bd) { const char *compat = "fsl,esdhc"; const char *status = "okay"; + if (!hwconfig("esdhc")) { status = "disabled"; goto out; } + do_fixup_by_compat_u32(blob, compat, "clock-frequency", gd->sdhc_clk, 1); out: do_fixup_by_compat(blob, compat, "status", status, strlen(status) + 1, 1); } - -/*! - * Configure the CMD line PAD configuration for strong or weak pull-up. - */ -/* -void esdhc_set_cmd_pullup(esdhc_pullup_t pull_up) -{ - u32 interface_esdhc = 0; - u32 pad_val = 0; - - interface_esdhc = (readl(0x53ff080c)) & (0x000000C0) >> 6; - - if (pull_up == STRONG) { - pad_val = PAD_CTL_PUE_PUD | PAD_CTL_PKE_ENABLE | - PAD_CTL_HYS_SCHMITZ | PAD_CTL_DRV_HIGH | - PAD_CTL_22K_PU | PAD_CTL_SRE_FAST; - } else { - pad_val = PAD_CTL_PUE_PUD | PAD_CTL_PKE_ENABLE | - PAD_CTL_HYS_SCHMITZ | PAD_CTL_DRV_MAX | - PAD_CTL_100K_PU | PAD_CTL_SRE_FAST; - } - - switch (interface_esdhc) { - case ESDHC1: - mxc_iomux_set_pad(MX51_PIN_SD1_CMD, pad_val); - break; - case ESDHC2: - mxc_iomux_set_pad(MX51_PIN_SD2_CMD, pad_val); - break; - case ESDHC3: - default: - break; - } -} -*/ diff --git a/drivers/net/mxc_fec.c b/drivers/net/mxc_fec.c index 91d248b..dcfc263 100644 --- a/drivers/net/mxc_fec.c +++ b/drivers/net/mxc_fec.c @@ -622,10 +622,10 @@ int fec_init(struct eth_device *dev, bd_t *bd) if (info->phy_addr < 0 || info->phy_addr > 0x1F) info->phy_addr = mxc_fec_mii_discover_phy(dev); #endif - setFecDuplexSpeed(fecp, (unsigned char)bd, info->dup_spd); + setFecDuplexSpeed(fecp, (unsigned char)info->phy_addr, info->dup_spd); #else #ifndef CONFIG_DISCOVER_PHY - setFecDuplexSpeed(fecp, (unsigned char)bd, + setFecDuplexSpeed(fecp, (unsigned char)info->phy_addr, (FECDUPLEX << 16) | FECSPEED); #endif /* ifndef CONFIG_SYS_DISCOVER_PHY */ #endif /* CONFIG_CMD_MII || CONFIG_MII */ diff --git a/include/configs/imx51.h b/include/configs/imx51.h index 23347d1..e5ae114 100644 --- a/include/configs/imx51.h +++ b/include/configs/imx51.h @@ -28,7 +28,6 @@ /* High Level Configuration Options */ #define CONFIG_ARMV7 1 /* This is armv7 Cortex-A8 CPU core */ -#define CONFIG_SYS_APCS_GNU #define CONFIG_L2_OFF #define CONFIG_MXC 1 @@ -85,13 +84,6 @@ /* * MMC Configs * */ -#define CONFIG_FSL_MMC 1 - -#define CONFIG_MMC 1 -#define CONFIG_CMD_MMC -#define CONFIG_DOS_PARTITION 1 -#define CONFIG_CMD_FAT 1 -#define CONFIG_MMC_BASE 0x0 /* * Eth Configs @@ -107,11 +99,6 @@ #define CONFIG_FEC0_PHY_ADDR 0x1F #define CONFIG_FEC0_MIIBASE -1 -#define CONFIG_CMD_PING -#define CONFIG_CMD_DHCP -#define CONFIG_CMD_MII -#define CONFIG_CMD_NET - /* allow to overwrite serial and ethaddr */ #define CONFIG_ENV_OVERWRITE #define CONFIG_CONS_INDEX 1 @@ -126,9 +113,11 @@ #define CONFIG_CMD_PING #define CONFIG_CMD_DHCP +#define CONFIG_CMD_MII +#define CONFIG_CMD_NET + /* Enable below configure when supporting nand */ -/* #define CONFIG_CMD_NAND */ -/* #define CONFIG_CMD_ENV */ +#define CONFIG_CMD_ENV #undef CONFIG_CMD_IMLS @@ -144,25 +133,13 @@ "uboot_addr=0xa0000000\0" \ "uboot=u-boot.bin\0" \ "kernel=uImage\0" \ - "nfsroot=/opt/eldk/arm\0" \ "bootargs_base=setenv bootargs console=ttymxc0,115200\0"\ "bootargs_nfs=setenv bootargs ${bootargs} root=/dev/nfs "\ "ip=dhcp nfsroot=${serverip}:${nfsroot},v3,tcp\0"\ "bootcmd=run bootcmd_net\0" \ "bootcmd_net=run bootargs_base bootargs_nfs; " \ "tftpboot ${loadaddr} ${kernel}; bootm\0" \ - "prg_uboot=tftpboot ${loadaddr} ${uboot}; " \ - "protect off ${uboot_addr} 0xa003ffff; " \ - "erase ${uboot_addr} 0xa003ffff; " \ - "cp.b ${loadaddr} ${uboot_addr} ${filesize}; " \ - "setenv filesize; saveenv\0" - -/*Support LAN9217*/ -/* -#define CONFIG_DRIVER_SMC911X 1 -#define CONFIG_DRIVER_SMC911X_16_BIT 1 -#define CONFIG_DRIVER_SMC911X_BASE_VARIABLE mx51_io_base_addr -*/ + "load_uboot=tftpboot ${loadaddr} ${uboot}\0" \ /* * The MX51 3stack board seems to have a hardware "peculiarity" confirmed under @@ -247,6 +224,7 @@ #define CONFIG_ENV_OFFSET (768 * 1024) #elif defined(CONFIG_FSL_ENV_IN_SF) #define CONFIG_ENV_IS_IN_SPI_FLASH 1 + #define CONFIG_ENV_IS_EMBEDDED 1 #define CONFIG_ENV_SPI_CS 1 #define CONFIG_ENV_OFFSET (768 * 1024) #else -- cgit v1.1