From 661a87a4516edb52ed91681967d34db5b3eb5e48 Mon Sep 17 00:00:00 2001 From: Waldemar Brodkorb Date: Fri, 27 Mar 2015 07:50:12 +0100 Subject: update to 3.18.10, sync rpi patch Rpi-Kernel includes the rpi-proto driver now. Always enable device-tree support for raspberry pi /pi2 as most of the new drivers will not work without. --- .../patches/3.18.10/solidrun-imx6-wlan.patch | 3252 ++++++++++++++++++++ .../patches/3.18.9/solidrun-imx6-wlan.patch | 3252 -------------------- 2 files changed, 3252 insertions(+), 3252 deletions(-) create mode 100644 target/arm/solidrun-imx6/patches/3.18.10/solidrun-imx6-wlan.patch delete mode 100644 target/arm/solidrun-imx6/patches/3.18.9/solidrun-imx6-wlan.patch (limited to 'target/arm/solidrun-imx6') diff --git a/target/arm/solidrun-imx6/patches/3.18.10/solidrun-imx6-wlan.patch b/target/arm/solidrun-imx6/patches/3.18.10/solidrun-imx6-wlan.patch new file mode 100644 index 000000000..3ab3081db --- /dev/null +++ b/target/arm/solidrun-imx6/patches/3.18.10/solidrun-imx6-wlan.patch @@ -0,0 +1,3252 @@ +diff -Nur linux-3.18.8.orig/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi linux-3.18.8/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi +--- linux-3.18.8.orig/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi 2015-02-27 02:49:36.000000000 +0100 ++++ linux-3.18.8/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi 2015-03-02 03:23:14.000000000 +0100 +@@ -170,6 +170,28 @@ + MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x13059 + >; + }; ++ ++ pinctrl_cubox_i_usdhc2_100mhz: cubox-i-usdhc2-100mhz { ++ fsl,pins = < ++ MX6QDL_PAD_SD2_CMD__SD2_CMD 0x170b9 ++ MX6QDL_PAD_SD2_CLK__SD2_CLK 0x100b9 ++ MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x170b9 ++ MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x170b9 ++ MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x170b9 ++ MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x130b9 ++ >; ++ }; ++ ++ pinctrl_cubox_i_usdhc2_200mhz: cubox-i-usdhc2-200mhz { ++ fsl,pins = < ++ MX6QDL_PAD_SD2_CMD__SD2_CMD 0x170f9 ++ MX6QDL_PAD_SD2_CLK__SD2_CLK 0x100f9 ++ MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x170f9 ++ MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x170f9 ++ MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x170f9 ++ MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x130f9 ++ >; ++ }; + }; + }; + +@@ -194,8 +216,10 @@ + }; + + &usdhc2 { +- pinctrl-names = "default"; ++ pinctrl-names = "default", "state_100mhz", "state_200mhz"; + pinctrl-0 = <&pinctrl_cubox_i_usdhc2_aux &pinctrl_cubox_i_usdhc2>; ++ pinctrl-1 = <&pinctrl_cubox_i_usdhc2_aux &pinctrl_cubox_i_usdhc2_100mhz>; ++ pinctrl-2 = <&pinctrl_cubox_i_usdhc2_aux &pinctrl_cubox_i_usdhc2_200mhz>; + vmmc-supply = <®_3p3v>; + cd-gpios = <&gpio1 4 0>; + status = "okay"; +diff -Nur linux-3.18.8.orig/arch/arm/boot/dts/imx6qdl-microsom.dtsi linux-3.18.8/arch/arm/boot/dts/imx6qdl-microsom.dtsi +--- linux-3.18.8.orig/arch/arm/boot/dts/imx6qdl-microsom.dtsi 2015-02-27 02:49:36.000000000 +0100 ++++ linux-3.18.8/arch/arm/boot/dts/imx6qdl-microsom.dtsi 2015-03-02 02:58:12.000000000 +0100 +@@ -1,15 +1,95 @@ + /* + * Copyright (C) 2013,2014 Russell King + */ ++#include ++/ { ++ regulators { ++ compatible = "simple-bus"; ++ ++ reg_brcm_osc: brcm-osc-reg { ++ compatible = "regulator-fixed"; ++ enable-active-high; ++ gpio = <&gpio5 5 0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pinctrl_microsom_brcm_osc_reg>; ++ regulator-name = "brcm_osc_reg"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ ++ reg_brcm: brcm-reg { ++ compatible = "regulator-fixed"; ++ enable-active-high; ++ gpio = <&gpio3 19 0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pinctrl_microsom_brcm_reg>; ++ regulator-name = "brcm_reg"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ startup-delay-us = <200000>; ++ }; ++ }; ++}; + + &iomuxc { + microsom { ++ pinctrl_microsom_brcm_bt: microsom-brcm-bt { ++ fsl,pins = < ++ MX6QDL_PAD_CSI0_DAT14__GPIO6_IO00 0x40013070 ++ MX6QDL_PAD_CSI0_DAT15__GPIO6_IO01 0x40013070 ++ MX6QDL_PAD_CSI0_DAT18__GPIO6_IO04 0x40013070 ++ >; ++ }; ++ ++ pinctrl_microsom_brcm_osc_reg: microsom-brcm-osc-reg { ++ fsl,pins = < ++ MX6QDL_PAD_DISP0_DAT11__GPIO5_IO05 0x40013070 ++ >; ++ }; ++ ++ pinctrl_microsom_brcm_reg: microsom-brcm-reg { ++ fsl,pins = < ++ MX6QDL_PAD_EIM_D19__GPIO3_IO19 0x40013070 ++ >; ++ }; ++ ++ pinctrl_microsom_brcm_wifi: microsom-brcm-wifi { ++ fsl,pins = < ++ MX6QDL_PAD_GPIO_8__XTALOSC_REF_CLK_32K 0x1b0b0 ++ MX6QDL_PAD_CSI0_DATA_EN__GPIO5_IO20 0x40013070 ++ MX6QDL_PAD_CSI0_DAT8__GPIO5_IO26 0x40013070 ++ MX6QDL_PAD_CSI0_DAT9__GPIO5_IO27 0x40013070 ++ >; ++ }; ++ + pinctrl_microsom_uart1: microsom-uart1 { + fsl,pins = < + MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA 0x1b0b1 + MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA 0x1b0b1 + >; + }; ++ ++ pinctrl_microsom_uart4_1: microsom-uart4 { ++ fsl,pins = < ++ MX6QDL_PAD_CSI0_DAT12__UART4_TX_DATA 0x1b0b1 ++ MX6QDL_PAD_CSI0_DAT13__UART4_RX_DATA 0x1b0b1 ++ MX6QDL_PAD_CSI0_DAT16__UART4_RTS_B 0x1b0b1 ++ MX6QDL_PAD_CSI0_DAT17__UART4_CTS_B 0x1b0b1 ++ >; ++ }; ++ ++ pinctrl_microsom_usdhc1: microsom-usdhc1 { ++ fsl,pins = < ++ MX6QDL_PAD_SD1_CMD__SD1_CMD 0x17059 ++ MX6QDL_PAD_SD1_CLK__SD1_CLK 0x10059 ++ MX6QDL_PAD_SD1_DAT0__SD1_DATA0 0x17059 ++ MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x17059 ++ MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x17059 ++ MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x17059 ++ >; ++ }; + }; + }; + +@@ -18,3 +98,23 @@ + pinctrl-0 = <&pinctrl_microsom_uart1>; + status = "okay"; + }; ++ ++/* UART4 - Connected to optional BRCM Wifi/BT/FM */ ++&uart4 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pinctrl_microsom_brcm_bt &pinctrl_microsom_uart4_1>; ++ fsl,uart-has-rtscts; ++ status = "okay"; ++}; ++ ++/* USDHC1 - Connected to optional BRCM Wifi/BT/FM */ ++&usdhc1 { ++ card-external-vcc-supply = <®_brcm>; ++ card-reset-gpios = <&gpio5 26 GPIO_ACTIVE_LOW>, <&gpio6 0 GPIO_ACTIVE_LOW>; ++ keep-power-in-suspend; ++ non-removable; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pinctrl_microsom_brcm_wifi &pinctrl_microsom_usdhc1>; ++ vmmc-supply = <®_brcm>; ++ status = "okay"; ++}; +diff -Nur linux-3.18.8.orig/Documentation/devicetree/bindings/mmc/mmc.txt linux-3.18.8/Documentation/devicetree/bindings/mmc/mmc.txt +--- linux-3.18.8.orig/Documentation/devicetree/bindings/mmc/mmc.txt 2015-02-27 02:49:36.000000000 +0100 ++++ linux-3.18.8/Documentation/devicetree/bindings/mmc/mmc.txt 2015-03-02 03:25:33.000000000 +0100 +@@ -5,6 +5,8 @@ + Interpreted by the OF core: + - reg: Registers location and length. + - interrupts: Interrupts used by the MMC controller. ++- clocks: Clocks needed for the host controller, if any. ++- clock-names: Goes with clocks above. + + Card detection: + If no property below is supplied, host native card detect is used. +@@ -43,6 +45,15 @@ + - dsr: Value the card's (optional) Driver Stage Register (DSR) should be + programmed with. Valid range: [0 .. 0xffff]. + ++Card power and reset control: ++The following properties can be specified for cases where the MMC ++peripheral needs additional reset, regulator and clock lines. It is for ++example common for WiFi/BT adapters to have these separate from the main ++MMC bus: ++ - card-reset-gpios: Specify GPIOs for card reset (reset active low) ++ - card-external-vcc-supply: Regulator to drive (independent) card VCC ++ - clock with name "card_ext_clock": External clock provided to the card ++ + *NOTE* on CD and WP polarity. To use common for all SD/MMC host controllers line + polarity properties, we have to fix the meaning of the "normal" and "inverted" + line levels. We choose to follow the SDHCI standard, which specifies both those +diff -Nur linux-3.18.8.orig/drivers/mmc/core/core.c linux-3.18.8/drivers/mmc/core/core.c +--- linux-3.18.8.orig/drivers/mmc/core/core.c 2015-02-27 02:49:36.000000000 +0100 ++++ linux-3.18.8/drivers/mmc/core/core.c 2015-03-02 03:25:33.000000000 +0100 +@@ -13,11 +13,13 @@ + #include + #include + #include ++#include + #include + #include + #include + #include + #include ++#include + #include + #include + #include +@@ -1507,6 +1509,43 @@ + mmc_host_clk_release(host); + } + ++static void mmc_card_power_up(struct mmc_host *host) ++{ ++ int i; ++ struct gpio_desc **gds = host->card_reset_gpios; ++ ++ for (i = 0; i < ARRAY_SIZE(host->card_reset_gpios); i++) { ++ if (gds[i]) { ++ dev_dbg(host->parent, "Asserting reset line %d", i); ++ gpiod_set_value(gds[i], 1); ++ } ++ } ++ ++ if (host->card_regulator) { ++ dev_dbg(host->parent, "Enabling external regulator"); ++ if (regulator_enable(host->card_regulator)) ++ dev_err(host->parent, "Failed to enable external regulator"); ++ } ++ ++ if (host->card_clk) { ++ dev_dbg(host->parent, "Enabling external clock"); ++ clk_prepare_enable(host->card_clk); ++ } ++ ++ /* 2ms delay to let clocks and power settle */ ++ mmc_delay(20); ++ ++ for (i = 0; i < ARRAY_SIZE(host->card_reset_gpios); i++) { ++ if (gds[i]) { ++ dev_dbg(host->parent, "Deasserting reset line %d", i); ++ gpiod_set_value(gds[i], 0); ++ } ++ } ++ ++ /* 2ms delay to after reset release */ ++ mmc_delay(20); ++} ++ + /* + * Apply power to the MMC stack. This is a two-stage process. + * First, we enable power to the card without the clock running. +@@ -1523,6 +1562,9 @@ + if (host->ios.power_mode == MMC_POWER_ON) + return; + ++ /* Power up the card/module first, if needed */ ++ mmc_card_power_up(host); ++ + mmc_host_clk_hold(host); + + host->ios.vdd = fls(ocr) - 1; +diff -Nur linux-3.18.8.orig/drivers/mmc/core/host.c linux-3.18.8/drivers/mmc/core/host.c +--- linux-3.18.8.orig/drivers/mmc/core/host.c 2015-02-27 02:49:36.000000000 +0100 ++++ linux-3.18.8/drivers/mmc/core/host.c 2015-03-02 03:26:23.000000000 +0100 +@@ -12,14 +12,18 @@ + * MMC host class device management + */ + ++#include ++#include + #include + #include ++#include + #include + #include + #include + #include + #include + #include ++#include + #include + #include + +@@ -466,6 +470,66 @@ + + EXPORT_SYMBOL(mmc_of_parse); + ++static int mmc_of_parse_child(struct mmc_host *host) ++{ ++ struct device_node *np; ++ struct clk *clk; ++ int i; ++ ++ if (!host->parent || !host->parent->of_node) ++ return 0; ++ ++ np = host->parent->of_node; ++ ++ host->card_regulator = regulator_get(host->parent, "card-external-vcc"); ++ if (IS_ERR(host->card_regulator)) { ++ if (PTR_ERR(host->card_regulator) == -EPROBE_DEFER) ++ return PTR_ERR(host->card_regulator); ++ host->card_regulator = NULL; ++ } ++ ++ /* Parse card power/reset/clock control */ ++ if (of_find_property(np, "card-reset-gpios", NULL)) { ++ struct gpio_desc *gpd; ++ int level = 0; ++ ++ /* ++ * If the regulator is enabled, then we can hold the ++ * card in reset with an active high resets. Otherwise, ++ * hold the resets low. ++ */ ++ if (host->card_regulator && regulator_is_enabled(host->card_regulator)) ++ level = 1; ++ ++ for (i = 0; i < ARRAY_SIZE(host->card_reset_gpios); i++) { ++ gpd = devm_gpiod_get_index(host->parent, "card-reset", i); ++ if (IS_ERR(gpd)) { ++ if (PTR_ERR(gpd) == -EPROBE_DEFER) ++ return PTR_ERR(gpd); ++ break; ++ } ++ gpiod_direction_output(gpd, gpiod_is_active_low(gpd) | level); ++ host->card_reset_gpios[i] = gpd; ++ } ++ ++ gpd = devm_gpiod_get_index(host->parent, "card-reset", ARRAY_SIZE(host->card_reset_gpios)); ++ if (!IS_ERR(gpd)) { ++ dev_warn(host->parent, "More reset gpios than we can handle"); ++ gpiod_put(gpd); ++ } ++ } ++ ++ clk = of_clk_get_by_name(np, "card_ext_clock"); ++ if (IS_ERR(clk)) { ++ if (PTR_ERR(clk) == -EPROBE_DEFER) ++ return PTR_ERR(clk); ++ clk = NULL; ++ } ++ host->card_clk = clk; ++ ++ return 0; ++} ++ + /** + * mmc_alloc_host - initialise the per-host structure. + * @extra: sizeof private data structure +@@ -545,6 +609,10 @@ + { + int err; + ++ err = mmc_of_parse_child(host); ++ if (err) ++ return err; ++ + WARN_ON((host->caps & MMC_CAP_SDIO_IRQ) && + !host->ops->enable_sdio_irq); + +diff -Nur linux-3.18.8.orig/drivers/mmc/host/dw_mmc.c linux-3.18.8/drivers/mmc/host/dw_mmc.c +--- linux-3.18.8.orig/drivers/mmc/host/dw_mmc.c 2015-02-27 02:49:36.000000000 +0100 ++++ linux-3.18.8/drivers/mmc/host/dw_mmc.c 2015-03-02 03:25:56.000000000 +0100 +@@ -2211,6 +2211,8 @@ + if (!mmc) + return -ENOMEM; + ++ mmc_of_parse(mmc); ++ + slot = mmc_priv(mmc); + slot->id = id; + slot->mmc = mmc; +diff -Nur linux-3.18.8.orig/drivers/mmc/host/dw_mmc.c.orig linux-3.18.8/drivers/mmc/host/dw_mmc.c.orig +--- linux-3.18.8.orig/drivers/mmc/host/dw_mmc.c.orig 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.18.8/drivers/mmc/host/dw_mmc.c.orig 2015-02-27 02:49:36.000000000 +0100 +@@ -0,0 +1,2855 @@ ++/* ++ * Synopsys DesignWare Multimedia Card Interface driver ++ * (Based on NXP driver for lpc 31xx) ++ * ++ * Copyright (C) 2009 NXP Semiconductors ++ * Copyright (C) 2009, 2010 Imagination Technologies Ltd. ++ * ++ * 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; either version 2 of the License, or ++ * (at your option) any later version. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "dw_mmc.h" ++ ++/* Common flag combinations */ ++#define DW_MCI_DATA_ERROR_FLAGS (SDMMC_INT_DRTO | SDMMC_INT_DCRC | \ ++ SDMMC_INT_HTO | SDMMC_INT_SBE | \ ++ SDMMC_INT_EBE) ++#define DW_MCI_CMD_ERROR_FLAGS (SDMMC_INT_RTO | SDMMC_INT_RCRC | \ ++ SDMMC_INT_RESP_ERR) ++#define DW_MCI_ERROR_FLAGS (DW_MCI_DATA_ERROR_FLAGS | \ ++ DW_MCI_CMD_ERROR_FLAGS | SDMMC_INT_HLE) ++#define DW_MCI_SEND_STATUS 1 ++#define DW_MCI_RECV_STATUS 2 ++#define DW_MCI_DMA_THRESHOLD 16 ++ ++#define DW_MCI_FREQ_MAX 200000000 /* unit: HZ */ ++#define DW_MCI_FREQ_MIN 400000 /* unit: HZ */ ++ ++#ifdef CONFIG_MMC_DW_IDMAC ++#define IDMAC_INT_CLR (SDMMC_IDMAC_INT_AI | SDMMC_IDMAC_INT_NI | \ ++ SDMMC_IDMAC_INT_CES | SDMMC_IDMAC_INT_DU | \ ++ SDMMC_IDMAC_INT_FBE | SDMMC_IDMAC_INT_RI | \ ++ SDMMC_IDMAC_INT_TI) ++ ++struct idmac_desc { ++ u32 des0; /* Control Descriptor */ ++#define IDMAC_DES0_DIC BIT(1) ++#define IDMAC_DES0_LD BIT(2) ++#define IDMAC_DES0_FD BIT(3) ++#define IDMAC_DES0_CH BIT(4) ++#define IDMAC_DES0_ER BIT(5) ++#define IDMAC_DES0_CES BIT(30) ++#define IDMAC_DES0_OWN BIT(31) ++ ++ u32 des1; /* Buffer sizes */ ++#define IDMAC_SET_BUFFER1_SIZE(d, s) \ ++ ((d)->des1 = ((d)->des1 & 0x03ffe000) | ((s) & 0x1fff)) ++ ++ u32 des2; /* buffer 1 physical address */ ++ ++ u32 des3; /* buffer 2 physical address */ ++}; ++#endif /* CONFIG_MMC_DW_IDMAC */ ++ ++static bool dw_mci_reset(struct dw_mci *host); ++ ++#if defined(CONFIG_DEBUG_FS) ++static int dw_mci_req_show(struct seq_file *s, void *v) ++{ ++ struct dw_mci_slot *slot = s->private; ++ struct mmc_request *mrq; ++ struct mmc_command *cmd; ++ struct mmc_command *stop; ++ struct mmc_data *data; ++ ++ /* Make sure we get a consistent snapshot */ ++ spin_lock_bh(&slot->host->lock); ++ mrq = slot->mrq; ++ ++ if (mrq) { ++ cmd = mrq->cmd; ++ data = mrq->data; ++ stop = mrq->stop; ++ ++ if (cmd) ++ seq_printf(s, ++ "CMD%u(0x%x) flg %x rsp %x %x %x %x err %d\n", ++ cmd->opcode, cmd->arg, cmd->flags, ++ cmd->resp[0], cmd->resp[1], cmd->resp[2], ++ cmd->resp[2], cmd->error); ++ if (data) ++ seq_printf(s, "DATA %u / %u * %u flg %x err %d\n", ++ data->bytes_xfered, data->blocks, ++ data->blksz, data->flags, data->error); ++ if (stop) ++ seq_printf(s, ++ "CMD%u(0x%x) flg %x rsp %x %x %x %x err %d\n", ++ stop->opcode, stop->arg, stop->flags, ++ stop->resp[0], stop->resp[1], stop->resp[2], ++ stop->resp[2], stop->error); ++ } ++ ++ spin_unlock_bh(&slot->host->lock); ++ ++ return 0; ++} ++ ++static int dw_mci_req_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, dw_mci_req_show, inode->i_private); ++} ++ ++static const struct file_operations dw_mci_req_fops = { ++ .owner = THIS_MODULE, ++ .open = dw_mci_req_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++ ++static int dw_mci_regs_show(struct seq_file *s, void *v) ++{ ++ seq_printf(s, "STATUS:\t0x%08x\n", SDMMC_STATUS); ++ seq_printf(s, "RINTSTS:\t0x%08x\n", SDMMC_RINTSTS); ++ seq_printf(s, "CMD:\t0x%08x\n", SDMMC_CMD); ++ seq_printf(s, "CTRL:\t0x%08x\n", SDMMC_CTRL); ++ seq_printf(s, "INTMASK:\t0x%08x\n", SDMMC_INTMASK); ++ seq_printf(s, "CLKENA:\t0x%08x\n", SDMMC_CLKENA); ++ ++ return 0; ++} ++ ++static int dw_mci_regs_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, dw_mci_regs_show, inode->i_private); ++} ++ ++static const struct file_operations dw_mci_regs_fops = { ++ .owner = THIS_MODULE, ++ .open = dw_mci_regs_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++ ++static void dw_mci_init_debugfs(struct dw_mci_slot *slot) ++{ ++ struct mmc_host *mmc = slot->mmc; ++ struct dw_mci *host = slot->host; ++ struct dentry *root; ++ struct dentry *node; ++ ++ root = mmc->debugfs_root; ++ if (!root) ++ return; ++ ++ node = debugfs_create_file("regs", S_IRUSR, root, host, ++ &dw_mci_regs_fops); ++ if (!node) ++ goto err; ++ ++ node = debugfs_create_file("req", S_IRUSR, root, slot, ++ &dw_mci_req_fops); ++ if (!node) ++ goto err; ++ ++ node = debugfs_create_u32("state", S_IRUSR, root, (u32 *)&host->state); ++ if (!node) ++ goto err; ++ ++ node = debugfs_create_x32("pending_events", S_IRUSR, root, ++ (u32 *)&host->pending_events); ++ if (!node) ++ goto err; ++ ++ node = debugfs_create_x32("completed_events", S_IRUSR, root, ++ (u32 *)&host->completed_events); ++ if (!node) ++ goto err; ++ ++ return; ++ ++err: ++ dev_err(&mmc->class_dev, "failed to initialize debugfs for slot\n"); ++} ++#endif /* defined(CONFIG_DEBUG_FS) */ ++ ++static void mci_send_cmd(struct dw_mci_slot *slot, u32 cmd, u32 arg); ++ ++static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd) ++{ ++ struct mmc_data *data; ++ struct dw_mci_slot *slot = mmc_priv(mmc); ++ struct dw_mci *host = slot->host; ++ const struct dw_mci_drv_data *drv_data = slot->host->drv_data; ++ u32 cmdr; ++ cmd->error = -EINPROGRESS; ++ ++ cmdr = cmd->opcode; ++ ++ if (cmd->opcode == MMC_STOP_TRANSMISSION || ++ cmd->opcode == MMC_GO_IDLE_STATE || ++ cmd->opcode == MMC_GO_INACTIVE_STATE || ++ (cmd->opcode == SD_IO_RW_DIRECT && ++ ((cmd->arg >> 9) & 0x1FFFF) == SDIO_CCCR_ABORT)) ++ cmdr |= SDMMC_CMD_STOP; ++ else if (cmd->opcode != MMC_SEND_STATUS && cmd->data) ++ cmdr |= SDMMC_CMD_PRV_DAT_WAIT; ++ ++ if (cmd->opcode == SD_SWITCH_VOLTAGE) { ++ u32 clk_en_a; ++ ++ /* Special bit makes CMD11 not die */ ++ cmdr |= SDMMC_CMD_VOLT_SWITCH; ++ ++ /* Change state to continue to handle CMD11 weirdness */ ++ WARN_ON(slot->host->state != STATE_SENDING_CMD); ++ slot->host->state = STATE_SENDING_CMD11; ++ ++ /* ++ * We need to disable low power mode (automatic clock stop) ++ * while doing voltage switch so we don't confuse the card, ++ * since stopping the clock is a specific part of the UHS ++ * voltage change dance. ++ * ++ * Note that low power mode (SDMMC_CLKEN_LOW_PWR) will be ++ * unconditionally turned back on in dw_mci_setup_bus() if it's ++ * ever called with a non-zero clock. That shouldn't happen ++ * until the voltage change is all done. ++ */ ++ clk_en_a = mci_readl(host, CLKENA); ++ clk_en_a &= ~(SDMMC_CLKEN_LOW_PWR << slot->id); ++ mci_writel(host, CLKENA, clk_en_a); ++ mci_send_cmd(slot, SDMMC_CMD_UPD_CLK | ++ SDMMC_CMD_PRV_DAT_WAIT, 0); ++ } ++ ++ if (cmd->flags & MMC_RSP_PRESENT) { ++ /* We expect a response, so set this bit */ ++ cmdr |= SDMMC_CMD_RESP_EXP; ++ if (cmd->flags & MMC_RSP_136) ++ cmdr |= SDMMC_CMD_RESP_LONG; ++ } ++ ++ if (cmd->flags & MMC_RSP_CRC) ++ cmdr |= SDMMC_CMD_RESP_CRC; ++ ++ data = cmd->data; ++ if (data) { ++ cmdr |= SDMMC_CMD_DAT_EXP; ++ if (data->flags & MMC_DATA_STREAM) ++ cmdr |= SDMMC_CMD_STRM_MODE; ++ if (data->flags & MMC_DATA_WRITE) ++ cmdr |= SDMMC_CMD_DAT_WR; ++ } ++ ++ if (drv_data && drv_data->prepare_command) ++ drv_data->prepare_command(slot->host, &cmdr); ++ ++ return cmdr; ++} ++ ++static u32 dw_mci_prep_stop_abort(struct dw_mci *host, struct mmc_command *cmd) ++{ ++ struct mmc_command *stop; ++ u32 cmdr; ++ ++ if (!cmd->data) ++ return 0; ++ ++ stop = &host->stop_abort; ++ cmdr = cmd->opcode; ++ memset(stop, 0, sizeof(struct mmc_command)); ++ ++ if (cmdr == MMC_READ_SINGLE_BLOCK || ++ cmdr == MMC_READ_MULTIPLE_BLOCK || ++ cmdr == MMC_WRITE_BLOCK || ++ cmdr == MMC_WRITE_MULTIPLE_BLOCK) { ++ stop->opcode = MMC_STOP_TRANSMISSION; ++ stop->arg = 0; ++ stop->flags = MMC_RSP_R1B | MMC_CMD_AC; ++ } else if (cmdr == SD_IO_RW_EXTENDED) { ++ stop->opcode = SD_IO_RW_DIRECT; ++ stop->arg |= (1 << 31) | (0 << 28) | (SDIO_CCCR_ABORT << 9) | ++ ((cmd->arg >> 28) & 0x7); ++ stop->flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_AC; ++ } else { ++ return 0; ++ } ++ ++ cmdr = stop->opcode | SDMMC_CMD_STOP | ++ SDMMC_CMD_RESP_CRC | SDMMC_CMD_RESP_EXP; ++ ++ return cmdr; ++} ++ ++static void dw_mci_start_command(struct dw_mci *host, ++ struct mmc_command *cmd, u32 cmd_flags) ++{ ++ host->cmd = cmd; ++ dev_vdbg(host->dev, ++ "start command: ARGR=0x%08x CMDR=0x%08x\n", ++ cmd->arg, cmd_flags); ++ ++ mci_writel(host, CMDARG, cmd->arg); ++ wmb(); ++ ++ mci_writel(host, CMD, cmd_flags | SDMMC_CMD_START); ++} ++ ++static inline void send_stop_abort(struct dw_mci *host, struct mmc_data *data) ++{ ++ struct mmc_command *stop = data->stop ? data->stop : &host->stop_abort; ++ dw_mci_start_command(host, stop, host->stop_cmdr); ++} ++ ++/* DMA interface functions */ ++static void dw_mci_stop_dma(struct dw_mci *host) ++{ ++ if (host->using_dma) { ++ host->dma_ops->stop(host); ++ host->dma_ops->cleanup(host); ++ } ++ ++ /* Data transfer was stopped by the interrupt handler */ ++ set_bit(EVENT_XFER_COMPLETE, &host->pending_events); ++} ++ ++static int dw_mci_get_dma_dir(struct mmc_data *data) ++{ ++ if (data->flags & MMC_DATA_WRITE) ++ return DMA_TO_DEVICE; ++ else ++ return DMA_FROM_DEVICE; ++} ++ ++#ifdef CONFIG_MMC_DW_IDMAC ++static void dw_mci_dma_cleanup(struct dw_mci *host) ++{ ++ struct mmc_data *data = host->data; ++ ++ if (data) ++ if (!data->host_cookie) ++ dma_unmap_sg(host->dev, ++ data->sg, ++ data->sg_len, ++ dw_mci_get_dma_dir(data)); ++} ++ ++static void dw_mci_idmac_reset(struct dw_mci *host) ++{ ++ u32 bmod = mci_readl(host, BMOD); ++ /* Software reset of DMA */ ++ bmod |= SDMMC_IDMAC_SWRESET; ++ mci_writel(host, BMOD, bmod); ++} ++ ++static void dw_mci_idmac_stop_dma(struct dw_mci *host) ++{ ++ u32 temp; ++ ++ /* Disable and reset the IDMAC interface */ ++ temp = mci_readl(host, CTRL); ++ temp &= ~SDMMC_CTRL_USE_IDMAC; ++ temp |= SDMMC_CTRL_DMA_RESET; ++ mci_writel(host, CTRL, temp); ++ ++ /* Stop the IDMAC running */ ++ temp = mci_readl(host, BMOD); ++ temp &= ~(SDMMC_IDMAC_ENABLE | SDMMC_IDMAC_FB); ++ temp |= SDMMC_IDMAC_SWRESET; ++ mci_writel(host, BMOD, temp); ++} ++ ++static void dw_mci_idmac_complete_dma(struct dw_mci *host) ++{ ++ struct mmc_data *data = host->data; ++ ++ dev_vdbg(host->dev, "DMA complete\n"); ++ ++ host->dma_ops->cleanup(host); ++ ++ /* ++ * If the card was removed, data will be NULL. No point in trying to ++ * send the stop command or waiting for NBUSY in this case. ++ */ ++ if (data) { ++ set_bit(EVENT_XFER_COMPLETE, &host->pending_events); ++ tasklet_schedule(&host->tasklet); ++ } ++} ++ ++static void dw_mci_translate_sglist(struct dw_mci *host, struct mmc_data *data, ++ unsigned int sg_len) ++{ ++ int i; ++ struct idmac_desc *desc = host->sg_cpu; ++ ++ for (i = 0; i < sg_len; i++, desc++) { ++ unsigned int length = sg_dma_len(&data->sg[i]); ++ u32 mem_addr = sg_dma_address(&data->sg[i]); ++ ++ /* Set the OWN bit and disable interrupts for this descriptor */ ++ desc->des0 = IDMAC_DES0_OWN | IDMAC_DES0_DIC | IDMAC_DES0_CH; ++ ++ /* Buffer length */ ++ IDMAC_SET_BUFFER1_SIZE(desc, length); ++ ++ /* Physical address to DMA to/from */ ++ desc->des2 = mem_addr; ++ } ++ ++ /* Set first descriptor */ ++ desc = host->sg_cpu; ++ desc->des0 |= IDMAC_DES0_FD; ++ ++ /* Set last descriptor */ ++ desc = host->sg_cpu + (i - 1) * sizeof(struct idmac_desc); ++ desc->des0 &= ~(IDMAC_DES0_CH | IDMAC_DES0_DIC); ++ desc->des0 |= IDMAC_DES0_LD; ++ ++ wmb(); ++} ++ ++static void dw_mci_idmac_start_dma(struct dw_mci *host, unsigned int sg_len) ++{ ++ u32 temp; ++ ++ dw_mci_translate_sglist(host, host->data, sg_len); ++ ++ /* Select IDMAC interface */ ++ temp = mci_readl(host, CTRL); ++ temp |= SDMMC_CTRL_USE_IDMAC; ++ mci_writel(host, CTRL, temp); ++ ++ wmb(); ++ ++ /* Enable the IDMAC */ ++ temp = mci_readl(host, BMOD); ++ temp |= SDMMC_IDMAC_ENABLE | SDMMC_IDMAC_FB; ++ mci_writel(host, BMOD, temp); ++ ++ /* Start it running */ ++ mci_writel(host, PLDMND, 1); ++} ++ ++static int dw_mci_idmac_init(struct dw_mci *host) ++{ ++ struct idmac_desc *p; ++ int i; ++ ++ /* Number of descriptors in the ring buffer */ ++ host->ring_size = PAGE_SIZE / sizeof(struct idmac_desc); ++ ++ /* Forward link the descriptor list */ ++ for (i = 0, p = host->sg_cpu; i < host->ring_size - 1; i++, p++) ++ p->des3 = host->sg_dma + (sizeof(struct idmac_desc) * (i + 1)); ++ ++ /* Set the last descriptor as the end-of-ring descriptor */ ++ p->des3 = host->sg_dma; ++ p->des0 = IDMAC_DES0_ER; ++ ++ dw_mci_idmac_reset(host); ++ ++ /* Mask out interrupts - get Tx & Rx complete only */ ++ mci_writel(host, IDSTS, IDMAC_INT_CLR); ++ mci_writel(host, IDINTEN, SDMMC_IDMAC_INT_NI | SDMMC_IDMAC_INT_RI | ++ SDMMC_IDMAC_INT_TI); ++ ++ /* Set the descriptor base address */ ++ mci_writel(host, DBADDR, host->sg_dma); ++ return 0; ++} ++ ++static const struct dw_mci_dma_ops dw_mci_idmac_ops = { ++ .init = dw_mci_idmac_init, ++ .start = dw_mci_idmac_start_dma, ++ .stop = dw_mci_idmac_stop_dma, ++ .complete = dw_mci_idmac_complete_dma, ++ .cleanup = dw_mci_dma_cleanup, ++}; ++#endif /* CONFIG_MMC_DW_IDMAC */ ++ ++static int dw_mci_pre_dma_transfer(struct dw_mci *host, ++ struct mmc_data *data, ++ bool next) ++{ ++ struct scatterlist *sg; ++ unsigned int i, sg_len; ++ ++ if (!next && data->host_cookie) ++ return data->host_cookie; ++ ++ /* ++ * We don't do DMA on "complex" transfers, i.e. with ++ * non-word-aligned buffers or lengths. Also, we don't bother ++ * with all the DMA setup overhead for short transfers. ++ */ ++ if (data->blocks * data->blksz < DW_MCI_DMA_THRESHOLD) ++ return -EINVAL; ++ ++ if (data->blksz & 3) ++ return -EINVAL; ++ ++ for_each_sg(data->sg, sg, data->sg_len, i) { ++ if (sg->offset & 3 || sg->length & 3) ++ return -EINVAL; ++ } ++ ++ sg_len = dma_map_sg(host->dev, ++ data->sg, ++ data->sg_len, ++ dw_mci_get_dma_dir(data)); ++ if (sg_len == 0) ++ return -EINVAL; ++ ++ if (next) ++ data->host_cookie = sg_len; ++ ++ return sg_len; ++} ++ ++static void dw_mci_pre_req(struct mmc_host *mmc, ++ struct mmc_request *mrq, ++ bool is_first_req) ++{ ++ struct dw_mci_slot *slot = mmc_priv(mmc); ++ struct mmc_data *data = mrq->data; ++ ++ if (!slot->host->use_dma || !data) ++ return; ++ ++ if (data->host_cookie) { ++ data->host_cookie = 0; ++ return; ++ } ++ ++ if (dw_mci_pre_dma_transfer(slot->host, mrq->data, 1) < 0) ++ data->host_cookie = 0; ++} ++ ++static void dw_mci_post_req(struct mmc_host *mmc, ++ struct mmc_request *mrq, ++ int err) ++{ ++ struct dw_mci_slot *slot = mmc_priv(mmc); ++ struct mmc_data *data = mrq->data; ++ ++ if (!slot->host->use_dma || !data) ++ return; ++ ++ if (data->host_cookie) ++ dma_unmap_sg(slot->host->dev, ++ data->sg, ++ data->sg_len, ++ dw_mci_get_dma_dir(data)); ++ data->host_cookie = 0; ++} ++ ++static void dw_mci_adjust_fifoth(struct dw_mci *host, struct mmc_data *data) ++{ ++#ifdef CONFIG_MMC_DW_IDMAC ++ unsigned int blksz = data->blksz; ++ const u32 mszs[] = {1, 4, 8, 16, 32, 64, 128, 256}; ++ u32 fifo_width = 1 << host->data_shift; ++ u32 blksz_depth = blksz / fifo_width, fifoth_val; ++ u32 msize = 0, rx_wmark = 1, tx_wmark, tx_wmark_invers; ++ int idx = (sizeof(mszs) / sizeof(mszs[0])) - 1; ++ ++ tx_wmark = (host->fifo_depth) / 2; ++ tx_wmark_invers = host->fifo_depth - tx_wmark; ++ ++ /* ++ * MSIZE is '1', ++ * if blksz is not a multiple of the FIFO width ++ */ ++ if (blksz % fifo_width) { ++ msize = 0; ++ rx_wmark = 1; ++ goto done; ++ } ++ ++ do { ++ if (!((blksz_depth % mszs[idx]) || ++ (tx_wmark_invers % mszs[idx]))) { ++ msize = idx; ++ rx_wmark = mszs[idx] - 1; ++ break; ++ } ++ } while (--idx > 0); ++ /* ++ * If idx is '0', it won't be tried ++ * Thus, initial values are uesed ++ */ ++done: ++ fifoth_val = SDMMC_SET_FIFOTH(msize, rx_wmark, tx_wmark); ++ mci_writel(host, FIFOTH, fifoth_val); ++#endif ++} ++ ++static void dw_mci_ctrl_rd_thld(struct dw_mci *host, struct mmc_data *data) ++{ ++ unsigned int blksz = data->blksz; ++ u32 blksz_depth, fifo_depth; ++ u16 thld_size; ++ ++ WARN_ON(!(data->flags & MMC_DATA_READ)); ++ ++ /* ++ * CDTHRCTL doesn't exist prior to 240A (in fact that register offset is ++ * in the FIFO region, so we really shouldn't access it). ++ */ ++ if (host->verid < DW_MMC_240A) ++ return; ++ ++ if (host->timing != MMC_TIMING_MMC_HS200 && ++ host->timing != MMC_TIMING_UHS_SDR104) ++ goto disable; ++ ++ blksz_depth = blksz / (1 << host->data_shift); ++ fifo_depth = host->fifo_depth; ++ ++ if (blksz_depth > fifo_depth) ++ goto disable; ++ ++ /* ++ * If (blksz_depth) >= (fifo_depth >> 1), should be 'thld_size <= blksz' ++ * If (blksz_depth) < (fifo_depth >> 1), should be thld_size = blksz ++ * Currently just choose blksz. ++ */ ++ thld_size = blksz; ++ mci_writel(host, CDTHRCTL, SDMMC_SET_RD_THLD(thld_size, 1)); ++ return; ++ ++disable: ++ mci_writel(host, CDTHRCTL, SDMMC_SET_RD_THLD(0, 0)); ++} ++ ++static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data) ++{ ++ int sg_len; ++ u32 temp; ++ ++ host->using_dma = 0; ++ ++ /* If we don't have a channel, we can't do DMA */ ++ if (!host->use_dma) ++ return -ENODEV; ++ ++ sg_len = dw_mci_pre_dma_transfer(host, data, 0); ++ if (sg_len < 0) { ++ host->dma_ops->stop(host); ++ return sg_len; ++ } ++ ++ host->using_dma = 1; ++ ++ dev_vdbg(host->dev, ++ "sd sg_cpu: %#lx sg_dma: %#lx sg_len: %d\n", ++ (unsigned long)host->sg_cpu, (unsigned long)host->sg_dma, ++ sg_len); ++ ++ /* ++ * Decide the MSIZE and RX/TX Watermark. ++ * If current block size is same with previous size, ++ * no need to update fifoth. ++ */ ++ if (host->prev_blksz != data->blksz) ++ dw_mci_adjust_fifoth(host, data); ++ ++ /* Enable the DMA interface */ ++ temp = mci_readl(host, CTRL); ++ temp |= SDMMC_CTRL_DMA_ENABLE; ++ mci_writel(host, CTRL, temp); ++ ++ /* Disable RX/TX IRQs, let DMA handle it */ ++ temp = mci_readl(host, INTMASK); ++ temp &= ~(SDMMC_INT_RXDR | SDMMC_INT_TXDR); ++ mci_writel(host, INTMASK, temp); ++ ++ host->dma_ops->start(host, sg_len); ++ ++ return 0; ++} ++ ++static void dw_mci_submit_data(struct dw_mci *host, struct mmc_data *data) ++{ ++ u32 temp; ++ ++ data->error = -EINPROGRESS; ++ ++ WARN_ON(host->data); ++ host->sg = NULL; ++ host->data = data; ++ ++ if (data->flags & MMC_DATA_READ) { ++ host->dir_status = DW_MCI_RECV_STATUS; ++ dw_mci_ctrl_rd_thld(host, data); ++ } else { ++ host->dir_status = DW_MCI_SEND_STATUS; ++ } ++ ++ if (dw_mci_submit_data_dma(host, data)) { ++ int flags = SG_MITER_ATOMIC; ++ if (host->data->flags & MMC_DATA_READ) ++ flags |= SG_MITER_TO_SG; ++ else ++ flags |= SG_MITER_FROM_SG; ++ ++ sg_miter_start(&host->sg_miter, data->sg, data->sg_len, flags); ++ host->sg = data->sg; ++ host->part_buf_start = 0; ++ host->part_buf_count = 0; ++ ++ mci_writel(host, RINTSTS, SDMMC_INT_TXDR | SDMMC_INT_RXDR); ++ temp = mci_readl(host, INTMASK); ++ temp |= SDMMC_INT_TXDR | SDMMC_INT_RXDR; ++ mci_writel(host, INTMASK, temp); ++ ++ temp = mci_readl(host, CTRL); ++ temp &= ~SDMMC_CTRL_DMA_ENABLE; ++ mci_writel(host, CTRL, temp); ++ ++ /* ++ * Use the initial fifoth_val for PIO mode. ++ * If next issued data may be transfered by DMA mode, ++ * prev_blksz should be invalidated. ++ */ ++ mci_writel(host, FIFOTH, host->fifoth_val); ++ host->prev_blksz = 0; ++ } else { ++ /* ++ * Keep the current block size. ++ * It will be used to decide whether to update ++ * fifoth register next time. ++ */ ++ host->prev_blksz = data->blksz; ++ } ++} ++ ++static void mci_send_cmd(struct dw_mci_slot *slot, u32 cmd, u32 arg) ++{ ++ struct dw_mci *host = slot->host; ++ unsigned long timeout = jiffies + msecs_to_jiffies(500); ++ unsigned int cmd_status = 0; ++ ++ mci_writel(host, CMDARG, arg); ++ wmb(); ++ mci_writel(host, CMD, SDMMC_CMD_START | cmd); ++ ++ while (time_before(jiffies, timeout)) { ++ cmd_status = mci_readl(host, CMD); ++ if (!(cmd_status & SDMMC_CMD_START)) ++ return; ++ } ++ dev_err(&slot->mmc->class_dev, ++ "Timeout sending command (cmd %#x arg %#x status %#x)\n", ++ cmd, arg, cmd_status); ++} ++ ++static void dw_mci_setup_bus(struct dw_mci_slot *slot, bool force_clkinit) ++{ ++ struct dw_mci *host = slot->host; ++ unsigned int clock = slot->clock; ++ u32 div; ++ u32 clk_en_a; ++ u32 sdmmc_cmd_bits = SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT; ++ ++ /* We must continue to set bit 28 in CMD until the change is complete */ ++ if (host->state == STATE_WAITING_CMD11_DONE) ++ sdmmc_cmd_bits |= SDMMC_CMD_VOLT_SWITCH; ++ ++ if (!clock) { ++ mci_writel(host, CLKENA, 0); ++ mci_send_cmd(slot, sdmmc_cmd_bits, 0); ++ } else if (clock != host->current_speed || force_clkinit) { ++ div = host->bus_hz / clock; ++ if (host->bus_hz % clock && host->bus_hz > clock) ++ /* ++ * move the + 1 after the divide to prevent ++ * over-clocking the card. ++ */ ++ div += 1; ++ ++ div = (host->bus_hz != clock) ? DIV_ROUND_UP(div, 2) : 0; ++ ++ if ((clock << div) != slot->__clk_old || force_clkinit) ++ dev_info(&slot->mmc->class_dev, ++ "Bus speed (slot %d) = %dHz (slot req %dHz, actual %dHZ div = %d)\n", ++ slot->id, host->bus_hz, clock, ++ div ? ((host->bus_hz / div) >> 1) : ++ host->bus_hz, div); ++ ++ /* disable clock */ ++ mci_writel(host, CLKENA, 0); ++ mci_writel(host, CLKSRC, 0); ++ ++ /* inform CIU */ ++ mci_send_cmd(slot, sdmmc_cmd_bits, 0); ++ ++ /* set clock to desired speed */ ++ mci_writel(host, CLKDIV, div); ++ ++ /* inform CIU */ ++ mci_send_cmd(slot, sdmmc_cmd_bits, 0); ++ ++ /* enable clock; only low power if no SDIO */ ++ clk_en_a = SDMMC_CLKEN_ENABLE << slot->id; ++ if (!(mci_readl(host, INTMASK) & SDMMC_INT_SDIO(slot->id))) ++ clk_en_a |= SDMMC_CLKEN_LOW_PWR << slot->id; ++ mci_writel(host, CLKENA, clk_en_a); ++ ++ /* inform CIU */ ++ mci_send_cmd(slot, sdmmc_cmd_bits, 0); ++ ++ /* keep the clock with reflecting clock dividor */ ++ slot->__clk_old = clock << div; ++ } ++ ++ host->current_speed = clock; ++ ++ /* Set the current slot bus width */ ++ mci_writel(host, CTYPE, (slot->ctype << slot->id)); ++} ++ ++static void __dw_mci_start_request(struct dw_mci *host, ++ struct dw_mci_slot *slot, ++ struct mmc_command *cmd) ++{ ++ struct mmc_request *mrq; ++ struct mmc_data *data; ++ u32 cmdflags; ++ ++ mrq = slot->mrq; ++ ++ host->cur_slot = slot; ++ host->mrq = mrq; ++ ++ host->pending_events = 0; ++ host->completed_events = 0; ++ host->cmd_status = 0; ++ host->data_status = 0; ++ host->dir_status = 0; ++ ++ data = cmd->data; ++ if (data) { ++ mci_writel(host, TMOUT, 0xFFFFFFFF); ++ mci_writel(host, BYTCNT, data->blksz*data->blocks); ++ mci_writel(host, BLKSIZ, data->blksz); ++ } ++ ++ cmdflags = dw_mci_prepare_command(slot->mmc, cmd); ++ ++ /* this is the first command, send the initialization clock */ ++ if (test_and_clear_bit(DW_MMC_CARD_NEED_INIT, &slot->flags)) ++ cmdflags |= SDMMC_CMD_INIT; ++ ++ if (data) { ++ dw_mci_submit_data(host, data); ++ wmb(); ++ } ++ ++ dw_mci_start_command(host, cmd, cmdflags); ++ ++ if (mrq->stop) ++ host->stop_cmdr = dw_mci_prepare_command(slot->mmc, mrq->stop); ++ else ++ host->stop_cmdr = dw_mci_prep_stop_abort(host, cmd); ++} ++ ++static void dw_mci_start_request(struct dw_mci *host, ++ struct dw_mci_slot *slot) ++{ ++ struct mmc_request *mrq = slot->mrq; ++ struct mmc_command *cmd; ++ ++ cmd = mrq->sbc ? mrq->sbc : mrq->cmd; ++ __dw_mci_start_request(host, slot, cmd); ++} ++ ++/* must be called with host->lock held */ ++static void dw_mci_queue_request(struct dw_mci *host, struct dw_mci_slot *slot, ++ struct mmc_request *mrq) ++{ ++ dev_vdbg(&slot->mmc->class_dev, "queue request: state=%d\n", ++ host->state); ++ ++ slot->mrq = mrq; ++ ++ if (host->state == STATE_WAITING_CMD11_DONE) { ++ dev_warn(&slot->mmc->class_dev, ++ "Voltage change didn't complete\n"); ++ /* ++ * this case isn't expected to happen, so we can ++ * either crash here or just try to continue on ++ * in the closest possible state ++ */ ++ host->state = STATE_IDLE; ++ } ++ ++ if (host->state == STATE_IDLE) { ++ host->state = STATE_SENDING_CMD; ++ dw_mci_start_request(host, slot); ++ } else { ++ list_add_tail(&slot->queue_node, &host->queue); ++ } ++} ++ ++static void dw_mci_request(struct mmc_host *mmc, struct mmc_request *mrq) ++{ ++ struct dw_mci_slot *slot = mmc_priv(mmc); ++ struct dw_mci *host = slot->host; ++ ++ WARN_ON(slot->mrq); ++ ++ /* ++ * The check for card presence and queueing of the request must be ++ * atomic, otherwise the card could be removed in between and the ++ * request wouldn't fail until another card was inserted. ++ */ ++ spin_lock_bh(&host->lock); ++ ++ if (!test_bit(DW_MMC_CARD_PRESENT, &slot->flags)) { ++ spin_unlock_bh(&host->lock); ++ mrq->cmd->error = -ENOMEDIUM; ++ mmc_request_done(mmc, mrq); ++ return; ++ } ++ ++ dw_mci_queue_request(host, slot, mrq); ++ ++ spin_unlock_bh(&host->lock); ++} ++ ++static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) ++{ ++ struct dw_mci_slot *slot = mmc_priv(mmc); ++ const struct dw_mci_drv_data *drv_data = slot->host->drv_data; ++ u32 regs; ++ int ret; ++ ++ switch (ios->bus_width) { ++ case MMC_BUS_WIDTH_4: ++ slot->ctype = SDMMC_CTYPE_4BIT; ++ break; ++ case MMC_BUS_WIDTH_8: ++ slot->ctype = SDMMC_CTYPE_8BIT; ++ break; ++ default: ++ /* set default 1 bit mode */ ++ slot->ctype = SDMMC_CTYPE_1BIT; ++ } ++ ++ regs = mci_readl(slot->host, UHS_REG); ++ ++ /* DDR mode set */ ++ if (ios->timing == MMC_TIMING_MMC_DDR52) ++ regs |= ((0x1 << slot->id) << 16); ++ else ++ regs &= ~((0x1 << slot->id) << 16); ++ ++ mci_writel(slot->host, UHS_REG, regs); ++ slot->host->timing = ios->timing; ++ ++ /* ++ * Use mirror of ios->clock to prevent race with mmc ++ * core ios update when finding the minimum. ++ */ ++ slot->clock = ios->clock; ++ ++ if (drv_data && drv_data->set_ios) ++ drv_data->set_ios(slot->host, ios); ++ ++ /* Slot specific timing and width adjustment */ ++ dw_mci_setup_bus(slot, false); ++ ++ if (slot->host->state == STATE_WAITING_CMD11_DONE && ios->clock != 0) ++ slot->host->state = STATE_IDLE; ++ ++ switch (ios->power_mode) { ++ case MMC_POWER_UP: ++ if (!IS_ERR(mmc->supply.vmmc)) { ++ ret = mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, ++ ios->vdd); ++ if (ret) { ++ dev_err(slot->host->dev, ++ "failed to enable vmmc regulator\n"); ++ /*return, if failed turn on vmmc*/ ++ return; ++ } ++ } ++ if (!IS_ERR(mmc->supply.vqmmc) && !slot->host->vqmmc_enabled) { ++ ret = regulator_enable(mmc->supply.vqmmc); ++ if (ret < 0) ++ dev_err(slot->host->dev, ++ "failed to enable vqmmc regulator\n"); ++ else ++ slot->host->vqmmc_enabled = true; ++ } ++ set_bit(DW_MMC_CARD_NEED_INIT, &slot->flags); ++ regs = mci_readl(slot->host, PWREN); ++ regs |= (1 << slot->id); ++ mci_writel(slot->host, PWREN, regs); ++ break; ++ case MMC_POWER_OFF: ++ if (!IS_ERR(mmc->supply.vmmc)) ++ mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0); ++ ++ if (!IS_ERR(mmc->supply.vqmmc) && slot->host->vqmmc_enabled) { ++ regulator_disable(mmc->supply.vqmmc); ++ slot->host->vqmmc_enabled = false; ++ } ++ ++ regs = mci_readl(slot->host, PWREN); ++ regs &= ~(1 << slot->id); ++ mci_writel(slot->host, PWREN, regs); ++ break; ++ default: ++ break; ++ } ++} ++ ++static int dw_mci_card_busy(struct mmc_host *mmc) ++{ ++ struct dw_mci_slot *slot = mmc_priv(mmc); ++ u32 status; ++ ++ /* ++ * Check the busy bit which is low when DAT[3:0] ++ * (the data lines) are 0000 ++ */ ++ status = mci_readl(slot->host, STATUS); ++ ++ return !!(status & SDMMC_STATUS_BUSY); ++} ++ ++static int dw_mci_switch_voltage(struct mmc_host *mmc, struct mmc_ios *ios) ++{ ++ struct dw_mci_slot *slot = mmc_priv(mmc); ++ struct dw_mci *host = slot->host; ++ u32 uhs; ++ u32 v18 = SDMMC_UHS_18V << slot->id; ++ int min_uv, max_uv; ++ int ret; ++ ++ /* ++ * Program the voltage. Note that some instances of dw_mmc may use ++ * the UHS_REG for this. For other instances (like exynos) the UHS_REG ++ * does no harm but you need to set the regulator directly. Try both. ++ */ ++ uhs = mci_readl(host, UHS_REG); ++ if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) { ++ min_uv = 2700000; ++ max_uv = 3600000; ++ uhs &= ~v18; ++ } else { ++ min_uv = 1700000; ++ max_uv = 1950000; ++ uhs |= v18; ++ } ++ if (!IS_ERR(mmc->supply.vqmmc)) { ++ ret = regulator_set_voltage(mmc->supply.vqmmc, min_uv, max_uv); ++ ++ if (ret) { ++ dev_err(&mmc->class_dev, ++ "Regulator set error %d: %d - %d\n", ++ ret, min_uv, max_uv); ++ return ret; ++ } ++ } ++ mci_writel(host, UHS_REG, uhs); ++ ++ return 0; ++} ++ ++static int dw_mci_get_ro(struct mmc_host *mmc) ++{ ++ int read_only; ++ struct dw_mci_slot *slot = mmc_priv(mmc); ++ int gpio_ro = mmc_gpio_get_ro(mmc); ++ ++ /* Use platform get_ro function, else try on board write protect */ ++ if ((slot->quirks & DW_MCI_SLOT_QUIRK_NO_WRITE_PROTECT) || ++ (slot->host->quirks & DW_MCI_QUIRK_NO_WRITE_PROTECT)) ++ read_only = 0; ++ else if (!IS_ERR_VALUE(gpio_ro)) ++ read_only = gpio_ro; ++ else ++ read_only = ++ mci_readl(slot->host, WRTPRT) & (1 << slot->id) ? 1 : 0; ++ ++ dev_dbg(&mmc->class_dev, "card is %s\n", ++ read_only ? "read-only" : "read-write"); ++ ++ return read_only; ++} ++ ++static int dw_mci_get_cd(struct mmc_host *mmc) ++{ ++ int present; ++ struct dw_mci_slot *slot = mmc_priv(mmc); ++ struct dw_mci_board *brd = slot->host->pdata; ++ struct dw_mci *host = slot->host; ++ int gpio_cd = mmc_gpio_get_cd(mmc); ++ ++ /* Use platform get_cd function, else try onboard card detect */ ++ if (brd->quirks & DW_MCI_QUIRK_BROKEN_CARD_DETECTION) ++ present = 1; ++ else if (!IS_ERR_VALUE(gpio_cd)) ++ present = gpio_cd; ++ else ++ present = (mci_readl(slot->host, CDETECT) & (1 << slot->id)) ++ == 0 ? 1 : 0; ++ ++ spin_lock_bh(&host->lock); ++ if (present) { ++ set_bit(DW_MMC_CARD_PRESENT, &slot->flags); ++ dev_dbg(&mmc->class_dev, "card is present\n"); ++ } else { ++ clear_bit(DW_MMC_CARD_PRESENT, &slot->flags); ++ dev_dbg(&mmc->class_dev, "card is not present\n"); ++ } ++ spin_unlock_bh(&host->lock); ++ ++ return present; ++} ++ ++/* ++ * Disable lower power mode. ++ * ++ * Low power mode will stop the card clock when idle. According to the ++ * description of the CLKENA register we should disable low power mode ++ * for SDIO cards if we need SDIO interrupts to work. ++ * ++ * This function is fast if low power mode is already disabled. ++ */ ++static void dw_mci_disable_low_power(struct dw_mci_slot *slot) ++{ ++ struct dw_mci *host = slot->host; ++ u32 clk_en_a; ++ const u32 clken_low_pwr = SDMMC_CLKEN_LOW_PWR << slot->id; ++ ++ clk_en_a = mci_readl(host, CLKENA); ++ ++ if (clk_en_a & clken_low_pwr) { ++ mci_writel(host, CLKENA, clk_en_a & ~clken_low_pwr); ++ mci_send_cmd(slot, SDMMC_CMD_UPD_CLK | ++ SDMMC_CMD_PRV_DAT_WAIT, 0); ++ } ++} ++ ++static void dw_mci_enable_sdio_irq(struct mmc_host *mmc, int enb) ++{ ++ struct dw_mci_slot *slot = mmc_priv(mmc); ++ struct dw_mci *host = slot->host; ++ u32 int_mask; ++ ++ /* Enable/disable Slot Specific SDIO interrupt */ ++ int_mask = mci_readl(host, INTMASK); ++ if (enb) { ++ /* ++ * Turn off low power mode if it was enabled. This is a bit of ++ * a heavy operation and we disable / enable IRQs a lot, so ++ * we'll leave low power mode disabled and it will get ++ * re-enabled again in dw_mci_setup_bus(). ++ */ ++ dw_mci_disable_low_power(slot); ++ ++ mci_writel(host, INTMASK, ++ (int_mask | SDMMC_INT_SDIO(slot->id))); ++ } else { ++ mci_writel(host, INTMASK, ++ (int_mask & ~SDMMC_INT_SDIO(slot->id))); ++ } ++} ++ ++static int dw_mci_execute_tuning(struct mmc_host *mmc, u32 opcode) ++{ ++ struct dw_mci_slot *slot = mmc_priv(mmc); ++ struct dw_mci *host = slot->host; ++ const struct dw_mci_drv_data *drv_data = host->drv_data; ++ struct dw_mci_tuning_data tuning_data; ++ int err = -ENOSYS; ++ ++ if (opcode == MMC_SEND_TUNING_BLOCK_HS200) { ++ if (mmc->ios.bus_width == MMC_BUS_WIDTH_8) { ++ tuning_data.blk_pattern = tuning_blk_pattern_8bit; ++ tuning_data.blksz = sizeof(tuning_blk_pattern_8bit); ++ } else if (mmc->ios.bus_width == MMC_BUS_WIDTH_4) { ++ tuning_data.blk_pattern = tuning_blk_pattern_4bit; ++ tuning_data.blksz = sizeof(tuning_blk_pattern_4bit); ++ } else { ++ return -EINVAL; ++ } ++ } else if (opcode == MMC_SEND_TUNING_BLOCK) { ++ tuning_data.blk_pattern = tuning_blk_pattern_4bit; ++ tuning_data.blksz = sizeof(tuning_blk_pattern_4bit); ++ } else { ++ dev_err(host->dev, ++ "Undefined command(%d) for tuning\n", opcode); ++ return -EINVAL; ++ } ++ ++ if (drv_data && drv_data->execute_tuning) ++ err = drv_data->execute_tuning(slot, opcode, &tuning_data); ++ return err; ++} ++ ++static const struct mmc_host_ops dw_mci_ops = { ++ .request = dw_mci_request, ++ .pre_req = dw_mci_pre_req, ++ .post_req = dw_mci_post_req, ++ .set_ios = dw_mci_set_ios, ++ .get_ro = dw_mci_get_ro, ++ .get_cd = dw_mci_get_cd, ++ .enable_sdio_irq = dw_mci_enable_sdio_irq, ++ .execute_tuning = dw_mci_execute_tuning, ++ .card_busy = dw_mci_card_busy, ++ .start_signal_voltage_switch = dw_mci_switch_voltage, ++ ++}; ++ ++static void dw_mci_request_end(struct dw_mci *host, struct mmc_request *mrq) ++ __releases(&host->lock) ++ __acquires(&host->lock) ++{ ++ struct dw_mci_slot *slot; ++ struct mmc_host *prev_mmc = host->cur_slot->mmc; ++ ++ WARN_ON(host->cmd || host->data); ++ ++ host->cur_slot->mrq = NULL; ++ host->mrq = NULL; ++ if (!list_empty(&host->queue)) { ++ slot = list_entry(host->queue.next, ++ struct dw_mci_slot, queue_node); ++ list_del(&slot->queue_node); ++ dev_vdbg(host->dev, "list not empty: %s is next\n", ++ mmc_hostname(slot->mmc)); ++ host->state = STATE_SENDING_CMD; ++ dw_mci_start_request(host, slot); ++ } else { ++ dev_vdbg(host->dev, "list empty\n"); ++ ++ if (host->state == STATE_SENDING_CMD11) ++ host->state = STATE_WAITING_CMD11_DONE; ++ else ++ host->state = STATE_IDLE; ++ } ++ ++ spin_unlock(&host->lock); ++ mmc_request_done(prev_mmc, mrq); ++ spin_lock(&host->lock); ++} ++ ++static int dw_mci_command_complete(struct dw_mci *host, struct mmc_command *cmd) ++{ ++ u32 status = host->cmd_status; ++ ++ host->cmd_status = 0; ++ ++ /* Read the response from the card (up to 16 bytes) */ ++ if (cmd->flags & MMC_RSP_PRESENT) { ++ if (cmd->flags & MMC_RSP_136) { ++ cmd->resp[3] = mci_readl(host, RESP0); ++ cmd->resp[2] = mci_readl(host, RESP1); ++ cmd->resp[1] = mci_readl(host, RESP2); ++ cmd->resp[0] = mci_readl(host, RESP3); ++ } else { ++ cmd->resp[0] = mci_readl(host, RESP0); ++ cmd->resp[1] = 0; ++ cmd->resp[2] = 0; ++ cmd->resp[3] = 0; ++ } ++ } ++ ++ if (status & SDMMC_INT_RTO) ++ cmd->error = -ETIMEDOUT; ++ else if ((cmd->flags & MMC_RSP_CRC) && (status & SDMMC_INT_RCRC)) ++ cmd->error = -EILSEQ; ++ else if (status & SDMMC_INT_RESP_ERR) ++ cmd->error = -EIO; ++ else ++ cmd->error = 0; ++ ++ if (cmd->error) { ++ /* newer ip versions need a delay between retries */ ++ if (host->quirks & DW_MCI_QUIRK_RETRY_DELAY) ++ mdelay(20); ++ } ++ ++ return cmd->error; ++} ++ ++static int dw_mci_data_complete(struct dw_mci *host, struct mmc_data *data) ++{ ++ u32 status = host->data_status; ++ ++ if (status & DW_MCI_DATA_ERROR_FLAGS) { ++ if (status & SDMMC_INT_DRTO) { ++ data->error = -ETIMEDOUT; ++ } else if (status & SDMMC_INT_DCRC) { ++ data->error = -EILSEQ; ++ } else if (status & SDMMC_INT_EBE) { ++ if (host->dir_status == ++ DW_MCI_SEND_STATUS) { ++ /* ++ * No data CRC status was returned. ++ * The number of bytes transferred ++ * will be exaggerated in PIO mode. ++ */ ++ data->bytes_xfered = 0; ++ data->error = -ETIMEDOUT; ++ } else if (host->dir_status == ++ DW_MCI_RECV_STATUS) { ++ data->error = -EIO; ++ } ++ } else { ++ /* SDMMC_INT_SBE is included */ ++ data->error = -EIO; ++ } ++ ++ dev_dbg(host->dev, "data error, status 0x%08x\n", status); ++ ++ /* ++ * After an error, there may be data lingering ++ * in the FIFO ++ */ ++ dw_mci_reset(host); ++ } else { ++ data->bytes_xfered = data->blocks * data->blksz; ++ data->error = 0; ++ } ++ ++ return data->error; ++} ++ ++static void dw_mci_tasklet_func(unsigned long priv) ++{ ++ struct dw_mci *host = (struct dw_mci *)priv; ++ struct mmc_data *data; ++ struct mmc_command *cmd; ++ struct mmc_request *mrq; ++ enum dw_mci_state state; ++ enum dw_mci_state prev_state; ++ unsigned int err; ++ ++ spin_lock(&host->lock); ++ ++ state = host->state; ++ data = host->data; ++ mrq = host->mrq; ++ ++ do { ++ prev_state = state; ++ ++ switch (state) { ++ case STATE_IDLE: ++ case STATE_WAITING_CMD11_DONE: ++ break; ++ ++ case STATE_SENDING_CMD11: ++ case STATE_SENDING_CMD: ++ if (!test_and_clear_bit(EVENT_CMD_COMPLETE, ++ &host->pending_events)) ++ break; ++ ++ cmd = host->cmd; ++ host->cmd = NULL; ++ set_bit(EVENT_CMD_COMPLETE, &host->completed_events); ++ err = dw_mci_command_complete(host, cmd); ++ if (cmd == mrq->sbc && !err) { ++ prev_state = state = STATE_SENDING_CMD; ++ __dw_mci_start_request(host, host->cur_slot, ++ mrq->cmd); ++ goto unlock; ++ } ++ ++ if (cmd->data && err) { ++ dw_mci_stop_dma(host); ++ send_stop_abort(host, data); ++ state = STATE_SENDING_STOP; ++ break; ++ } ++ ++ if (!cmd->data || err) { ++ dw_mci_request_end(host, mrq); ++ goto unlock; ++ } ++ ++ prev_state = state = STATE_SENDING_DATA; ++ /* fall through */ ++ ++ case STATE_SENDING_DATA: ++ /* ++ * We could get a data error and never a transfer ++ * complete so we'd better check for it here. ++ * ++ * Note that we don't really care if we also got a ++ * transfer complete; stopping the DMA and sending an ++ * abort won't hurt. ++ */ ++ if (test_and_clear_bit(EVENT_DATA_ERROR, ++ &host->pending_events)) { ++ dw_mci_stop_dma(host); ++ send_stop_abort(host, data); ++ state = STATE_DATA_ERROR; ++ break; ++ } ++ ++ if (!test_and_clear_bit(EVENT_XFER_COMPLETE, ++ &host->pending_events)) ++ break; ++ ++ set_bit(EVENT_XFER_COMPLETE, &host->completed_events); ++ ++ /* ++ * Handle an EVENT_DATA_ERROR that might have shown up ++ * before the transfer completed. This might not have ++ * been caught by the check above because the interrupt ++ * could have gone off between the previous check and ++ * the check for transfer complete. ++ * ++ * Technically this ought not be needed assuming we ++ * get a DATA_COMPLETE eventually (we'll notice the ++ * error and end the request), but it shouldn't hurt. ++ * ++ * This has the advantage of sending the stop command. ++ */ ++ if (test_and_clear_bit(EVENT_DATA_ERROR, ++ &host->pending_events)) { ++ dw_mci_stop_dma(host); ++ send_stop_abort(host, data); ++ state = STATE_DATA_ERROR; ++ break; ++ } ++ prev_state = state = STATE_DATA_BUSY; ++ ++ /* fall through */ ++ ++ case STATE_DATA_BUSY: ++ if (!test_and_clear_bit(EVENT_DATA_COMPLETE, ++ &host->pending_events)) ++ break; ++ ++ host->data = NULL; ++ set_bit(EVENT_DATA_COMPLETE, &host->completed_events); ++ err = dw_mci_data_complete(host, data); ++ ++ if (!err) { ++ if (!data->stop || mrq->sbc) { ++ if (mrq->sbc && data->stop) ++ data->stop->error = 0; ++ dw_mci_request_end(host, mrq); ++ goto unlock; ++ } ++ ++ /* stop command for open-ended transfer*/ ++ if (data->stop) ++ send_stop_abort(host, data); ++ } else { ++ /* ++ * If we don't have a command complete now we'll ++ * never get one since we just reset everything; ++ * better end the request. ++ * ++ * If we do have a command complete we'll fall ++ * through to the SENDING_STOP command and ++ * everything will be peachy keen. ++ */ ++ if (!test_bit(EVENT_CMD_COMPLETE, ++ &host->pending_events)) { ++ host->cmd = NULL; ++ dw_mci_request_end(host, mrq); ++ goto unlock; ++ } ++ } ++ ++ /* ++ * If err has non-zero, ++ * stop-abort command has been already issued. ++ */ ++ prev_state = state = STATE_SENDING_STOP; ++ ++ /* fall through */ ++ ++ case STATE_SENDING_STOP: ++ if (!test_and_clear_bit(EVENT_CMD_COMPLETE, ++ &host->pending_events)) ++ break; ++ ++ /* CMD error in data command */ ++ if (mrq->cmd->error && mrq->data) ++ dw_mci_reset(host); ++ ++ host->cmd = NULL; ++ host->data = NULL; ++ ++ if (mrq->stop) ++ dw_mci_command_complete(host, mrq->stop); ++ else ++ host->cmd_status = 0; ++ ++ dw_mci_request_end(host, mrq); ++ goto unlock; ++ ++ case STATE_DATA_ERROR: ++ if (!test_and_clear_bit(EVENT_XFER_COMPLETE, ++ &host->pending_events)) ++ break; ++ ++ state = STATE_DATA_BUSY; ++ break; ++ } ++ } while (state != prev_state); ++ ++ host->state = state; ++unlock: ++ spin_unlock(&host->lock); ++ ++} ++ ++/* push final bytes to part_buf, only use during push */ ++static void dw_mci_set_part_bytes(struct dw_mci *host, void *buf, int cnt) ++{ ++ memcpy((void *)&host->part_buf, buf, cnt); ++ host->part_buf_count = cnt; ++} ++ ++/* append bytes to part_buf, only use during push */ ++static int dw_mci_push_part_bytes(struct dw_mci *host, void *buf, int cnt) ++{ ++ cnt = min(cnt, (1 << host->data_shift) - host->part_buf_count); ++ memcpy((void *)&host->part_buf + host->part_buf_count, buf, cnt); ++ host->part_buf_count += cnt; ++ return cnt; ++} ++ ++/* pull first bytes from part_buf, only use during pull */ ++static int dw_mci_pull_part_bytes(struct dw_mci *host, void *buf, int cnt) ++{ ++ cnt = min(cnt, (int)host->part_buf_count); ++ if (cnt) { ++ memcpy(buf, (void *)&host->part_buf + host->part_buf_start, ++ cnt); ++ host->part_buf_count -= cnt; ++ host->part_buf_start += cnt; ++ } ++ return cnt; ++} ++ ++/* pull final bytes from the part_buf, assuming it's just been filled */ ++static void dw_mci_pull_final_bytes(struct dw_mci *host, void *buf, int cnt) ++{ ++ memcpy(buf, &host->part_buf, cnt); ++ host->part_buf_start = cnt; ++ host->part_buf_count = (1 << host->data_shift) - cnt; ++} ++ ++static void dw_mci_push_data16(struct dw_mci *host, void *buf, int cnt) ++{ ++ struct mmc_data *data = host->data; ++ int init_cnt = cnt; ++ ++ /* try and push anything in the part_buf */ ++ if (unlikely(host->part_buf_count)) { ++ int len = dw_mci_push_part_bytes(host, buf, cnt); ++ buf += len; ++ cnt -= len; ++ if (host->part_buf_count == 2) { ++ mci_writew(host, DATA(host->data_offset), ++ host->part_buf16); ++ host->part_buf_count = 0; ++ } ++ } ++#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS ++ if (unlikely((unsigned long)buf & 0x1)) { ++ while (cnt >= 2) { ++ u16 aligned_buf[64]; ++ int len = min(cnt & -2, (int)sizeof(aligned_buf)); ++ int items = len >> 1; ++ int i; ++ /* memcpy from input buffer into aligned buffer */ ++ memcpy(aligned_buf, buf, len); ++ buf += len; ++ cnt -= len; ++ /* push data from aligned buffer into fifo */ ++ for (i = 0; i < items; ++i) ++ mci_writew(host, DATA(host->data_offset), ++ aligned_buf[i]); ++ } ++ } else ++#endif ++ { ++ u16 *pdata = buf; ++ for (; cnt >= 2; cnt -= 2) ++ mci_writew(host, DATA(host->data_offset), *pdata++); ++ buf = pdata; ++ } ++ /* put anything remaining in the part_buf */ ++ if (cnt) { ++ dw_mci_set_part_bytes(host, buf, cnt); ++ /* Push data if we have reached the expected data length */ ++ if ((data->bytes_xfered + init_cnt) == ++ (data->blksz * data->blocks)) ++ mci_writew(host, DATA(host->data_offset), ++ host->part_buf16); ++ } ++} ++ ++static void dw_mci_pull_data16(struct dw_mci *host, void *buf, int cnt) ++{ ++#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS ++ if (unlikely((unsigned long)buf & 0x1)) { ++ while (cnt >= 2) { ++ /* pull data from fifo into aligned buffer */ ++ u16 aligned_buf[64]; ++ int len = min(cnt & -2, (int)sizeof(aligned_buf)); ++ int items = len >> 1; ++ int i; ++ for (i = 0; i < items; ++i) ++ aligned_buf[i] = mci_readw(host, ++ DATA(host->data_offset)); ++ /* memcpy from aligned buffer into output buffer */ ++ memcpy(buf, aligned_buf, len); ++ buf += len; ++ cnt -= len; ++ } ++ } else ++#endif ++ { ++ u16 *pdata = buf; ++ for (; cnt >= 2; cnt -= 2) ++ *pdata++ = mci_readw(host, DATA(host->data_offset)); ++ buf = pdata; ++ } ++ if (cnt) { ++ host->part_buf16 = mci_readw(host, DATA(host->data_offset)); ++ dw_mci_pull_final_bytes(host, buf, cnt); ++ } ++} ++ ++static void dw_mci_push_data32(struct dw_mci *host, void *buf, int cnt) ++{ ++ struct mmc_data *data = host->data; ++ int init_cnt = cnt; ++ ++ /* try and push anything in the part_buf */ ++ if (unlikely(host->part_buf_count)) { ++ int len = dw_mci_push_part_bytes(host, buf, cnt); ++ buf += len; ++ cnt -= len; ++ if (host->part_buf_count == 4) { ++ mci_writel(host, DATA(host->data_offset), ++ host->part_buf32); ++ host->part_buf_count = 0; ++ } ++ } ++#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS ++ if (unlikely((unsigned long)buf & 0x3)) { ++ while (cnt >= 4) { ++ u32 aligned_buf[32]; ++ int len = min(cnt & -4, (int)sizeof(aligned_buf)); ++ int items = len >> 2; ++ int i; ++ /* memcpy from input buffer into aligned buffer */ ++ memcpy(aligned_buf, buf, len); ++ buf += len; ++ cnt -= len; ++ /* push data from aligned buffer into fifo */ ++ for (i = 0; i < items; ++i) ++ mci_writel(host, DATA(host->data_offset), ++ aligned_buf[i]); ++ } ++ } else ++#endif ++ { ++ u32 *pdata = buf; ++ for (; cnt >= 4; cnt -= 4) ++ mci_writel(host, DATA(host->data_offset), *pdata++); ++ buf = pdata; ++ } ++ /* put anything remaining in the part_buf */ ++ if (cnt) { ++ dw_mci_set_part_bytes(host, buf, cnt); ++ /* Push data if we have reached the expected data length */ ++ if ((data->bytes_xfered + init_cnt) == ++ (data->blksz * data->blocks)) ++ mci_writel(host, DATA(host->data_offset), ++ host->part_buf32); ++ } ++} ++ ++static void dw_mci_pull_data32(struct dw_mci *host, void *buf, int cnt) ++{ ++#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS ++ if (unlikely((unsigned long)buf & 0x3)) { ++ while (cnt >= 4) { ++ /* pull data from fifo into aligned buffer */ ++ u32 aligned_buf[32]; ++ int len = min(cnt & -4, (int)sizeof(aligned_buf)); ++ int items = len >> 2; ++ int i; ++ for (i = 0; i < items; ++i) ++ aligned_buf[i] = mci_readl(host, ++ DATA(host->data_offset)); ++ /* memcpy from aligned buffer into output buffer */ ++ memcpy(buf, aligned_buf, len); ++ buf += len; ++ cnt -= len; ++ } ++ } else ++#endif ++ { ++ u32 *pdata = buf; ++ for (; cnt >= 4; cnt -= 4) ++ *pdata++ = mci_readl(host, DATA(host->data_offset)); ++ buf = pdata; ++ } ++ if (cnt) { ++ host->part_buf32 = mci_readl(host, DATA(host->data_offset)); ++ dw_mci_pull_final_bytes(host, buf, cnt); ++ } ++} ++ ++static void dw_mci_push_data64(struct dw_mci *host, void *buf, int cnt) ++{ ++ struct mmc_data *data = host->data; ++ int init_cnt = cnt; ++ ++ /* try and push anything in the part_buf */ ++ if (unlikely(host->part_buf_count)) { ++ int len = dw_mci_push_part_bytes(host, buf, cnt); ++ buf += len; ++ cnt -= len; ++ ++ if (host->part_buf_count == 8) { ++ mci_writeq(host, DATA(host->data_offset), ++ host->part_buf); ++ host->part_buf_count = 0; ++ } ++ } ++#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS ++ if (unlikely((unsigned long)buf & 0x7)) { ++ while (cnt >= 8) { ++ u64 aligned_buf[16]; ++ int len = min(cnt & -8, (int)sizeof(aligned_buf)); ++ int items = len >> 3; ++ int i; ++ /* memcpy from input buffer into aligned buffer */ ++ memcpy(aligned_buf, buf, len); ++ buf += len; ++ cnt -= len; ++ /* push data from aligned buffer into fifo */ ++ for (i = 0; i < items; ++i) ++ mci_writeq(host, DATA(host->data_offset), ++ aligned_buf[i]); ++ } ++ } else ++#endif ++ { ++ u64 *pdata = buf; ++ for (; cnt >= 8; cnt -= 8) ++ mci_writeq(host, DATA(host->data_offset), *pdata++); ++ buf = pdata; ++ } ++ /* put anything remaining in the part_buf */ ++ if (cnt) { ++ dw_mci_set_part_bytes(host, buf, cnt); ++ /* Push data if we have reached the expected data length */ ++ if ((data->bytes_xfered + init_cnt) == ++ (data->blksz * data->blocks)) ++ mci_writeq(host, DATA(host->data_offset), ++ host->part_buf); ++ } ++} ++ ++static void dw_mci_pull_data64(struct dw_mci *host, void *buf, int cnt) ++{ ++#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS ++ if (unlikely((unsigned long)buf & 0x7)) { ++ while (cnt >= 8) { ++ /* pull data from fifo into aligned buffer */ ++ u64 aligned_buf[16]; ++ int len = min(cnt & -8, (int)sizeof(aligned_buf)); ++ int items = len >> 3; ++ int i; ++ for (i = 0; i < items; ++i) ++ aligned_buf[i] = mci_readq(host, ++ DATA(host->data_offset)); ++ /* memcpy from aligned buffer into output buffer */ ++ memcpy(buf, aligned_buf, len); ++ buf += len; ++ cnt -= len; ++ } ++ } else ++#endif ++ { ++ u64 *pdata = buf; ++ for (; cnt >= 8; cnt -= 8) ++ *pdata++ = mci_readq(host, DATA(host->data_offset)); ++ buf = pdata; ++ } ++ if (cnt) { ++ host->part_buf = mci_readq(host, DATA(host->data_offset)); ++ dw_mci_pull_final_bytes(host, buf, cnt); ++ } ++} ++ ++static void dw_mci_pull_data(struct dw_mci *host, void *buf, int cnt) ++{ ++ int len; ++ ++ /* get remaining partial bytes */ ++ len = dw_mci_pull_part_bytes(host, buf, cnt); ++ if (unlikely(len == cnt)) ++ return; ++ buf += len; ++ cnt -= len; ++ ++ /* get the rest of the data */ ++ host->pull_data(host, buf, cnt); ++} ++ ++static void dw_mci_read_data_pio(struct dw_mci *host, bool dto) ++{ ++ struct sg_mapping_iter *sg_miter = &host->sg_miter; ++ void *buf; ++ unsigned int offset; ++ struct mmc_data *data = host->data; ++ int shift = host->data_shift; ++ u32 status; ++ unsigned int len; ++ unsigned int remain, fcnt; ++ ++ do { ++ if (!sg_miter_next(sg_miter)) ++ goto done; ++ ++ host->sg = sg_miter->piter.sg; ++ buf = sg_miter->addr; ++ remain = sg_miter->length; ++ offset = 0; ++ ++ do { ++ fcnt = (SDMMC_GET_FCNT(mci_readl(host, STATUS)) ++ << shift) + host->part_buf_count; ++ len = min(remain, fcnt); ++ if (!len) ++ break; ++ dw_mci_pull_data(host, (void *)(buf + offset), len); ++ data->bytes_xfered += len; ++ offset += len; ++ remain -= len; ++ } while (remain); ++ ++ sg_miter->consumed = offset; ++ status = mci_readl(host, MINTSTS); ++ mci_writel(host, RINTSTS, SDMMC_INT_RXDR); ++ /* if the RXDR is ready read again */ ++ } while ((status & SDMMC_INT_RXDR) || ++ (dto && SDMMC_GET_FCNT(mci_readl(host, STATUS)))); ++ ++ if (!remain) { ++ if (!sg_miter_next(sg_miter)) ++ goto done; ++ sg_miter->consumed = 0; ++ } ++ sg_miter_stop(sg_miter); ++ return; ++ ++done: ++ sg_miter_stop(sg_miter); ++ host->sg = NULL; ++ smp_wmb(); ++ set_bit(EVENT_XFER_COMPLETE, &host->pending_events); ++} ++ ++static void dw_mci_write_data_pio(struct dw_mci *host) ++{ ++ struct sg_mapping_iter *sg_miter = &host->sg_miter; ++ void *buf; ++ unsigned int offset; ++ struct mmc_data *data = host->data; ++ int shift = host->data_shift; ++ u32 status; ++ unsigned int len; ++ unsigned int fifo_depth = host->fifo_depth; ++ unsigned int remain, fcnt; ++ ++ do { ++ if (!sg_miter_next(sg_miter)) ++ goto done; ++ ++ host->sg = sg_miter->piter.sg; ++ buf = sg_miter->addr; ++ remain = sg_miter->length; ++ offset = 0; ++ ++ do { ++ fcnt = ((fifo_depth - ++ SDMMC_GET_FCNT(mci_readl(host, STATUS))) ++ << shift) - host->part_buf_count; ++ len = min(remain, fcnt); ++ if (!len) ++ break; ++ host->push_data(host, (void *)(buf + offset), len); ++ data->bytes_xfered += len; ++ offset += len; ++ remain -= len; ++ } while (remain); ++ ++ sg_miter->consumed = offset; ++ status = mci_readl(host, MINTSTS); ++ mci_writel(host, RINTSTS, SDMMC_INT_TXDR); ++ } while (status & SDMMC_INT_TXDR); /* if TXDR write again */ ++ ++ if (!remain) { ++ if (!sg_miter_next(sg_miter)) ++ goto done; ++ sg_miter->consumed = 0; ++ } ++ sg_miter_stop(sg_miter); ++ return; ++ ++done: ++ sg_miter_stop(sg_miter); ++ host->sg = NULL; ++ smp_wmb(); ++ set_bit(EVENT_XFER_COMPLETE, &host->pending_events); ++} ++ ++static void dw_mci_cmd_interrupt(struct dw_mci *host, u32 status) ++{ ++ if (!host->cmd_status) ++ host->cmd_status = status; ++ ++ smp_wmb(); ++ ++ set_bit(EVENT_CMD_COMPLETE, &host->pending_events); ++ tasklet_schedule(&host->tasklet); ++} ++ ++static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) ++{ ++ struct dw_mci *host = dev_id; ++ u32 pending; ++ int i; ++ ++ pending = mci_readl(host, MINTSTS); /* read-only mask reg */ ++ ++ /* ++ * DTO fix - version 2.10a and below, and only if internal DMA ++ * is configured. ++ */ ++ if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO) { ++ if (!pending && ++ ((mci_readl(host, STATUS) >> 17) & 0x1fff)) ++ pending |= SDMMC_INT_DATA_OVER; ++ } ++ ++ if (pending) { ++ /* Check volt switch first, since it can look like an error */ ++ if ((host->state == STATE_SENDING_CMD11) && ++ (pending & SDMMC_INT_VOLT_SWITCH)) { ++ mci_writel(host, RINTSTS, SDMMC_INT_VOLT_SWITCH); ++ pending &= ~SDMMC_INT_VOLT_SWITCH; ++ dw_mci_cmd_interrupt(host, pending); ++ } ++ ++ if (pending & DW_MCI_CMD_ERROR_FLAGS) { ++ mci_writel(host, RINTSTS, DW_MCI_CMD_ERROR_FLAGS); ++ host->cmd_status = pending; ++ smp_wmb(); ++ set_bit(EVENT_CMD_COMPLETE, &host->pending_events); ++ } ++ ++ if (pending & DW_MCI_DATA_ERROR_FLAGS) { ++ /* if there is an error report DATA_ERROR */ ++ mci_writel(host, RINTSTS, DW_MCI_DATA_ERROR_FLAGS); ++ host->data_status = pending; ++ smp_wmb(); ++ set_bit(EVENT_DATA_ERROR, &host->pending_events); ++ tasklet_schedule(&host->tasklet); ++ } ++ ++ if (pending & SDMMC_INT_DATA_OVER) { ++ mci_writel(host, RINTSTS, SDMMC_INT_DATA_OVER); ++ if (!host->data_status) ++ host->data_status = pending; ++ smp_wmb(); ++ if (host->dir_status == DW_MCI_RECV_STATUS) { ++ if (host->sg != NULL) ++ dw_mci_read_data_pio(host, true); ++ } ++ set_bit(EVENT_DATA_COMPLETE, &host->pending_events); ++ tasklet_schedule(&host->tasklet); ++ } ++ ++ if (pending & SDMMC_INT_RXDR) { ++ mci_writel(host, RINTSTS, SDMMC_INT_RXDR); ++ if (host->dir_status == DW_MCI_RECV_STATUS && host->sg) ++ dw_mci_read_data_pio(host, false); ++ } ++ ++ if (pending & SDMMC_INT_TXDR) { ++ mci_writel(host, RINTSTS, SDMMC_INT_TXDR); ++ if (host->dir_status == DW_MCI_SEND_STATUS && host->sg) ++ dw_mci_write_data_pio(host); ++ } ++ ++ if (pending & SDMMC_INT_CMD_DONE) { ++ mci_writel(host, RINTSTS, SDMMC_INT_CMD_DONE); ++ dw_mci_cmd_interrupt(host, pending); ++ } ++ ++ if (pending & SDMMC_INT_CD) { ++ mci_writel(host, RINTSTS, SDMMC_INT_CD); ++ queue_work(host->card_workqueue, &host->card_work); ++ } ++ ++ /* Handle SDIO Interrupts */ ++ for (i = 0; i < host->num_slots; i++) { ++ struct dw_mci_slot *slot = host->slot[i]; ++ if (pending & SDMMC_INT_SDIO(i)) { ++ mci_writel(host, RINTSTS, SDMMC_INT_SDIO(i)); ++ mmc_signal_sdio_irq(slot->mmc); ++ } ++ } ++ ++ } ++ ++#ifdef CONFIG_MMC_DW_IDMAC ++ /* Handle DMA interrupts */ ++ pending = mci_readl(host, IDSTS); ++ if (pending & (SDMMC_IDMAC_INT_TI | SDMMC_IDMAC_INT_RI)) { ++ mci_writel(host, IDSTS, SDMMC_IDMAC_INT_TI | SDMMC_IDMAC_INT_RI); ++ mci_writel(host, IDSTS, SDMMC_IDMAC_INT_NI); ++ host->dma_ops->complete(host); ++ } ++#endif ++ ++ return IRQ_HANDLED; ++} ++ ++static void dw_mci_work_routine_card(struct work_struct *work) ++{ ++ struct dw_mci *host = container_of(work, struct dw_mci, card_work); ++ int i; ++ ++ for (i = 0; i < host->num_slots; i++) { ++ struct dw_mci_slot *slot = host->slot[i]; ++ struct mmc_host *mmc = slot->mmc; ++ struct mmc_request *mrq; ++ int present; ++ ++ present = dw_mci_get_cd(mmc); ++ while (present != slot->last_detect_state) { ++ dev_dbg(&slot->mmc->class_dev, "card %s\n", ++ present ? "inserted" : "removed"); ++ ++ spin_lock_bh(&host->lock); ++ ++ /* Card change detected */ ++ slot->last_detect_state = present; ++ ++ /* Clean up queue if present */ ++ mrq = slot->mrq; ++ if (mrq) { ++ if (mrq == host->mrq) { ++ host->data = NULL; ++ host->cmd = NULL; ++ ++ switch (host->state) { ++ case STATE_IDLE: ++ case STATE_WAITING_CMD11_DONE: ++ break; ++ case STATE_SENDING_CMD11: ++ case STATE_SENDING_CMD: ++ mrq->cmd->error = -ENOMEDIUM; ++ if (!mrq->data) ++ break; ++ /* fall through */ ++ case STATE_SENDING_DATA: ++ mrq->data->error = -ENOMEDIUM; ++ dw_mci_stop_dma(host); ++ break; ++ case STATE_DATA_BUSY: ++ case STATE_DATA_ERROR: ++ if (mrq->data->error == -EINPROGRESS) ++ mrq->data->error = -ENOMEDIUM; ++ /* fall through */ ++ case STATE_SENDING_STOP: ++ if (mrq->stop) ++ mrq->stop->error = -ENOMEDIUM; ++ break; ++ } ++ ++ dw_mci_request_end(host, mrq); ++ } else { ++ list_del(&slot->queue_node); ++ mrq->cmd->error = -ENOMEDIUM; ++ if (mrq->data) ++ mrq->data->error = -ENOMEDIUM; ++ if (mrq->stop) ++ mrq->stop->error = -ENOMEDIUM; ++ ++ spin_unlock(&host->lock); ++ mmc_request_done(slot->mmc, mrq); ++ spin_lock(&host->lock); ++ } ++ } ++ ++ /* Power down slot */ ++ if (present == 0) ++ dw_mci_reset(host); ++ ++ spin_unlock_bh(&host->lock); ++ ++ present = dw_mci_get_cd(mmc); ++ } ++ ++ mmc_detect_change(slot->mmc, ++ msecs_to_jiffies(host->pdata->detect_delay_ms)); ++ } ++} ++ ++#ifdef CONFIG_OF ++/* given a slot id, find out the device node representing that slot */ ++static struct device_node *dw_mci_of_find_slot_node(struct device *dev, u8 slot) ++{ ++ struct device_node *np; ++ const __be32 *addr; ++ int len; ++ ++ if (!dev || !dev->of_node) ++ return NULL; ++ ++ for_each_child_of_node(dev->of_node, np) { ++ addr = of_get_property(np, "reg", &len); ++ if (!addr || (len < sizeof(int))) ++ continue; ++ if (be32_to_cpup(addr) == slot) ++ return np; ++ } ++ return NULL; ++} ++ ++static struct dw_mci_of_slot_quirks { ++ char *quirk; ++ int id; ++} of_slot_quirks[] = { ++ { ++ .quirk = "disable-wp", ++ .id = DW_MCI_SLOT_QUIRK_NO_WRITE_PROTECT, ++ }, ++}; ++ ++static int dw_mci_of_get_slot_quirks(struct device *dev, u8 slot) ++{ ++ struct device_node *np = dw_mci_of_find_slot_node(dev, slot); ++ int quirks = 0; ++ int idx; ++ ++ /* get quirks */ ++ for (idx = 0; idx < ARRAY_SIZE(of_slot_quirks); idx++) ++ if (of_get_property(np, of_slot_quirks[idx].quirk, NULL)) { ++ dev_warn(dev, "Slot quirk %s is deprecated\n", ++ of_slot_quirks[idx].quirk); ++ quirks |= of_slot_quirks[idx].id; ++ } ++ ++ return quirks; ++} ++#else /* CONFIG_OF */ ++static int dw_mci_of_get_slot_quirks(struct device *dev, u8 slot) ++{ ++ return 0; ++} ++#endif /* CONFIG_OF */ ++ ++static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) ++{ ++ struct mmc_host *mmc; ++ struct dw_mci_slot *slot; ++ const struct dw_mci_drv_data *drv_data = host->drv_data; ++ int ctrl_id, ret; ++ u32 freq[2]; ++ ++ mmc = mmc_alloc_host(sizeof(struct dw_mci_slot), host->dev); ++ if (!mmc) ++ return -ENOMEM; ++ ++ slot = mmc_priv(mmc); ++ slot->id = id; ++ slot->mmc = mmc; ++ slot->host = host; ++ host->slot[id] = slot; ++ ++ slot->quirks = dw_mci_of_get_slot_quirks(host->dev, slot->id); ++ ++ mmc->ops = &dw_mci_ops; ++ if (of_property_read_u32_array(host->dev->of_node, ++ "clock-freq-min-max", freq, 2)) { ++ mmc->f_min = DW_MCI_FREQ_MIN; ++ mmc->f_max = DW_MCI_FREQ_MAX; ++ } else { ++ mmc->f_min = freq[0]; ++ mmc->f_max = freq[1]; ++ } ++ ++ /*if there are external regulators, get them*/ ++ ret = mmc_regulator_get_supply(mmc); ++ if (ret == -EPROBE_DEFER) ++ goto err_host_allocated; ++ ++ if (!mmc->ocr_avail) ++ mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; ++ ++ if (host->pdata->caps) ++ mmc->caps = host->pdata->caps; ++ ++ if (host->pdata->pm_caps) ++ mmc->pm_caps = host->pdata->pm_caps; ++ ++ if (host->dev->of_node) { ++ ctrl_id = of_alias_get_id(host->dev->of_node, "mshc"); ++ if (ctrl_id < 0) ++ ctrl_id = 0; ++ } else { ++ ctrl_id = to_platform_device(host->dev)->id; ++ } ++ if (drv_data && drv_data->caps) ++ mmc->caps |= drv_data->caps[ctrl_id]; ++ ++ if (host->pdata->caps2) ++ mmc->caps2 = host->pdata->caps2; ++ ++ ret = mmc_of_parse(mmc); ++ if (ret) ++ goto err_host_allocated; ++ ++ if (host->pdata->blk_settings) { ++ mmc->max_segs = host->pdata->blk_settings->max_segs; ++ mmc->max_blk_size = host->pdata->blk_settings->max_blk_size; ++ mmc->max_blk_count = host->pdata->blk_settings->max_blk_count; ++ mmc->max_req_size = host->pdata->blk_settings->max_req_size; ++ mmc->max_seg_size = host->pdata->blk_settings->max_seg_size; ++ } else { ++ /* Useful defaults if platform data is unset. */ ++#ifdef CONFIG_MMC_DW_IDMAC ++ mmc->max_segs = host->ring_size; ++ mmc->max_blk_size = 65536; ++ mmc->max_blk_count = host->ring_size; ++ mmc->max_seg_size = 0x1000; ++ mmc->max_req_size = mmc->max_seg_size * mmc->max_blk_count; ++#else ++ mmc->max_segs = 64; ++ mmc->max_blk_size = 65536; /* BLKSIZ is 16 bits */ ++ mmc->max_blk_count = 512; ++ mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; ++ mmc->max_seg_size = mmc->max_req_size; ++#endif /* CONFIG_MMC_DW_IDMAC */ ++ } ++ ++ if (dw_mci_get_cd(mmc)) ++ set_bit(DW_MMC_CARD_PRESENT, &slot->flags); ++ else ++ clear_bit(DW_MMC_CARD_PRESENT, &slot->flags); ++ ++ ret = mmc_add_host(mmc); ++ if (ret) ++ goto err_host_allocated; ++ ++#if defined(CONFIG_DEBUG_FS) ++ dw_mci_init_debugfs(slot); ++#endif ++ ++ /* Card initially undetected */ ++ slot->last_detect_state = 0; ++ ++ return 0; ++ ++err_host_allocated: ++ mmc_free_host(mmc); ++ return ret; ++} ++ ++static void dw_mci_cleanup_slot(struct dw_mci_slot *slot, unsigned int id) ++{ ++ /* Debugfs stuff is cleaned up by mmc core */ ++ mmc_remove_host(slot->mmc); ++ slot->host->slot[id] = NULL; ++ mmc_free_host(slot->mmc); ++} ++ ++static void dw_mci_init_dma(struct dw_mci *host) ++{ ++ /* Alloc memory for sg translation */ ++ host->sg_cpu = dmam_alloc_coherent(host->dev, PAGE_SIZE, ++ &host->sg_dma, GFP_KERNEL); ++ if (!host->sg_cpu) { ++ dev_err(host->dev, "%s: could not alloc DMA memory\n", ++ __func__); ++ goto no_dma; ++ } ++ ++ /* Determine which DMA interface to use */ ++#ifdef CONFIG_MMC_DW_IDMAC ++ host->dma_ops = &dw_mci_idmac_ops; ++ dev_info(host->dev, "Using internal DMA controller.\n"); ++#endif ++ ++ if (!host->dma_ops) ++ goto no_dma; ++ ++ if (host->dma_ops->init && host->dma_ops->start && ++ host->dma_ops->stop && host->dma_ops->cleanup) { ++ if (host->dma_ops->init(host)) { ++ dev_err(host->dev, "%s: Unable to initialize " ++ "DMA Controller.\n", __func__); ++ goto no_dma; ++ } ++ } else { ++ dev_err(host->dev, "DMA initialization not found.\n"); ++ goto no_dma; ++ } ++ ++ host->use_dma = 1; ++ return; ++ ++no_dma: ++ dev_info(host->dev, "Using PIO mode.\n"); ++ host->use_dma = 0; ++ return; ++} ++ ++static bool dw_mci_ctrl_reset(struct dw_mci *host, u32 reset) ++{ ++ unsigned long timeout = jiffies + msecs_to_jiffies(500); ++ u32 ctrl; ++ ++ ctrl = mci_readl(host, CTRL); ++ ctrl |= reset; ++ mci_writel(host, CTRL, ctrl); ++ ++ /* wait till resets clear */ ++ do { ++ ctrl = mci_readl(host, CTRL); ++ if (!(ctrl & reset)) ++ return true; ++ } while (time_before(jiffies, timeout)); ++ ++ dev_err(host->dev, ++ "Timeout resetting block (ctrl reset %#x)\n", ++ ctrl & reset); ++ ++ return false; ++} ++ ++static bool dw_mci_reset(struct dw_mci *host) ++{ ++ u32 flags = SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET; ++ bool ret = false; ++ ++ /* ++ * Reseting generates a block interrupt, hence setting ++ * the scatter-gather pointer to NULL. ++ */ ++ if (host->sg) { ++ sg_miter_stop(&host->sg_miter); ++ host->sg = NULL; ++ } ++ ++ if (host->use_dma) ++ flags |= SDMMC_CTRL_DMA_RESET; ++ ++ if (dw_mci_ctrl_reset(host, flags)) { ++ /* ++ * In all cases we clear the RAWINTS register to clear any ++ * interrupts. ++ */ ++ mci_writel(host, RINTSTS, 0xFFFFFFFF); ++ ++ /* if using dma we wait for dma_req to clear */ ++ if (host->use_dma) { ++ unsigned long timeout = jiffies + msecs_to_jiffies(500); ++ u32 status; ++ do { ++ status = mci_readl(host, STATUS); ++ if (!(status & SDMMC_STATUS_DMA_REQ)) ++ break; ++ cpu_relax(); ++ } while (time_before(jiffies, timeout)); ++ ++ if (status & SDMMC_STATUS_DMA_REQ) { ++ dev_err(host->dev, ++ "%s: Timeout waiting for dma_req to " ++ "clear during reset\n", __func__); ++ goto ciu_out; ++ } ++ ++ /* when using DMA next we reset the fifo again */ ++ if (!dw_mci_ctrl_reset(host, SDMMC_CTRL_FIFO_RESET)) ++ goto ciu_out; ++ } ++ } else { ++ /* if the controller reset bit did clear, then set clock regs */ ++ if (!(mci_readl(host, CTRL) & SDMMC_CTRL_RESET)) { ++ dev_err(host->dev, "%s: fifo/dma reset bits didn't " ++ "clear but ciu was reset, doing clock update\n", ++ __func__); ++ goto ciu_out; ++ } ++ } ++ ++#if IS_ENABLED(CONFIG_MMC_DW_IDMAC) ++ /* It is also recommended that we reset and reprogram idmac */ ++ dw_mci_idmac_reset(host); ++#endif ++ ++ ret = true; ++ ++ciu_out: ++ /* After a CTRL reset we need to have CIU set clock registers */ ++ mci_send_cmd(host->cur_slot, SDMMC_CMD_UPD_CLK, 0); ++ ++ return ret; ++} ++ ++#ifdef CONFIG_OF ++static struct dw_mci_of_quirks { ++ char *quirk; ++ int id; ++} of_quirks[] = { ++ { ++ .quirk = "broken-cd", ++ .id = DW_MCI_QUIRK_BROKEN_CARD_DETECTION, ++ }, { ++ .quirk = "disable-wp", ++ .id = DW_MCI_QUIRK_NO_WRITE_PROTECT, ++ }, ++}; ++ ++static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host) ++{ ++ struct dw_mci_board *pdata; ++ struct device *dev = host->dev; ++ struct device_node *np = dev->of_node; ++ const struct dw_mci_drv_data *drv_data = host->drv_data; ++ int idx, ret; ++ u32 clock_frequency; ++ ++ pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); ++ if (!pdata) { ++ dev_err(dev, "could not allocate memory for pdata\n"); ++ return ERR_PTR(-ENOMEM); ++ } ++ ++ /* find out number of slots supported */ ++ if (of_property_read_u32(dev->of_node, "num-slots", ++ &pdata->num_slots)) { ++ dev_info(dev, "num-slots property not found, " ++ "assuming 1 slot is available\n"); ++ pdata->num_slots = 1; ++ } ++ ++ /* get quirks */ ++ for (idx = 0; idx < ARRAY_SIZE(of_quirks); idx++) ++ if (of_get_property(np, of_quirks[idx].quirk, NULL)) ++ pdata->quirks |= of_quirks[idx].id; ++ ++ if (of_property_read_u32(np, "fifo-depth", &pdata->fifo_depth)) ++ dev_info(dev, "fifo-depth property not found, using " ++ "value of FIFOTH register as default\n"); ++ ++ of_property_read_u32(np, "card-detect-delay", &pdata->detect_delay_ms); ++ ++ if (!of_property_read_u32(np, "clock-frequency", &clock_frequency)) ++ pdata->bus_hz = clock_frequency; ++ ++ if (drv_data && drv_data->parse_dt) { ++ ret = drv_data->parse_dt(host); ++ if (ret) ++ return ERR_PTR(ret); ++ } ++ ++ if (of_find_property(np, "supports-highspeed", NULL)) ++ pdata->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED; ++ ++ return pdata; ++} ++ ++#else /* CONFIG_OF */ ++static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host) ++{ ++ return ERR_PTR(-EINVAL); ++} ++#endif /* CONFIG_OF */ ++ ++int dw_mci_probe(struct dw_mci *host) ++{ ++ const struct dw_mci_drv_data *drv_data = host->drv_data; ++ int width, i, ret = 0; ++ u32 fifo_size; ++ int init_slots = 0; ++ ++ if (!host->pdata) { ++ host->pdata = dw_mci_parse_dt(host); ++ if (IS_ERR(host->pdata)) { ++ dev_err(host->dev, "platform data not available\n"); ++ return -EINVAL; ++ } ++ } ++ ++ if (host->pdata->num_slots > 1) { ++ dev_err(host->dev, ++ "Platform data must supply num_slots.\n"); ++ return -ENODEV; ++ } ++ ++ host->biu_clk = devm_clk_get(host->dev, "biu"); ++ if (IS_ERR(host->biu_clk)) { ++ dev_dbg(host->dev, "biu clock not available\n"); ++ } else { ++ ret = clk_prepare_enable(host->biu_clk); ++ if (ret) { ++ dev_err(host->dev, "failed to enable biu clock\n"); ++ return ret; ++ } ++ } ++ ++ host->ciu_clk = devm_clk_get(host->dev, "ciu"); ++ if (IS_ERR(host->ciu_clk)) { ++ dev_dbg(host->dev, "ciu clock not available\n"); ++ host->bus_hz = host->pdata->bus_hz; ++ } else { ++ ret = clk_prepare_enable(host->ciu_clk); ++ if (ret) { ++ dev_err(host->dev, "failed to enable ciu clock\n"); ++ goto err_clk_biu; ++ } ++ ++ if (host->pdata->bus_hz) { ++ ret = clk_set_rate(host->ciu_clk, host->pdata->bus_hz); ++ if (ret) ++ dev_warn(host->dev, ++ "Unable to set bus rate to %uHz\n", ++ host->pdata->bus_hz); ++ } ++ host->bus_hz = clk_get_rate(host->ciu_clk); ++ } ++ ++ if (!host->bus_hz) { ++ dev_err(host->dev, ++ "Platform data must supply bus speed\n"); ++ ret = -ENODEV; ++ goto err_clk_ciu; ++ } ++ ++ if (drv_data && drv_data->init) { ++ ret = drv_data->init(host); ++ if (ret) { ++ dev_err(host->dev, ++ "implementation specific init failed\n"); ++ goto err_clk_ciu; ++ } ++ } ++ ++ if (drv_data && drv_data->setup_clock) { ++ ret = drv_data->setup_clock(host); ++ if (ret) { ++ dev_err(host->dev, ++ "implementation specific clock setup failed\n"); ++ goto err_clk_ciu; ++ } ++ } ++ ++ host->quirks = host->pdata->quirks; ++ ++ spin_lock_init(&host->lock); ++ INIT_LIST_HEAD(&host->queue); ++ ++ /* ++ * Get the host data width - this assumes that HCON has been set with ++ * the correct values. ++ */ ++ i = (mci_readl(host, HCON) >> 7) & 0x7; ++ if (!i) { ++ host->push_data = dw_mci_push_data16; ++ host->pull_data = dw_mci_pull_data16; ++ width = 16; ++ host->data_shift = 1; ++ } else if (i == 2) { ++ host->push_data = dw_mci_push_data64; ++ host->pull_data = dw_mci_pull_data64; ++ width = 64; ++ host->data_shift = 3; ++ } else { ++ /* Check for a reserved value, and warn if it is */ ++ WARN((i != 1), ++ "HCON reports a reserved host data width!\n" ++ "Defaulting to 32-bit access.\n"); ++ host->push_data = dw_mci_push_data32; ++ host->pull_data = dw_mci_pull_data32; ++ width = 32; ++ host->data_shift = 2; ++ } ++ ++ /* Reset all blocks */ ++ if (!dw_mci_ctrl_reset(host, SDMMC_CTRL_ALL_RESET_FLAGS)) ++ return -ENODEV; ++ ++ host->dma_ops = host->pdata->dma_ops; ++ dw_mci_init_dma(host); ++ ++ /* Clear the interrupts for the host controller */ ++ mci_writel(host, RINTSTS, 0xFFFFFFFF); ++ mci_writel(host, INTMASK, 0); /* disable all mmc interrupt first */ ++ ++ /* Put in max timeout */ ++ mci_writel(host, TMOUT, 0xFFFFFFFF); ++ ++ /* ++ * FIFO threshold settings RxMark = fifo_size / 2 - 1, ++ * Tx Mark = fifo_size / 2 DMA Size = 8 ++ */ ++ if (!host->pdata->fifo_depth) { ++ /* ++ * Power-on value of RX_WMark is FIFO_DEPTH-1, but this may ++ * have been overwritten by the bootloader, just like we're ++ * about to do, so if you know the value for your hardware, you ++ * should put it in the platform data. ++ */ ++ fifo_size = mci_readl(host, FIFOTH); ++ fifo_size = 1 + ((fifo_size >> 16) & 0xfff); ++ } else { ++ fifo_size = host->pdata->fifo_depth; ++ } ++ host->fifo_depth = fifo_size; ++ host->fifoth_val = ++ SDMMC_SET_FIFOTH(0x2, fifo_size / 2 - 1, fifo_size / 2); ++ mci_writel(host, FIFOTH, host->fifoth_val); ++ ++ /* disable clock to CIU */ ++ mci_writel(host, CLKENA, 0); ++ mci_writel(host, CLKSRC, 0); ++ ++ /* ++ * In 2.40a spec, Data offset is changed. ++ * Need to check the version-id and set data-offset for DATA register. ++ */ ++ host->verid = SDMMC_GET_VERID(mci_readl(host, VERID)); ++ dev_info(host->dev, "Version ID is %04x\n", host->verid); ++ ++ if (host->verid < DW_MMC_240A) ++ host->data_offset = DATA_OFFSET; ++ else ++ host->data_offset = DATA_240A_OFFSET; ++ ++ tasklet_init(&host->tasklet, dw_mci_tasklet_func, (unsigned long)host); ++ host->card_workqueue = alloc_workqueue("dw-mci-card", ++ WQ_MEM_RECLAIM, 1); ++ if (!host->card_workqueue) { ++ ret = -ENOMEM; ++ goto err_dmaunmap; ++ } ++ INIT_WORK(&host->card_work, dw_mci_work_routine_card); ++ ret = devm_request_irq(host->dev, host->irq, dw_mci_interrupt, ++ host->irq_flags, "dw-mci", host); ++ if (ret) ++ goto err_workqueue; ++ ++ if (host->pdata->num_slots) ++ host->num_slots = host->pdata->num_slots; ++ else ++ host->num_slots = ((mci_readl(host, HCON) >> 1) & 0x1F) + 1; ++ ++ /* ++ * Enable interrupts for command done, data over, data empty, card det, ++ * receive ready and error such as transmit, receive timeout, crc error ++ */ ++ mci_writel(host, RINTSTS, 0xFFFFFFFF); ++ mci_writel(host, INTMASK, SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER | ++ SDMMC_INT_TXDR | SDMMC_INT_RXDR | ++ DW_MCI_ERROR_FLAGS | SDMMC_INT_CD); ++ mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); /* Enable mci interrupt */ ++ ++ dev_info(host->dev, "DW MMC controller at irq %d, " ++ "%d bit host data width, " ++ "%u deep fifo\n", ++ host->irq, width, fifo_size); ++ ++ /* We need at least one slot to succeed */ ++ for (i = 0; i < host->num_slots; i++) { ++ ret = dw_mci_init_slot(host, i); ++ if (ret) ++ dev_dbg(host->dev, "slot %d init failed\n", i); ++ else ++ init_slots++; ++ } ++ ++ if (init_slots) { ++ dev_info(host->dev, "%d slots initialized\n", init_slots); ++ } else { ++ dev_dbg(host->dev, "attempted to initialize %d slots, " ++ "but failed on all\n", host->num_slots); ++ goto err_workqueue; ++ } ++ ++ if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO) ++ dev_info(host->dev, "Internal DMAC interrupt fix enabled.\n"); ++ ++ return 0; ++ ++err_workqueue: ++ destroy_workqueue(host->card_workqueue); ++ ++err_dmaunmap: ++ if (host->use_dma && host->dma_ops->exit) ++ host->dma_ops->exit(host); ++ ++err_clk_ciu: ++ if (!IS_ERR(host->ciu_clk)) ++ clk_disable_unprepare(host->ciu_clk); ++ ++err_clk_biu: ++ if (!IS_ERR(host->biu_clk)) ++ clk_disable_unprepare(host->biu_clk); ++ ++ return ret; ++} ++EXPORT_SYMBOL(dw_mci_probe); ++ ++void dw_mci_remove(struct dw_mci *host) ++{ ++ int i; ++ ++ mci_writel(host, RINTSTS, 0xFFFFFFFF); ++ mci_writel(host, INTMASK, 0); /* disable all mmc interrupt first */ ++ ++ for (i = 0; i < host->num_slots; i++) { ++ dev_dbg(host->dev, "remove slot %d\n", i); ++ if (host->slot[i]) ++ dw_mci_cleanup_slot(host->slot[i], i); ++ } ++ ++ /* disable clock to CIU */ ++ mci_writel(host, CLKENA, 0); ++ mci_writel(host, CLKSRC, 0); ++ ++ destroy_workqueue(host->card_workqueue); ++ ++ if (host->use_dma && host->dma_ops->exit) ++ host->dma_ops->exit(host); ++ ++ if (!IS_ERR(host->ciu_clk)) ++ clk_disable_unprepare(host->ciu_clk); ++ ++ if (!IS_ERR(host->biu_clk)) ++ clk_disable_unprepare(host->biu_clk); ++} ++EXPORT_SYMBOL(dw_mci_remove); ++ ++ ++ ++#ifdef CONFIG_PM_SLEEP ++/* ++ * TODO: we should probably disable the clock to the card in the suspend path. ++ */ ++int dw_mci_suspend(struct dw_mci *host) ++{ ++ return 0; ++} ++EXPORT_SYMBOL(dw_mci_suspend); ++ ++int dw_mci_resume(struct dw_mci *host) ++{ ++ int i, ret; ++ ++ if (!dw_mci_ctrl_reset(host, SDMMC_CTRL_ALL_RESET_FLAGS)) { ++ ret = -ENODEV; ++ return ret; ++ } ++ ++ if (host->use_dma && host->dma_ops->init) ++ host->dma_ops->init(host); ++ ++ /* ++ * Restore the initial value at FIFOTH register ++ * And Invalidate the prev_blksz with zero ++ */ ++ mci_writel(host, FIFOTH, host->fifoth_val); ++ host->prev_blksz = 0; ++ ++ /* Put in max timeout */ ++ mci_writel(host, TMOUT, 0xFFFFFFFF); ++ ++ mci_writel(host, RINTSTS, 0xFFFFFFFF); ++ mci_writel(host, INTMASK, SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER | ++ SDMMC_INT_TXDR | SDMMC_INT_RXDR | ++ DW_MCI_ERROR_FLAGS | SDMMC_INT_CD); ++ mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); ++ ++ for (i = 0; i < host->num_slots; i++) { ++ struct dw_mci_slot *slot = host->slot[i]; ++ if (!slot) ++ continue; ++ if (slot->mmc->pm_flags & MMC_PM_KEEP_POWER) { ++ dw_mci_set_ios(slot->mmc, &slot->mmc->ios); ++ dw_mci_setup_bus(slot, true); ++ } ++ } ++ return 0; ++} ++EXPORT_SYMBOL(dw_mci_resume); ++#endif /* CONFIG_PM_SLEEP */ ++ ++static int __init dw_mci_init(void) ++{ ++ pr_info("Synopsys Designware Multimedia Card Interface Driver\n"); ++ return 0; ++} ++ ++static void __exit dw_mci_exit(void) ++{ ++} ++ ++module_init(dw_mci_init); ++module_exit(dw_mci_exit); ++ ++MODULE_DESCRIPTION("DW Multimedia Card Interface driver"); ++MODULE_AUTHOR("NXP Semiconductor VietNam"); ++MODULE_AUTHOR("Imagination Technologies Ltd"); ++MODULE_LICENSE("GPL v2"); +diff -Nur linux-3.18.8.orig/include/linux/mmc/host.h linux-3.18.8/include/linux/mmc/host.h +--- linux-3.18.8.orig/include/linux/mmc/host.h 2015-02-27 02:49:36.000000000 +0100 ++++ linux-3.18.8/include/linux/mmc/host.h 2015-03-02 03:25:33.000000000 +0100 +@@ -305,6 +305,11 @@ + unsigned long clkgate_delay; + #endif + ++ /* card specific properties to deal with power and reset */ ++ struct regulator *card_regulator; /* External VCC needed by the card */ ++ struct gpio_desc *card_reset_gpios[2]; /* External resets, active low */ ++ struct clk *card_clk; /* External clock needed by the card */ ++ + /* host specific block data */ + unsigned int max_seg_size; /* see blk_queue_max_segment_size */ + unsigned short max_segs; /* see blk_queue_max_segments */ diff --git a/target/arm/solidrun-imx6/patches/3.18.9/solidrun-imx6-wlan.patch b/target/arm/solidrun-imx6/patches/3.18.9/solidrun-imx6-wlan.patch deleted file mode 100644 index 3ab3081db..000000000 --- a/target/arm/solidrun-imx6/patches/3.18.9/solidrun-imx6-wlan.patch +++ /dev/null @@ -1,3252 +0,0 @@ -diff -Nur linux-3.18.8.orig/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi linux-3.18.8/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi ---- linux-3.18.8.orig/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi 2015-02-27 02:49:36.000000000 +0100 -+++ linux-3.18.8/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi 2015-03-02 03:23:14.000000000 +0100 -@@ -170,6 +170,28 @@ - MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x13059 - >; - }; -+ -+ pinctrl_cubox_i_usdhc2_100mhz: cubox-i-usdhc2-100mhz { -+ fsl,pins = < -+ MX6QDL_PAD_SD2_CMD__SD2_CMD 0x170b9 -+ MX6QDL_PAD_SD2_CLK__SD2_CLK 0x100b9 -+ MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x170b9 -+ MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x170b9 -+ MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x170b9 -+ MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x130b9 -+ >; -+ }; -+ -+ pinctrl_cubox_i_usdhc2_200mhz: cubox-i-usdhc2-200mhz { -+ fsl,pins = < -+ MX6QDL_PAD_SD2_CMD__SD2_CMD 0x170f9 -+ MX6QDL_PAD_SD2_CLK__SD2_CLK 0x100f9 -+ MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x170f9 -+ MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x170f9 -+ MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x170f9 -+ MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x130f9 -+ >; -+ }; - }; - }; - -@@ -194,8 +216,10 @@ - }; - - &usdhc2 { -- pinctrl-names = "default"; -+ pinctrl-names = "default", "state_100mhz", "state_200mhz"; - pinctrl-0 = <&pinctrl_cubox_i_usdhc2_aux &pinctrl_cubox_i_usdhc2>; -+ pinctrl-1 = <&pinctrl_cubox_i_usdhc2_aux &pinctrl_cubox_i_usdhc2_100mhz>; -+ pinctrl-2 = <&pinctrl_cubox_i_usdhc2_aux &pinctrl_cubox_i_usdhc2_200mhz>; - vmmc-supply = <®_3p3v>; - cd-gpios = <&gpio1 4 0>; - status = "okay"; -diff -Nur linux-3.18.8.orig/arch/arm/boot/dts/imx6qdl-microsom.dtsi linux-3.18.8/arch/arm/boot/dts/imx6qdl-microsom.dtsi ---- linux-3.18.8.orig/arch/arm/boot/dts/imx6qdl-microsom.dtsi 2015-02-27 02:49:36.000000000 +0100 -+++ linux-3.18.8/arch/arm/boot/dts/imx6qdl-microsom.dtsi 2015-03-02 02:58:12.000000000 +0100 -@@ -1,15 +1,95 @@ - /* - * Copyright (C) 2013,2014 Russell King - */ -+#include -+/ { -+ regulators { -+ compatible = "simple-bus"; -+ -+ reg_brcm_osc: brcm-osc-reg { -+ compatible = "regulator-fixed"; -+ enable-active-high; -+ gpio = <&gpio5 5 0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_microsom_brcm_osc_reg>; -+ regulator-name = "brcm_osc_reg"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ regulator-boot-on; -+ }; -+ -+ reg_brcm: brcm-reg { -+ compatible = "regulator-fixed"; -+ enable-active-high; -+ gpio = <&gpio3 19 0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_microsom_brcm_reg>; -+ regulator-name = "brcm_reg"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ startup-delay-us = <200000>; -+ }; -+ }; -+}; - - &iomuxc { - microsom { -+ pinctrl_microsom_brcm_bt: microsom-brcm-bt { -+ fsl,pins = < -+ MX6QDL_PAD_CSI0_DAT14__GPIO6_IO00 0x40013070 -+ MX6QDL_PAD_CSI0_DAT15__GPIO6_IO01 0x40013070 -+ MX6QDL_PAD_CSI0_DAT18__GPIO6_IO04 0x40013070 -+ >; -+ }; -+ -+ pinctrl_microsom_brcm_osc_reg: microsom-brcm-osc-reg { -+ fsl,pins = < -+ MX6QDL_PAD_DISP0_DAT11__GPIO5_IO05 0x40013070 -+ >; -+ }; -+ -+ pinctrl_microsom_brcm_reg: microsom-brcm-reg { -+ fsl,pins = < -+ MX6QDL_PAD_EIM_D19__GPIO3_IO19 0x40013070 -+ >; -+ }; -+ -+ pinctrl_microsom_brcm_wifi: microsom-brcm-wifi { -+ fsl,pins = < -+ MX6QDL_PAD_GPIO_8__XTALOSC_REF_CLK_32K 0x1b0b0 -+ MX6QDL_PAD_CSI0_DATA_EN__GPIO5_IO20 0x40013070 -+ MX6QDL_PAD_CSI0_DAT8__GPIO5_IO26 0x40013070 -+ MX6QDL_PAD_CSI0_DAT9__GPIO5_IO27 0x40013070 -+ >; -+ }; -+ - pinctrl_microsom_uart1: microsom-uart1 { - fsl,pins = < - MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA 0x1b0b1 - MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA 0x1b0b1 - >; - }; -+ -+ pinctrl_microsom_uart4_1: microsom-uart4 { -+ fsl,pins = < -+ MX6QDL_PAD_CSI0_DAT12__UART4_TX_DATA 0x1b0b1 -+ MX6QDL_PAD_CSI0_DAT13__UART4_RX_DATA 0x1b0b1 -+ MX6QDL_PAD_CSI0_DAT16__UART4_RTS_B 0x1b0b1 -+ MX6QDL_PAD_CSI0_DAT17__UART4_CTS_B 0x1b0b1 -+ >; -+ }; -+ -+ pinctrl_microsom_usdhc1: microsom-usdhc1 { -+ fsl,pins = < -+ MX6QDL_PAD_SD1_CMD__SD1_CMD 0x17059 -+ MX6QDL_PAD_SD1_CLK__SD1_CLK 0x10059 -+ MX6QDL_PAD_SD1_DAT0__SD1_DATA0 0x17059 -+ MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x17059 -+ MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x17059 -+ MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x17059 -+ >; -+ }; - }; - }; - -@@ -18,3 +98,23 @@ - pinctrl-0 = <&pinctrl_microsom_uart1>; - status = "okay"; - }; -+ -+/* UART4 - Connected to optional BRCM Wifi/BT/FM */ -+&uart4 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_microsom_brcm_bt &pinctrl_microsom_uart4_1>; -+ fsl,uart-has-rtscts; -+ status = "okay"; -+}; -+ -+/* USDHC1 - Connected to optional BRCM Wifi/BT/FM */ -+&usdhc1 { -+ card-external-vcc-supply = <®_brcm>; -+ card-reset-gpios = <&gpio5 26 GPIO_ACTIVE_LOW>, <&gpio6 0 GPIO_ACTIVE_LOW>; -+ keep-power-in-suspend; -+ non-removable; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_microsom_brcm_wifi &pinctrl_microsom_usdhc1>; -+ vmmc-supply = <®_brcm>; -+ status = "okay"; -+}; -diff -Nur linux-3.18.8.orig/Documentation/devicetree/bindings/mmc/mmc.txt linux-3.18.8/Documentation/devicetree/bindings/mmc/mmc.txt ---- linux-3.18.8.orig/Documentation/devicetree/bindings/mmc/mmc.txt 2015-02-27 02:49:36.000000000 +0100 -+++ linux-3.18.8/Documentation/devicetree/bindings/mmc/mmc.txt 2015-03-02 03:25:33.000000000 +0100 -@@ -5,6 +5,8 @@ - Interpreted by the OF core: - - reg: Registers location and length. - - interrupts: Interrupts used by the MMC controller. -+- clocks: Clocks needed for the host controller, if any. -+- clock-names: Goes with clocks above. - - Card detection: - If no property below is supplied, host native card detect is used. -@@ -43,6 +45,15 @@ - - dsr: Value the card's (optional) Driver Stage Register (DSR) should be - programmed with. Valid range: [0 .. 0xffff]. - -+Card power and reset control: -+The following properties can be specified for cases where the MMC -+peripheral needs additional reset, regulator and clock lines. It is for -+example common for WiFi/BT adapters to have these separate from the main -+MMC bus: -+ - card-reset-gpios: Specify GPIOs for card reset (reset active low) -+ - card-external-vcc-supply: Regulator to drive (independent) card VCC -+ - clock with name "card_ext_clock": External clock provided to the card -+ - *NOTE* on CD and WP polarity. To use common for all SD/MMC host controllers line - polarity properties, we have to fix the meaning of the "normal" and "inverted" - line levels. We choose to follow the SDHCI standard, which specifies both those -diff -Nur linux-3.18.8.orig/drivers/mmc/core/core.c linux-3.18.8/drivers/mmc/core/core.c ---- linux-3.18.8.orig/drivers/mmc/core/core.c 2015-02-27 02:49:36.000000000 +0100 -+++ linux-3.18.8/drivers/mmc/core/core.c 2015-03-02 03:25:33.000000000 +0100 -@@ -13,11 +13,13 @@ - #include - #include - #include -+#include - #include - #include - #include - #include - #include -+#include - #include - #include - #include -@@ -1507,6 +1509,43 @@ - mmc_host_clk_release(host); - } - -+static void mmc_card_power_up(struct mmc_host *host) -+{ -+ int i; -+ struct gpio_desc **gds = host->card_reset_gpios; -+ -+ for (i = 0; i < ARRAY_SIZE(host->card_reset_gpios); i++) { -+ if (gds[i]) { -+ dev_dbg(host->parent, "Asserting reset line %d", i); -+ gpiod_set_value(gds[i], 1); -+ } -+ } -+ -+ if (host->card_regulator) { -+ dev_dbg(host->parent, "Enabling external regulator"); -+ if (regulator_enable(host->card_regulator)) -+ dev_err(host->parent, "Failed to enable external regulator"); -+ } -+ -+ if (host->card_clk) { -+ dev_dbg(host->parent, "Enabling external clock"); -+ clk_prepare_enable(host->card_clk); -+ } -+ -+ /* 2ms delay to let clocks and power settle */ -+ mmc_delay(20); -+ -+ for (i = 0; i < ARRAY_SIZE(host->card_reset_gpios); i++) { -+ if (gds[i]) { -+ dev_dbg(host->parent, "Deasserting reset line %d", i); -+ gpiod_set_value(gds[i], 0); -+ } -+ } -+ -+ /* 2ms delay to after reset release */ -+ mmc_delay(20); -+} -+ - /* - * Apply power to the MMC stack. This is a two-stage process. - * First, we enable power to the card without the clock running. -@@ -1523,6 +1562,9 @@ - if (host->ios.power_mode == MMC_POWER_ON) - return; - -+ /* Power up the card/module first, if needed */ -+ mmc_card_power_up(host); -+ - mmc_host_clk_hold(host); - - host->ios.vdd = fls(ocr) - 1; -diff -Nur linux-3.18.8.orig/drivers/mmc/core/host.c linux-3.18.8/drivers/mmc/core/host.c ---- linux-3.18.8.orig/drivers/mmc/core/host.c 2015-02-27 02:49:36.000000000 +0100 -+++ linux-3.18.8/drivers/mmc/core/host.c 2015-03-02 03:26:23.000000000 +0100 -@@ -12,14 +12,18 @@ - * MMC host class device management - */ - -+#include -+#include - #include - #include -+#include - #include - #include - #include - #include - #include - #include -+#include - #include - #include - -@@ -466,6 +470,66 @@ - - EXPORT_SYMBOL(mmc_of_parse); - -+static int mmc_of_parse_child(struct mmc_host *host) -+{ -+ struct device_node *np; -+ struct clk *clk; -+ int i; -+ -+ if (!host->parent || !host->parent->of_node) -+ return 0; -+ -+ np = host->parent->of_node; -+ -+ host->card_regulator = regulator_get(host->parent, "card-external-vcc"); -+ if (IS_ERR(host->card_regulator)) { -+ if (PTR_ERR(host->card_regulator) == -EPROBE_DEFER) -+ return PTR_ERR(host->card_regulator); -+ host->card_regulator = NULL; -+ } -+ -+ /* Parse card power/reset/clock control */ -+ if (of_find_property(np, "card-reset-gpios", NULL)) { -+ struct gpio_desc *gpd; -+ int level = 0; -+ -+ /* -+ * If the regulator is enabled, then we can hold the -+ * card in reset with an active high resets. Otherwise, -+ * hold the resets low. -+ */ -+ if (host->card_regulator && regulator_is_enabled(host->card_regulator)) -+ level = 1; -+ -+ for (i = 0; i < ARRAY_SIZE(host->card_reset_gpios); i++) { -+ gpd = devm_gpiod_get_index(host->parent, "card-reset", i); -+ if (IS_ERR(gpd)) { -+ if (PTR_ERR(gpd) == -EPROBE_DEFER) -+ return PTR_ERR(gpd); -+ break; -+ } -+ gpiod_direction_output(gpd, gpiod_is_active_low(gpd) | level); -+ host->card_reset_gpios[i] = gpd; -+ } -+ -+ gpd = devm_gpiod_get_index(host->parent, "card-reset", ARRAY_SIZE(host->card_reset_gpios)); -+ if (!IS_ERR(gpd)) { -+ dev_warn(host->parent, "More reset gpios than we can handle"); -+ gpiod_put(gpd); -+ } -+ } -+ -+ clk = of_clk_get_by_name(np, "card_ext_clock"); -+ if (IS_ERR(clk)) { -+ if (PTR_ERR(clk) == -EPROBE_DEFER) -+ return PTR_ERR(clk); -+ clk = NULL; -+ } -+ host->card_clk = clk; -+ -+ return 0; -+} -+ - /** - * mmc_alloc_host - initialise the per-host structure. - * @extra: sizeof private data structure -@@ -545,6 +609,10 @@ - { - int err; - -+ err = mmc_of_parse_child(host); -+ if (err) -+ return err; -+ - WARN_ON((host->caps & MMC_CAP_SDIO_IRQ) && - !host->ops->enable_sdio_irq); - -diff -Nur linux-3.18.8.orig/drivers/mmc/host/dw_mmc.c linux-3.18.8/drivers/mmc/host/dw_mmc.c ---- linux-3.18.8.orig/drivers/mmc/host/dw_mmc.c 2015-02-27 02:49:36.000000000 +0100 -+++ linux-3.18.8/drivers/mmc/host/dw_mmc.c 2015-03-02 03:25:56.000000000 +0100 -@@ -2211,6 +2211,8 @@ - if (!mmc) - return -ENOMEM; - -+ mmc_of_parse(mmc); -+ - slot = mmc_priv(mmc); - slot->id = id; - slot->mmc = mmc; -diff -Nur linux-3.18.8.orig/drivers/mmc/host/dw_mmc.c.orig linux-3.18.8/drivers/mmc/host/dw_mmc.c.orig ---- linux-3.18.8.orig/drivers/mmc/host/dw_mmc.c.orig 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.18.8/drivers/mmc/host/dw_mmc.c.orig 2015-02-27 02:49:36.000000000 +0100 -@@ -0,0 +1,2855 @@ -+/* -+ * Synopsys DesignWare Multimedia Card Interface driver -+ * (Based on NXP driver for lpc 31xx) -+ * -+ * Copyright (C) 2009 NXP Semiconductors -+ * Copyright (C) 2009, 2010 Imagination Technologies Ltd. -+ * -+ * 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; either version 2 of the License, or -+ * (at your option) any later version. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "dw_mmc.h" -+ -+/* Common flag combinations */ -+#define DW_MCI_DATA_ERROR_FLAGS (SDMMC_INT_DRTO | SDMMC_INT_DCRC | \ -+ SDMMC_INT_HTO | SDMMC_INT_SBE | \ -+ SDMMC_INT_EBE) -+#define DW_MCI_CMD_ERROR_FLAGS (SDMMC_INT_RTO | SDMMC_INT_RCRC | \ -+ SDMMC_INT_RESP_ERR) -+#define DW_MCI_ERROR_FLAGS (DW_MCI_DATA_ERROR_FLAGS | \ -+ DW_MCI_CMD_ERROR_FLAGS | SDMMC_INT_HLE) -+#define DW_MCI_SEND_STATUS 1 -+#define DW_MCI_RECV_STATUS 2 -+#define DW_MCI_DMA_THRESHOLD 16 -+ -+#define DW_MCI_FREQ_MAX 200000000 /* unit: HZ */ -+#define DW_MCI_FREQ_MIN 400000 /* unit: HZ */ -+ -+#ifdef CONFIG_MMC_DW_IDMAC -+#define IDMAC_INT_CLR (SDMMC_IDMAC_INT_AI | SDMMC_IDMAC_INT_NI | \ -+ SDMMC_IDMAC_INT_CES | SDMMC_IDMAC_INT_DU | \ -+ SDMMC_IDMAC_INT_FBE | SDMMC_IDMAC_INT_RI | \ -+ SDMMC_IDMAC_INT_TI) -+ -+struct idmac_desc { -+ u32 des0; /* Control Descriptor */ -+#define IDMAC_DES0_DIC BIT(1) -+#define IDMAC_DES0_LD BIT(2) -+#define IDMAC_DES0_FD BIT(3) -+#define IDMAC_DES0_CH BIT(4) -+#define IDMAC_DES0_ER BIT(5) -+#define IDMAC_DES0_CES BIT(30) -+#define IDMAC_DES0_OWN BIT(31) -+ -+ u32 des1; /* Buffer sizes */ -+#define IDMAC_SET_BUFFER1_SIZE(d, s) \ -+ ((d)->des1 = ((d)->des1 & 0x03ffe000) | ((s) & 0x1fff)) -+ -+ u32 des2; /* buffer 1 physical address */ -+ -+ u32 des3; /* buffer 2 physical address */ -+}; -+#endif /* CONFIG_MMC_DW_IDMAC */ -+ -+static bool dw_mci_reset(struct dw_mci *host); -+ -+#if defined(CONFIG_DEBUG_FS) -+static int dw_mci_req_show(struct seq_file *s, void *v) -+{ -+ struct dw_mci_slot *slot = s->private; -+ struct mmc_request *mrq; -+ struct mmc_command *cmd; -+ struct mmc_command *stop; -+ struct mmc_data *data; -+ -+ /* Make sure we get a consistent snapshot */ -+ spin_lock_bh(&slot->host->lock); -+ mrq = slot->mrq; -+ -+ if (mrq) { -+ cmd = mrq->cmd; -+ data = mrq->data; -+ stop = mrq->stop; -+ -+ if (cmd) -+ seq_printf(s, -+ "CMD%u(0x%x) flg %x rsp %x %x %x %x err %d\n", -+ cmd->opcode, cmd->arg, cmd->flags, -+ cmd->resp[0], cmd->resp[1], cmd->resp[2], -+ cmd->resp[2], cmd->error); -+ if (data) -+ seq_printf(s, "DATA %u / %u * %u flg %x err %d\n", -+ data->bytes_xfered, data->blocks, -+ data->blksz, data->flags, data->error); -+ if (stop) -+ seq_printf(s, -+ "CMD%u(0x%x) flg %x rsp %x %x %x %x err %d\n", -+ stop->opcode, stop->arg, stop->flags, -+ stop->resp[0], stop->resp[1], stop->resp[2], -+ stop->resp[2], stop->error); -+ } -+ -+ spin_unlock_bh(&slot->host->lock); -+ -+ return 0; -+} -+ -+static int dw_mci_req_open(struct inode *inode, struct file *file) -+{ -+ return single_open(file, dw_mci_req_show, inode->i_private); -+} -+ -+static const struct file_operations dw_mci_req_fops = { -+ .owner = THIS_MODULE, -+ .open = dw_mci_req_open, -+ .read = seq_read, -+ .llseek = seq_lseek, -+ .release = single_release, -+}; -+ -+static int dw_mci_regs_show(struct seq_file *s, void *v) -+{ -+ seq_printf(s, "STATUS:\t0x%08x\n", SDMMC_STATUS); -+ seq_printf(s, "RINTSTS:\t0x%08x\n", SDMMC_RINTSTS); -+ seq_printf(s, "CMD:\t0x%08x\n", SDMMC_CMD); -+ seq_printf(s, "CTRL:\t0x%08x\n", SDMMC_CTRL); -+ seq_printf(s, "INTMASK:\t0x%08x\n", SDMMC_INTMASK); -+ seq_printf(s, "CLKENA:\t0x%08x\n", SDMMC_CLKENA); -+ -+ return 0; -+} -+ -+static int dw_mci_regs_open(struct inode *inode, struct file *file) -+{ -+ return single_open(file, dw_mci_regs_show, inode->i_private); -+} -+ -+static const struct file_operations dw_mci_regs_fops = { -+ .owner = THIS_MODULE, -+ .open = dw_mci_regs_open, -+ .read = seq_read, -+ .llseek = seq_lseek, -+ .release = single_release, -+}; -+ -+static void dw_mci_init_debugfs(struct dw_mci_slot *slot) -+{ -+ struct mmc_host *mmc = slot->mmc; -+ struct dw_mci *host = slot->host; -+ struct dentry *root; -+ struct dentry *node; -+ -+ root = mmc->debugfs_root; -+ if (!root) -+ return; -+ -+ node = debugfs_create_file("regs", S_IRUSR, root, host, -+ &dw_mci_regs_fops); -+ if (!node) -+ goto err; -+ -+ node = debugfs_create_file("req", S_IRUSR, root, slot, -+ &dw_mci_req_fops); -+ if (!node) -+ goto err; -+ -+ node = debugfs_create_u32("state", S_IRUSR, root, (u32 *)&host->state); -+ if (!node) -+ goto err; -+ -+ node = debugfs_create_x32("pending_events", S_IRUSR, root, -+ (u32 *)&host->pending_events); -+ if (!node) -+ goto err; -+ -+ node = debugfs_create_x32("completed_events", S_IRUSR, root, -+ (u32 *)&host->completed_events); -+ if (!node) -+ goto err; -+ -+ return; -+ -+err: -+ dev_err(&mmc->class_dev, "failed to initialize debugfs for slot\n"); -+} -+#endif /* defined(CONFIG_DEBUG_FS) */ -+ -+static void mci_send_cmd(struct dw_mci_slot *slot, u32 cmd, u32 arg); -+ -+static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd) -+{ -+ struct mmc_data *data; -+ struct dw_mci_slot *slot = mmc_priv(mmc); -+ struct dw_mci *host = slot->host; -+ const struct dw_mci_drv_data *drv_data = slot->host->drv_data; -+ u32 cmdr; -+ cmd->error = -EINPROGRESS; -+ -+ cmdr = cmd->opcode; -+ -+ if (cmd->opcode == MMC_STOP_TRANSMISSION || -+ cmd->opcode == MMC_GO_IDLE_STATE || -+ cmd->opcode == MMC_GO_INACTIVE_STATE || -+ (cmd->opcode == SD_IO_RW_DIRECT && -+ ((cmd->arg >> 9) & 0x1FFFF) == SDIO_CCCR_ABORT)) -+ cmdr |= SDMMC_CMD_STOP; -+ else if (cmd->opcode != MMC_SEND_STATUS && cmd->data) -+ cmdr |= SDMMC_CMD_PRV_DAT_WAIT; -+ -+ if (cmd->opcode == SD_SWITCH_VOLTAGE) { -+ u32 clk_en_a; -+ -+ /* Special bit makes CMD11 not die */ -+ cmdr |= SDMMC_CMD_VOLT_SWITCH; -+ -+ /* Change state to continue to handle CMD11 weirdness */ -+ WARN_ON(slot->host->state != STATE_SENDING_CMD); -+ slot->host->state = STATE_SENDING_CMD11; -+ -+ /* -+ * We need to disable low power mode (automatic clock stop) -+ * while doing voltage switch so we don't confuse the card, -+ * since stopping the clock is a specific part of the UHS -+ * voltage change dance. -+ * -+ * Note that low power mode (SDMMC_CLKEN_LOW_PWR) will be -+ * unconditionally turned back on in dw_mci_setup_bus() if it's -+ * ever called with a non-zero clock. That shouldn't happen -+ * until the voltage change is all done. -+ */ -+ clk_en_a = mci_readl(host, CLKENA); -+ clk_en_a &= ~(SDMMC_CLKEN_LOW_PWR << slot->id); -+ mci_writel(host, CLKENA, clk_en_a); -+ mci_send_cmd(slot, SDMMC_CMD_UPD_CLK | -+ SDMMC_CMD_PRV_DAT_WAIT, 0); -+ } -+ -+ if (cmd->flags & MMC_RSP_PRESENT) { -+ /* We expect a response, so set this bit */ -+ cmdr |= SDMMC_CMD_RESP_EXP; -+ if (cmd->flags & MMC_RSP_136) -+ cmdr |= SDMMC_CMD_RESP_LONG; -+ } -+ -+ if (cmd->flags & MMC_RSP_CRC) -+ cmdr |= SDMMC_CMD_RESP_CRC; -+ -+ data = cmd->data; -+ if (data) { -+ cmdr |= SDMMC_CMD_DAT_EXP; -+ if (data->flags & MMC_DATA_STREAM) -+ cmdr |= SDMMC_CMD_STRM_MODE; -+ if (data->flags & MMC_DATA_WRITE) -+ cmdr |= SDMMC_CMD_DAT_WR; -+ } -+ -+ if (drv_data && drv_data->prepare_command) -+ drv_data->prepare_command(slot->host, &cmdr); -+ -+ return cmdr; -+} -+ -+static u32 dw_mci_prep_stop_abort(struct dw_mci *host, struct mmc_command *cmd) -+{ -+ struct mmc_command *stop; -+ u32 cmdr; -+ -+ if (!cmd->data) -+ return 0; -+ -+ stop = &host->stop_abort; -+ cmdr = cmd->opcode; -+ memset(stop, 0, sizeof(struct mmc_command)); -+ -+ if (cmdr == MMC_READ_SINGLE_BLOCK || -+ cmdr == MMC_READ_MULTIPLE_BLOCK || -+ cmdr == MMC_WRITE_BLOCK || -+ cmdr == MMC_WRITE_MULTIPLE_BLOCK) { -+ stop->opcode = MMC_STOP_TRANSMISSION; -+ stop->arg = 0; -+ stop->flags = MMC_RSP_R1B | MMC_CMD_AC; -+ } else if (cmdr == SD_IO_RW_EXTENDED) { -+ stop->opcode = SD_IO_RW_DIRECT; -+ stop->arg |= (1 << 31) | (0 << 28) | (SDIO_CCCR_ABORT << 9) | -+ ((cmd->arg >> 28) & 0x7); -+ stop->flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_AC; -+ } else { -+ return 0; -+ } -+ -+ cmdr = stop->opcode | SDMMC_CMD_STOP | -+ SDMMC_CMD_RESP_CRC | SDMMC_CMD_RESP_EXP; -+ -+ return cmdr; -+} -+ -+static void dw_mci_start_command(struct dw_mci *host, -+ struct mmc_command *cmd, u32 cmd_flags) -+{ -+ host->cmd = cmd; -+ dev_vdbg(host->dev, -+ "start command: ARGR=0x%08x CMDR=0x%08x\n", -+ cmd->arg, cmd_flags); -+ -+ mci_writel(host, CMDARG, cmd->arg); -+ wmb(); -+ -+ mci_writel(host, CMD, cmd_flags | SDMMC_CMD_START); -+} -+ -+static inline void send_stop_abort(struct dw_mci *host, struct mmc_data *data) -+{ -+ struct mmc_command *stop = data->stop ? data->stop : &host->stop_abort; -+ dw_mci_start_command(host, stop, host->stop_cmdr); -+} -+ -+/* DMA interface functions */ -+static void dw_mci_stop_dma(struct dw_mci *host) -+{ -+ if (host->using_dma) { -+ host->dma_ops->stop(host); -+ host->dma_ops->cleanup(host); -+ } -+ -+ /* Data transfer was stopped by the interrupt handler */ -+ set_bit(EVENT_XFER_COMPLETE, &host->pending_events); -+} -+ -+static int dw_mci_get_dma_dir(struct mmc_data *data) -+{ -+ if (data->flags & MMC_DATA_WRITE) -+ return DMA_TO_DEVICE; -+ else -+ return DMA_FROM_DEVICE; -+} -+ -+#ifdef CONFIG_MMC_DW_IDMAC -+static void dw_mci_dma_cleanup(struct dw_mci *host) -+{ -+ struct mmc_data *data = host->data; -+ -+ if (data) -+ if (!data->host_cookie) -+ dma_unmap_sg(host->dev, -+ data->sg, -+ data->sg_len, -+ dw_mci_get_dma_dir(data)); -+} -+ -+static void dw_mci_idmac_reset(struct dw_mci *host) -+{ -+ u32 bmod = mci_readl(host, BMOD); -+ /* Software reset of DMA */ -+ bmod |= SDMMC_IDMAC_SWRESET; -+ mci_writel(host, BMOD, bmod); -+} -+ -+static void dw_mci_idmac_stop_dma(struct dw_mci *host) -+{ -+ u32 temp; -+ -+ /* Disable and reset the IDMAC interface */ -+ temp = mci_readl(host, CTRL); -+ temp &= ~SDMMC_CTRL_USE_IDMAC; -+ temp |= SDMMC_CTRL_DMA_RESET; -+ mci_writel(host, CTRL, temp); -+ -+ /* Stop the IDMAC running */ -+ temp = mci_readl(host, BMOD); -+ temp &= ~(SDMMC_IDMAC_ENABLE | SDMMC_IDMAC_FB); -+ temp |= SDMMC_IDMAC_SWRESET; -+ mci_writel(host, BMOD, temp); -+} -+ -+static void dw_mci_idmac_complete_dma(struct dw_mci *host) -+{ -+ struct mmc_data *data = host->data; -+ -+ dev_vdbg(host->dev, "DMA complete\n"); -+ -+ host->dma_ops->cleanup(host); -+ -+ /* -+ * If the card was removed, data will be NULL. No point in trying to -+ * send the stop command or waiting for NBUSY in this case. -+ */ -+ if (data) { -+ set_bit(EVENT_XFER_COMPLETE, &host->pending_events); -+ tasklet_schedule(&host->tasklet); -+ } -+} -+ -+static void dw_mci_translate_sglist(struct dw_mci *host, struct mmc_data *data, -+ unsigned int sg_len) -+{ -+ int i; -+ struct idmac_desc *desc = host->sg_cpu; -+ -+ for (i = 0; i < sg_len; i++, desc++) { -+ unsigned int length = sg_dma_len(&data->sg[i]); -+ u32 mem_addr = sg_dma_address(&data->sg[i]); -+ -+ /* Set the OWN bit and disable interrupts for this descriptor */ -+ desc->des0 = IDMAC_DES0_OWN | IDMAC_DES0_DIC | IDMAC_DES0_CH; -+ -+ /* Buffer length */ -+ IDMAC_SET_BUFFER1_SIZE(desc, length); -+ -+ /* Physical address to DMA to/from */ -+ desc->des2 = mem_addr; -+ } -+ -+ /* Set first descriptor */ -+ desc = host->sg_cpu; -+ desc->des0 |= IDMAC_DES0_FD; -+ -+ /* Set last descriptor */ -+ desc = host->sg_cpu + (i - 1) * sizeof(struct idmac_desc); -+ desc->des0 &= ~(IDMAC_DES0_CH | IDMAC_DES0_DIC); -+ desc->des0 |= IDMAC_DES0_LD; -+ -+ wmb(); -+} -+ -+static void dw_mci_idmac_start_dma(struct dw_mci *host, unsigned int sg_len) -+{ -+ u32 temp; -+ -+ dw_mci_translate_sglist(host, host->data, sg_len); -+ -+ /* Select IDMAC interface */ -+ temp = mci_readl(host, CTRL); -+ temp |= SDMMC_CTRL_USE_IDMAC; -+ mci_writel(host, CTRL, temp); -+ -+ wmb(); -+ -+ /* Enable the IDMAC */ -+ temp = mci_readl(host, BMOD); -+ temp |= SDMMC_IDMAC_ENABLE | SDMMC_IDMAC_FB; -+ mci_writel(host, BMOD, temp); -+ -+ /* Start it running */ -+ mci_writel(host, PLDMND, 1); -+} -+ -+static int dw_mci_idmac_init(struct dw_mci *host) -+{ -+ struct idmac_desc *p; -+ int i; -+ -+ /* Number of descriptors in the ring buffer */ -+ host->ring_size = PAGE_SIZE / sizeof(struct idmac_desc); -+ -+ /* Forward link the descriptor list */ -+ for (i = 0, p = host->sg_cpu; i < host->ring_size - 1; i++, p++) -+ p->des3 = host->sg_dma + (sizeof(struct idmac_desc) * (i + 1)); -+ -+ /* Set the last descriptor as the end-of-ring descriptor */ -+ p->des3 = host->sg_dma; -+ p->des0 = IDMAC_DES0_ER; -+ -+ dw_mci_idmac_reset(host); -+ -+ /* Mask out interrupts - get Tx & Rx complete only */ -+ mci_writel(host, IDSTS, IDMAC_INT_CLR); -+ mci_writel(host, IDINTEN, SDMMC_IDMAC_INT_NI | SDMMC_IDMAC_INT_RI | -+ SDMMC_IDMAC_INT_TI); -+ -+ /* Set the descriptor base address */ -+ mci_writel(host, DBADDR, host->sg_dma); -+ return 0; -+} -+ -+static const struct dw_mci_dma_ops dw_mci_idmac_ops = { -+ .init = dw_mci_idmac_init, -+ .start = dw_mci_idmac_start_dma, -+ .stop = dw_mci_idmac_stop_dma, -+ .complete = dw_mci_idmac_complete_dma, -+ .cleanup = dw_mci_dma_cleanup, -+}; -+#endif /* CONFIG_MMC_DW_IDMAC */ -+ -+static int dw_mci_pre_dma_transfer(struct dw_mci *host, -+ struct mmc_data *data, -+ bool next) -+{ -+ struct scatterlist *sg; -+ unsigned int i, sg_len; -+ -+ if (!next && data->host_cookie) -+ return data->host_cookie; -+ -+ /* -+ * We don't do DMA on "complex" transfers, i.e. with -+ * non-word-aligned buffers or lengths. Also, we don't bother -+ * with all the DMA setup overhead for short transfers. -+ */ -+ if (data->blocks * data->blksz < DW_MCI_DMA_THRESHOLD) -+ return -EINVAL; -+ -+ if (data->blksz & 3) -+ return -EINVAL; -+ -+ for_each_sg(data->sg, sg, data->sg_len, i) { -+ if (sg->offset & 3 || sg->length & 3) -+ return -EINVAL; -+ } -+ -+ sg_len = dma_map_sg(host->dev, -+ data->sg, -+ data->sg_len, -+ dw_mci_get_dma_dir(data)); -+ if (sg_len == 0) -+ return -EINVAL; -+ -+ if (next) -+ data->host_cookie = sg_len; -+ -+ return sg_len; -+} -+ -+static void dw_mci_pre_req(struct mmc_host *mmc, -+ struct mmc_request *mrq, -+ bool is_first_req) -+{ -+ struct dw_mci_slot *slot = mmc_priv(mmc); -+ struct mmc_data *data = mrq->data; -+ -+ if (!slot->host->use_dma || !data) -+ return; -+ -+ if (data->host_cookie) { -+ data->host_cookie = 0; -+ return; -+ } -+ -+ if (dw_mci_pre_dma_transfer(slot->host, mrq->data, 1) < 0) -+ data->host_cookie = 0; -+} -+ -+static void dw_mci_post_req(struct mmc_host *mmc, -+ struct mmc_request *mrq, -+ int err) -+{ -+ struct dw_mci_slot *slot = mmc_priv(mmc); -+ struct mmc_data *data = mrq->data; -+ -+ if (!slot->host->use_dma || !data) -+ return; -+ -+ if (data->host_cookie) -+ dma_unmap_sg(slot->host->dev, -+ data->sg, -+ data->sg_len, -+ dw_mci_get_dma_dir(data)); -+ data->host_cookie = 0; -+} -+ -+static void dw_mci_adjust_fifoth(struct dw_mci *host, struct mmc_data *data) -+{ -+#ifdef CONFIG_MMC_DW_IDMAC -+ unsigned int blksz = data->blksz; -+ const u32 mszs[] = {1, 4, 8, 16, 32, 64, 128, 256}; -+ u32 fifo_width = 1 << host->data_shift; -+ u32 blksz_depth = blksz / fifo_width, fifoth_val; -+ u32 msize = 0, rx_wmark = 1, tx_wmark, tx_wmark_invers; -+ int idx = (sizeof(mszs) / sizeof(mszs[0])) - 1; -+ -+ tx_wmark = (host->fifo_depth) / 2; -+ tx_wmark_invers = host->fifo_depth - tx_wmark; -+ -+ /* -+ * MSIZE is '1', -+ * if blksz is not a multiple of the FIFO width -+ */ -+ if (blksz % fifo_width) { -+ msize = 0; -+ rx_wmark = 1; -+ goto done; -+ } -+ -+ do { -+ if (!((blksz_depth % mszs[idx]) || -+ (tx_wmark_invers % mszs[idx]))) { -+ msize = idx; -+ rx_wmark = mszs[idx] - 1; -+ break; -+ } -+ } while (--idx > 0); -+ /* -+ * If idx is '0', it won't be tried -+ * Thus, initial values are uesed -+ */ -+done: -+ fifoth_val = SDMMC_SET_FIFOTH(msize, rx_wmark, tx_wmark); -+ mci_writel(host, FIFOTH, fifoth_val); -+#endif -+} -+ -+static void dw_mci_ctrl_rd_thld(struct dw_mci *host, struct mmc_data *data) -+{ -+ unsigned int blksz = data->blksz; -+ u32 blksz_depth, fifo_depth; -+ u16 thld_size; -+ -+ WARN_ON(!(data->flags & MMC_DATA_READ)); -+ -+ /* -+ * CDTHRCTL doesn't exist prior to 240A (in fact that register offset is -+ * in the FIFO region, so we really shouldn't access it). -+ */ -+ if (host->verid < DW_MMC_240A) -+ return; -+ -+ if (host->timing != MMC_TIMING_MMC_HS200 && -+ host->timing != MMC_TIMING_UHS_SDR104) -+ goto disable; -+ -+ blksz_depth = blksz / (1 << host->data_shift); -+ fifo_depth = host->fifo_depth; -+ -+ if (blksz_depth > fifo_depth) -+ goto disable; -+ -+ /* -+ * If (blksz_depth) >= (fifo_depth >> 1), should be 'thld_size <= blksz' -+ * If (blksz_depth) < (fifo_depth >> 1), should be thld_size = blksz -+ * Currently just choose blksz. -+ */ -+ thld_size = blksz; -+ mci_writel(host, CDTHRCTL, SDMMC_SET_RD_THLD(thld_size, 1)); -+ return; -+ -+disable: -+ mci_writel(host, CDTHRCTL, SDMMC_SET_RD_THLD(0, 0)); -+} -+ -+static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data) -+{ -+ int sg_len; -+ u32 temp; -+ -+ host->using_dma = 0; -+ -+ /* If we don't have a channel, we can't do DMA */ -+ if (!host->use_dma) -+ return -ENODEV; -+ -+ sg_len = dw_mci_pre_dma_transfer(host, data, 0); -+ if (sg_len < 0) { -+ host->dma_ops->stop(host); -+ return sg_len; -+ } -+ -+ host->using_dma = 1; -+ -+ dev_vdbg(host->dev, -+ "sd sg_cpu: %#lx sg_dma: %#lx sg_len: %d\n", -+ (unsigned long)host->sg_cpu, (unsigned long)host->sg_dma, -+ sg_len); -+ -+ /* -+ * Decide the MSIZE and RX/TX Watermark. -+ * If current block size is same with previous size, -+ * no need to update fifoth. -+ */ -+ if (host->prev_blksz != data->blksz) -+ dw_mci_adjust_fifoth(host, data); -+ -+ /* Enable the DMA interface */ -+ temp = mci_readl(host, CTRL); -+ temp |= SDMMC_CTRL_DMA_ENABLE; -+ mci_writel(host, CTRL, temp); -+ -+ /* Disable RX/TX IRQs, let DMA handle it */ -+ temp = mci_readl(host, INTMASK); -+ temp &= ~(SDMMC_INT_RXDR | SDMMC_INT_TXDR); -+ mci_writel(host, INTMASK, temp); -+ -+ host->dma_ops->start(host, sg_len); -+ -+ return 0; -+} -+ -+static void dw_mci_submit_data(struct dw_mci *host, struct mmc_data *data) -+{ -+ u32 temp; -+ -+ data->error = -EINPROGRESS; -+ -+ WARN_ON(host->data); -+ host->sg = NULL; -+ host->data = data; -+ -+ if (data->flags & MMC_DATA_READ) { -+ host->dir_status = DW_MCI_RECV_STATUS; -+ dw_mci_ctrl_rd_thld(host, data); -+ } else { -+ host->dir_status = DW_MCI_SEND_STATUS; -+ } -+ -+ if (dw_mci_submit_data_dma(host, data)) { -+ int flags = SG_MITER_ATOMIC; -+ if (host->data->flags & MMC_DATA_READ) -+ flags |= SG_MITER_TO_SG; -+ else -+ flags |= SG_MITER_FROM_SG; -+ -+ sg_miter_start(&host->sg_miter, data->sg, data->sg_len, flags); -+ host->sg = data->sg; -+ host->part_buf_start = 0; -+ host->part_buf_count = 0; -+ -+ mci_writel(host, RINTSTS, SDMMC_INT_TXDR | SDMMC_INT_RXDR); -+ temp = mci_readl(host, INTMASK); -+ temp |= SDMMC_INT_TXDR | SDMMC_INT_RXDR; -+ mci_writel(host, INTMASK, temp); -+ -+ temp = mci_readl(host, CTRL); -+ temp &= ~SDMMC_CTRL_DMA_ENABLE; -+ mci_writel(host, CTRL, temp); -+ -+ /* -+ * Use the initial fifoth_val for PIO mode. -+ * If next issued data may be transfered by DMA mode, -+ * prev_blksz should be invalidated. -+ */ -+ mci_writel(host, FIFOTH, host->fifoth_val); -+ host->prev_blksz = 0; -+ } else { -+ /* -+ * Keep the current block size. -+ * It will be used to decide whether to update -+ * fifoth register next time. -+ */ -+ host->prev_blksz = data->blksz; -+ } -+} -+ -+static void mci_send_cmd(struct dw_mci_slot *slot, u32 cmd, u32 arg) -+{ -+ struct dw_mci *host = slot->host; -+ unsigned long timeout = jiffies + msecs_to_jiffies(500); -+ unsigned int cmd_status = 0; -+ -+ mci_writel(host, CMDARG, arg); -+ wmb(); -+ mci_writel(host, CMD, SDMMC_CMD_START | cmd); -+ -+ while (time_before(jiffies, timeout)) { -+ cmd_status = mci_readl(host, CMD); -+ if (!(cmd_status & SDMMC_CMD_START)) -+ return; -+ } -+ dev_err(&slot->mmc->class_dev, -+ "Timeout sending command (cmd %#x arg %#x status %#x)\n", -+ cmd, arg, cmd_status); -+} -+ -+static void dw_mci_setup_bus(struct dw_mci_slot *slot, bool force_clkinit) -+{ -+ struct dw_mci *host = slot->host; -+ unsigned int clock = slot->clock; -+ u32 div; -+ u32 clk_en_a; -+ u32 sdmmc_cmd_bits = SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT; -+ -+ /* We must continue to set bit 28 in CMD until the change is complete */ -+ if (host->state == STATE_WAITING_CMD11_DONE) -+ sdmmc_cmd_bits |= SDMMC_CMD_VOLT_SWITCH; -+ -+ if (!clock) { -+ mci_writel(host, CLKENA, 0); -+ mci_send_cmd(slot, sdmmc_cmd_bits, 0); -+ } else if (clock != host->current_speed || force_clkinit) { -+ div = host->bus_hz / clock; -+ if (host->bus_hz % clock && host->bus_hz > clock) -+ /* -+ * move the + 1 after the divide to prevent -+ * over-clocking the card. -+ */ -+ div += 1; -+ -+ div = (host->bus_hz != clock) ? DIV_ROUND_UP(div, 2) : 0; -+ -+ if ((clock << div) != slot->__clk_old || force_clkinit) -+ dev_info(&slot->mmc->class_dev, -+ "Bus speed (slot %d) = %dHz (slot req %dHz, actual %dHZ div = %d)\n", -+ slot->id, host->bus_hz, clock, -+ div ? ((host->bus_hz / div) >> 1) : -+ host->bus_hz, div); -+ -+ /* disable clock */ -+ mci_writel(host, CLKENA, 0); -+ mci_writel(host, CLKSRC, 0); -+ -+ /* inform CIU */ -+ mci_send_cmd(slot, sdmmc_cmd_bits, 0); -+ -+ /* set clock to desired speed */ -+ mci_writel(host, CLKDIV, div); -+ -+ /* inform CIU */ -+ mci_send_cmd(slot, sdmmc_cmd_bits, 0); -+ -+ /* enable clock; only low power if no SDIO */ -+ clk_en_a = SDMMC_CLKEN_ENABLE << slot->id; -+ if (!(mci_readl(host, INTMASK) & SDMMC_INT_SDIO(slot->id))) -+ clk_en_a |= SDMMC_CLKEN_LOW_PWR << slot->id; -+ mci_writel(host, CLKENA, clk_en_a); -+ -+ /* inform CIU */ -+ mci_send_cmd(slot, sdmmc_cmd_bits, 0); -+ -+ /* keep the clock with reflecting clock dividor */ -+ slot->__clk_old = clock << div; -+ } -+ -+ host->current_speed = clock; -+ -+ /* Set the current slot bus width */ -+ mci_writel(host, CTYPE, (slot->ctype << slot->id)); -+} -+ -+static void __dw_mci_start_request(struct dw_mci *host, -+ struct dw_mci_slot *slot, -+ struct mmc_command *cmd) -+{ -+ struct mmc_request *mrq; -+ struct mmc_data *data; -+ u32 cmdflags; -+ -+ mrq = slot->mrq; -+ -+ host->cur_slot = slot; -+ host->mrq = mrq; -+ -+ host->pending_events = 0; -+ host->completed_events = 0; -+ host->cmd_status = 0; -+ host->data_status = 0; -+ host->dir_status = 0; -+ -+ data = cmd->data; -+ if (data) { -+ mci_writel(host, TMOUT, 0xFFFFFFFF); -+ mci_writel(host, BYTCNT, data->blksz*data->blocks); -+ mci_writel(host, BLKSIZ, data->blksz); -+ } -+ -+ cmdflags = dw_mci_prepare_command(slot->mmc, cmd); -+ -+ /* this is the first command, send the initialization clock */ -+ if (test_and_clear_bit(DW_MMC_CARD_NEED_INIT, &slot->flags)) -+ cmdflags |= SDMMC_CMD_INIT; -+ -+ if (data) { -+ dw_mci_submit_data(host, data); -+ wmb(); -+ } -+ -+ dw_mci_start_command(host, cmd, cmdflags); -+ -+ if (mrq->stop) -+ host->stop_cmdr = dw_mci_prepare_command(slot->mmc, mrq->stop); -+ else -+ host->stop_cmdr = dw_mci_prep_stop_abort(host, cmd); -+} -+ -+static void dw_mci_start_request(struct dw_mci *host, -+ struct dw_mci_slot *slot) -+{ -+ struct mmc_request *mrq = slot->mrq; -+ struct mmc_command *cmd; -+ -+ cmd = mrq->sbc ? mrq->sbc : mrq->cmd; -+ __dw_mci_start_request(host, slot, cmd); -+} -+ -+/* must be called with host->lock held */ -+static void dw_mci_queue_request(struct dw_mci *host, struct dw_mci_slot *slot, -+ struct mmc_request *mrq) -+{ -+ dev_vdbg(&slot->mmc->class_dev, "queue request: state=%d\n", -+ host->state); -+ -+ slot->mrq = mrq; -+ -+ if (host->state == STATE_WAITING_CMD11_DONE) { -+ dev_warn(&slot->mmc->class_dev, -+ "Voltage change didn't complete\n"); -+ /* -+ * this case isn't expected to happen, so we can -+ * either crash here or just try to continue on -+ * in the closest possible state -+ */ -+ host->state = STATE_IDLE; -+ } -+ -+ if (host->state == STATE_IDLE) { -+ host->state = STATE_SENDING_CMD; -+ dw_mci_start_request(host, slot); -+ } else { -+ list_add_tail(&slot->queue_node, &host->queue); -+ } -+} -+ -+static void dw_mci_request(struct mmc_host *mmc, struct mmc_request *mrq) -+{ -+ struct dw_mci_slot *slot = mmc_priv(mmc); -+ struct dw_mci *host = slot->host; -+ -+ WARN_ON(slot->mrq); -+ -+ /* -+ * The check for card presence and queueing of the request must be -+ * atomic, otherwise the card could be removed in between and the -+ * request wouldn't fail until another card was inserted. -+ */ -+ spin_lock_bh(&host->lock); -+ -+ if (!test_bit(DW_MMC_CARD_PRESENT, &slot->flags)) { -+ spin_unlock_bh(&host->lock); -+ mrq->cmd->error = -ENOMEDIUM; -+ mmc_request_done(mmc, mrq); -+ return; -+ } -+ -+ dw_mci_queue_request(host, slot, mrq); -+ -+ spin_unlock_bh(&host->lock); -+} -+ -+static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) -+{ -+ struct dw_mci_slot *slot = mmc_priv(mmc); -+ const struct dw_mci_drv_data *drv_data = slot->host->drv_data; -+ u32 regs; -+ int ret; -+ -+ switch (ios->bus_width) { -+ case MMC_BUS_WIDTH_4: -+ slot->ctype = SDMMC_CTYPE_4BIT; -+ break; -+ case MMC_BUS_WIDTH_8: -+ slot->ctype = SDMMC_CTYPE_8BIT; -+ break; -+ default: -+ /* set default 1 bit mode */ -+ slot->ctype = SDMMC_CTYPE_1BIT; -+ } -+ -+ regs = mci_readl(slot->host, UHS_REG); -+ -+ /* DDR mode set */ -+ if (ios->timing == MMC_TIMING_MMC_DDR52) -+ regs |= ((0x1 << slot->id) << 16); -+ else -+ regs &= ~((0x1 << slot->id) << 16); -+ -+ mci_writel(slot->host, UHS_REG, regs); -+ slot->host->timing = ios->timing; -+ -+ /* -+ * Use mirror of ios->clock to prevent race with mmc -+ * core ios update when finding the minimum. -+ */ -+ slot->clock = ios->clock; -+ -+ if (drv_data && drv_data->set_ios) -+ drv_data->set_ios(slot->host, ios); -+ -+ /* Slot specific timing and width adjustment */ -+ dw_mci_setup_bus(slot, false); -+ -+ if (slot->host->state == STATE_WAITING_CMD11_DONE && ios->clock != 0) -+ slot->host->state = STATE_IDLE; -+ -+ switch (ios->power_mode) { -+ case MMC_POWER_UP: -+ if (!IS_ERR(mmc->supply.vmmc)) { -+ ret = mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, -+ ios->vdd); -+ if (ret) { -+ dev_err(slot->host->dev, -+ "failed to enable vmmc regulator\n"); -+ /*return, if failed turn on vmmc*/ -+ return; -+ } -+ } -+ if (!IS_ERR(mmc->supply.vqmmc) && !slot->host->vqmmc_enabled) { -+ ret = regulator_enable(mmc->supply.vqmmc); -+ if (ret < 0) -+ dev_err(slot->host->dev, -+ "failed to enable vqmmc regulator\n"); -+ else -+ slot->host->vqmmc_enabled = true; -+ } -+ set_bit(DW_MMC_CARD_NEED_INIT, &slot->flags); -+ regs = mci_readl(slot->host, PWREN); -+ regs |= (1 << slot->id); -+ mci_writel(slot->host, PWREN, regs); -+ break; -+ case MMC_POWER_OFF: -+ if (!IS_ERR(mmc->supply.vmmc)) -+ mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0); -+ -+ if (!IS_ERR(mmc->supply.vqmmc) && slot->host->vqmmc_enabled) { -+ regulator_disable(mmc->supply.vqmmc); -+ slot->host->vqmmc_enabled = false; -+ } -+ -+ regs = mci_readl(slot->host, PWREN); -+ regs &= ~(1 << slot->id); -+ mci_writel(slot->host, PWREN, regs); -+ break; -+ default: -+ break; -+ } -+} -+ -+static int dw_mci_card_busy(struct mmc_host *mmc) -+{ -+ struct dw_mci_slot *slot = mmc_priv(mmc); -+ u32 status; -+ -+ /* -+ * Check the busy bit which is low when DAT[3:0] -+ * (the data lines) are 0000 -+ */ -+ status = mci_readl(slot->host, STATUS); -+ -+ return !!(status & SDMMC_STATUS_BUSY); -+} -+ -+static int dw_mci_switch_voltage(struct mmc_host *mmc, struct mmc_ios *ios) -+{ -+ struct dw_mci_slot *slot = mmc_priv(mmc); -+ struct dw_mci *host = slot->host; -+ u32 uhs; -+ u32 v18 = SDMMC_UHS_18V << slot->id; -+ int min_uv, max_uv; -+ int ret; -+ -+ /* -+ * Program the voltage. Note that some instances of dw_mmc may use -+ * the UHS_REG for this. For other instances (like exynos) the UHS_REG -+ * does no harm but you need to set the regulator directly. Try both. -+ */ -+ uhs = mci_readl(host, UHS_REG); -+ if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) { -+ min_uv = 2700000; -+ max_uv = 3600000; -+ uhs &= ~v18; -+ } else { -+ min_uv = 1700000; -+ max_uv = 1950000; -+ uhs |= v18; -+ } -+ if (!IS_ERR(mmc->supply.vqmmc)) { -+ ret = regulator_set_voltage(mmc->supply.vqmmc, min_uv, max_uv); -+ -+ if (ret) { -+ dev_err(&mmc->class_dev, -+ "Regulator set error %d: %d - %d\n", -+ ret, min_uv, max_uv); -+ return ret; -+ } -+ } -+ mci_writel(host, UHS_REG, uhs); -+ -+ return 0; -+} -+ -+static int dw_mci_get_ro(struct mmc_host *mmc) -+{ -+ int read_only; -+ struct dw_mci_slot *slot = mmc_priv(mmc); -+ int gpio_ro = mmc_gpio_get_ro(mmc); -+ -+ /* Use platform get_ro function, else try on board write protect */ -+ if ((slot->quirks & DW_MCI_SLOT_QUIRK_NO_WRITE_PROTECT) || -+ (slot->host->quirks & DW_MCI_QUIRK_NO_WRITE_PROTECT)) -+ read_only = 0; -+ else if (!IS_ERR_VALUE(gpio_ro)) -+ read_only = gpio_ro; -+ else -+ read_only = -+ mci_readl(slot->host, WRTPRT) & (1 << slot->id) ? 1 : 0; -+ -+ dev_dbg(&mmc->class_dev, "card is %s\n", -+ read_only ? "read-only" : "read-write"); -+ -+ return read_only; -+} -+ -+static int dw_mci_get_cd(struct mmc_host *mmc) -+{ -+ int present; -+ struct dw_mci_slot *slot = mmc_priv(mmc); -+ struct dw_mci_board *brd = slot->host->pdata; -+ struct dw_mci *host = slot->host; -+ int gpio_cd = mmc_gpio_get_cd(mmc); -+ -+ /* Use platform get_cd function, else try onboard card detect */ -+ if (brd->quirks & DW_MCI_QUIRK_BROKEN_CARD_DETECTION) -+ present = 1; -+ else if (!IS_ERR_VALUE(gpio_cd)) -+ present = gpio_cd; -+ else -+ present = (mci_readl(slot->host, CDETECT) & (1 << slot->id)) -+ == 0 ? 1 : 0; -+ -+ spin_lock_bh(&host->lock); -+ if (present) { -+ set_bit(DW_MMC_CARD_PRESENT, &slot->flags); -+ dev_dbg(&mmc->class_dev, "card is present\n"); -+ } else { -+ clear_bit(DW_MMC_CARD_PRESENT, &slot->flags); -+ dev_dbg(&mmc->class_dev, "card is not present\n"); -+ } -+ spin_unlock_bh(&host->lock); -+ -+ return present; -+} -+ -+/* -+ * Disable lower power mode. -+ * -+ * Low power mode will stop the card clock when idle. According to the -+ * description of the CLKENA register we should disable low power mode -+ * for SDIO cards if we need SDIO interrupts to work. -+ * -+ * This function is fast if low power mode is already disabled. -+ */ -+static void dw_mci_disable_low_power(struct dw_mci_slot *slot) -+{ -+ struct dw_mci *host = slot->host; -+ u32 clk_en_a; -+ const u32 clken_low_pwr = SDMMC_CLKEN_LOW_PWR << slot->id; -+ -+ clk_en_a = mci_readl(host, CLKENA); -+ -+ if (clk_en_a & clken_low_pwr) { -+ mci_writel(host, CLKENA, clk_en_a & ~clken_low_pwr); -+ mci_send_cmd(slot, SDMMC_CMD_UPD_CLK | -+ SDMMC_CMD_PRV_DAT_WAIT, 0); -+ } -+} -+ -+static void dw_mci_enable_sdio_irq(struct mmc_host *mmc, int enb) -+{ -+ struct dw_mci_slot *slot = mmc_priv(mmc); -+ struct dw_mci *host = slot->host; -+ u32 int_mask; -+ -+ /* Enable/disable Slot Specific SDIO interrupt */ -+ int_mask = mci_readl(host, INTMASK); -+ if (enb) { -+ /* -+ * Turn off low power mode if it was enabled. This is a bit of -+ * a heavy operation and we disable / enable IRQs a lot, so -+ * we'll leave low power mode disabled and it will get -+ * re-enabled again in dw_mci_setup_bus(). -+ */ -+ dw_mci_disable_low_power(slot); -+ -+ mci_writel(host, INTMASK, -+ (int_mask | SDMMC_INT_SDIO(slot->id))); -+ } else { -+ mci_writel(host, INTMASK, -+ (int_mask & ~SDMMC_INT_SDIO(slot->id))); -+ } -+} -+ -+static int dw_mci_execute_tuning(struct mmc_host *mmc, u32 opcode) -+{ -+ struct dw_mci_slot *slot = mmc_priv(mmc); -+ struct dw_mci *host = slot->host; -+ const struct dw_mci_drv_data *drv_data = host->drv_data; -+ struct dw_mci_tuning_data tuning_data; -+ int err = -ENOSYS; -+ -+ if (opcode == MMC_SEND_TUNING_BLOCK_HS200) { -+ if (mmc->ios.bus_width == MMC_BUS_WIDTH_8) { -+ tuning_data.blk_pattern = tuning_blk_pattern_8bit; -+ tuning_data.blksz = sizeof(tuning_blk_pattern_8bit); -+ } else if (mmc->ios.bus_width == MMC_BUS_WIDTH_4) { -+ tuning_data.blk_pattern = tuning_blk_pattern_4bit; -+ tuning_data.blksz = sizeof(tuning_blk_pattern_4bit); -+ } else { -+ return -EINVAL; -+ } -+ } else if (opcode == MMC_SEND_TUNING_BLOCK) { -+ tuning_data.blk_pattern = tuning_blk_pattern_4bit; -+ tuning_data.blksz = sizeof(tuning_blk_pattern_4bit); -+ } else { -+ dev_err(host->dev, -+ "Undefined command(%d) for tuning\n", opcode); -+ return -EINVAL; -+ } -+ -+ if (drv_data && drv_data->execute_tuning) -+ err = drv_data->execute_tuning(slot, opcode, &tuning_data); -+ return err; -+} -+ -+static const struct mmc_host_ops dw_mci_ops = { -+ .request = dw_mci_request, -+ .pre_req = dw_mci_pre_req, -+ .post_req = dw_mci_post_req, -+ .set_ios = dw_mci_set_ios, -+ .get_ro = dw_mci_get_ro, -+ .get_cd = dw_mci_get_cd, -+ .enable_sdio_irq = dw_mci_enable_sdio_irq, -+ .execute_tuning = dw_mci_execute_tuning, -+ .card_busy = dw_mci_card_busy, -+ .start_signal_voltage_switch = dw_mci_switch_voltage, -+ -+}; -+ -+static void dw_mci_request_end(struct dw_mci *host, struct mmc_request *mrq) -+ __releases(&host->lock) -+ __acquires(&host->lock) -+{ -+ struct dw_mci_slot *slot; -+ struct mmc_host *prev_mmc = host->cur_slot->mmc; -+ -+ WARN_ON(host->cmd || host->data); -+ -+ host->cur_slot->mrq = NULL; -+ host->mrq = NULL; -+ if (!list_empty(&host->queue)) { -+ slot = list_entry(host->queue.next, -+ struct dw_mci_slot, queue_node); -+ list_del(&slot->queue_node); -+ dev_vdbg(host->dev, "list not empty: %s is next\n", -+ mmc_hostname(slot->mmc)); -+ host->state = STATE_SENDING_CMD; -+ dw_mci_start_request(host, slot); -+ } else { -+ dev_vdbg(host->dev, "list empty\n"); -+ -+ if (host->state == STATE_SENDING_CMD11) -+ host->state = STATE_WAITING_CMD11_DONE; -+ else -+ host->state = STATE_IDLE; -+ } -+ -+ spin_unlock(&host->lock); -+ mmc_request_done(prev_mmc, mrq); -+ spin_lock(&host->lock); -+} -+ -+static int dw_mci_command_complete(struct dw_mci *host, struct mmc_command *cmd) -+{ -+ u32 status = host->cmd_status; -+ -+ host->cmd_status = 0; -+ -+ /* Read the response from the card (up to 16 bytes) */ -+ if (cmd->flags & MMC_RSP_PRESENT) { -+ if (cmd->flags & MMC_RSP_136) { -+ cmd->resp[3] = mci_readl(host, RESP0); -+ cmd->resp[2] = mci_readl(host, RESP1); -+ cmd->resp[1] = mci_readl(host, RESP2); -+ cmd->resp[0] = mci_readl(host, RESP3); -+ } else { -+ cmd->resp[0] = mci_readl(host, RESP0); -+ cmd->resp[1] = 0; -+ cmd->resp[2] = 0; -+ cmd->resp[3] = 0; -+ } -+ } -+ -+ if (status & SDMMC_INT_RTO) -+ cmd->error = -ETIMEDOUT; -+ else if ((cmd->flags & MMC_RSP_CRC) && (status & SDMMC_INT_RCRC)) -+ cmd->error = -EILSEQ; -+ else if (status & SDMMC_INT_RESP_ERR) -+ cmd->error = -EIO; -+ else -+ cmd->error = 0; -+ -+ if (cmd->error) { -+ /* newer ip versions need a delay between retries */ -+ if (host->quirks & DW_MCI_QUIRK_RETRY_DELAY) -+ mdelay(20); -+ } -+ -+ return cmd->error; -+} -+ -+static int dw_mci_data_complete(struct dw_mci *host, struct mmc_data *data) -+{ -+ u32 status = host->data_status; -+ -+ if (status & DW_MCI_DATA_ERROR_FLAGS) { -+ if (status & SDMMC_INT_DRTO) { -+ data->error = -ETIMEDOUT; -+ } else if (status & SDMMC_INT_DCRC) { -+ data->error = -EILSEQ; -+ } else if (status & SDMMC_INT_EBE) { -+ if (host->dir_status == -+ DW_MCI_SEND_STATUS) { -+ /* -+ * No data CRC status was returned. -+ * The number of bytes transferred -+ * will be exaggerated in PIO mode. -+ */ -+ data->bytes_xfered = 0; -+ data->error = -ETIMEDOUT; -+ } else if (host->dir_status == -+ DW_MCI_RECV_STATUS) { -+ data->error = -EIO; -+ } -+ } else { -+ /* SDMMC_INT_SBE is included */ -+ data->error = -EIO; -+ } -+ -+ dev_dbg(host->dev, "data error, status 0x%08x\n", status); -+ -+ /* -+ * After an error, there may be data lingering -+ * in the FIFO -+ */ -+ dw_mci_reset(host); -+ } else { -+ data->bytes_xfered = data->blocks * data->blksz; -+ data->error = 0; -+ } -+ -+ return data->error; -+} -+ -+static void dw_mci_tasklet_func(unsigned long priv) -+{ -+ struct dw_mci *host = (struct dw_mci *)priv; -+ struct mmc_data *data; -+ struct mmc_command *cmd; -+ struct mmc_request *mrq; -+ enum dw_mci_state state; -+ enum dw_mci_state prev_state; -+ unsigned int err; -+ -+ spin_lock(&host->lock); -+ -+ state = host->state; -+ data = host->data; -+ mrq = host->mrq; -+ -+ do { -+ prev_state = state; -+ -+ switch (state) { -+ case STATE_IDLE: -+ case STATE_WAITING_CMD11_DONE: -+ break; -+ -+ case STATE_SENDING_CMD11: -+ case STATE_SENDING_CMD: -+ if (!test_and_clear_bit(EVENT_CMD_COMPLETE, -+ &host->pending_events)) -+ break; -+ -+ cmd = host->cmd; -+ host->cmd = NULL; -+ set_bit(EVENT_CMD_COMPLETE, &host->completed_events); -+ err = dw_mci_command_complete(host, cmd); -+ if (cmd == mrq->sbc && !err) { -+ prev_state = state = STATE_SENDING_CMD; -+ __dw_mci_start_request(host, host->cur_slot, -+ mrq->cmd); -+ goto unlock; -+ } -+ -+ if (cmd->data && err) { -+ dw_mci_stop_dma(host); -+ send_stop_abort(host, data); -+ state = STATE_SENDING_STOP; -+ break; -+ } -+ -+ if (!cmd->data || err) { -+ dw_mci_request_end(host, mrq); -+ goto unlock; -+ } -+ -+ prev_state = state = STATE_SENDING_DATA; -+ /* fall through */ -+ -+ case STATE_SENDING_DATA: -+ /* -+ * We could get a data error and never a transfer -+ * complete so we'd better check for it here. -+ * -+ * Note that we don't really care if we also got a -+ * transfer complete; stopping the DMA and sending an -+ * abort won't hurt. -+ */ -+ if (test_and_clear_bit(EVENT_DATA_ERROR, -+ &host->pending_events)) { -+ dw_mci_stop_dma(host); -+ send_stop_abort(host, data); -+ state = STATE_DATA_ERROR; -+ break; -+ } -+ -+ if (!test_and_clear_bit(EVENT_XFER_COMPLETE, -+ &host->pending_events)) -+ break; -+ -+ set_bit(EVENT_XFER_COMPLETE, &host->completed_events); -+ -+ /* -+ * Handle an EVENT_DATA_ERROR that might have shown up -+ * before the transfer completed. This might not have -+ * been caught by the check above because the interrupt -+ * could have gone off between the previous check and -+ * the check for transfer complete. -+ * -+ * Technically this ought not be needed assuming we -+ * get a DATA_COMPLETE eventually (we'll notice the -+ * error and end the request), but it shouldn't hurt. -+ * -+ * This has the advantage of sending the stop command. -+ */ -+ if (test_and_clear_bit(EVENT_DATA_ERROR, -+ &host->pending_events)) { -+ dw_mci_stop_dma(host); -+ send_stop_abort(host, data); -+ state = STATE_DATA_ERROR; -+ break; -+ } -+ prev_state = state = STATE_DATA_BUSY; -+ -+ /* fall through */ -+ -+ case STATE_DATA_BUSY: -+ if (!test_and_clear_bit(EVENT_DATA_COMPLETE, -+ &host->pending_events)) -+ break; -+ -+ host->data = NULL; -+ set_bit(EVENT_DATA_COMPLETE, &host->completed_events); -+ err = dw_mci_data_complete(host, data); -+ -+ if (!err) { -+ if (!data->stop || mrq->sbc) { -+ if (mrq->sbc && data->stop) -+ data->stop->error = 0; -+ dw_mci_request_end(host, mrq); -+ goto unlock; -+ } -+ -+ /* stop command for open-ended transfer*/ -+ if (data->stop) -+ send_stop_abort(host, data); -+ } else { -+ /* -+ * If we don't have a command complete now we'll -+ * never get one since we just reset everything; -+ * better end the request. -+ * -+ * If we do have a command complete we'll fall -+ * through to the SENDING_STOP command and -+ * everything will be peachy keen. -+ */ -+ if (!test_bit(EVENT_CMD_COMPLETE, -+ &host->pending_events)) { -+ host->cmd = NULL; -+ dw_mci_request_end(host, mrq); -+ goto unlock; -+ } -+ } -+ -+ /* -+ * If err has non-zero, -+ * stop-abort command has been already issued. -+ */ -+ prev_state = state = STATE_SENDING_STOP; -+ -+ /* fall through */ -+ -+ case STATE_SENDING_STOP: -+ if (!test_and_clear_bit(EVENT_CMD_COMPLETE, -+ &host->pending_events)) -+ break; -+ -+ /* CMD error in data command */ -+ if (mrq->cmd->error && mrq->data) -+ dw_mci_reset(host); -+ -+ host->cmd = NULL; -+ host->data = NULL; -+ -+ if (mrq->stop) -+ dw_mci_command_complete(host, mrq->stop); -+ else -+ host->cmd_status = 0; -+ -+ dw_mci_request_end(host, mrq); -+ goto unlock; -+ -+ case STATE_DATA_ERROR: -+ if (!test_and_clear_bit(EVENT_XFER_COMPLETE, -+ &host->pending_events)) -+ break; -+ -+ state = STATE_DATA_BUSY; -+ break; -+ } -+ } while (state != prev_state); -+ -+ host->state = state; -+unlock: -+ spin_unlock(&host->lock); -+ -+} -+ -+/* push final bytes to part_buf, only use during push */ -+static void dw_mci_set_part_bytes(struct dw_mci *host, void *buf, int cnt) -+{ -+ memcpy((void *)&host->part_buf, buf, cnt); -+ host->part_buf_count = cnt; -+} -+ -+/* append bytes to part_buf, only use during push */ -+static int dw_mci_push_part_bytes(struct dw_mci *host, void *buf, int cnt) -+{ -+ cnt = min(cnt, (1 << host->data_shift) - host->part_buf_count); -+ memcpy((void *)&host->part_buf + host->part_buf_count, buf, cnt); -+ host->part_buf_count += cnt; -+ return cnt; -+} -+ -+/* pull first bytes from part_buf, only use during pull */ -+static int dw_mci_pull_part_bytes(struct dw_mci *host, void *buf, int cnt) -+{ -+ cnt = min(cnt, (int)host->part_buf_count); -+ if (cnt) { -+ memcpy(buf, (void *)&host->part_buf + host->part_buf_start, -+ cnt); -+ host->part_buf_count -= cnt; -+ host->part_buf_start += cnt; -+ } -+ return cnt; -+} -+ -+/* pull final bytes from the part_buf, assuming it's just been filled */ -+static void dw_mci_pull_final_bytes(struct dw_mci *host, void *buf, int cnt) -+{ -+ memcpy(buf, &host->part_buf, cnt); -+ host->part_buf_start = cnt; -+ host->part_buf_count = (1 << host->data_shift) - cnt; -+} -+ -+static void dw_mci_push_data16(struct dw_mci *host, void *buf, int cnt) -+{ -+ struct mmc_data *data = host->data; -+ int init_cnt = cnt; -+ -+ /* try and push anything in the part_buf */ -+ if (unlikely(host->part_buf_count)) { -+ int len = dw_mci_push_part_bytes(host, buf, cnt); -+ buf += len; -+ cnt -= len; -+ if (host->part_buf_count == 2) { -+ mci_writew(host, DATA(host->data_offset), -+ host->part_buf16); -+ host->part_buf_count = 0; -+ } -+ } -+#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS -+ if (unlikely((unsigned long)buf & 0x1)) { -+ while (cnt >= 2) { -+ u16 aligned_buf[64]; -+ int len = min(cnt & -2, (int)sizeof(aligned_buf)); -+ int items = len >> 1; -+ int i; -+ /* memcpy from input buffer into aligned buffer */ -+ memcpy(aligned_buf, buf, len); -+ buf += len; -+ cnt -= len; -+ /* push data from aligned buffer into fifo */ -+ for (i = 0; i < items; ++i) -+ mci_writew(host, DATA(host->data_offset), -+ aligned_buf[i]); -+ } -+ } else -+#endif -+ { -+ u16 *pdata = buf; -+ for (; cnt >= 2; cnt -= 2) -+ mci_writew(host, DATA(host->data_offset), *pdata++); -+ buf = pdata; -+ } -+ /* put anything remaining in the part_buf */ -+ if (cnt) { -+ dw_mci_set_part_bytes(host, buf, cnt); -+ /* Push data if we have reached the expected data length */ -+ if ((data->bytes_xfered + init_cnt) == -+ (data->blksz * data->blocks)) -+ mci_writew(host, DATA(host->data_offset), -+ host->part_buf16); -+ } -+} -+ -+static void dw_mci_pull_data16(struct dw_mci *host, void *buf, int cnt) -+{ -+#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS -+ if (unlikely((unsigned long)buf & 0x1)) { -+ while (cnt >= 2) { -+ /* pull data from fifo into aligned buffer */ -+ u16 aligned_buf[64]; -+ int len = min(cnt & -2, (int)sizeof(aligned_buf)); -+ int items = len >> 1; -+ int i; -+ for (i = 0; i < items; ++i) -+ aligned_buf[i] = mci_readw(host, -+ DATA(host->data_offset)); -+ /* memcpy from aligned buffer into output buffer */ -+ memcpy(buf, aligned_buf, len); -+ buf += len; -+ cnt -= len; -+ } -+ } else -+#endif -+ { -+ u16 *pdata = buf; -+ for (; cnt >= 2; cnt -= 2) -+ *pdata++ = mci_readw(host, DATA(host->data_offset)); -+ buf = pdata; -+ } -+ if (cnt) { -+ host->part_buf16 = mci_readw(host, DATA(host->data_offset)); -+ dw_mci_pull_final_bytes(host, buf, cnt); -+ } -+} -+ -+static void dw_mci_push_data32(struct dw_mci *host, void *buf, int cnt) -+{ -+ struct mmc_data *data = host->data; -+ int init_cnt = cnt; -+ -+ /* try and push anything in the part_buf */ -+ if (unlikely(host->part_buf_count)) { -+ int len = dw_mci_push_part_bytes(host, buf, cnt); -+ buf += len; -+ cnt -= len; -+ if (host->part_buf_count == 4) { -+ mci_writel(host, DATA(host->data_offset), -+ host->part_buf32); -+ host->part_buf_count = 0; -+ } -+ } -+#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS -+ if (unlikely((unsigned long)buf & 0x3)) { -+ while (cnt >= 4) { -+ u32 aligned_buf[32]; -+ int len = min(cnt & -4, (int)sizeof(aligned_buf)); -+ int items = len >> 2; -+ int i; -+ /* memcpy from input buffer into aligned buffer */ -+ memcpy(aligned_buf, buf, len); -+ buf += len; -+ cnt -= len; -+ /* push data from aligned buffer into fifo */ -+ for (i = 0; i < items; ++i) -+ mci_writel(host, DATA(host->data_offset), -+ aligned_buf[i]); -+ } -+ } else -+#endif -+ { -+ u32 *pdata = buf; -+ for (; cnt >= 4; cnt -= 4) -+ mci_writel(host, DATA(host->data_offset), *pdata++); -+ buf = pdata; -+ } -+ /* put anything remaining in the part_buf */ -+ if (cnt) { -+ dw_mci_set_part_bytes(host, buf, cnt); -+ /* Push data if we have reached the expected data length */ -+ if ((data->bytes_xfered + init_cnt) == -+ (data->blksz * data->blocks)) -+ mci_writel(host, DATA(host->data_offset), -+ host->part_buf32); -+ } -+} -+ -+static void dw_mci_pull_data32(struct dw_mci *host, void *buf, int cnt) -+{ -+#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS -+ if (unlikely((unsigned long)buf & 0x3)) { -+ while (cnt >= 4) { -+ /* pull data from fifo into aligned buffer */ -+ u32 aligned_buf[32]; -+ int len = min(cnt & -4, (int)sizeof(aligned_buf)); -+ int items = len >> 2; -+ int i; -+ for (i = 0; i < items; ++i) -+ aligned_buf[i] = mci_readl(host, -+ DATA(host->data_offset)); -+ /* memcpy from aligned buffer into output buffer */ -+ memcpy(buf, aligned_buf, len); -+ buf += len; -+ cnt -= len; -+ } -+ } else -+#endif -+ { -+ u32 *pdata = buf; -+ for (; cnt >= 4; cnt -= 4) -+ *pdata++ = mci_readl(host, DATA(host->data_offset)); -+ buf = pdata; -+ } -+ if (cnt) { -+ host->part_buf32 = mci_readl(host, DATA(host->data_offset)); -+ dw_mci_pull_final_bytes(host, buf, cnt); -+ } -+} -+ -+static void dw_mci_push_data64(struct dw_mci *host, void *buf, int cnt) -+{ -+ struct mmc_data *data = host->data; -+ int init_cnt = cnt; -+ -+ /* try and push anything in the part_buf */ -+ if (unlikely(host->part_buf_count)) { -+ int len = dw_mci_push_part_bytes(host, buf, cnt); -+ buf += len; -+ cnt -= len; -+ -+ if (host->part_buf_count == 8) { -+ mci_writeq(host, DATA(host->data_offset), -+ host->part_buf); -+ host->part_buf_count = 0; -+ } -+ } -+#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS -+ if (unlikely((unsigned long)buf & 0x7)) { -+ while (cnt >= 8) { -+ u64 aligned_buf[16]; -+ int len = min(cnt & -8, (int)sizeof(aligned_buf)); -+ int items = len >> 3; -+ int i; -+ /* memcpy from input buffer into aligned buffer */ -+ memcpy(aligned_buf, buf, len); -+ buf += len; -+ cnt -= len; -+ /* push data from aligned buffer into fifo */ -+ for (i = 0; i < items; ++i) -+ mci_writeq(host, DATA(host->data_offset), -+ aligned_buf[i]); -+ } -+ } else -+#endif -+ { -+ u64 *pdata = buf; -+ for (; cnt >= 8; cnt -= 8) -+ mci_writeq(host, DATA(host->data_offset), *pdata++); -+ buf = pdata; -+ } -+ /* put anything remaining in the part_buf */ -+ if (cnt) { -+ dw_mci_set_part_bytes(host, buf, cnt); -+ /* Push data if we have reached the expected data length */ -+ if ((data->bytes_xfered + init_cnt) == -+ (data->blksz * data->blocks)) -+ mci_writeq(host, DATA(host->data_offset), -+ host->part_buf); -+ } -+} -+ -+static void dw_mci_pull_data64(struct dw_mci *host, void *buf, int cnt) -+{ -+#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS -+ if (unlikely((unsigned long)buf & 0x7)) { -+ while (cnt >= 8) { -+ /* pull data from fifo into aligned buffer */ -+ u64 aligned_buf[16]; -+ int len = min(cnt & -8, (int)sizeof(aligned_buf)); -+ int items = len >> 3; -+ int i; -+ for (i = 0; i < items; ++i) -+ aligned_buf[i] = mci_readq(host, -+ DATA(host->data_offset)); -+ /* memcpy from aligned buffer into output buffer */ -+ memcpy(buf, aligned_buf, len); -+ buf += len; -+ cnt -= len; -+ } -+ } else -+#endif -+ { -+ u64 *pdata = buf; -+ for (; cnt >= 8; cnt -= 8) -+ *pdata++ = mci_readq(host, DATA(host->data_offset)); -+ buf = pdata; -+ } -+ if (cnt) { -+ host->part_buf = mci_readq(host, DATA(host->data_offset)); -+ dw_mci_pull_final_bytes(host, buf, cnt); -+ } -+} -+ -+static void dw_mci_pull_data(struct dw_mci *host, void *buf, int cnt) -+{ -+ int len; -+ -+ /* get remaining partial bytes */ -+ len = dw_mci_pull_part_bytes(host, buf, cnt); -+ if (unlikely(len == cnt)) -+ return; -+ buf += len; -+ cnt -= len; -+ -+ /* get the rest of the data */ -+ host->pull_data(host, buf, cnt); -+} -+ -+static void dw_mci_read_data_pio(struct dw_mci *host, bool dto) -+{ -+ struct sg_mapping_iter *sg_miter = &host->sg_miter; -+ void *buf; -+ unsigned int offset; -+ struct mmc_data *data = host->data; -+ int shift = host->data_shift; -+ u32 status; -+ unsigned int len; -+ unsigned int remain, fcnt; -+ -+ do { -+ if (!sg_miter_next(sg_miter)) -+ goto done; -+ -+ host->sg = sg_miter->piter.sg; -+ buf = sg_miter->addr; -+ remain = sg_miter->length; -+ offset = 0; -+ -+ do { -+ fcnt = (SDMMC_GET_FCNT(mci_readl(host, STATUS)) -+ << shift) + host->part_buf_count; -+ len = min(remain, fcnt); -+ if (!len) -+ break; -+ dw_mci_pull_data(host, (void *)(buf + offset), len); -+ data->bytes_xfered += len; -+ offset += len; -+ remain -= len; -+ } while (remain); -+ -+ sg_miter->consumed = offset; -+ status = mci_readl(host, MINTSTS); -+ mci_writel(host, RINTSTS, SDMMC_INT_RXDR); -+ /* if the RXDR is ready read again */ -+ } while ((status & SDMMC_INT_RXDR) || -+ (dto && SDMMC_GET_FCNT(mci_readl(host, STATUS)))); -+ -+ if (!remain) { -+ if (!sg_miter_next(sg_miter)) -+ goto done; -+ sg_miter->consumed = 0; -+ } -+ sg_miter_stop(sg_miter); -+ return; -+ -+done: -+ sg_miter_stop(sg_miter); -+ host->sg = NULL; -+ smp_wmb(); -+ set_bit(EVENT_XFER_COMPLETE, &host->pending_events); -+} -+ -+static void dw_mci_write_data_pio(struct dw_mci *host) -+{ -+ struct sg_mapping_iter *sg_miter = &host->sg_miter; -+ void *buf; -+ unsigned int offset; -+ struct mmc_data *data = host->data; -+ int shift = host->data_shift; -+ u32 status; -+ unsigned int len; -+ unsigned int fifo_depth = host->fifo_depth; -+ unsigned int remain, fcnt; -+ -+ do { -+ if (!sg_miter_next(sg_miter)) -+ goto done; -+ -+ host->sg = sg_miter->piter.sg; -+ buf = sg_miter->addr; -+ remain = sg_miter->length; -+ offset = 0; -+ -+ do { -+ fcnt = ((fifo_depth - -+ SDMMC_GET_FCNT(mci_readl(host, STATUS))) -+ << shift) - host->part_buf_count; -+ len = min(remain, fcnt); -+ if (!len) -+ break; -+ host->push_data(host, (void *)(buf + offset), len); -+ data->bytes_xfered += len; -+ offset += len; -+ remain -= len; -+ } while (remain); -+ -+ sg_miter->consumed = offset; -+ status = mci_readl(host, MINTSTS); -+ mci_writel(host, RINTSTS, SDMMC_INT_TXDR); -+ } while (status & SDMMC_INT_TXDR); /* if TXDR write again */ -+ -+ if (!remain) { -+ if (!sg_miter_next(sg_miter)) -+ goto done; -+ sg_miter->consumed = 0; -+ } -+ sg_miter_stop(sg_miter); -+ return; -+ -+done: -+ sg_miter_stop(sg_miter); -+ host->sg = NULL; -+ smp_wmb(); -+ set_bit(EVENT_XFER_COMPLETE, &host->pending_events); -+} -+ -+static void dw_mci_cmd_interrupt(struct dw_mci *host, u32 status) -+{ -+ if (!host->cmd_status) -+ host->cmd_status = status; -+ -+ smp_wmb(); -+ -+ set_bit(EVENT_CMD_COMPLETE, &host->pending_events); -+ tasklet_schedule(&host->tasklet); -+} -+ -+static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) -+{ -+ struct dw_mci *host = dev_id; -+ u32 pending; -+ int i; -+ -+ pending = mci_readl(host, MINTSTS); /* read-only mask reg */ -+ -+ /* -+ * DTO fix - version 2.10a and below, and only if internal DMA -+ * is configured. -+ */ -+ if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO) { -+ if (!pending && -+ ((mci_readl(host, STATUS) >> 17) & 0x1fff)) -+ pending |= SDMMC_INT_DATA_OVER; -+ } -+ -+ if (pending) { -+ /* Check volt switch first, since it can look like an error */ -+ if ((host->state == STATE_SENDING_CMD11) && -+ (pending & SDMMC_INT_VOLT_SWITCH)) { -+ mci_writel(host, RINTSTS, SDMMC_INT_VOLT_SWITCH); -+ pending &= ~SDMMC_INT_VOLT_SWITCH; -+ dw_mci_cmd_interrupt(host, pending); -+ } -+ -+ if (pending & DW_MCI_CMD_ERROR_FLAGS) { -+ mci_writel(host, RINTSTS, DW_MCI_CMD_ERROR_FLAGS); -+ host->cmd_status = pending; -+ smp_wmb(); -+ set_bit(EVENT_CMD_COMPLETE, &host->pending_events); -+ } -+ -+ if (pending & DW_MCI_DATA_ERROR_FLAGS) { -+ /* if there is an error report DATA_ERROR */ -+ mci_writel(host, RINTSTS, DW_MCI_DATA_ERROR_FLAGS); -+ host->data_status = pending; -+ smp_wmb(); -+ set_bit(EVENT_DATA_ERROR, &host->pending_events); -+ tasklet_schedule(&host->tasklet); -+ } -+ -+ if (pending & SDMMC_INT_DATA_OVER) { -+ mci_writel(host, RINTSTS, SDMMC_INT_DATA_OVER); -+ if (!host->data_status) -+ host->data_status = pending; -+ smp_wmb(); -+ if (host->dir_status == DW_MCI_RECV_STATUS) { -+ if (host->sg != NULL) -+ dw_mci_read_data_pio(host, true); -+ } -+ set_bit(EVENT_DATA_COMPLETE, &host->pending_events); -+ tasklet_schedule(&host->tasklet); -+ } -+ -+ if (pending & SDMMC_INT_RXDR) { -+ mci_writel(host, RINTSTS, SDMMC_INT_RXDR); -+ if (host->dir_status == DW_MCI_RECV_STATUS && host->sg) -+ dw_mci_read_data_pio(host, false); -+ } -+ -+ if (pending & SDMMC_INT_TXDR) { -+ mci_writel(host, RINTSTS, SDMMC_INT_TXDR); -+ if (host->dir_status == DW_MCI_SEND_STATUS && host->sg) -+ dw_mci_write_data_pio(host); -+ } -+ -+ if (pending & SDMMC_INT_CMD_DONE) { -+ mci_writel(host, RINTSTS, SDMMC_INT_CMD_DONE); -+ dw_mci_cmd_interrupt(host, pending); -+ } -+ -+ if (pending & SDMMC_INT_CD) { -+ mci_writel(host, RINTSTS, SDMMC_INT_CD); -+ queue_work(host->card_workqueue, &host->card_work); -+ } -+ -+ /* Handle SDIO Interrupts */ -+ for (i = 0; i < host->num_slots; i++) { -+ struct dw_mci_slot *slot = host->slot[i]; -+ if (pending & SDMMC_INT_SDIO(i)) { -+ mci_writel(host, RINTSTS, SDMMC_INT_SDIO(i)); -+ mmc_signal_sdio_irq(slot->mmc); -+ } -+ } -+ -+ } -+ -+#ifdef CONFIG_MMC_DW_IDMAC -+ /* Handle DMA interrupts */ -+ pending = mci_readl(host, IDSTS); -+ if (pending & (SDMMC_IDMAC_INT_TI | SDMMC_IDMAC_INT_RI)) { -+ mci_writel(host, IDSTS, SDMMC_IDMAC_INT_TI | SDMMC_IDMAC_INT_RI); -+ mci_writel(host, IDSTS, SDMMC_IDMAC_INT_NI); -+ host->dma_ops->complete(host); -+ } -+#endif -+ -+ return IRQ_HANDLED; -+} -+ -+static void dw_mci_work_routine_card(struct work_struct *work) -+{ -+ struct dw_mci *host = container_of(work, struct dw_mci, card_work); -+ int i; -+ -+ for (i = 0; i < host->num_slots; i++) { -+ struct dw_mci_slot *slot = host->slot[i]; -+ struct mmc_host *mmc = slot->mmc; -+ struct mmc_request *mrq; -+ int present; -+ -+ present = dw_mci_get_cd(mmc); -+ while (present != slot->last_detect_state) { -+ dev_dbg(&slot->mmc->class_dev, "card %s\n", -+ present ? "inserted" : "removed"); -+ -+ spin_lock_bh(&host->lock); -+ -+ /* Card change detected */ -+ slot->last_detect_state = present; -+ -+ /* Clean up queue if present */ -+ mrq = slot->mrq; -+ if (mrq) { -+ if (mrq == host->mrq) { -+ host->data = NULL; -+ host->cmd = NULL; -+ -+ switch (host->state) { -+ case STATE_IDLE: -+ case STATE_WAITING_CMD11_DONE: -+ break; -+ case STATE_SENDING_CMD11: -+ case STATE_SENDING_CMD: -+ mrq->cmd->error = -ENOMEDIUM; -+ if (!mrq->data) -+ break; -+ /* fall through */ -+ case STATE_SENDING_DATA: -+ mrq->data->error = -ENOMEDIUM; -+ dw_mci_stop_dma(host); -+ break; -+ case STATE_DATA_BUSY: -+ case STATE_DATA_ERROR: -+ if (mrq->data->error == -EINPROGRESS) -+ mrq->data->error = -ENOMEDIUM; -+ /* fall through */ -+ case STATE_SENDING_STOP: -+ if (mrq->stop) -+ mrq->stop->error = -ENOMEDIUM; -+ break; -+ } -+ -+ dw_mci_request_end(host, mrq); -+ } else { -+ list_del(&slot->queue_node); -+ mrq->cmd->error = -ENOMEDIUM; -+ if (mrq->data) -+ mrq->data->error = -ENOMEDIUM; -+ if (mrq->stop) -+ mrq->stop->error = -ENOMEDIUM; -+ -+ spin_unlock(&host->lock); -+ mmc_request_done(slot->mmc, mrq); -+ spin_lock(&host->lock); -+ } -+ } -+ -+ /* Power down slot */ -+ if (present == 0) -+ dw_mci_reset(host); -+ -+ spin_unlock_bh(&host->lock); -+ -+ present = dw_mci_get_cd(mmc); -+ } -+ -+ mmc_detect_change(slot->mmc, -+ msecs_to_jiffies(host->pdata->detect_delay_ms)); -+ } -+} -+ -+#ifdef CONFIG_OF -+/* given a slot id, find out the device node representing that slot */ -+static struct device_node *dw_mci_of_find_slot_node(struct device *dev, u8 slot) -+{ -+ struct device_node *np; -+ const __be32 *addr; -+ int len; -+ -+ if (!dev || !dev->of_node) -+ return NULL; -+ -+ for_each_child_of_node(dev->of_node, np) { -+ addr = of_get_property(np, "reg", &len); -+ if (!addr || (len < sizeof(int))) -+ continue; -+ if (be32_to_cpup(addr) == slot) -+ return np; -+ } -+ return NULL; -+} -+ -+static struct dw_mci_of_slot_quirks { -+ char *quirk; -+ int id; -+} of_slot_quirks[] = { -+ { -+ .quirk = "disable-wp", -+ .id = DW_MCI_SLOT_QUIRK_NO_WRITE_PROTECT, -+ }, -+}; -+ -+static int dw_mci_of_get_slot_quirks(struct device *dev, u8 slot) -+{ -+ struct device_node *np = dw_mci_of_find_slot_node(dev, slot); -+ int quirks = 0; -+ int idx; -+ -+ /* get quirks */ -+ for (idx = 0; idx < ARRAY_SIZE(of_slot_quirks); idx++) -+ if (of_get_property(np, of_slot_quirks[idx].quirk, NULL)) { -+ dev_warn(dev, "Slot quirk %s is deprecated\n", -+ of_slot_quirks[idx].quirk); -+ quirks |= of_slot_quirks[idx].id; -+ } -+ -+ return quirks; -+} -+#else /* CONFIG_OF */ -+static int dw_mci_of_get_slot_quirks(struct device *dev, u8 slot) -+{ -+ return 0; -+} -+#endif /* CONFIG_OF */ -+ -+static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) -+{ -+ struct mmc_host *mmc; -+ struct dw_mci_slot *slot; -+ const struct dw_mci_drv_data *drv_data = host->drv_data; -+ int ctrl_id, ret; -+ u32 freq[2]; -+ -+ mmc = mmc_alloc_host(sizeof(struct dw_mci_slot), host->dev); -+ if (!mmc) -+ return -ENOMEM; -+ -+ slot = mmc_priv(mmc); -+ slot->id = id; -+ slot->mmc = mmc; -+ slot->host = host; -+ host->slot[id] = slot; -+ -+ slot->quirks = dw_mci_of_get_slot_quirks(host->dev, slot->id); -+ -+ mmc->ops = &dw_mci_ops; -+ if (of_property_read_u32_array(host->dev->of_node, -+ "clock-freq-min-max", freq, 2)) { -+ mmc->f_min = DW_MCI_FREQ_MIN; -+ mmc->f_max = DW_MCI_FREQ_MAX; -+ } else { -+ mmc->f_min = freq[0]; -+ mmc->f_max = freq[1]; -+ } -+ -+ /*if there are external regulators, get them*/ -+ ret = mmc_regulator_get_supply(mmc); -+ if (ret == -EPROBE_DEFER) -+ goto err_host_allocated; -+ -+ if (!mmc->ocr_avail) -+ mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; -+ -+ if (host->pdata->caps) -+ mmc->caps = host->pdata->caps; -+ -+ if (host->pdata->pm_caps) -+ mmc->pm_caps = host->pdata->pm_caps; -+ -+ if (host->dev->of_node) { -+ ctrl_id = of_alias_get_id(host->dev->of_node, "mshc"); -+ if (ctrl_id < 0) -+ ctrl_id = 0; -+ } else { -+ ctrl_id = to_platform_device(host->dev)->id; -+ } -+ if (drv_data && drv_data->caps) -+ mmc->caps |= drv_data->caps[ctrl_id]; -+ -+ if (host->pdata->caps2) -+ mmc->caps2 = host->pdata->caps2; -+ -+ ret = mmc_of_parse(mmc); -+ if (ret) -+ goto err_host_allocated; -+ -+ if (host->pdata->blk_settings) { -+ mmc->max_segs = host->pdata->blk_settings->max_segs; -+ mmc->max_blk_size = host->pdata->blk_settings->max_blk_size; -+ mmc->max_blk_count = host->pdata->blk_settings->max_blk_count; -+ mmc->max_req_size = host->pdata->blk_settings->max_req_size; -+ mmc->max_seg_size = host->pdata->blk_settings->max_seg_size; -+ } else { -+ /* Useful defaults if platform data is unset. */ -+#ifdef CONFIG_MMC_DW_IDMAC -+ mmc->max_segs = host->ring_size; -+ mmc->max_blk_size = 65536; -+ mmc->max_blk_count = host->ring_size; -+ mmc->max_seg_size = 0x1000; -+ mmc->max_req_size = mmc->max_seg_size * mmc->max_blk_count; -+#else -+ mmc->max_segs = 64; -+ mmc->max_blk_size = 65536; /* BLKSIZ is 16 bits */ -+ mmc->max_blk_count = 512; -+ mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; -+ mmc->max_seg_size = mmc->max_req_size; -+#endif /* CONFIG_MMC_DW_IDMAC */ -+ } -+ -+ if (dw_mci_get_cd(mmc)) -+ set_bit(DW_MMC_CARD_PRESENT, &slot->flags); -+ else -+ clear_bit(DW_MMC_CARD_PRESENT, &slot->flags); -+ -+ ret = mmc_add_host(mmc); -+ if (ret) -+ goto err_host_allocated; -+ -+#if defined(CONFIG_DEBUG_FS) -+ dw_mci_init_debugfs(slot); -+#endif -+ -+ /* Card initially undetected */ -+ slot->last_detect_state = 0; -+ -+ return 0; -+ -+err_host_allocated: -+ mmc_free_host(mmc); -+ return ret; -+} -+ -+static void dw_mci_cleanup_slot(struct dw_mci_slot *slot, unsigned int id) -+{ -+ /* Debugfs stuff is cleaned up by mmc core */ -+ mmc_remove_host(slot->mmc); -+ slot->host->slot[id] = NULL; -+ mmc_free_host(slot->mmc); -+} -+ -+static void dw_mci_init_dma(struct dw_mci *host) -+{ -+ /* Alloc memory for sg translation */ -+ host->sg_cpu = dmam_alloc_coherent(host->dev, PAGE_SIZE, -+ &host->sg_dma, GFP_KERNEL); -+ if (!host->sg_cpu) { -+ dev_err(host->dev, "%s: could not alloc DMA memory\n", -+ __func__); -+ goto no_dma; -+ } -+ -+ /* Determine which DMA interface to use */ -+#ifdef CONFIG_MMC_DW_IDMAC -+ host->dma_ops = &dw_mci_idmac_ops; -+ dev_info(host->dev, "Using internal DMA controller.\n"); -+#endif -+ -+ if (!host->dma_ops) -+ goto no_dma; -+ -+ if (host->dma_ops->init && host->dma_ops->start && -+ host->dma_ops->stop && host->dma_ops->cleanup) { -+ if (host->dma_ops->init(host)) { -+ dev_err(host->dev, "%s: Unable to initialize " -+ "DMA Controller.\n", __func__); -+ goto no_dma; -+ } -+ } else { -+ dev_err(host->dev, "DMA initialization not found.\n"); -+ goto no_dma; -+ } -+ -+ host->use_dma = 1; -+ return; -+ -+no_dma: -+ dev_info(host->dev, "Using PIO mode.\n"); -+ host->use_dma = 0; -+ return; -+} -+ -+static bool dw_mci_ctrl_reset(struct dw_mci *host, u32 reset) -+{ -+ unsigned long timeout = jiffies + msecs_to_jiffies(500); -+ u32 ctrl; -+ -+ ctrl = mci_readl(host, CTRL); -+ ctrl |= reset; -+ mci_writel(host, CTRL, ctrl); -+ -+ /* wait till resets clear */ -+ do { -+ ctrl = mci_readl(host, CTRL); -+ if (!(ctrl & reset)) -+ return true; -+ } while (time_before(jiffies, timeout)); -+ -+ dev_err(host->dev, -+ "Timeout resetting block (ctrl reset %#x)\n", -+ ctrl & reset); -+ -+ return false; -+} -+ -+static bool dw_mci_reset(struct dw_mci *host) -+{ -+ u32 flags = SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET; -+ bool ret = false; -+ -+ /* -+ * Reseting generates a block interrupt, hence setting -+ * the scatter-gather pointer to NULL. -+ */ -+ if (host->sg) { -+ sg_miter_stop(&host->sg_miter); -+ host->sg = NULL; -+ } -+ -+ if (host->use_dma) -+ flags |= SDMMC_CTRL_DMA_RESET; -+ -+ if (dw_mci_ctrl_reset(host, flags)) { -+ /* -+ * In all cases we clear the RAWINTS register to clear any -+ * interrupts. -+ */ -+ mci_writel(host, RINTSTS, 0xFFFFFFFF); -+ -+ /* if using dma we wait for dma_req to clear */ -+ if (host->use_dma) { -+ unsigned long timeout = jiffies + msecs_to_jiffies(500); -+ u32 status; -+ do { -+ status = mci_readl(host, STATUS); -+ if (!(status & SDMMC_STATUS_DMA_REQ)) -+ break; -+ cpu_relax(); -+ } while (time_before(jiffies, timeout)); -+ -+ if (status & SDMMC_STATUS_DMA_REQ) { -+ dev_err(host->dev, -+ "%s: Timeout waiting for dma_req to " -+ "clear during reset\n", __func__); -+ goto ciu_out; -+ } -+ -+ /* when using DMA next we reset the fifo again */ -+ if (!dw_mci_ctrl_reset(host, SDMMC_CTRL_FIFO_RESET)) -+ goto ciu_out; -+ } -+ } else { -+ /* if the controller reset bit did clear, then set clock regs */ -+ if (!(mci_readl(host, CTRL) & SDMMC_CTRL_RESET)) { -+ dev_err(host->dev, "%s: fifo/dma reset bits didn't " -+ "clear but ciu was reset, doing clock update\n", -+ __func__); -+ goto ciu_out; -+ } -+ } -+ -+#if IS_ENABLED(CONFIG_MMC_DW_IDMAC) -+ /* It is also recommended that we reset and reprogram idmac */ -+ dw_mci_idmac_reset(host); -+#endif -+ -+ ret = true; -+ -+ciu_out: -+ /* After a CTRL reset we need to have CIU set clock registers */ -+ mci_send_cmd(host->cur_slot, SDMMC_CMD_UPD_CLK, 0); -+ -+ return ret; -+} -+ -+#ifdef CONFIG_OF -+static struct dw_mci_of_quirks { -+ char *quirk; -+ int id; -+} of_quirks[] = { -+ { -+ .quirk = "broken-cd", -+ .id = DW_MCI_QUIRK_BROKEN_CARD_DETECTION, -+ }, { -+ .quirk = "disable-wp", -+ .id = DW_MCI_QUIRK_NO_WRITE_PROTECT, -+ }, -+}; -+ -+static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host) -+{ -+ struct dw_mci_board *pdata; -+ struct device *dev = host->dev; -+ struct device_node *np = dev->of_node; -+ const struct dw_mci_drv_data *drv_data = host->drv_data; -+ int idx, ret; -+ u32 clock_frequency; -+ -+ pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); -+ if (!pdata) { -+ dev_err(dev, "could not allocate memory for pdata\n"); -+ return ERR_PTR(-ENOMEM); -+ } -+ -+ /* find out number of slots supported */ -+ if (of_property_read_u32(dev->of_node, "num-slots", -+ &pdata->num_slots)) { -+ dev_info(dev, "num-slots property not found, " -+ "assuming 1 slot is available\n"); -+ pdata->num_slots = 1; -+ } -+ -+ /* get quirks */ -+ for (idx = 0; idx < ARRAY_SIZE(of_quirks); idx++) -+ if (of_get_property(np, of_quirks[idx].quirk, NULL)) -+ pdata->quirks |= of_quirks[idx].id; -+ -+ if (of_property_read_u32(np, "fifo-depth", &pdata->fifo_depth)) -+ dev_info(dev, "fifo-depth property not found, using " -+ "value of FIFOTH register as default\n"); -+ -+ of_property_read_u32(np, "card-detect-delay", &pdata->detect_delay_ms); -+ -+ if (!of_property_read_u32(np, "clock-frequency", &clock_frequency)) -+ pdata->bus_hz = clock_frequency; -+ -+ if (drv_data && drv_data->parse_dt) { -+ ret = drv_data->parse_dt(host); -+ if (ret) -+ return ERR_PTR(ret); -+ } -+ -+ if (of_find_property(np, "supports-highspeed", NULL)) -+ pdata->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED; -+ -+ return pdata; -+} -+ -+#else /* CONFIG_OF */ -+static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host) -+{ -+ return ERR_PTR(-EINVAL); -+} -+#endif /* CONFIG_OF */ -+ -+int dw_mci_probe(struct dw_mci *host) -+{ -+ const struct dw_mci_drv_data *drv_data = host->drv_data; -+ int width, i, ret = 0; -+ u32 fifo_size; -+ int init_slots = 0; -+ -+ if (!host->pdata) { -+ host->pdata = dw_mci_parse_dt(host); -+ if (IS_ERR(host->pdata)) { -+ dev_err(host->dev, "platform data not available\n"); -+ return -EINVAL; -+ } -+ } -+ -+ if (host->pdata->num_slots > 1) { -+ dev_err(host->dev, -+ "Platform data must supply num_slots.\n"); -+ return -ENODEV; -+ } -+ -+ host->biu_clk = devm_clk_get(host->dev, "biu"); -+ if (IS_ERR(host->biu_clk)) { -+ dev_dbg(host->dev, "biu clock not available\n"); -+ } else { -+ ret = clk_prepare_enable(host->biu_clk); -+ if (ret) { -+ dev_err(host->dev, "failed to enable biu clock\n"); -+ return ret; -+ } -+ } -+ -+ host->ciu_clk = devm_clk_get(host->dev, "ciu"); -+ if (IS_ERR(host->ciu_clk)) { -+ dev_dbg(host->dev, "ciu clock not available\n"); -+ host->bus_hz = host->pdata->bus_hz; -+ } else { -+ ret = clk_prepare_enable(host->ciu_clk); -+ if (ret) { -+ dev_err(host->dev, "failed to enable ciu clock\n"); -+ goto err_clk_biu; -+ } -+ -+ if (host->pdata->bus_hz) { -+ ret = clk_set_rate(host->ciu_clk, host->pdata->bus_hz); -+ if (ret) -+ dev_warn(host->dev, -+ "Unable to set bus rate to %uHz\n", -+ host->pdata->bus_hz); -+ } -+ host->bus_hz = clk_get_rate(host->ciu_clk); -+ } -+ -+ if (!host->bus_hz) { -+ dev_err(host->dev, -+ "Platform data must supply bus speed\n"); -+ ret = -ENODEV; -+ goto err_clk_ciu; -+ } -+ -+ if (drv_data && drv_data->init) { -+ ret = drv_data->init(host); -+ if (ret) { -+ dev_err(host->dev, -+ "implementation specific init failed\n"); -+ goto err_clk_ciu; -+ } -+ } -+ -+ if (drv_data && drv_data->setup_clock) { -+ ret = drv_data->setup_clock(host); -+ if (ret) { -+ dev_err(host->dev, -+ "implementation specific clock setup failed\n"); -+ goto err_clk_ciu; -+ } -+ } -+ -+ host->quirks = host->pdata->quirks; -+ -+ spin_lock_init(&host->lock); -+ INIT_LIST_HEAD(&host->queue); -+ -+ /* -+ * Get the host data width - this assumes that HCON has been set with -+ * the correct values. -+ */ -+ i = (mci_readl(host, HCON) >> 7) & 0x7; -+ if (!i) { -+ host->push_data = dw_mci_push_data16; -+ host->pull_data = dw_mci_pull_data16; -+ width = 16; -+ host->data_shift = 1; -+ } else if (i == 2) { -+ host->push_data = dw_mci_push_data64; -+ host->pull_data = dw_mci_pull_data64; -+ width = 64; -+ host->data_shift = 3; -+ } else { -+ /* Check for a reserved value, and warn if it is */ -+ WARN((i != 1), -+ "HCON reports a reserved host data width!\n" -+ "Defaulting to 32-bit access.\n"); -+ host->push_data = dw_mci_push_data32; -+ host->pull_data = dw_mci_pull_data32; -+ width = 32; -+ host->data_shift = 2; -+ } -+ -+ /* Reset all blocks */ -+ if (!dw_mci_ctrl_reset(host, SDMMC_CTRL_ALL_RESET_FLAGS)) -+ return -ENODEV; -+ -+ host->dma_ops = host->pdata->dma_ops; -+ dw_mci_init_dma(host); -+ -+ /* Clear the interrupts for the host controller */ -+ mci_writel(host, RINTSTS, 0xFFFFFFFF); -+ mci_writel(host, INTMASK, 0); /* disable all mmc interrupt first */ -+ -+ /* Put in max timeout */ -+ mci_writel(host, TMOUT, 0xFFFFFFFF); -+ -+ /* -+ * FIFO threshold settings RxMark = fifo_size / 2 - 1, -+ * Tx Mark = fifo_size / 2 DMA Size = 8 -+ */ -+ if (!host->pdata->fifo_depth) { -+ /* -+ * Power-on value of RX_WMark is FIFO_DEPTH-1, but this may -+ * have been overwritten by the bootloader, just like we're -+ * about to do, so if you know the value for your hardware, you -+ * should put it in the platform data. -+ */ -+ fifo_size = mci_readl(host, FIFOTH); -+ fifo_size = 1 + ((fifo_size >> 16) & 0xfff); -+ } else { -+ fifo_size = host->pdata->fifo_depth; -+ } -+ host->fifo_depth = fifo_size; -+ host->fifoth_val = -+ SDMMC_SET_FIFOTH(0x2, fifo_size / 2 - 1, fifo_size / 2); -+ mci_writel(host, FIFOTH, host->fifoth_val); -+ -+ /* disable clock to CIU */ -+ mci_writel(host, CLKENA, 0); -+ mci_writel(host, CLKSRC, 0); -+ -+ /* -+ * In 2.40a spec, Data offset is changed. -+ * Need to check the version-id and set data-offset for DATA register. -+ */ -+ host->verid = SDMMC_GET_VERID(mci_readl(host, VERID)); -+ dev_info(host->dev, "Version ID is %04x\n", host->verid); -+ -+ if (host->verid < DW_MMC_240A) -+ host->data_offset = DATA_OFFSET; -+ else -+ host->data_offset = DATA_240A_OFFSET; -+ -+ tasklet_init(&host->tasklet, dw_mci_tasklet_func, (unsigned long)host); -+ host->card_workqueue = alloc_workqueue("dw-mci-card", -+ WQ_MEM_RECLAIM, 1); -+ if (!host->card_workqueue) { -+ ret = -ENOMEM; -+ goto err_dmaunmap; -+ } -+ INIT_WORK(&host->card_work, dw_mci_work_routine_card); -+ ret = devm_request_irq(host->dev, host->irq, dw_mci_interrupt, -+ host->irq_flags, "dw-mci", host); -+ if (ret) -+ goto err_workqueue; -+ -+ if (host->pdata->num_slots) -+ host->num_slots = host->pdata->num_slots; -+ else -+ host->num_slots = ((mci_readl(host, HCON) >> 1) & 0x1F) + 1; -+ -+ /* -+ * Enable interrupts for command done, data over, data empty, card det, -+ * receive ready and error such as transmit, receive timeout, crc error -+ */ -+ mci_writel(host, RINTSTS, 0xFFFFFFFF); -+ mci_writel(host, INTMASK, SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER | -+ SDMMC_INT_TXDR | SDMMC_INT_RXDR | -+ DW_MCI_ERROR_FLAGS | SDMMC_INT_CD); -+ mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); /* Enable mci interrupt */ -+ -+ dev_info(host->dev, "DW MMC controller at irq %d, " -+ "%d bit host data width, " -+ "%u deep fifo\n", -+ host->irq, width, fifo_size); -+ -+ /* We need at least one slot to succeed */ -+ for (i = 0; i < host->num_slots; i++) { -+ ret = dw_mci_init_slot(host, i); -+ if (ret) -+ dev_dbg(host->dev, "slot %d init failed\n", i); -+ else -+ init_slots++; -+ } -+ -+ if (init_slots) { -+ dev_info(host->dev, "%d slots initialized\n", init_slots); -+ } else { -+ dev_dbg(host->dev, "attempted to initialize %d slots, " -+ "but failed on all\n", host->num_slots); -+ goto err_workqueue; -+ } -+ -+ if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO) -+ dev_info(host->dev, "Internal DMAC interrupt fix enabled.\n"); -+ -+ return 0; -+ -+err_workqueue: -+ destroy_workqueue(host->card_workqueue); -+ -+err_dmaunmap: -+ if (host->use_dma && host->dma_ops->exit) -+ host->dma_ops->exit(host); -+ -+err_clk_ciu: -+ if (!IS_ERR(host->ciu_clk)) -+ clk_disable_unprepare(host->ciu_clk); -+ -+err_clk_biu: -+ if (!IS_ERR(host->biu_clk)) -+ clk_disable_unprepare(host->biu_clk); -+ -+ return ret; -+} -+EXPORT_SYMBOL(dw_mci_probe); -+ -+void dw_mci_remove(struct dw_mci *host) -+{ -+ int i; -+ -+ mci_writel(host, RINTSTS, 0xFFFFFFFF); -+ mci_writel(host, INTMASK, 0); /* disable all mmc interrupt first */ -+ -+ for (i = 0; i < host->num_slots; i++) { -+ dev_dbg(host->dev, "remove slot %d\n", i); -+ if (host->slot[i]) -+ dw_mci_cleanup_slot(host->slot[i], i); -+ } -+ -+ /* disable clock to CIU */ -+ mci_writel(host, CLKENA, 0); -+ mci_writel(host, CLKSRC, 0); -+ -+ destroy_workqueue(host->card_workqueue); -+ -+ if (host->use_dma && host->dma_ops->exit) -+ host->dma_ops->exit(host); -+ -+ if (!IS_ERR(host->ciu_clk)) -+ clk_disable_unprepare(host->ciu_clk); -+ -+ if (!IS_ERR(host->biu_clk)) -+ clk_disable_unprepare(host->biu_clk); -+} -+EXPORT_SYMBOL(dw_mci_remove); -+ -+ -+ -+#ifdef CONFIG_PM_SLEEP -+/* -+ * TODO: we should probably disable the clock to the card in the suspend path. -+ */ -+int dw_mci_suspend(struct dw_mci *host) -+{ -+ return 0; -+} -+EXPORT_SYMBOL(dw_mci_suspend); -+ -+int dw_mci_resume(struct dw_mci *host) -+{ -+ int i, ret; -+ -+ if (!dw_mci_ctrl_reset(host, SDMMC_CTRL_ALL_RESET_FLAGS)) { -+ ret = -ENODEV; -+ return ret; -+ } -+ -+ if (host->use_dma && host->dma_ops->init) -+ host->dma_ops->init(host); -+ -+ /* -+ * Restore the initial value at FIFOTH register -+ * And Invalidate the prev_blksz with zero -+ */ -+ mci_writel(host, FIFOTH, host->fifoth_val); -+ host->prev_blksz = 0; -+ -+ /* Put in max timeout */ -+ mci_writel(host, TMOUT, 0xFFFFFFFF); -+ -+ mci_writel(host, RINTSTS, 0xFFFFFFFF); -+ mci_writel(host, INTMASK, SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER | -+ SDMMC_INT_TXDR | SDMMC_INT_RXDR | -+ DW_MCI_ERROR_FLAGS | SDMMC_INT_CD); -+ mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); -+ -+ for (i = 0; i < host->num_slots; i++) { -+ struct dw_mci_slot *slot = host->slot[i]; -+ if (!slot) -+ continue; -+ if (slot->mmc->pm_flags & MMC_PM_KEEP_POWER) { -+ dw_mci_set_ios(slot->mmc, &slot->mmc->ios); -+ dw_mci_setup_bus(slot, true); -+ } -+ } -+ return 0; -+} -+EXPORT_SYMBOL(dw_mci_resume); -+#endif /* CONFIG_PM_SLEEP */ -+ -+static int __init dw_mci_init(void) -+{ -+ pr_info("Synopsys Designware Multimedia Card Interface Driver\n"); -+ return 0; -+} -+ -+static void __exit dw_mci_exit(void) -+{ -+} -+ -+module_init(dw_mci_init); -+module_exit(dw_mci_exit); -+ -+MODULE_DESCRIPTION("DW Multimedia Card Interface driver"); -+MODULE_AUTHOR("NXP Semiconductor VietNam"); -+MODULE_AUTHOR("Imagination Technologies Ltd"); -+MODULE_LICENSE("GPL v2"); -diff -Nur linux-3.18.8.orig/include/linux/mmc/host.h linux-3.18.8/include/linux/mmc/host.h ---- linux-3.18.8.orig/include/linux/mmc/host.h 2015-02-27 02:49:36.000000000 +0100 -+++ linux-3.18.8/include/linux/mmc/host.h 2015-03-02 03:25:33.000000000 +0100 -@@ -305,6 +305,11 @@ - unsigned long clkgate_delay; - #endif - -+ /* card specific properties to deal with power and reset */ -+ struct regulator *card_regulator; /* External VCC needed by the card */ -+ struct gpio_desc *card_reset_gpios[2]; /* External resets, active low */ -+ struct clk *card_clk; /* External clock needed by the card */ -+ - /* host specific block data */ - unsigned int max_seg_size; /* see blk_queue_max_segment_size */ - unsigned short max_segs; /* see blk_queue_max_segments */ -- cgit v1.2.3