summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2019-02-26 08:13:31 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2019-03-05 06:46:41 +0100
commit49ffafe0a8b59ce5669f69a727d6a83d89aafab1 (patch)
tree9c63ceda25b4996712e150087c69c6f6981b8172 /arch
parentedde68e3258e5b22abf44294c92211f025c7974e (diff)
downloadbarebox-49ffafe0a8b59ce5669f69a727d6a83d89aafab1.tar.gz
barebox-49ffafe0a8b59ce5669f69a727d6a83d89aafab1.tar.xz
esdhc-xload: Move to drivers/mci
The esdhc-xload code will be used by upcoming Layerscape support aswell, so move it from architecture code to drivers/mci/. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-imx/Kconfig5
-rw-r--r--arch/arm/mach-imx/Makefile2
-rw-r--r--arch/arm/mach-imx/xload-esdhc.c383
3 files changed, 6 insertions, 384 deletions
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 3c69ce00a3..f3f3a49339 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -388,6 +388,7 @@ config MACH_TECHNEXION_WANDBOARD
bool "Technexion Wandboard"
select ARCH_IMX6
select ARM_USE_COMPRESSED_DTB
+ select MCI_IMX_ESDHC_PBL
config MACH_EMBEST_RIOTBOARD
bool "Embest RIoTboard"
@@ -439,6 +440,7 @@ config MACH_ZII_RDU1
config MACH_ZII_RDU2
bool "ZII i.MX6Q(+) RDU2"
select ARCH_IMX6
+ select MCI_IMX_ESDHC_PBL
config MACH_ZII_IMX8MQ_DEV
bool "ZII i.MX8MQ based devices"
@@ -446,6 +448,7 @@ config MACH_ZII_IMX8MQ_DEV
select FIRMWARE_IMX_LPDDR4_PMU_TRAIN
select FIRMWARE_IMX8MQ_ATF
select ARM_SMCCC
+ select MCI_IMX_ESDHC_PBL
config MACH_ZII_VF610_DEV
bool "ZII VF610 Dev Family"
@@ -482,6 +485,7 @@ config MACH_NXP_IMX8MQ_EVK
select FIRMWARE_IMX_LPDDR4_PMU_TRAIN
select FIRMWARE_IMX8MQ_ATF
select ARM_SMCCC
+ select MCI_IMX_ESDHC_PBL
config MACH_PHYTEC_SOM_IMX8MQ
bool "Phytec i.MX8M SOM"
@@ -489,6 +493,7 @@ config MACH_PHYTEC_SOM_IMX8MQ
select FIRMWARE_IMX_LPDDR4_PMU_TRAIN
select FIRMWARE_IMX8MQ_ATF
select ARM_SMCCC
+ select MCI_IMX_ESDHC_PBL
config MACH_GRINN_LITEBOARD
bool "Grinn liteboard"
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index 97c54406e6..2b817e5dd8 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -26,4 +26,4 @@ obj-$(CONFIG_BAREBOX_UPDATE) += imx-bbu-internal.o
obj-$(CONFIG_BAREBOX_UPDATE_IMX_EXTERNAL_NAND) += imx-bbu-external-nand.o
obj-$(CONFIG_RESET_IMX_SRC) += src.o
lwl-y += cpu_init.o
-pbl-y += xload-spi.o xload-esdhc.o xload-common.o xload-imx-nand.o
+pbl-y += xload-spi.o xload-common.o xload-imx-nand.o
diff --git a/arch/arm/mach-imx/xload-esdhc.c b/arch/arm/mach-imx/xload-esdhc.c
deleted file mode 100644
index 6455cabf98..0000000000
--- a/arch/arm/mach-imx/xload-esdhc.c
+++ /dev/null
@@ -1,383 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; version 2.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-#define pr_fmt(fmt) "xload-esdhc: " fmt
-
-#include <common.h>
-#include <io.h>
-#include <mci.h>
-#include <mach/atf.h>
-#include <mach/imx6-regs.h>
-#include <mach/imx8mq-regs.h>
-#include <mach/xload.h>
-#include <linux/sizes.h>
-#include <mach/imx-header.h>
-#include "../../../drivers/mci/sdhci.h"
-#include "../../../drivers/mci/imx-esdhc.h"
-
-#define SECTOR_SIZE 512
-
-#define esdhc_read32(a) readl(a)
-#define esdhc_write32(a, v) writel(v,a)
-#define IMX_SDHCI_MIXCTRL 0x48
-
-struct esdhc {
- void __iomem *regs;
- int is_mx6;
-};
-
-static void __udelay(int us)
-{
- volatile int i;
-
- for (i = 0; i < us * 4; i++);
-}
-
-static u32 esdhc_xfertyp(struct mci_cmd *cmd, struct mci_data *data)
-{
- u32 xfertyp = 0;
-
- if (data)
- xfertyp |= COMMAND_DPSEL | TRANSFER_MODE_MSBSEL |
- TRANSFER_MODE_BCEN |TRANSFER_MODE_DTDSEL;
-
- if (cmd->resp_type & MMC_RSP_CRC)
- xfertyp |= COMMAND_CCCEN;
- if (cmd->resp_type & MMC_RSP_OPCODE)
- xfertyp |= COMMAND_CICEN;
- if (cmd->resp_type & MMC_RSP_136)
- xfertyp |= COMMAND_RSPTYP_136;
- else if (cmd->resp_type & MMC_RSP_BUSY)
- xfertyp |= COMMAND_RSPTYP_48_BUSY;
- else if (cmd->resp_type & MMC_RSP_PRESENT)
- xfertyp |= COMMAND_RSPTYP_48;
-
- return COMMAND_CMD(cmd->cmdidx) | xfertyp;
-}
-
-static int esdhc_do_data(struct esdhc *esdhc, struct mci_data *data)
-{
- void __iomem *regs = esdhc->regs;
- char *buffer;
- u32 databuf;
- u32 size;
- u32 irqstat;
- u32 timeout;
- u32 present;
-
- buffer = data->dest;
-
- timeout = 1000000;
- size = data->blocksize * data->blocks;
- irqstat = esdhc_read32(regs + SDHCI_INT_STATUS);
-
- while (size) {
- present = esdhc_read32(regs + SDHCI_PRESENT_STATE) & PRSSTAT_BREN;
- if (present) {
- databuf = esdhc_read32(regs + SDHCI_BUFFER);
- *((u32 *)buffer) = databuf;
- buffer += 4;
- size -= 4;
- }
-
- if (!timeout--) {
- pr_err("read time out\n");
- return -ETIMEDOUT;
- }
- }
-
- return 0;
-}
-
-static int
-esdhc_send_cmd(struct esdhc *esdhc, struct mci_cmd *cmd, struct mci_data *data)
-{
- u32 xfertyp, mixctrl;
- u32 irqstat;
- void __iomem *regs = esdhc->regs;
- int ret;
- int timeout;
-
- esdhc_write32(regs + SDHCI_INT_STATUS, -1);
-
- /* Wait at least 8 SD clock cycles before the next command */
- __udelay(1);
-
- if (data) {
- unsigned long dest = (unsigned long)data->dest;
-
- if (dest > 0xffffffff)
- return -EINVAL;
-
- /* Set up for a data transfer if we have one */
- esdhc_write32(regs + SDHCI_DMA_ADDRESS, (u32)dest);
- esdhc_write32(regs + SDHCI_BLOCK_SIZE__BLOCK_COUNT, data->blocks << 16 | SECTOR_SIZE);
- }
-
- /* Figure out the transfer arguments */
- xfertyp = esdhc_xfertyp(cmd, data);
-
- /* Send the command */
- esdhc_write32(regs + SDHCI_ARGUMENT, cmd->cmdarg);
-
- if (esdhc->is_mx6) {
- /* write lower-half of xfertyp to mixctrl */
- mixctrl = xfertyp & 0xFFFF;
- /* Keep the bits 22-25 of the register as is */
- mixctrl |= (esdhc_read32(regs + IMX_SDHCI_MIXCTRL) & (0xF << 22));
- esdhc_write32(regs + IMX_SDHCI_MIXCTRL, mixctrl);
- }
-
- esdhc_write32(regs + SDHCI_TRANSFER_MODE__COMMAND, xfertyp);
-
- /* Wait for the command to complete */
- timeout = 10000;
- while (!(esdhc_read32(regs + SDHCI_INT_STATUS) & IRQSTAT_CC)) {
- __udelay(1);
- if (!timeout--)
- return -ETIMEDOUT;
- }
-
- irqstat = esdhc_read32(regs + SDHCI_INT_STATUS);
- esdhc_write32(regs + SDHCI_INT_STATUS, irqstat);
-
- if (irqstat & CMD_ERR)
- return -EIO;
-
- if (irqstat & IRQSTAT_CTOE)
- return -ETIMEDOUT;
-
- /* Copy the response to the response buffer */
- cmd->response[0] = esdhc_read32(regs + SDHCI_RESPONSE_0);
-
- /* Wait until all of the blocks are transferred */
- if (data) {
- ret = esdhc_do_data(esdhc, data);
- if (ret)
- return ret;
- }
-
- esdhc_write32(regs + SDHCI_INT_STATUS, -1);
-
- /* Wait for the bus to be idle */
- timeout = 10000;
- while (esdhc_read32(regs + SDHCI_PRESENT_STATE) &
- (PRSSTAT_CICHB | PRSSTAT_CIDHB | PRSSTAT_DLA)) {
- __udelay(1);
- if (!timeout--)
- return -ETIMEDOUT;
- }
-
- return 0;
-}
-
-static int esdhc_read_blocks(struct esdhc *esdhc, void *dst, size_t len)
-{
- struct mci_cmd cmd;
- struct mci_data data;
- u32 val;
- int ret;
-
- writel(IRQSTATEN_CC | IRQSTATEN_TC | IRQSTATEN_CINT | IRQSTATEN_CTOE |
- IRQSTATEN_CCE | IRQSTATEN_CEBE | IRQSTATEN_CIE |
- IRQSTATEN_DTOE | IRQSTATEN_DCE | IRQSTATEN_DEBE |
- IRQSTATEN_DINT, esdhc->regs + SDHCI_INT_ENABLE);
-
- val = readl(esdhc->regs + SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET);
- val |= SYSCTL_HCKEN | SYSCTL_IPGEN;
- writel(val, esdhc->regs + SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET);
-
- cmd.cmdidx = MMC_CMD_READ_MULTIPLE_BLOCK;
- cmd.cmdarg = 0;
- cmd.resp_type = MMC_RSP_R1;
-
- data.dest = dst;
- data.blocks = len / SECTOR_SIZE;
- data.blocksize = SECTOR_SIZE;
- data.flags = MMC_DATA_READ;
-
- ret = esdhc_send_cmd(esdhc, &cmd, &data);
- if (ret) {
- pr_debug("send command failed with %d\n", ret);
- return ret;
- }
-
- cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION;
- cmd.cmdarg = 0;
- cmd.resp_type = MMC_RSP_R1b;
-
- esdhc_send_cmd(esdhc, &cmd, NULL);
-
- return 0;
-}
-
-static int
-esdhc_start_image(struct esdhc *esdhc, ptrdiff_t address, ptrdiff_t entry, u32 offset)
-{
-
- void *buf = (void *)address;
- struct imx_flash_header_v2 *hdr;
- int ret, len;
- void __noreturn (*bb)(void);
- unsigned int ofs;
- int i, header_count = 1;
-
- len = imx_image_size();
- len = ALIGN(len, SECTOR_SIZE);
-
- for (i = 0; i < header_count; i++) {
- ret = esdhc_read_blocks(esdhc, buf,
- offset + SZ_1K + SECTOR_SIZE);
- if (ret)
- return ret;
-
- hdr = buf + offset + SZ_1K;
-
- 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++;
- }
- }
-
- 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' gvies us the
- * adjustement 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(esdhc, buf, offset + len);
- if (ret) {
- pr_err("Loading image failed with %d\n", ret);
- return ret;
- }
-
- pr_debug("Image loaded successfully\n");
-
- bb = buf + ofs;
-
- bb();
-}
-
-/**
- * imx6_esdhc_start_image - Load and start an image from USDHC controller
- * @instance: The USDHC controller instance (0..4)
- *
- * 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.
- *
- * Return: If successful, this function does not return. A negative error
- * code is returned when this function fails.
- */
-int imx6_esdhc_start_image(int instance)
-{
- struct esdhc esdhc;
-
- switch (instance) {
- case 0:
- esdhc.regs = IOMEM(MX6_USDHC1_BASE_ADDR);
- break;
- case 1:
- esdhc.regs = IOMEM(MX6_USDHC2_BASE_ADDR);
- break;
- case 2:
- esdhc.regs = IOMEM(MX6_USDHC3_BASE_ADDR);
- break;
- case 3:
- esdhc.regs = IOMEM(MX6_USDHC4_BASE_ADDR);
- break;
- default:
- return -EINVAL;
- }
-
- esdhc.is_mx6 = 1;
-
- return esdhc_start_image(&esdhc, 0x10000000, 0x10000000, 0);
-}
-
-/**
- * imx8_esdhc_start_image - Load and start an image from USDHC controller
- * @instance: The USDHC controller instance (0..2)
- *
- * 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.
- *
- * Return: If successful, this function does not return. A negative error
- * code is returned when this function fails.
- */
-int imx8_esdhc_start_image(int instance)
-{
- struct esdhc esdhc;
-
- switch (instance) {
- case 0:
- esdhc.regs = IOMEM(MX8MQ_USDHC1_BASE_ADDR);
- break;
- case 1:
- esdhc.regs = IOMEM(MX8MQ_USDHC2_BASE_ADDR);
- break;
- default:
- return -EINVAL;
- }
-
- esdhc.is_mx6 = 1;
-
- return esdhc_start_image(&esdhc, MX8MQ_DDR_CSD1_BASE_ADDR,
- MX8MQ_ATF_BL33_BASE_ADDR, SZ_32K);
-} \ No newline at end of file