1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
21ac63e40SJerry Huang /*
31ac63e40SJerry Huang * Copyright 2011 Freescale Semiconductor, Inc.
41ac63e40SJerry Huang */
51ac63e40SJerry Huang
61ac63e40SJerry Huang #include <common.h>
71ac63e40SJerry Huang #include <mmc.h>
81ac63e40SJerry Huang #include <malloc.h>
91ac63e40SJerry Huang
101ac63e40SJerry Huang /*
111ac63e40SJerry Huang * The environment variables are written to just after the u-boot image
121ac63e40SJerry Huang * on SDCard, so we must read the MBR to get the start address and code
131ac63e40SJerry Huang * length of the u-boot image, then calculate the address of the env.
141ac63e40SJerry Huang */
151ac63e40SJerry Huang #define ESDHC_BOOT_IMAGE_SIZE 0x48
161ac63e40SJerry Huang #define ESDHC_BOOT_IMAGE_ADDR 0x50
171ac63e40SJerry Huang
18f28bea00SHaijun.Zhang #define ESDHC_DEFAULT_ENVADDR 0x400
19f28bea00SHaijun.Zhang
mmc_get_env_addr(struct mmc * mmc,int copy,u32 * env_addr)20d196bd88SMichael Heimpold int mmc_get_env_addr(struct mmc *mmc, int copy, u32 *env_addr)
211ac63e40SJerry Huang {
221ac63e40SJerry Huang u8 *tmp_buf;
231ac63e40SJerry Huang u32 blklen, code_offset, code_len, n;
241ac63e40SJerry Huang
251ac63e40SJerry Huang blklen = mmc->read_bl_len;
261ac63e40SJerry Huang tmp_buf = malloc(blklen);
271ac63e40SJerry Huang if (!tmp_buf)
281ac63e40SJerry Huang return 1;
291ac63e40SJerry Huang
301ac63e40SJerry Huang /* read out the first block, get the config data information */
317c4213f6SStephen Warren n = mmc->block_dev.block_read(&mmc->block_dev, 0, 1, tmp_buf);
321ac63e40SJerry Huang if (!n) {
331ac63e40SJerry Huang free(tmp_buf);
341ac63e40SJerry Huang return 1;
351ac63e40SJerry Huang }
361ac63e40SJerry Huang
371ac63e40SJerry Huang /* Get the Source Address, from offset 0x50 */
381ac63e40SJerry Huang code_offset = *(u32 *)(tmp_buf + ESDHC_BOOT_IMAGE_ADDR);
391ac63e40SJerry Huang
401ac63e40SJerry Huang /* Get the code size from offset 0x48 */
411ac63e40SJerry Huang code_len = *(u32 *)(tmp_buf + ESDHC_BOOT_IMAGE_SIZE);
421ac63e40SJerry Huang
43f28bea00SHaijun.Zhang #ifdef CONFIG_ESDHC_HC_BLK_ADDR
44f28bea00SHaijun.Zhang /*
45f28bea00SHaijun.Zhang * On soc BSC9131, BSC9132:
46f28bea00SHaijun.Zhang * In High Capacity SD Cards (> 2 GBytes), the 32-bit source address and
47f28bea00SHaijun.Zhang * code length of these soc specify the memory address in block address
48f28bea00SHaijun.Zhang * format. Block length is fixed to 512 bytes as per the SD High
49f28bea00SHaijun.Zhang * Capacity specification.
50f28bea00SHaijun.Zhang */
51f28bea00SHaijun.Zhang u64 tmp;
52f28bea00SHaijun.Zhang
53f28bea00SHaijun.Zhang if (mmc->high_capacity) {
54f28bea00SHaijun.Zhang tmp = (u64)code_offset * blklen;
55f28bea00SHaijun.Zhang tmp += code_len * blklen;
56f28bea00SHaijun.Zhang } else
57f28bea00SHaijun.Zhang tmp = code_offset + code_len;
58f28bea00SHaijun.Zhang
59f28bea00SHaijun.Zhang if ((tmp + CONFIG_ENV_SIZE > mmc->capacity) ||
60f28bea00SHaijun.Zhang (tmp > 0xFFFFFFFFU))
61f28bea00SHaijun.Zhang *env_addr = ESDHC_DEFAULT_ENVADDR;
62f28bea00SHaijun.Zhang else
63f28bea00SHaijun.Zhang *env_addr = tmp;
64f28bea00SHaijun.Zhang
65f28bea00SHaijun.Zhang free(tmp_buf);
66f28bea00SHaijun.Zhang
67f28bea00SHaijun.Zhang return 0;
68f28bea00SHaijun.Zhang #endif
69f28bea00SHaijun.Zhang
701ac63e40SJerry Huang *env_addr = code_offset + code_len;
711ac63e40SJerry Huang
721ac63e40SJerry Huang free(tmp_buf);
731ac63e40SJerry Huang
741ac63e40SJerry Huang return 0;
751ac63e40SJerry Huang }
76