summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcel Ziswiler <marcel.ziswiler@toradex.com>2013-08-12 10:37:32 +0200
committerMarcel Ziswiler <marcel.ziswiler@toradex.com>2013-08-12 10:37:32 +0200
commitd63f3c73a767b82ba1e28c30a46a1e88616ed66e (patch)
tree572ab70727626189353b577e0840d60b7fa61c9c
parent1cf83224ac11e2ea1a0b3546b27ecd9a59fac247 (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.c29
-rw-r--r--drivers/mmc/tegra_mmc.c39
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;
+}