summaryrefslogtreecommitdiffstats
path: root/drivers/mci/imx-esdhc-pbl.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mci/imx-esdhc-pbl.c')
-rw-r--r--drivers/mci/imx-esdhc-pbl.c277
1 files changed, 126 insertions, 151 deletions
diff --git a/drivers/mci/imx-esdhc-pbl.c b/drivers/mci/imx-esdhc-pbl.c
index 5a76e7a663..5b1d9a3cf4 100644
--- a/drivers/mci/imx-esdhc-pbl.c
+++ b/drivers/mci/imx-esdhc-pbl.c
@@ -8,14 +8,20 @@
#include <linux/sizes.h>
#include <asm/sections.h>
#include <asm/cache.h>
-#include <mach/xload.h>
+#include <mach/imx/xload.h>
+#include <firmware.h>
+#include <asm/atf_common.h>
#ifdef CONFIG_ARCH_IMX
-#include <mach/atf.h>
-#include <mach/imx6-regs.h>
-#include <mach/imx7-regs.h>
-#include <mach/imx8mq-regs.h>
-#include <mach/imx8mm-regs.h>
-#include <mach/imx-header.h>
+#include <mach/imx/atf.h>
+#include <mach/imx/imx6-regs.h>
+#include <mach/imx/imx7-regs.h>
+#include <mach/imx/imx8mq-regs.h>
+#include <mach/imx/imx8mm-regs.h>
+#include <mach/imx/imx-header.h>
+#endif
+#ifdef CONFIG_ARCH_LAYERSCAPE
+#include <mach/layerscape/xload.h>
+#include <mach/layerscape/layerscape.h>
#endif
#include "sdhci.h"
#include "imx-esdhc.h"
@@ -44,7 +50,7 @@ static int esdhc_send_ext_csd(struct fsl_esdhc_host *host)
return esdhc_send_cmd(host, &cmd, &data);
}
-static bool esdhc_bootpart_active(struct fsl_esdhc_host *host)
+static bool __maybe_unused esdhc_bootpart_active(struct fsl_esdhc_host *host)
{
unsigned bootpart;
@@ -101,122 +107,24 @@ static int esdhc_read_blocks(struct fsl_esdhc_host *host, void *dst, size_t len)
}
#ifdef CONFIG_ARCH_IMX
-static int esdhc_search_header(struct fsl_esdhc_host *host,
- struct imx_flash_header_v2 **header_pointer,
- void *buffer, u32 *offset, u32 ivt_offset)
+static int imx_read_blocks(void *dest, size_t len, void *priv)
{
- int ret;
- int i, header_count = 1;
- void *buf = buffer;
- struct imx_flash_header_v2 *hdr;
-
- for (i = 0; i < header_count; i++) {
- ret = esdhc_read_blocks(host, buf,
- *offset + ivt_offset + SECTOR_SIZE);
- if (ret)
- return ret;
-
- hdr = buf + *offset + ivt_offset;
-
- if (!is_imx_flash_header_v2(hdr)) {
- pr_debug("IVT header not found on SD card. "
- "Found tag: 0x%02x length: 0x%04x "
- "version: %02x\n",
- hdr->header.tag, hdr->header.length,
- hdr->header.version);
- return -EINVAL;
- }
-
- if (IS_ENABLED(CONFIG_ARCH_IMX8MQ) &&
- hdr->boot_data.plugin & PLUGIN_HDMI_IMAGE) {
- /*
- * In images that include signed HDMI
- * firmware, first v2 header would be
- * dedicated to that and would not contain any
- * useful for us information. In order for us
- * to pull the rest of the bootloader image
- * in, we need to re-read header from SD/MMC,
- * this time skipping anything HDMI firmware
- * related.
- */
- *offset += hdr->boot_data.size + hdr->header.length;
- header_count++;
- }
- }
- *header_pointer = hdr;
- return 0;
+ return esdhc_read_blocks(priv, dest, len);
}
static int
esdhc_load_image(struct fsl_esdhc_host *host, ptrdiff_t address,
ptrdiff_t entry, u32 offset, u32 ivt_offset, bool start)
{
-
- void *buf = (void *)address;
- struct imx_flash_header_v2 *hdr = NULL;
- int ret, len;
- void __noreturn (*bb)(void);
- unsigned int ofs;
-
- len = imx_image_size();
- len = ALIGN(len, SECTOR_SIZE);
-
- ret = esdhc_search_header(host, &hdr, buf, &offset, ivt_offset);
- if (ret)
- return ret;
-
- pr_debug("Check ok, loading image\n");
-
- ofs = offset + hdr->entry - hdr->boot_data.start;
-
- if (entry != address) {
- /*
- * Passing entry different from address is interpreted
- * as a request to place the image such that its entry
- * point would be exactly at 'entry', that is:
- *
- * buf + ofs = entry
- *
- * solving the above for 'buf' gives us the
- * adjustment that needs to be made:
- *
- * buf = entry - ofs
- *
- */
- if (WARN_ON(entry - ofs < address)) {
- /*
- * We want to make sure we won't try to place
- * the start of the image before the beginning
- * of the memory buffer we were given in
- * address.
- */
- return -EINVAL;
- }
-
- buf = (void *)(entry - ofs);
- }
-
- ret = esdhc_read_blocks(host, buf, offset + len);
- if (ret) {
- pr_err("Loading image failed with %d\n", ret);
- return ret;
- }
-
- pr_debug("Image loaded successfully\n");
-
- if (!start)
- return 0;
-
- bb = buf + ofs;
-
- sync_caches_for_execution();
-
- bb();
+ return imx_load_image(address, entry, offset, ivt_offset, start,
+ SECTOR_SIZE, imx_read_blocks, host);
}
static void imx_esdhc_init(struct fsl_esdhc_host *host,
struct esdhc_soc_data *data)
{
+ u32 mixctrl;
+
data->flags = ESDHC_FLAG_USDHC;
host->socdata = data;
esdhc_populate_sdhci(host);
@@ -226,6 +134,10 @@ static void imx_esdhc_init(struct fsl_esdhc_host *host,
FIELD_PREP(WML_WR_WML_MASK, SECTOR_WML) |
FIELD_PREP(WML_RD_BRST_LEN, 16) |
FIELD_PREP(WML_RD_WML_MASK, SECTOR_WML));
+
+ mixctrl = sdhci_read32(&host->sdhci, IMX_SDHCI_MIXCTRL);
+ if (mixctrl & MIX_CTRL_DDREN)
+ host->sdhci.timing = MMC_TIMING_MMC_DDR52;
}
static int imx8m_esdhc_init(struct fsl_esdhc_host *host,
@@ -330,17 +242,17 @@ int imx7_esdhc_start_image(int instance)
/**
* imx8m_esdhc_load_image - Load and optionally start an image from USDHC controller
* @instance: The USDHC controller instance (0..2)
- * @start: Whether to directly start the loaded image
+ * @bl33: Where to load the bl33 barebox image
*
* This uses esdhc_start_image() to load an image from SD/MMC. It is
* assumed that the image is the currently running barebox image (This
* information is used to calculate the length of the image). The
- * image is started afterwards.
+ * image is not started afterwards.
*
- * Return: If successful, this function does not return (if directly started)
- * or 0. A negative error code is returned when this function fails.
+ * Return: If image successfully loaded, returns 0.
+ * A negative error code is returned when this function fails.
*/
-int imx8m_esdhc_load_image(int instance, bool start)
+int imx8m_esdhc_load_image(int instance, void *bl33)
{
struct esdhc_soc_data data;
struct fsl_esdhc_host host = { 0 };
@@ -351,24 +263,24 @@ int imx8m_esdhc_load_image(int instance, bool start)
return ret;
return esdhc_load_image(&host, MX8M_DDR_CSD1_BASE_ADDR,
- MX8MQ_ATF_BL33_BASE_ADDR, SZ_32K, SZ_1K,
- start);
+ (ptrdiff_t)bl33, SZ_32K, SZ_1K,
+ false);
}
/**
* imx8mp_esdhc_load_image - Load and optionally start an image from USDHC controller
* @instance: The USDHC controller instance (0..2)
- * @start: Whether to directly start the loaded image
+ * @bl33: Where to load the bl33 barebox image
*
* This uses esdhc_start_image() to load an image from SD/MMC. It is
* assumed that the image is the currently running barebox image (This
* information is used to calculate the length of the image). The
- * image is started afterwards.
+ * image is not started afterwards.
*
- * Return: If successful, this function does not return (if directly started)
- * or 0. A negative error code is returned when this function fails.
+ * Return: If image successfully loaded, returns 0.
+ * A negative error code is returned when this function fails.
*/
-int imx8mp_esdhc_load_image(int instance, bool start)
+int imx8mp_esdhc_load_image(int instance, void *bl33)
{
struct esdhc_soc_data data;
struct fsl_esdhc_host host = { 0 };
@@ -382,14 +294,47 @@ int imx8mp_esdhc_load_image(int instance, bool start)
offset = esdhc_bootpart_active(&host)? 0 : SZ_32K;
return esdhc_load_image(&host, MX8M_DDR_CSD1_BASE_ADDR,
- MX8MQ_ATF_BL33_BASE_ADDR, offset, 0, start);
+ (ptrdiff_t)bl33, offset, 0, false);
}
-int imx8mn_esdhc_load_image(int instance, bool start)
+int imx8mn_esdhc_load_image(int instance, void *bl33)
__alias(imx8mp_esdhc_load_image);
#endif
-#ifdef CONFIG_ARCH_LS1046
+#ifdef CONFIG_ARCH_LAYERSCAPE
+
+static int layerscape_esdhc_load_image(struct fsl_esdhc_host *host, void *adr, unsigned long size,
+ uint32_t div_val)
+{
+ uint32_t val;
+ int ret;
+
+ esdhc_populate_sdhci(host);
+ sdhci_write32(&host->sdhci, IMX_SDHCI_WML, 0);
+
+ /*
+ * The ROM leaves us here with a clock frequency of around 400kHz. Speed
+ * this up a bit. FIXME: The resulting frequency has not yet been verified
+ * to work on all cards.
+ */
+ val = sdhci_read32(&host->sdhci, SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET);
+ val &= ~0x0000fff0;
+ val |= div_val;
+ sdhci_write32(&host->sdhci, SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET, val);
+
+ sdhci_write32(&host->sdhci, ESDHC_DMA_SYSCTL,
+ ESDHC_SYSCTL_DMA_SNOOP | ESDHC_SYSCTL_PERIPHERAL_CLK_SEL);
+
+ ret = esdhc_read_blocks(host, adr, size);
+ if (ret) {
+ pr_err("%s: reading blocks failed with: %d\n", __func__, ret);
+ return ret;
+ }
+
+ sync_caches_for_execution();
+
+ return 0;
+}
/*
* The image on the SD card starts at 0x1000. We reserved 128KiB for the PBL,
@@ -410,46 +355,76 @@ int imx8mn_esdhc_load_image(int instance, bool start)
int ls1046a_esdhc_start_image(unsigned long r0, unsigned long r1, unsigned long r2)
{
int ret;
- uint32_t val;
struct esdhc_soc_data data = {
- .flags = ESDHC_FLAG_BIGENDIAN,
+ .flags = ESDHC_FLAG_MULTIBLK_NO_INT | ESDHC_FLAG_BIGENDIAN,
};
struct fsl_esdhc_host host = {
.sdhci.base = IOMEM(0x01560000),
.socdata = &data,
};
- unsigned long sdram = 0x80000000;
+ void *sdram = (void *)0x80000000;
+ unsigned long size = ALIGN(barebox_image_size + LS1046A_SD_IMAGE_OFFSET, 512);
void (*barebox)(unsigned long, unsigned long, unsigned long) =
- (void *)(sdram + LS1046A_SD_IMAGE_OFFSET);
+ (sdram + LS1046A_SD_IMAGE_OFFSET);
- esdhc_populate_sdhci(&host);
- sdhci_write32(&host.sdhci, IMX_SDHCI_WML, 0);
+ ret = layerscape_esdhc_load_image(&host, sdram, size, (8 << 8) | (3 << 4));
+ if (ret)
+ return ret;
- /*
- * The ROM leaves us here with a clock frequency of around 400kHz. Speed
- * this up a bit. FIXME: The resulting frequency has not yet been verified
- * to work on all cards.
- */
- val = sdhci_read32(&host.sdhci, SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET);
- val &= ~0x0000fff0;
- val |= (8 << 8) | (3 << 4);
- sdhci_write32(&host.sdhci, SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET, val);
+ printf("Starting barebox\n");
- sdhci_write32(&host.sdhci, ESDHC_DMA_SYSCTL, ESDHC_SYSCTL_DMA_SNOOP);
+ barebox(r0, r1, r2);
- ret = esdhc_read_blocks(&host, (void *)sdram,
- ALIGN(barebox_image_size + LS1046A_SD_IMAGE_OFFSET, 512));
- if (ret) {
- pr_err("%s: reading blocks failed with: %d\n", __func__, ret);
+ return -EINVAL;
+}
+
+static int ls1028a_esdhc_start_image(void __iomem *base, struct dram_regions_info *dram_info)
+{
+ struct esdhc_soc_data data = {
+ .flags = ESDHC_FLAG_MULTIBLK_NO_INT,
+ };
+ struct fsl_esdhc_host host = {
+ .sdhci.base = base,
+ .socdata = &data,
+ };
+ void *sdram = (void *)0x80000000;
+ void (*bl31)(void) = (void *)LS1028A_TFA_RESERVED_START;
+ size_t bl31_size;
+ void *bl31_image;
+ struct bl2_to_bl31_params_mem_v2 *params;
+ unsigned long size = ALIGN(barebox_image_size + LS1046A_SD_IMAGE_OFFSET, 512);
+ void (*barebox)(unsigned long, unsigned long, unsigned long) =
+ (sdram + LS1046A_SD_IMAGE_OFFSET);
+ int ret;
+
+ ret = layerscape_esdhc_load_image(&host, sdram, size, 8 << 4);
+ if (ret)
return ret;
- }
- sync_caches_for_execution();
+ get_builtin_firmware_ext(ls1028a_bl31_bin, barebox, &bl31_image, &bl31_size);
+ memcpy(bl31, bl31_image, bl31_size);
- printf("Starting barebox\n");
+ /* Setup an initial stack for EL2 */
+ asm volatile("msr sp_el2, %0" : : "r" ((unsigned long)barebox - 16) : "cc");
- barebox(r0, r1, r2);
+ params = bl2_plat_get_bl31_params_v2(0, (uintptr_t)barebox, 0);
+ params->bl31_ep_info.args.arg3 = (unsigned long)dram_info;
+
+ printf("Starting bl31\n");
+
+ bl31_entry_v2((uintptr_t)bl31, &params->bl_params, NULL);
return -EINVAL;
}
+
+int ls1028a_esdhc1_start_image(struct dram_regions_info *dram_info)
+{
+ return ls1028a_esdhc_start_image(IOMEM(0x2140000), dram_info);
+}
+
+int ls1028a_esdhc2_start_image(struct dram_regions_info *dram_info)
+{
+ return ls1028a_esdhc_start_image(IOMEM(0x2150000), dram_info);
+}
+
#endif