xref: /openbmc/u-boot/board/freescale/common/sdhc_boot.c (revision 83d290c56fab2d38cd1ab4c4cc7099559c1d5046)
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