From 49ffafe0a8b59ce5669f69a727d6a83d89aafab1 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Tue, 26 Feb 2019 08:13:31 +0100 Subject: 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 --- arch/arm/mach-imx/Kconfig | 5 + arch/arm/mach-imx/Makefile | 2 +- arch/arm/mach-imx/xload-esdhc.c | 383 ---------------------------------------- 3 files changed, 6 insertions(+), 384 deletions(-) delete mode 100644 arch/arm/mach-imx/xload-esdhc.c (limited to 'arch') 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 -#include -#include -#include -#include -#include -#include -#include -#include -#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 -- cgit v1.2.3