From b5596798849fca960e272833d8b6ffc600d3be90 Mon Sep 17 00:00:00 2001 From: Nan Li Date: Tue, 23 May 2017 15:03:35 +0800 Subject: [PATCH] sdio: slove sdio & emmc dealocks on m8b PD#141217: slove sdio & emmc dealocks on m8b. 1) Add a semaphore to avoid emmc deadlocks occur and sdio when they shared the same controller. 2) remove sd ro of dts. 3) add m400 dts support. Change-Id: I5fe0a76517a341313513e5abdbc16366724cbbe9 Signed-off-by: Nan Li --- arch/arm/boot/dts/amlogic/meson8b.dtsi | 53 +----------- arch/arm/boot/dts/amlogic/meson8b_m200.dts | 93 +++++++++++++++++++++- arch/arm/boot/dts/amlogic/meson8b_m400.dts | 41 +--------- drivers/amlogic/mmc/aml_sdhc_m8.c | 40 +++++++++- include/linux/amlogic/amlsd.h | 2 + 5 files changed, 137 insertions(+), 92 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/meson8b.dtsi b/arch/arm/boot/dts/amlogic/meson8b.dtsi index 5bc98e8f4a0c..020b1f6fe3f5 100644 --- a/arch/arm/boot/dts/amlogic/meson8b.dtsi +++ b/arch/arm/boot/dts/amlogic/meson8b.dtsi @@ -499,26 +499,17 @@ }; sdhc_emmc_clk_cmd_pins:sdhc_emmc_clk_cmd_pins { - mux1 { + mux { groups = "sdxc_clk_c", "sdxc_cmd_c"; function = "sdxc_c"; input-enable; bias-pull-up; }; - mux2 { - groups = "GPIOX_0", - "GPIOX_1", - "GPIOX_2", - "GPIOX_3", - "GPIOX_8", - "GPIOX_9"; - function = "gpio"; - }; }; sdhc_emmc_all_pins:sdhc_emmc_all_pins { - mux1 { + mux { groups = "sdxc_d0_c", "sdxc_d13_c", "sdxc_d47_c", @@ -528,15 +519,6 @@ input-enable; bias-pull-up; }; - mux2 { - groups = "GPIOX_0", - "GPIOX_1", - "GPIOX_2", - "GPIOX_3", - "GPIOX_8", - "GPIOX_9"; - function = "gpio"; - }; }; sdhc_sd_clk_cmd_pins:sdhc_sd_clk_cmd_pins { @@ -562,31 +544,17 @@ }; sdhc_sdio_clk_cmd_pins:sdhc_sdio_clk_cmd_pins { - mux1 { + mux { groups = "sdxc_clk_a", "sdxc_cmd_a"; function = "sdxc_a"; input-enable; bias-pull-up; }; - mux2 { - groups = "BOOT_0", - "BOOT_1", - "BOOT_2", - "BOOT_3", - "BOOT_4", - "BOOT_5", - "BOOT_6", - "BOOT_7", - "BOOT_8", - "BOOT_10"; - function = "gpio"; - }; - }; sdhc_sdio_all_pins:sdhc_sdio_all_pins { - mux1 { + mux { groups = "sdxc_d0_1_a", "sdxc_d13_1_a", "sdxc_clk_a", @@ -595,19 +563,6 @@ input-enable; bias-pull-up; }; - mux2 { - groups = "BOOT_0", - "BOOT_1", - "BOOT_2", - "BOOT_3", - "BOOT_4", - "BOOT_5", - "BOOT_6", - "BOOT_7", - "BOOT_8", - "BOOT_10"; - function = "gpio"; - }; }; uart_a_pins: uart_a_pins { diff --git a/arch/arm/boot/dts/amlogic/meson8b_m200.dts b/arch/arm/boot/dts/amlogic/meson8b_m200.dts index 72b4f68a41ff..5d85664c6ae8 100644 --- a/arch/arm/boot/dts/amlogic/meson8b_m200.dts +++ b/arch/arm/boot/dts/amlogic/meson8b_m200.dts @@ -112,7 +112,7 @@ gpio_dat3 = <&gpio CARD_4 GPIO_ACTIVE_HIGH>; jtag_pin = <&gpio CARD_0 GPIO_ACTIVE_HIGH>; gpio_cd = <&gpio CARD_6 GPIO_ACTIVE_HIGH>; - gpio_ro = <&gpio GPIODV_25 GPIO_ACTIVE_HIGH>; + /*gpio_ro = <&gpio GPIODV_25 GPIO_ACTIVE_HIGH>;*/ card_type = <5>; /* 0:unknown, * 1:mmc card(include eMMC), @@ -559,4 +559,95 @@ &i2c_ao { status = "ok"; }; +&pinctrl_cbus { + sdhc_emmc_clk_cmd_pins:sdhc_emmc_clk_cmd_pins { + mux { + groups = "sdxc_clk_c", + "sdxc_cmd_c"; + function = "sdxc_c"; + input-enable; + bias-pull-up; + }; + mux1 { + groups = "GPIOX_0", + "GPIOX_1", + "GPIOX_2", + "GPIOX_3", + "GPIOX_8", + "GPIOX_9"; + function = "gpio"; + }; + }; + + sdhc_emmc_all_pins:sdhc_emmc_all_pins { + mux { + groups = "sdxc_d0_c", + "sdxc_d13_c", + "sdxc_d47_c", + "sdxc_clk_c", + "sdxc_cmd_c"; + function = "sdxc_c"; + input-enable; + bias-pull-up; + }; + mux1 { + groups = "GPIOX_0", + "GPIOX_1", + "GPIOX_2", + "GPIOX_3", + "GPIOX_8", + "GPIOX_9"; + function = "gpio"; + }; + }; + + sdhc_sdio_clk_cmd_pins:sdhc_sdio_clk_cmd_pins { + mux { + groups = "sdxc_clk_a", + "sdxc_cmd_a"; + function = "sdxc_a"; + input-enable; + bias-pull-up; + }; + mux1 { + groups = "BOOT_0", + "BOOT_1", + "BOOT_2", + "BOOT_3", + "BOOT_4", + "BOOT_5", + "BOOT_6", + "BOOT_7", + "BOOT_8", + "BOOT_10"; + function = "gpio"; + }; + + }; + + sdhc_sdio_all_pins:sdhc_sdio_all_pins { + mux { + groups = "sdxc_d0_1_a", + "sdxc_d13_1_a", + "sdxc_clk_a", + "sdxc_cmd_a"; + function = "sdxc_a"; + input-enable; + bias-pull-up; + }; + mux1 { + groups = "BOOT_0", + "BOOT_1", + "BOOT_2", + "BOOT_3", + "BOOT_4", + "BOOT_5", + "BOOT_6", + "BOOT_7", + "BOOT_8", + "BOOT_10"; + function = "gpio"; + }; + }; +}; diff --git a/arch/arm/boot/dts/amlogic/meson8b_m400.dts b/arch/arm/boot/dts/amlogic/meson8b_m400.dts index 534d193bb295..d67cf92418ab 100644 --- a/arch/arm/boot/dts/amlogic/meson8b_m400.dts +++ b/arch/arm/boot/dts/amlogic/meson8b_m400.dts @@ -94,7 +94,7 @@ gpio_dat3 = <&gpio CARD_4 GPIO_ACTIVE_HIGH>; jtag_pin = <&gpio CARD_0 GPIO_ACTIVE_HIGH>; gpio_cd = <&gpio CARD_6 GPIO_ACTIVE_HIGH>; - gpio_ro = <&gpio GPIODV_25 GPIO_ACTIVE_HIGH>; + /*gpio_ro = <&gpio GPIODV_25 GPIO_ACTIVE_HIGH>;*/ card_type = <5>; /* 0:unknown, * 1:mmc card(include eMMC), @@ -110,7 +110,7 @@ sdhc { compatible = "amlogic, aml_sdhc"; dev_name = "aml_sdhc.0"; - status = "disable"; + status = "okay"; interrupts = <0 78 1>; reg = <0xc1108e00 0x3c>; pinctrl-names = "sdhc_sd_clk_cmd_pins", @@ -129,42 +129,6 @@ <&clkc CLKID_FCLK_DIV3>; clock-names = "core", "div3"; - emmc { - status = "okay"; - port = <5>; - /* 0:sdio_a, - * 1:sdio_b, - * 2:sdio_c, - * 3:sdhc_a, - * 4:sdhc_b, - * 5:sdhc_c - */ - pinname = "emmc"; - ocr_avail = <0x00200080>; - /* 3.3:0x200000, 1.8+3.3:0x00200080 */ - caps = "MMC_CAP_8_BIT_DATA", - "MMC_CAP_MMC_HIGHSPEED", - "MMC_CAP_SD_HIGHSPEED", - "MMC_CAP_NONREMOVABLE", - "MMC_CAP_ERASE", - "MMC_CAP_HW_RESET"; - caps2 = "MMC_CAP2_HS200_1_8V_SDR"; - f_min = <300000>; - f_max = <100000000>; - max_req_size = <0x20000>; /* 128KB */ - gpio_dat3 = <&gpio BOOT_3 GPIO_ACTIVE_HIGH>; - hw_reset = <&gpio BOOT_9 GPIO_ACTIVE_HIGH>; - card_type = <1>; - /* 0:unknown, - * 1:mmc card(include eMMC), - * 2:sd card(include tSD), - * 3:sdio device(ie:sdio-wifi), - * 4:SD combo (IO+mem) card, - * 5:NON sdio device(means sd/mmc card), - * other:reserved - */ - }; - sdio { status = "okay"; port = <3>; @@ -581,4 +545,3 @@ &i2c_ao { status = "ok"; }; - diff --git a/drivers/amlogic/mmc/aml_sdhc_m8.c b/drivers/amlogic/mmc/aml_sdhc_m8.c index e8298aaeb632..1b64bf51946c 100644 --- a/drivers/amlogic/mmc/aml_sdhc_m8.c +++ b/drivers/amlogic/mmc/aml_sdhc_m8.c @@ -54,7 +54,8 @@ unsigned int timeout_cnt; static unsigned int sdhc_error_flag; static unsigned int sdhc_debug_flag; static int sdhc_err_bak; -static struct semaphore sdhc_sema; +wait_queue_head_t mmc_req_wait_q; +static int wait_req_flag; static void aml_sdhc_send_stop(struct amlsd_host *host); static void aml_sdhc_emmc_clock_switch_on(struct amlsd_platform *pdata); @@ -875,6 +876,8 @@ void aml_sdhc_request_done(struct mmc_host *mmc, struct mmc_request *mrq) } aml_sdhc_clk_switch_off(host); mmc_request_done(host->mmc, mrq); + wake_up_interruptible(&mmc_req_wait_q); + wait_req_flag = 0; } char *msg_err[] = { @@ -1031,6 +1034,8 @@ static void aml_sdhc_timeout(struct work_struct *work) if (host->xfer_step == XFER_FINISHED) { spin_unlock_irqrestore(&host->mrq_lock, flags); sdhc_err("timeout after xfer finished\n"); + wake_up_interruptible(&mmc_req_wait_q); + wait_req_flag = 0; return; } @@ -1049,7 +1054,8 @@ static void aml_sdhc_timeout(struct work_struct *work) mmc_hostname(host->mmc), host->mrq->cmd->opcode, host->xfer_step, time_start_cnt, timeout_cnt); - up(&sdhc_sema); + wake_up_interruptible(&mmc_req_wait_q); + wait_req_flag = 0; return; } timeout_handle: @@ -1125,6 +1131,7 @@ void aml_sdhc_request(struct mmc_host *mmc, struct mmc_request *mrq) unsigned long flags; unsigned int timeout; u32 tuning_opcode; + long status; WARN_ON(!mmc); WARN_ON(!mrq); @@ -1132,8 +1139,21 @@ void aml_sdhc_request(struct mmc_host *mmc, struct mmc_request *mrq) pdata = mmc_priv(mmc); host = (void *)pdata->host; - if (aml_check_unsupport_cmd(mmc, mrq)) + status = wait_event_interruptible_timeout(mmc_req_wait_q, + wait_req_flag == 0, WAIT_UNTIL_REQ_DONE); + if (status == 0) { + mmc_request_done(mmc, mrq); + sdhc_err("SDHC CMD conflict!\n"); return; + } else if (status < 0) + return; + wait_req_flag = 1; + + if (aml_check_unsupport_cmd(mmc, mrq)) { + wake_up_interruptible(&mmc_req_wait_q); + wait_req_flag = 0; + return; + } aml_sdhc_emmc_clock_switch_on(pdata); /* only for SDCARD */ if (!pdata->is_in || (!host->init_flag && aml_card_type_sd(pdata))) { @@ -1142,14 +1162,27 @@ void aml_sdhc_request(struct mmc_host *mmc, struct mmc_request *mrq) mrq->cmd->retries = 0; spin_unlock_irqrestore(&host->mrq_lock, flags); mmc_request_done(mmc, mrq); + wake_up_interruptible(&mmc_req_wait_q); + wait_req_flag = 0; return; } if (pdata->need_retuning && mmc->card) { + wake_up_interruptible(&mmc_req_wait_q); + wait_req_flag = 0; /* eMMC uses cmd21 but sd and sdio use cmd19 */ tuning_opcode = (mmc->card->type == MMC_TYPE_MMC) ? MMC_SEND_TUNING_BLOCK_HS200 : MMC_SEND_TUNING_BLOCK; aml_sdhc_execute_tuning(mmc, tuning_opcode); + status = wait_event_interruptible_timeout(mmc_req_wait_q, + wait_req_flag == 0, WAIT_UNTIL_REQ_DONE); + if (status == 0) { + mmc_request_done(mmc, mrq); + sdhc_err(" SDHC CMD conflict in tuning\n"); + return; + } else if (status < 0) + return; + wait_req_flag = 1; } aml_sdhc_disable_imask(host, SDHC_ICTL_ALL); @@ -2230,6 +2263,7 @@ static int aml_sdhc_probe(struct platform_device *pdev) host->dev = &pdev->dev; platform_set_drvdata(pdev, host); aml_sdhc_reg_init(host); + init_waitqueue_head(&mmc_req_wait_q); /* for (i = 0; i < MMC_MAX_DEVICE; i++) {*/ for (i = 0; i < 2; i++) { diff --git a/include/linux/amlogic/amlsd.h b/include/linux/amlogic/amlsd.h index 07827c3f7544..e376a61c6f22 100644 --- a/include/linux/amlogic/amlsd.h +++ b/include/linux/amlogic/amlsd.h @@ -160,6 +160,8 @@ extern const u8 tuning_blk_pattern_8bit[128]; #define SD_CAPS(a, b) { .caps = a, .name = b } +#define WAIT_UNTIL_REQ_DONE msecs_to_jiffies(10000) + struct sd_caps { unsigned int caps; const char *name;