diff options
author | Marcel Ziswiler <marcel.ziswiler@toradex.com> | 2013-08-12 10:37:32 +0200 |
---|---|---|
committer | Marcel Ziswiler <marcel.ziswiler@toradex.com> | 2013-08-12 10:37:32 +0200 |
commit | d63f3c73a767b82ba1e28c30a46a1e88616ed66e (patch) | |
tree | 572ab70727626189353b577e0840d60b7fa61c9c | |
parent | 1cf83224ac11e2ea1a0b3546b27ecd9a59fac247 (diff) |
apalis/colibri_t30: implement emmc pt offset auto detection
In preparation for the new Apalis T30 SKUs implement eMMC PT offset
auto detection.
The PT offset has been calculated from the .cfg eMMC partition
configuration file using virtual linearised addressing across all eMMC
regions as expected by nvflash.
Due to the lack of a region control mechanism in nvflash/.cfg flashing
utility in order to obtain the actual PT offset from the start of the
user region the size of the boot regions must be subtracted.
An eMMC device is specified to have 0 or 2 boot regions and they must
have the same size ranging from 0 to 2 MiB. The boot region size can be
queried from the device through the BOOT_SIZE_MULT field of the
response to the EXT_CSD command sequence.
Tested on initial samples of Apalis T30 1GB V1.0A,
Apalis T30 2GB V1.0B, Apalis T30 2GB V1.0C and Colibri T30 V1.1C.
-rw-r--r-- | board/toradex/common/tegra2_partitions.c | 29 | ||||
-rw-r--r-- | drivers/mmc/tegra_mmc.c | 39 |
2 files changed, 64 insertions, 4 deletions
diff --git a/board/toradex/common/tegra2_partitions.c b/board/toradex/common/tegra2_partitions.c index 7589760fbdc..77308d165d8 100644 --- a/board/toradex/common/tegra2_partitions.c +++ b/board/toradex/common/tegra2_partitions.c @@ -43,6 +43,14 @@ static int block_size; #if (defined(CONFIG_ENV_IS_IN_MMC) && defined(CONFIG_COLIBRI_T20)) || \ defined(CONFIG_COLIBRI_T30) || defined(CONFIG_APALIS_T30) +static u32 __def_get_boot_size_mult(struct mmc *mmc) +{ + /* return default boot size. */ + return 0; +} +u32 get_boot_size_mult(struct mmc *mmc) + __attribute__((weak, alias("__def_get_boot_size_mult"))); + /** * nvtegra_mmc_read - read data from mmc (unaligned) * @param startAddress: data offset in bytes @@ -80,8 +88,7 @@ ulong nvtegra_mmc_read(ulong startAddress, ulong dataCount, void *dst) free(buffer); return 0; } - memcpy(dst, buffer + (startAddress - startBlock * EMMC_BLOCK_SIZE), - dataCount); + memcpy(dst, buffer, dataCount); free(buffer); return dataCount; @@ -172,8 +179,8 @@ int nvtegra_read_partition_table(nvtegra_parttable_t * pt, int boot_media) #endif /* Search PT logical offset - Note: 0x326 for T30 Fastboot, 0xB48 for Eboot resp. Android - Fastboot and 0xEEC for Vibrante Fastboot */ + Note: 0x326 for T30 Fastboot, 0xb48 for Eboot resp. Android + Fastboot and 0xeec for Vibrante Fastboot */ for (i = 0; i < 0x800; i++) { if (readw(bct_start) == 0x40) { /* Either previous or 3rd next word */ @@ -227,6 +234,20 @@ int nvtegra_read_partition_table(nvtegra_parttable_t * pt, int boot_media) } else #endif /* CONFIG_COLIBRI_T20 */ { +#if (defined(CONFIG_ENV_IS_IN_MMC) && defined(CONFIG_COLIBRI_T20)) || \ + defined(CONFIG_COLIBRI_T30) || defined(CONFIG_APALIS_T30) + /* The PT offset has been calculated from the .cfg eMMC + partition configuration file using virtual linearised + addressing across all eMMC regions as expected by nvflash. + Due to the lack of a region control mechanism in nvflash/ + .cfg flashing utility in order to obtain the actual PT + offset from the start of the user region the size of the + boot regions must be subtracted. */ + struct mmc *mmc = find_mmc_device(EMMC_DEV); + if (mmc && !mmc_init(mmc) && (get_boot_size_mult(mmc) == 16)) + pt_logical -= 0x5000; //why? +#endif + /* StartLogicalSector / LogicalBlockSize * PhysicalBlockSize + BootPartitions */ pt_offset = pt_logical / block_size * 512 + 1024 * 1024; diff --git a/drivers/mmc/tegra_mmc.c b/drivers/mmc/tegra_mmc.c index e05655b261d..42ab2081350 100644 --- a/drivers/mmc/tegra_mmc.c +++ b/drivers/mmc/tegra_mmc.c @@ -735,3 +735,42 @@ int tegra_mmc_init(const void *blob) #endif return 0; } + +/* An eMMC device is specified to have 0 or 2 boot regions and they must have + the same size ranging from 0 to 2 MiB. The boot region size can be queried + from the device through the BOOT_SIZE_MULT field of the response to the + EXT_CSD command sequence. */ +#define BOOT_SIZE_MULT 226 +u32 get_boot_size_mult(struct mmc *mmc) +{ + u32 ret = 0; + char *ext_csd = memalign(CACHE_LINE_SIZE, 512); + + if (ext_csd) { + int err; + struct mmc_cmd cmd; + struct mmc_data data; + + /* Get the Card Status Register */ + cmd.cmdidx = MMC_CMD_SEND_EXT_CSD; + cmd.resp_type = MMC_RSP_R1; + cmd.cmdarg = 0; + cmd.flags = 0; + + data.dest = ext_csd; + data.blocks = 1; + data.blocksize = 512; + data.flags = MMC_DATA_READ; + + /* + * If EXT_CSD cmd fails, then just return CONFIG_ENV_OFFSET, + * because the eMMC is not supporting boot regions (no boot + * regions). + */ + err = mmc_send_cmd(mmc, &cmd, &data); + if (!err) + ret = (int)ext_csd[BOOT_SIZE_MULT]; + free(ext_csd); + } + return ret; +} |