From f4f7f7d70bc982d6689f09bf97e62caec223629f Mon Sep 17 00:00:00 2001 From: Michael Brandt Date: Fri, 19 Feb 2010 10:15:10 +0100 Subject: HREF V1 updates This patch is part of WP254081 which depends on WP252006. * Fixed I2C, use real timeouts instead of counter * Undefined CONFIG_BOOTTIME, since it as to be changed to new timer.c * Merged V1 patches from Bangalore The patches were merged manually, because of the differences of the U-Boot baseline (Bangalore U-Boot 1.3.1, Lund 2009.11). The original patches were created by Rabin Vincent . and were applied originally to Branches: blr_lsp, remotes/origin/blr_lsp Follows: qpppaaa_20100210_094651 0001-u8500-gpio-add-I2C0-altfun.patch 0002-u8500-use-correct-v1-macros.patch 0003-emmc-clean-up-paritioning.patch 0004-u8500-remove-incorrect-ram-settings.patch 0005-u8500-gpio-remove-unnecessary-ifdefs.patch 0006-u8500-add-ED-v1-detection-and-handle-eMMC-diff.patch 0008-u8500-mmc-don-t-disable-altfuns.patch 0009-u8500-gpio-remove-unused-defined.patch 0010-u8500-mmc-add-barrier-for-while-loop.patch 0011-u8500-mmc-handle-non-block-addressed-cards.patch 0012-u8500-mmc-remove-unused-gpio-settings-on-v1.patch 0013-u8500-emmc-build-fix.patch 0014-u8500-handle-v1-gpios-and-clocks.patch 0015-mmc-build-fix-for-block-addressing.patch 0016-u8500-add-clocks-and-hardware-files.patch 0017-u8500-enable-PRCUM-timers-reg-for-ED.patch 0018-u8500-handle-MTU-for-v1-ED.patch 0019-u8500-emmc-remove-unnecessary-GPIO-settings.patch 0020-u8500-remove-dead-code.patch 0021-u8500-add-working-MTU-timer.patch 0022-pl011-empty-rx-fifo-if-necessary.patch 0023-u8500-gpio-fix-cont-handling-in-altfunc.patch 0024-u8500-reduce-bootdelay-to-1-and-enable-zero-check.patch 0025-u8500-disable-forcing-of-verify-but-set-n-by-default.patch 0029-u8500-fix-some-gpio-settings.patch 0030-emmc-make-v1-paritioning-differences-explicit.patch Signed-off-by: Michael Brandt Change-Id: I1106702e393c34f630e71f071e06c3952b0d3a1a Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/182 Reviewed-by: Michael BRANDT Tested-by: Jonas ABERG Reviewed-by: Jonas ABERG --- board/st/u8500/Makefile | 2 +- board/st/u8500/clock.c | 56 +++++++++++++ board/st/u8500/common.h | 1 + board/st/u8500/emmc.c | 192 +++++++++++++++++++++------------------------ board/st/u8500/gpio.c | 18 ++--- board/st/u8500/gpio.h | 2 - board/st/u8500/init_mmc.c | 8 +- board/st/u8500/mmc.c | 27 ++++--- board/st/u8500/mmc.h | 1 + board/st/u8500/mmc_utils.c | 2 - board/st/u8500/u8500.c | 178 +++++++++++++++++++++++++++++++---------- board/st/u8500/u8500_i2c.c | 70 ++++++----------- 12 files changed, 340 insertions(+), 217 deletions(-) create mode 100755 board/st/u8500/clock.c mode change 100755 => 100644 board/st/u8500/common.h mode change 100755 => 100644 board/st/u8500/mmc.h (limited to 'board') diff --git a/board/st/u8500/Makefile b/board/st/u8500/Makefile index b5dfc7bdd..3ed1ab0e1 100644 --- a/board/st/u8500/Makefile +++ b/board/st/u8500/Makefile @@ -26,7 +26,7 @@ include $(TOPDIR)/config.mk CFLAGS += -D__RELEASE -D__STN_8500 LIB = $(obj)lib$(BOARD).a -COBJS := u8500.o flash.o gpio.o u8500_i2c.o mmc.o mmc_utils.o init_mmc.o emmc.o +COBJS := u8500.o flash.o gpio.o u8500_i2c.o mmc.o mmc_utils.o init_mmc.o emmc.o clock.o SOBJS := core2.o SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) diff --git a/board/st/u8500/clock.c b/board/st/u8500/clock.c new file mode 100755 index 000000000..41f1bb254 --- /dev/null +++ b/board/st/u8500/clock.c @@ -0,0 +1,56 @@ +/* + * (C) Copyright 2009 ST-Ericsson + * + * 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 +#include + +DECLARE_GLOBAL_DATA_PTR; + +struct clkrst { + unsigned int pcken; + unsigned int pckdis; + unsigned int kcken; + unsigned int kckdis; +}; + +static unsigned int clkrst_base[] = { + U8500_CLKRST1_BASE, + U8500_CLKRST2_BASE, + U8500_CLKRST3_BASE, + NULL, + U8500_CLKRST5_BASE, + U8500_CLKRST6_BASE, + U8500_CLKRST7_BASE, /* ED only */ +}; + +/* Turn on peripheral clock at PRCC level */ +void u8500_clock_enable(int periph, int cluster, int kern) +{ + struct clkrst *clkrst = (struct clkrst *) clkrst_base[periph - 1]; + + if (kern != -1) + writel(1 << kern, &clkrst->kcken); + + if (cluster != -1) + writel(1 << cluster, &clkrst->pcken); +} diff --git a/board/st/u8500/common.h b/board/st/u8500/common.h old mode 100755 new mode 100644 index b6185081a..24c283f69 --- a/board/st/u8500/common.h +++ b/board/st/u8500/common.h @@ -130,5 +130,6 @@ typedef u32 t_logical_address; /*function prototypes*/ void gpio_init(void); int emmc_init (u8); +extern int u8500_is_earlydrop(void); #endif /* _COMMON_H_ */ diff --git a/board/st/u8500/emmc.c b/board/st/u8500/emmc.c index eec9a1a8b..bfb33c803 100644 --- a/board/st/u8500/emmc.c +++ b/board/st/u8500/emmc.c @@ -39,11 +39,13 @@ int emmc_init(u8 card_num) t_mmc_error mmc_error; t_mmc_error response; gpio_error gpioerror; + t_logical_address mmcbase; int error; -#ifndef CONFIG_U8500_V1 + mmcbase = u8500_is_earlydrop() ? CFG_EMMC_BASE_ED : CFG_EMMC_BASE_V1; + /* Initialize the base address of eMMC */ - mmc_error = mmc_init(card_num, CFG_EMMC_BASE); + mmc_error = mmc_init(card_num, mmcbase); if (MMC_OK != mmc_error) { @@ -51,36 +53,37 @@ int emmc_init(u8 card_num) goto end; } - /* Initialize the gpio alternate function for eMMC */ - struct gpio_register *p_gpio_register = (void *) IO_ADDRESS(CFG_GPIO_6_BASE); - p_gpio_register -> gpio_dats |= 0x0000FFE0; - p_gpio_register -> gpio_pdis &= ~0x0000FFE0; - - //enable the alternate function of EMMC - gpioerror = gpio_altfuncenable(GPIO_ALT_EMMC, "EMMC"); - if(gpioerror != GPIO_OK) - { - printf("emmc_init() gpio_altfuncenable %d failed\n", gpioerror); - goto end; - } + /* + * FIXME The following code is not required on v1. Check if it is really + * needed on ED or can be dropped. + */ + if (u8500_is_earlydrop()) { +#ifndef CONFIG_U8500_V1 + /* Initialize the gpio alternate function for eMMC */ + struct gpio_register *p_gpio_register = (void *) IO_ADDRESS(CFG_GPIO_6_BASE); + p_gpio_register -> gpio_dats |= 0x0000FFE0; + p_gpio_register -> gpio_pdis &= ~0x0000FFE0; + + //enable the alternate function of EMMC + gpioerror = gpio_altfuncenable(GPIO_ALT_EMMC, "EMMC"); + if(gpioerror != GPIO_OK) + { + printf("emmc_init() gpio_altfuncenable %d failed\n", gpioerror); + goto end; + } #else -/* Initialize the base address of PoP eMMC */ - mmc_error = mmc_init(card_num, CFG_POP_EMMC_BASE); - - if (MMC_OK != mmc_error) - { - printf("emmc_init() %d \n", mmc_error); - goto end; - } - //enable the alternate function of PoP EMMC - gpioerror = gpio_altfuncenable(GPIO_ALT_POP_EMMC, "EMMC"); - if (gpioerror != GPIO_OK) { - printf("emmc_init() gpio_altfuncenable %d failed \n", - gpioerror); - goto end; - } + //enable the alternate function of PoP EMMC + // gpioerror = gpio_altfuncenable(GPIO_ALT_POP_EMMC, "EMMC"); + gpioerror = gpio_altfuncenable(GPIO_ALT_EMMC, "EMMC"); + if (gpioerror != GPIO_OK) { + printf("emmc_init() gpio_altfuncenable %d failed \n", + gpioerror); + goto end; + } #endif + } + //Power-on the controller response = mmc_poweron(card_num); if (response != MMC_OK) @@ -105,91 +108,71 @@ int emmc_init(u8 card_num) return 0; end: -#ifndef CONFIG_U8500_V1 - gpio_altfuncdisable(GPIO_ALT_EMMC, "EMMC"); -#else - gpio_altfuncdisable(GPIO_ALT_POP_EMMC, "EMMC"); -#endif mmc_poweroff(card_num); return 1; } +struct partition { + unsigned char boot_ind; /* 0x80 - active */ + unsigned char head; /* starting head */ + unsigned char sector; /* starting sector */ + unsigned char cyl; /* starting cylinder */ + unsigned char sys_ind; /* What partition type */ + unsigned char end_head; /* end head */ + unsigned char end_sector; /* end sector */ + unsigned char end_cyl; /* end cylinder */ + u32 start_sect; /* starting sector counting from 0 */ + u32 nr_sects; /* nr of sectors in partition */ +} __attribute__((packed)); + +#define PART(type, start, num) \ + { \ + .boot_ind = 0x00, \ + .head = 0x03, \ + .sector = 0xD0, \ + .cyl = 0xff, \ + .sys_ind = type, \ + .end_head = 0x03, \ + .end_sector = 0xd0, \ + .end_cyl = 0xff, \ + .start_sect = start, \ + .nr_sects = num, \ + } + +static struct partition partitions_ed[] = { + [0] = PART(0x83, 0x000A0000, 0x00004000), /* Kernel */ + [1] = PART(0x83, 0x000A4000, 0x00080000), /* Root file system */ + [2] = PART(0x83, 0x00124000, 0x0022c000), + [3] = PART(0x0c, 0x00350000, 0x00b9a000), +}; + +static struct partition partitions_v1[] = { + [0] = PART(0x83, 0x000A0000, 0x00004000), /* Kernel */ + [1] = PART(0x83, 0x000A4000, 0x00080000), /* Root file system */ + [2] = PART(0x83, 0x00124000, 0x00000800), /* Modem parameters */ + [3] = {0}, +}; + +#undef PART + int emmc_write_pib(void) { int i; t_mmc_error mmc_error; u32 block_offset = PIB_EMMC_ADDR; - u8 emmc_last_sector[512]; u8 card_num = 4; + u8 mbr[512]; - for (i = 0; i < 0x1BF; i++) { - emmc_last_sector[i] = 0; - } - emmc_last_sector[0x1BF] = 0x03; - emmc_last_sector[0x1C0] = 0xD0; - emmc_last_sector[0x1C1] = 0xFF; - emmc_last_sector[0x1C2] = 0x83; - emmc_last_sector[0x1C3] = 0x03; - emmc_last_sector[0x1C4] = 0xD0; - emmc_last_sector[0x1C5] = 0xFF; - emmc_last_sector[0x1C6] = 0x00; - emmc_last_sector[0x1C7] = 0x00; - emmc_last_sector[0x1C8] = 0x0A; - emmc_last_sector[0x1C9] = 0x00; - emmc_last_sector[0x1CA] = 0x00; - emmc_last_sector[0x1CB] = 0x40; - emmc_last_sector[0x1CC] = 0x00; - emmc_last_sector[0x1CD] = 0x00; - emmc_last_sector[0x1CE] = 0x00; - emmc_last_sector[0x1CF] = 0x03; - emmc_last_sector[0x1D0] = 0xD0; - emmc_last_sector[0x1D1] = 0xFF; - emmc_last_sector[0x1D2] = 0x83; - emmc_last_sector[0x1D3] = 0x03; - emmc_last_sector[0x1D4] = 0xD0; - emmc_last_sector[0x1D5] = 0xFF; - emmc_last_sector[0x1D6] = 0x00; - emmc_last_sector[0x1D7] = 0x40; - emmc_last_sector[0x1D8] = 0x0A; - emmc_last_sector[0x1D9] = 0x00; - emmc_last_sector[0x1DA] = 0x00; - emmc_last_sector[0x1DB] = 0x00; - emmc_last_sector[0x1DC] = 0x08; - emmc_last_sector[0x1DD] = 0x00; - emmc_last_sector[0x1DE] = 0x00; - emmc_last_sector[0x1DF] = 0x03; - emmc_last_sector[0x1E0] = 0xD0; - emmc_last_sector[0x1E1] = 0xFF; - emmc_last_sector[0x1E2] = 0x83; - emmc_last_sector[0x1E3] = 0x03; - emmc_last_sector[0x1E4] = 0xD0; - emmc_last_sector[0x1E5] = 0xFF; - emmc_last_sector[0x1E6] = 0x00; - emmc_last_sector[0x1E7] = 0x40; - emmc_last_sector[0x1E8] = 0x12; - emmc_last_sector[0x1E9] = 0x00; - emmc_last_sector[0x1EA] = 0x00; - emmc_last_sector[0x1EB] = 0xC0; - emmc_last_sector[0x1EC] = 0x22; - emmc_last_sector[0x1ED] = 0x00; - emmc_last_sector[0x1EE] = 0x00; - emmc_last_sector[0x1EF] = 0x03; - emmc_last_sector[0x1F0] = 0xD0; - emmc_last_sector[0x1F1] = 0xFF; - emmc_last_sector[0x1F2] = 0x0C; - emmc_last_sector[0x1F3] = 0x03; - emmc_last_sector[0x1F4] = 0xD0; - emmc_last_sector[0x1F5] = 0xFF; - emmc_last_sector[0x1F6] = 0x00; - emmc_last_sector[0x1F7] = 0x00; - emmc_last_sector[0x1F8] = 0x35; - emmc_last_sector[0x1F9] = 0x00; - emmc_last_sector[0x1FA] = 0x00; - emmc_last_sector[0x1FB] = 0xA0; - emmc_last_sector[0x1FC] = 0xB9; - emmc_last_sector[0x1FD] = 0x00; - emmc_last_sector[0x1FE] = 0x55; - emmc_last_sector[0x1FF] = 0xAA; + memset(mbr, 0, 0x1be); + + if (u8500_is_earlydrop()) + memcpy(mbr + 0x1be, partitions_ed, sizeof(partitions_ed)); + else + memcpy(mbr + 0x1be, partitions_v1, sizeof(partitions_v1)); + + /* magic */ + mbr[0x1fe] = 0x55; + mbr[0x1ff] = 0xAA; /* HACK required for HREF board as erase block size = 512KB */ /* @@ -199,8 +182,9 @@ int emmc_write_pib(void) return 1; } */ + mmc_error = - mmc_writeblocks(card_num, block_offset, (u32 *) emmc_last_sector, + mmc_writeblocks(card_num, block_offset, (u32 *) mbr, 512, 1); if (mmc_error != MMC_OK) { printf(" eMMC PIB write failed \n"); diff --git a/board/st/u8500/gpio.c b/board/st/u8500/gpio.c index 52c585be6..8623150a3 100644 --- a/board/st/u8500/gpio.c +++ b/board/st/u8500/gpio.c @@ -67,10 +67,8 @@ struct gpio_altfun_data altfun_table[] = { GPIO_ALTF_A,}, {.altfun = GPIO_ALT_EMMC,.start = 197,.end = 207,.cont = 0,.type = GPIO_ALTF_A,}, -#ifdef CONFIG_STM_8500_V1 {.altfun = GPIO_ALT_POP_EMMC,.start = 128,.end = 138,.cont = 0,.type = GPIO_ALTF_A,}, -#endif }; /* @@ -164,13 +162,12 @@ gpio_error gpio_altfunction(gpio_alt_function alt_func, gpio_error error = -1; for (i = 0; i < sz_altfun_tbl; i++) { - if (altfun_table[i].altfun == alt_func) - break; - } - start = altfun_table[i].start; - end = altfun_table[i].end; - for (j = start; j <= end; j++) { - { + if (altfun_table[i].altfun != alt_func) + continue; + + start = altfun_table[i].start; + end = altfun_table[i].end; + for (j = start; j <= end; j++) { if (which_altfunc == GPIO_ALTF_FIND) { altfun_pinconfig.mode = altfun_table[i].type; @@ -195,6 +192,9 @@ gpio_error gpio_altfunction(gpio_alt_function alt_func, error = GPIO_INVALID_PARAMETER; return (error); } + + if (!altfun_table[i].cont) + break; } return (error); } diff --git a/board/st/u8500/gpio.h b/board/st/u8500/gpio.h index 5277fa4b4..b0850faa2 100644 --- a/board/st/u8500/gpio.h +++ b/board/st/u8500/gpio.h @@ -424,9 +424,7 @@ typedef enum { GPIO_ALT_CAM, GPIO_ALT_CCP1, GPIO_ALT_EMMC, -#ifdef CONFIG_NOMADIK_8500_V1 GPIO_ALT_POP_EMMC, -#endif GPIO_ALT_FUNMAX /* Add new alt func before this */ } gpio_alt_function; diff --git a/board/st/u8500/init_mmc.c b/board/st/u8500/init_mmc.c index b9c22e0bc..f89e30500 100644 --- a/board/st/u8500/init_mmc.c +++ b/board/st/u8500/init_mmc.c @@ -180,9 +180,11 @@ static int init_mmc(void) return 1 ; } - gpio_base_address = (void *) IO_ADDRESS(CFG_GPIO_0_BASE); - gpio_base_address -> gpio_dats |= 0xFFC0000; - gpio_base_address -> gpio_pdis &= ~0xFFC0000; + if (u8500_is_earlydrop()) { + gpio_base_address = (void *) IO_ADDRESS(CFG_GPIO_0_BASE); + gpio_base_address -> gpio_dats |= 0xFFC0000; + gpio_base_address -> gpio_pdis &= ~0xFFC0000; + } if (mmc_hw_init() != 0) { printf("mmc_init: hw init failed\n"); diff --git a/board/st/u8500/mmc.c b/board/st/u8500/mmc.c index 48c2b86dd..97508af8d 100644 --- a/board/st/u8500/mmc.c +++ b/board/st/u8500/mmc.c @@ -603,7 +603,10 @@ t_mmc_error mmc_poweron(u8 card_num) t_mmc[card_num]->mmc_Argument = 0; t_mmc[card_num]->mmc_Command = APP_CMD | RespExpected | CmdPathEnable; - for (delay = 0; delay < (one_msec * 27); delay++) ; +#define barrier() asm volatile("" ::: "memory") + for (delay = 0; delay < (one_msec * 27); delay++) + barrier(); + error = mmc_cmdresp145error(APP_CMD, card_num); /* IF ERROR IS COMMAND TIMEOUT IT IS MMC CARD */ @@ -844,6 +847,12 @@ t_mmc_error mmc_initializeCards(u8 card_num) t_mmc[card_num]->mmc_Power = 0x3; t_mmc[card_num]->mmc_Clock = 0x7500; + /* TODO remove this and use EXT_CSD to determine it */ + if (mmc_card == 1 && t_mmc[card_num] == 0x80005000) + card_array[card_num].blockaddressed = 0; + else + card_array[card_num].blockaddressed = 1; + return error; } @@ -1310,7 +1319,7 @@ t_mmc_error mmc_readblocks(u8 card_num, u32 addr, u32 * readbuff, u16 blocksize, dest_buffer = readbuff; - t_mmc[card_num]->mmc_Argument = addr >> 9; + t_mmc[card_num]->mmc_Argument = card_array[card_num].blockaddressed ? (addr >> 9) : addr; t_mmc[card_num]->mmc_Command = READ_MULT_BLOCK | RespExpected | CmdPathEnable; error = mmc_cmdresp145error(READ_MULT_BLOCK, card_num); @@ -1335,7 +1344,7 @@ t_mmc_error mmc_readblocks(u8 card_num, u32 addr, u32 * readbuff, u16 blocksize, dest_buffer = readbuff; - t_mmc[card_num]->mmc_Argument = addr >> 9; + t_mmc[card_num]->mmc_Argument = card_array[card_num].blockaddressed ? (addr >> 9) : addr; t_mmc[card_num]->mmc_Command = READ_SINGLE_BLOCK | RespExpected | CmdPathEnable; error = mmc_cmdresp145error(READ_SINGLE_BLOCK, card_num); @@ -1426,7 +1435,7 @@ t_mmc_error mmc_readblocks(u8 card_num, u32 addr, u32 * readbuff, u16 blocksize, dest_buffer = readbuff; - t_mmc[card_num]->mmc_Argument = addr >> 9; + t_mmc[card_num]->mmc_Argument = card_array[card_num].blockaddressed ? (addr >> 9) : addr; t_mmc[card_num]->mmc_Command = READ_MULT_BLOCK | RespExpected | CmdPathEnable; error = mmc_cmdresp145error(READ_MULT_BLOCK, card_num); if (error != MMC_OK) @@ -1593,7 +1602,7 @@ t_mmc_error mmc_writeblocks(u8 card_num, u32 addr, u32 * writebuff, source_buffer = writebuff; - t_mmc[card_num]->mmc_Argument = addr >> 9; + t_mmc[card_num]->mmc_Argument = card_array[card_num].blockaddressed ? (addr >> 9) : addr; t_mmc[card_num]->mmc_Command = WRITE_MULT_BLOCK | RespExpected | CmdPathEnable; error = mmc_cmdresp145error(WRITE_MULT_BLOCK, card_num); @@ -1648,7 +1657,7 @@ t_mmc_error mmc_writeblocks(u8 card_num, u32 addr, u32 * writebuff, /*Till here*/ /*SEND CMD24 WRITE_SINGLE_BLOCK */ - t_mmc[card_num]->mmc_Argument = addr >> 9; + t_mmc[card_num]->mmc_Argument = card_array[card_num].blockaddressed ? (addr >> 9) : addr; t_mmc[card_num]->mmc_Command = WRITE_SINGLE_BLOCK | RespExpected | CmdPathEnable; error = mmc_cmdresp145error(WRITE_SINGLE_BLOCK, card_num); if (error != MMC_OK) @@ -1758,7 +1767,7 @@ t_mmc_error mmc_writeblocks(u8 card_num, u32 addr, u32 * writebuff, source_buffer = writebuff; /*SEND CMD25 WRITE_MULT_BLOCK with argument data address*/ - t_mmc[card_num]->mmc_Argument = addr >> 9; + t_mmc[card_num]->mmc_Argument = card_array[card_num].blockaddressed ? (addr >> 9) : addr; t_mmc[card_num]->mmc_Command = WRITE_MULT_BLOCK | RespExpected | CmdPathEnable; error = mmc_cmdresp145error(WRITE_MULT_BLOCK, card_num); @@ -1917,7 +1926,7 @@ t_mmc_error mmc_erase(u8 card_num, u32 StartAddr, u32 EndAddr) return (error); } - t_mmc[card_num]->mmc_Argument = StartAddr >> 9; + t_mmc[card_num]->mmc_Argument = card_array[card_num].blockaddressed ? (StartAddr >> 9) : StartAddr; t_mmc[card_num]->mmc_Command = ERASE_GRP_START | RespExpected | CmdPathEnable; error = mmc_cmdresp145error(ERASE_GRP_START, card_num); if (error != MMC_OK) @@ -1948,7 +1957,7 @@ t_mmc_error mmc_erase(u8 card_num, u32 StartAddr, u32 EndAddr) return error; } - t_mmc[card_num]->mmc_Argument = EndAddr >> 9; + t_mmc[card_num]->mmc_Argument = card_array[card_num].blockaddressed ? (EndAddr >> 9) : EndAddr; t_mmc[card_num]->mmc_Command = ERASE_GRP_END | RespExpected | CmdPathEnable; error = mmc_cmdresp145error(ERASE_GRP_END, card_num); if (error != MMC_OK) diff --git a/board/st/u8500/mmc.h b/board/st/u8500/mmc.h old mode 100755 new mode 100644 index c114ffab8..895a4d180 --- a/board/st/u8500/mmc.h +++ b/board/st/u8500/mmc.h @@ -196,6 +196,7 @@ typedef struct { t_mmc_card_type card_type; u8 padding; u8 sdio_cccr[4]; /* I/O ready, CCCR/SDIO revision, SD Specification revision, and Card Capability registers */ + int blockaddressed; } t_mmc_card_info; typedef struct { diff --git a/board/st/u8500/mmc_utils.c b/board/st/u8500/mmc_utils.c index 6bfcb91da..8e868bbb5 100644 --- a/board/st/u8500/mmc_utils.c +++ b/board/st/u8500/mmc_utils.c @@ -796,8 +796,6 @@ t_mmc_error mmc_read_file (char *filename, u32 address, u32 * FileSize) } end: - gpio_altfuncdisable(GPIO_ALT_SD_CARD0, "MMC"); - response2 = mmc_disable (); return response; } diff --git a/board/st/u8500/u8500.c b/board/st/u8500/u8500.c index 83e899434..d106f0195 100644 --- a/board/st/u8500/u8500.c +++ b/board/st/u8500/u8500.c @@ -1,25 +1,9 @@ /* -* (C) Copyright 2009 -* ST-Ericsson, -* -* 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 -*/ + * (C) Copyright 2009 + * ST-Ericsson, + * + * License terms: GNU General Public License (GPL), version 2. + */ #include #include @@ -27,9 +11,12 @@ #include #include #include +#include +#include +#include "gpio.h" #include "common.h" -#define NOMADIK_PER4_BASE (0x80150000) +#define NOMADIK_PER4_BASE (0x80150000) #define NOMADIK_BACKUPRAM0_BASE (NOMADIK_PER4_BASE + 0x00000) #define NOMADIK_BACKUPRAM1_BASE (NOMADIK_PER4_BASE + 0x01000) @@ -151,6 +138,15 @@ void show_boot_progress(int progress) } #endif +int u8500_is_earlydrop(void) +{ + unsigned int *address = (void *)U8500_BOOTROM_BASE + + U8500_BOOTROM_ASIC_ID_OFFSET; + + /* 0x01 for ED, 0xA0 for v1 */ + return (readl(address) & 0xff) == 0x01; +} + /* * Miscellaneous platform dependent initialisations */ @@ -159,8 +155,11 @@ int board_init(void) { gd->bd->bi_arch_number = 0x1A4; gd->bd->bi_boot_params = 0x00000100; - /* MTU timer clock always enabled (not clocked) */ - writel(0x20000, PRCM_TCR); + + if (u8500_is_earlydrop()) { + /* MTU timer clock always enabled (not clocked) */ + writel(0x20000, PRCM_TCR); + } icache_enable(); gpio_init(); @@ -168,22 +167,10 @@ int board_init(void) return 0; } -#ifdef CONFIG_MISC_INIT_R -int misc_init_r(void) -{ - setenv("verify", "n"); - return (0); -} -#endif - int dram_init(void) { gd->bd->bi_dram[0].start = PHYS_SDRAM_1; gd->bd->bi_dram[0].size = PHYS_SDRAM_SIZE_1; -#ifdef CONFIG_U8500_V1 - gd->bd->bi_dram[1].start = PHYS_SDRAM_2; - gd->bd->bi_dram[1].size = PHYS_SDRAM_SIZE_2; -#endif wake_up_other_cores(); return 0; } @@ -212,7 +199,7 @@ unsigned int addr_vall_arr[] = { 0xA03FF008, 0x00000001, // USB 0xA03FE00C, 0x00000000, // USB 0xA03FE020, 0x00000FFF, // USB -0xA03FE024, 0x00000000 // USB +0xA03FE024, 0x00000000 // USB }; #ifdef BOARD_LATE_INIT @@ -270,15 +257,120 @@ int board_late_init(void) static void init_regs(void) { - int i; - for(i = 0; i < ARRAY_SIZE(addr_vall_arr)/2; i++) - { + /* FIXME Remove magic register array settings for ED also */ + if (u8500_is_earlydrop()) { + int i; - *((volatile unsigned int *)(addr_vall_arr[2 * i])) - = addr_vall_arr[(2 * i) + 1]; - } + for(i = 0; i < ARRAY_SIZE(addr_vall_arr)/2; i++) + { + + *((volatile unsigned int *)(addr_vall_arr[2 * i])) + = addr_vall_arr[(2 * i) + 1]; + } + } else { + struct prcmu *prcmu = (struct prcmu *) U8500_PRCMU_BASE; + u32 tmp; + + /* Enable timers */ + writel(1 << 17, &prcmu->tcr); + + u8500_prcmu_enable(&prcmu->per1clk_mgt); + u8500_prcmu_enable(&prcmu->per2clk_mgt); + u8500_prcmu_enable(&prcmu->per3clk_mgt); + u8500_prcmu_enable(&prcmu->per5clk_mgt); + u8500_prcmu_enable(&prcmu->per6clk_mgt); + u8500_prcmu_enable(&prcmu->per7clk_mgt); + + u8500_prcmu_enable(&prcmu->uartclk_mgt); + u8500_prcmu_enable(&prcmu->i2cclk_mgt); + + if (!u8500_is_earlydrop()) { + /* Switch SDMMCCLK to 52Mhz instead of 104Mhz */ + tmp = readl(&prcmu->sdmmcclk_mgt); + tmp = (tmp & ~0x1f) | 16; + writel(tmp, &prcmu->sdmmcclk_mgt); + } + + u8500_prcmu_enable(&prcmu->sdmmcclk_mgt); + + u8500_clock_enable(1, 9, -1); /* GPIO0 */ + + if (u8500_is_earlydrop()) + u8500_clock_enable(2, 12, -1); /* GPIO1 */ + else + u8500_clock_enable(2, 11, -1); /* GPIO1 */ + + u8500_clock_enable(3, 8, -1); /* GPIO2 */ + u8500_clock_enable(5, 1, -1); /* GPIO3 */ + + u8500_clock_enable(3, 6, 6); /* UART2 */ + + gpio_altfuncenable(GPIO_ALT_I2C_0, "I2C0"); + u8500_clock_enable(3, 3, 3); /* I2C0 */ + + { + /* UART2: 29, 30 */ + struct gpio_register *p_gpio_register = (void *) IO_ADDRESS(CFG_GPIO_0_BASE); + p_gpio_register -> gpio_dats |= 0x60000000; + p_gpio_register -> gpio_pdis &= ~0x60000000; + } + gpio_altfuncenable(GPIO_ALT_UART_2, "UART2"); + + { + /* 197 - 207 */ + struct gpio_register *p_gpio_register = (void *) IO_ADDRESS(CFG_GPIO_6_BASE); + p_gpio_register -> gpio_dats |= 0x0000ffe0; + p_gpio_register -> gpio_pdis &= ~0x0000ffe0; + } + gpio_altfuncenable(GPIO_ALT_EMMC, "EMMC"); + + { + /* 18 - 28 */ + struct gpio_register *p_gpio_register = (void *) IO_ADDRESS(CFG_GPIO_0_BASE); + // p_gpio_register -> gpio_dats |= 0x0ffc0000; + p_gpio_register -> gpio_pdis &= ~0x0ffc0000; + } + gpio_altfuncenable(GPIO_ALT_SD_CARD0, "SDCARD"); + + u8500_clock_enable(1, 5, 5); /* SDI0 */ + u8500_clock_enable(2, 4, 2); /* SDI4 */ + + if (u8500_is_earlydrop()) { + u8500_clock_enable(7, 2, -1); /* MTU0 */ + } else { + u8500_clock_enable(6, 7, -1); /* MTU0 */ + u8500_clock_enable(3, 4, 4); /* SDI2 */ + + { + /* 128 - 138 */ + struct gpio_register *p_gpio_register = (void *) IO_ADDRESS(CFG_GPIO_4_BASE); + p_gpio_register -> gpio_dats |= 0x000007ff; + p_gpio_register -> gpio_pdis &= ~0x000007ff; + } + + gpio_altfuncenable(GPIO_ALT_POP_EMMC, "EMMC"); + } + + /* + * Enabling clocks for all devices which are AMBA devices in the + * kernel. Otherwise they will not get probe()'d because the + * peripheral ID register will not be powered. + */ + + /* XXX: some of these differ between ED/V1 */ + + u8500_clock_enable(1, 1, 1); /* UART1 */ + u8500_clock_enable(1, 0, 0); /* UART0 */ + + u8500_clock_enable(3, 2, 2); /* SSP1 */ + u8500_clock_enable(3, 1, 1); /* SSP0 */ + + u8500_clock_enable(2, 8, -1); /* SPI0 */ + u8500_clock_enable(2, 5, 3); /* MSP2 */ + } } + /* * get_pll_freq_khz - return PLL frequency in kHz */ diff --git a/board/st/u8500/u8500_i2c.c b/board/st/u8500/u8500_i2c.c index fe1b7ae56..e41f7ef51 100644 --- a/board/st/u8500/u8500_i2c.c +++ b/board/st/u8500/u8500_i2c.c @@ -1,5 +1,5 @@ /* - * Copyright (C) ST-Ericsson AB 2009 + * Copyright (C) ST-Ericsson AB 2010 * * Basic U-Boot I2C interface for STn8500/DB8500 * Author: Michael Brandt @@ -8,11 +8,7 @@ */ /* - * Only 7-bit I2C device address are supported. - * - * TODO: - * - eliminate "timeout" loop counters and replace with real - * timeouts based on timer ticks. + * Only 7-bit I2C device addresses are supported. */ #include @@ -33,8 +29,8 @@ typedef enum { I2C_OVFL } i2c_error_t; -#define I2C_ENDAD_COUNTER 500000 /* I2C bus "timeout" */ -#define I2C_FIFO_FLUSH_COUNTER 50000 /* flush "timeout" */ +#define I2C_ENDAD_COUNTER (CONFIG_SYS_HZ/100) /* I2C bus timeout */ +#define I2C_FIFO_FLUSH_COUNTER 500000 /* flush "timeout" */ #define I2C_SCL_FREQ 100000 /* I2C bus clock frequency.*/ #define I2C_INPUT_FREQ 48000000 /* Input clock frequency.*/ #define TX_FIFO_THRESHOLD 0x4 @@ -162,37 +158,38 @@ void i2c_init(int speed, int slaveaddr) * loop_till_bit_clear - polls on a bit till it clears * ioreg: register where you want to check status * mask: bit mask for the bit you wish to check - * end_counter: upper limit to the counter when you stop checking + * timeout: timeout in ticks/s */ -static int loop_till_bit_clear(void *io_reg, u32 mask, int end_counter) +static int loop_till_bit_clear(void *io_reg, u32 mask, unsigned long timeout) { - int loop = 0; - while (1) { + unsigned long timebase = get_timer(0); + + do { if ((readl(io_reg) & mask) == 0x0UL) return 0; - loop++; - if (loop == end_counter) - return 1; - } + } while (get_timer(timebase) < timeout); + + debug("loop_till_bit_clear timed out\n"); + return -1; } /* * loop_till_bit_set - polls on a bit till it is set. * ioreg: register where you want to check status * mask: bit mask for the bit you wish to check - * end_counter: upper limit to the counter when you stop checking - * + * timeout: timeout in ticks/s */ -static int loop_till_bit_set(void * io_reg, u32 mask, int end_counter) +static int loop_till_bit_set(void * io_reg, u32 mask, unsigned long timeout) { - int loop = 0; - while (1) { + unsigned long timebase = get_timer(0); + + do { if ((readl(io_reg) & mask) != 0x0UL) return 0; - loop++; - if (loop == end_counter) - return 1; - } + } while (get_timer(timebase) < timeout); + + debug("loop_till_bit_set timed out\n"); + return -1; } /* @@ -260,7 +257,7 @@ static void i2c_abort(t_i2c_registers *p_i2c_registers) #ifdef DEBUG print_abort_reason(p_i2c_registers); #endif - /* flush fifo */ + /* flush RX and TX fifos */ flush_fifo(p_i2c_registers); /* Acknowledge the Master Transaction Done */ @@ -269,14 +266,7 @@ static void i2c_abort(t_i2c_registers *p_i2c_registers) /* Acknowledge the Master Transaction Done Without Stop */ I2C_SET_BIT(p_i2c_registers->icr, I2C_INT_MTDWS); - /* disable controller */ - I2C_CLR_BIT(p_i2c_registers->cr, I2C_CR_PE); - - /* delay 10 milliseconds */ - udelay(10*1000); - - /* enable controller */ - I2C_SET_BIT(p_i2c_registers->cr, I2C_CR_PE); + i2c_init(i2c_bus_speed[i2c_bus_num], CONFIG_SYS_I2C_SLAVE); } /* @@ -587,7 +577,6 @@ int i2c_set_bus_num(unsigned int bus) int i2c_set_bus_speed(unsigned int speed) { - t_i2c_registers *p_i2c_registers; if (speed > I2C_MAX_STANDARD_SCL) { debug("i2c_set_bus_speed: only up to %d supported\n", @@ -595,15 +584,8 @@ int i2c_set_bus_speed(unsigned int speed) return -1; } - p_i2c_registers = i2c_dev[i2c_bus_num]; - - /* Disable the controller */ - I2C_CLR_BIT(p_i2c_registers->cr, I2C_CR_PE); - - i2c_bus_speed[i2c_bus_num] = __i2c_set_bus_speed(speed); - - /* Enable the controller */ - I2C_SET_BIT(p_i2c_registers->cr, I2C_CR_PE); + /* sets as side effect i2c_bus_speed[i2c_bus_num] */ + i2c_init(speed, CONFIG_SYS_I2C_SLAVE); return 0; } -- cgit v1.2.3