From patchwork Fri Jul 10 11:08:06 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Chuang X-Patchwork-Id: 11656253 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 2D871618 for ; Fri, 10 Jul 2020 11:07:27 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 073A02077D for ; Fri, 10 Jul 2020 11:07:27 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="mSUW52wn" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727780AbgGJLHZ (ORCPT ); Fri, 10 Jul 2020 07:07:25 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40826 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727772AbgGJLHY (ORCPT ); Fri, 10 Jul 2020 07:07:24 -0400 Received: from mail-pj1-x1042.google.com (mail-pj1-x1042.google.com [IPv6:2607:f8b0:4864:20::1042]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9A92FC08C5CE; Fri, 10 Jul 2020 04:07:24 -0700 (PDT) Received: by mail-pj1-x1042.google.com with SMTP id ch3so2465579pjb.5; Fri, 10 Jul 2020 04:07:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=TkLFv5ZrNG0D7Do3uQLUMmgdHfa+DeDrwgAx0JrIK6Y=; b=mSUW52wntiHDmcM3j4RTLoUJpo3E95txCAh6ZgVZ8v40FoKtR8PzNB8mLHNjk3+Fyg 1+WhTStSXGeyQexvgf9pya5FjU5sv+PQzHsgmIJEPo0I34nDbzAGjg609KHdgfsYPPwL SLRc8uSciG0jLf+yrkavjf1/qVXvwlxYrr7hOHvuE/ZFxQfe/OD4IRl35hs4V60+w4VH Onci8M3hqEXZA9+7ONuEuLUrJ6KTVMlUUBE0MsCOsmABUwH6HrBa5+ZpBM7y08iGENIt HH0Fr/syO7udNCljmLxCnKnhSYVNDng0ly8rNHw/e/SWvUWdTO38cOVgw6RwvVhDGW24 mM0g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=TkLFv5ZrNG0D7Do3uQLUMmgdHfa+DeDrwgAx0JrIK6Y=; b=IghTvjpOq1u8SFbmWeD5Tuw0wPY32EGqT+8hM2QbiQKdB6+SHP2sGSGQ8W/QcXRx6P 6fUXA6d1Wmjbfu4GfGqGpBvNH2jFFIplDX2EkU3XWDsCIG58zrPsofeS0S8/nXtqH+w5 ijxWf1Lj7fUwqGssd9QzezwGOVTJ6nBDw3dTki2fsv0mC/kP5HoJfW8T1GmhCw3fntg3 9CA0siDxblsSzosU0iQTu7ArYVypwzvn2sNCJEE8ONOA2lDfIPGxWU19revTL4wQMnwX LsOz2Nw+aB8RsIUaMuqz3I3L0431dcyN+wSmGn6Cyee7Mssib+hL7zgbtTyFOetlg86L snIg== X-Gm-Message-State: AOAM532KeABKKjKbPKkbmrn5Peo4uA9ViQa5BV37K6g84Z4E6C7SL4R+ tH0wahwvpPj2lSE3i3g1ZRpN25i8 X-Google-Smtp-Source: ABdhPJy+6wvtgnUGcYwkdhWIgPp6DFZiYG0XkHQ1XlGUu+Q84LDIBWsHjUQWccGV7vOQ2eqkdV8aTQ== X-Received: by 2002:a17:90a:206a:: with SMTP id n97mr5042144pjc.94.1594379244144; Fri, 10 Jul 2020 04:07:24 -0700 (PDT) Received: from gli-arch.genesyslogic.com.tw (60-251-58-169.HINET-IP.hinet.net. [60.251.58.169]) by smtp.gmail.com with ESMTPSA id j26sm5395590pfe.200.2020.07.10.04.07.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 10 Jul 2020 04:07:23 -0700 (PDT) From: Ben Chuang To: adrian.hunter@intel.com, ulf.hansson@linaro.org Cc: linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, ben.chuang@genesyslogic.com.tw, takahiro.akashi@linaro.org, greg.tu@genesyslogic.com.tw, Ben Chuang Subject: [RFC PATCH V3 01/21] mmc: add UHS-II related definitions in public headers Date: Fri, 10 Jul 2020 19:08:06 +0800 Message-Id: <20200710110806.28905-1-benchuanggli@gmail.com> X-Mailer: git-send-email 2.27.0 MIME-Version: 1.0 Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org From: Ben Chuang Add UHS-II support in public headers Signed-off-by: Ben Chuang Signed-off-by: AKASHI Takahiro --- include/linux/mmc/card.h | 1 + include/linux/mmc/core.h | 6 + include/linux/mmc/host.h | 30 +++++ include/linux/mmc/uhs2.h | 268 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 305 insertions(+) create mode 100644 include/linux/mmc/uhs2.h diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 7d46411ffaa2..b7a7ce928155 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -181,6 +181,7 @@ struct sd_switch_caps { #define SD_SET_CURRENT_LIMIT_400 1 #define SD_SET_CURRENT_LIMIT_600 2 #define SD_SET_CURRENT_LIMIT_800 3 +#define SD_SET_CURRENT_LIMIT_1000 4 #define SD_SET_CURRENT_NO_CHANGE (-1) #define SD_MAX_CURRENT_200 (1 << SD_SET_CURRENT_LIMIT_200) diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h index 29aa50711626..52cb628d03fd 100644 --- a/include/linux/mmc/core.h +++ b/include/linux/mmc/core.h @@ -7,6 +7,7 @@ #include #include +#include struct mmc_data; struct mmc_request; @@ -109,6 +110,11 @@ struct mmc_command { unsigned int busy_timeout; /* busy detect timeout in ms */ struct mmc_data *data; /* data segment associated with cmd */ struct mmc_request *mrq; /* associated request */ + + struct uhs2_command *uhs2_cmd; /* UHS2 command */ + u8 *uhs2_resp; /* UHS2 native cmd resp */ + u8 uhs2_resp_len; /* UHS2 native cmd resp len */ + u8 uhs2_tmode0_flag; /* UHS2 transfer mode flag */ }; struct mmc_data { diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 7149bab555d7..56bdb153ef16 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -15,10 +15,12 @@ #include #include #include +#include struct mmc_ios { unsigned int clock; /* clock rate */ unsigned short vdd; + unsigned short vdd2; /* UHS2 VDD2 power supply */ unsigned int power_delay_ms; /* waiting for stable power */ /* vdd stores the bit number of the selected voltage range from below. */ @@ -60,6 +62,7 @@ struct mmc_ios { #define MMC_TIMING_MMC_DDR52 8 #define MMC_TIMING_MMC_HS200 9 #define MMC_TIMING_MMC_HS400 10 +#define MMC_TIMING_UHS2 11 unsigned char signal_voltage; /* signalling voltage (1.8V or 3.3V) */ @@ -172,6 +175,11 @@ struct mmc_host_ops { */ int (*multi_io_quirk)(struct mmc_card *card, unsigned int direction, int blk_size); + /* UHS2 interfaces */ + int (*uhs2_detect_init)(struct mmc_host *host); + int (*uhs2_set_reg)(struct mmc_host *host, enum uhs2_act act); + void (*uhs2_disable_clk)(struct mmc_host *host); + void (*uhs2_enable_clk)(struct mmc_host *host); }; struct mmc_cqe_ops { @@ -264,6 +272,7 @@ struct mmc_pwrseq; struct mmc_supply { struct regulator *vmmc; /* Card power supply */ + struct regulator *vmmc2; /* UHS2 VDD2 power supply */ struct regulator *vqmmc; /* Optional Vccq supply */ }; @@ -284,12 +293,14 @@ struct mmc_host { u32 ocr_avail_sdio; /* SDIO-specific OCR */ u32 ocr_avail_sd; /* SD-specific OCR */ u32 ocr_avail_mmc; /* MMC-specific OCR */ + u32 ocr_avail_uhs2; /* UHS2-specific OCR */ #ifdef CONFIG_PM_SLEEP struct notifier_block pm_notify; #endif u32 max_current_330; u32 max_current_300; u32 max_current_180; + u32 max_current_180_vdd2; /* UHS2 vdd2 max curt. */ #define MMC_VDD_165_195 0x00000080 /* VDD voltage 1.65 - 1.95 */ #define MMC_VDD_20_21 0x00000100 /* VDD voltage 2.0 ~ 2.1 */ @@ -308,6 +319,7 @@ struct mmc_host { #define MMC_VDD_33_34 0x00200000 /* VDD voltage 3.3 ~ 3.4 */ #define MMC_VDD_34_35 0x00400000 /* VDD voltage 3.4 ~ 3.5 */ #define MMC_VDD_35_36 0x00800000 /* VDD voltage 3.5 ~ 3.6 */ +#define MMC_VDD2_165_195 0x00000080 /* UHS2 VDD2 1.65 ~ 1.95 */ u32 caps; /* Host capabilities */ @@ -341,6 +353,7 @@ struct mmc_host { #define MMC_CAP_DRIVER_TYPE_A (1 << 23) /* Host supports Driver Type A */ #define MMC_CAP_DRIVER_TYPE_C (1 << 24) /* Host supports Driver Type C */ #define MMC_CAP_DRIVER_TYPE_D (1 << 25) /* Host supports Driver Type D */ +#define MMC_CAP_UHS2 BIT(26) /* Host supports UHS2 mode */ #define MMC_CAP_DONE_COMPLETE (1 << 27) /* RW reqs can be completed within mmc_request_done() */ #define MMC_CAP_CD_WAKE (1 << 28) /* Enable card detect wake */ #define MMC_CAP_CMD_DURING_TFR (1 << 29) /* Commands during data transfer */ @@ -379,6 +392,17 @@ struct mmc_host { mmc_pm_flag_t pm_caps; /* supported pm features */ + struct uhs2_host_caps uhs2_caps; /* UHS2 host capabilities */ + struct uhs2_card_prop uhs2_dev_prop; /* UHS2 device properties */ + u32 group_desc; /* UHS2 property */ + int flags; +#define MMC_UHS2_SUPPORT BIT(0) +#define MMC_UHS2_INITIALIZED BIT(1) +#define MMC_UHS2_2L_HD BIT(2) +#define MMC_UHS2_APP_CMD BIT(3) +#define MMC_UHS2_SPEED_B BIT(4) +#define MMC_SUPPORT_ADMA3 BIT(5) + /* host specific block data */ unsigned int max_seg_size; /* see blk_queue_max_segment_size */ unsigned short max_segs; /* see blk_queue_max_segments */ @@ -574,6 +598,12 @@ static inline int mmc_card_uhs(struct mmc_card *card) card->host->ios.timing <= MMC_TIMING_UHS_DDR50; } +static inline bool mmc_card_uhs2(struct mmc_card *card) +{ + return (card->host->flags & MMC_UHS2_SUPPORT) && + (card->host->flags & MMC_UHS2_INITIALIZED); +} + void mmc_retune_timer_stop(struct mmc_host *host); static inline void mmc_retune_needed(struct mmc_host *host) diff --git a/include/linux/mmc/uhs2.h b/include/linux/mmc/uhs2.h new file mode 100644 index 000000000000..298ac7cd8904 --- /dev/null +++ b/include/linux/mmc/uhs2.h @@ -0,0 +1,268 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * linux/drivers/mmc/host/uhs2.h - UHS-II driver + * + * Header file for UHS-II packets, Host Controller registers and I/O + * accessors. + * + * Copyright (C) 2014 Intel Corp, All Rights Reserved. + */ +#ifndef LINUX_MMC_UHS2_H +#define LINUX_MMC_UHS2_H + +struct mmc_request; + +/* LINK Layer definition */ +/* UHS2 Header */ +#define UHS2_NATIVE_PACKET_POS 7 +#define UHS2_NATIVE_PACKET (1 << UHS2_NATIVE_PACKET_POS) + +#define UHS2_PACKET_TYPE_POS 4 +#define UHS2_PACKET_TYPE_CCMD (0 << UHS2_PACKET_TYPE_POS) +#define UHS2_PACKET_TYPE_DCMD (1 << UHS2_PACKET_TYPE_POS) +#define UHS2_PACKET_TYPE_RES (2 << UHS2_PACKET_TYPE_POS) +#define UHS2_PACKET_TYPE_DATA (3 << UHS2_PACKET_TYPE_POS) +#define UHS2_PACKET_TYPE_MSG (7 << UHS2_PACKET_TYPE_POS) + +#define UHS2_DEST_ID_MASK 0x0F +#define UHS2_DEST_ID 0x1 + +#define UHS2_SRC_ID_POS 12 +#define UHS2_SRC_ID_MASK 0xF000 + +#define UHS2_TRANS_ID_POS 8 +#define UHS2_TRANS_ID_MASK 0x0700 + +/* UHS2 MSG */ +#define UHS2_MSG_CTG_POS 5 +#define UHS2_MSG_CTG_LMSG 0x00 +#define UHS2_MSG_CTG_INT 0x60 +#define UHS2_MSG_CTG_AMSG 0x80 + +#define UHS2_MSG_CTG_FCREQ 0x00 +#define UHS2_MSG_CTG_FCRDY 0x01 +#define UHS2_MSG_CTG_STAT 0x02 + +#define UHS2_MSG_CODE_POS 8 +#define UHS2_MSG_CODE_FC_UNRECOVER_ERR 0x8 +#define UHS2_MSG_CODE_STAT_UNRECOVER_ERR 0x8 +#define UHS2_MSG_CODE_STAT_RECOVER_ERR 0x1 + +/* TRANS Layer definition */ + +/* Native packets*/ +#define UHS2_NATIVE_CMD_RW_POS 7 +#define UHS2_NATIVE_CMD_WRITE (1 << UHS2_NATIVE_CMD_RW_POS) +#define UHS2_NATIVE_CMD_READ (0 << UHS2_NATIVE_CMD_RW_POS) + +#define UHS2_NATIVE_CMD_PLEN_POS 4 +#define UHS2_NATIVE_CMD_PLEN_4B (1 << UHS2_NATIVE_CMD_PLEN_POS) +#define UHS2_NATIVE_CMD_PLEN_8B (2 << UHS2_NATIVE_CMD_PLEN_POS) +#define UHS2_NATIVE_CMD_PLEN_16B (3 << UHS2_NATIVE_CMD_PLEN_POS) + +#define UHS2_NATIVE_CCMD_GET_MIOADR_MASK 0xF00 +#define UHS2_NATIVE_CCMD_MIOADR_MASK 0x0F + +#define UHS2_NATIVE_CCMD_LIOADR_POS 8 +#define UHS2_NATIVE_CCMD_GET_LIOADR_MASK 0x0FF + +#define UHS2_DCMD_DM_POS 6 +#define UHS2_DCMD_2L_HD_MODE (1 << UHS2_DCMD_DM_POS) +#define UHS2_DCMD_LM_POS 5 +#define UHS2_DCMD_LM_TLEN_EXIST (1 << UHS2_DCMD_LM_POS) +#define UHS2_DCMD_TLUM_POS 4 +#define UHS2_DCMD_TLUM_BYTE_MODE (1 << UHS2_DCMD_TLUM_POS) +#define UHS2_NATIVE_DCMD_DAM_POS 3 +#define UHS2_NATIVE_DCMD_DAM_IO (1 << UHS2_NATIVE_DCMD_DAM_POS) +/* + * Per UHS2 spec, DCMD payload should be MSB first. There may be + * two types of data be assembled to MSB: + * 1. TLEN: Input block size for single read/write and number of blocks + * for multiple read/write to calculate TLEN as MSB first per spec. + * 2. SD command argument. + */ +static inline u32 uhs2_dcmd_convert_msb(u32 input) +{ + u32 ret = 0; + + ret = ((input & 0xFF) << 24) | + (((input >> 8) & 0xFF) << 16) | + (((input >> 16) & 0xFF) << 8) | + ((input >> 24) & 0xFF); + return ret; +} + +#define UHS2_RES_NACK_POS 7 +#define UHS2_RES_NACK_MASK (0x1 << UHS2_RES_NACK_POS) + +#define UHS2_RES_ECODE_POS 4 +#define UHS2_RES_ECODE_MASK 0x7 +#define UHS2_RES_ECODE_COND 1 +#define UHS2_RES_ECODE_ARG 2 +#define UHS2_RES_ECODE_GEN 3 + +/* IOADR of device registers */ +#define UHS2_IOADR_GENERIC_CAPS 0x00 +#define UHS2_IOADR_PHY_CAPS 0x02 +#define UHS2_IOADR_LINK_CAPS 0x04 +#define UHS2_IOADR_RSV_CAPS 0x06 +#define UHS2_IOADR_GENERIC_SETTINGS 0x08 +#define UHS2_IOADR_PHY_SETTINGS 0x0A +#define UHS2_IOADR_LINK_SETTINGS 0x0C +#define UHS2_IOADR_PRESET 0x40 + +/* SD application packets */ +#define UHS2_SD_CMD_INDEX_POS 8 + +#define UHS2_SD_CMD_APP_POS 14 +#define UHS2_SD_CMD_APP (1 << UHS2_SD_CMD_APP_POS) + +struct uhs2_command { + u16 header; + u16 arg; + u32 *payload; + u32 payload_len; + u32 packet_len; +}; + +struct uhs2_host_caps { + u32 dap; + u32 gap; + u32 maxblk_len; + u32 n_fcu; + u8 n_lanes; + u8 addr64; + u8 card_type; + u8 phy_rev; + u8 speed_range; + u8 can_hibernate; + u8 n_lss_sync; + u8 n_lss_dir; + u8 link_rev; + u8 host_type; + u8 n_data_gap; + + u32 maxblk_len_set; + u32 n_fcu_set; + u8 n_lanes_set; + u8 n_lss_sync_set; + u8 n_lss_dir_set; + u8 n_data_gap_set; + u8 max_retry_set; +}; + +struct uhs2_card_prop { + u32 node_id; + u32 dap; + u32 gap; + u32 n_fcu; + u32 maxblk_len; + u8 n_lanes; + u8 dadr_len; + u8 app_type; + u8 phy_minor_rev; + u8 phy_major_rev; + u8 can_hibernate; + u8 n_lss_sync; + u8 n_lss_dir; + u8 link_minor_rev; + u8 link_major_rev; + u8 dev_type; + u8 n_data_gap; + + u32 n_fcu_set; + u32 maxblk_len_set; + u8 n_lanes_set; + u8 speed_range_set; + u8 n_lss_sync_set; + u8 n_lss_dir_set; + u8 n_data_gap_set; + u8 pwrctrl_mode_set; + u8 max_retry_set; + + u8 cfg_complete; +}; + +enum uhs2_act { + SET_CONFIG, + ENABLE_INT, + DISABLE_INT, + SET_SPEED_B, + CHECK_DORMANT, +}; + +/* UHS-II Device Registers */ +#define UHS2_DEV_CONFIG_REG 0x000 + +/* General Caps and Settings registers */ +#define UHS2_DEV_CONFIG_GEN_CAPS (UHS2_DEV_CONFIG_REG + 0x000) +#define UHS2_DEV_CONFIG_N_LANES_POS 8 +#define UHS2_DEV_CONFIG_N_LANES_MASK 0x3F +#define UHS2_DEV_CONFIG_2L_HD_FD 0x1 +#define UHS2_DEV_CONFIG_2D1U_FD 0x2 +#define UHS2_DEV_CONFIG_1D2U_FD 0x4 +#define UHS2_DEV_CONFIG_2D2U_FD 0x8 +#define UHS2_DEV_CONFIG_DADR_POS 14 +#define UHS2_DEV_CONFIG_DADR_MASK 0x1 +#define UHS2_DEV_CONFIG_APP_POS 16 +#define UHS2_DEV_CONFIG_APP_MASK 0xFF +#define UHS2_DEV_CONFIG_APP_SD_MEM 0x1 + +#define UHS2_DEV_CONFIG_GEN_SET (UHS2_DEV_CONFIG_REG + 0x008) +#define UHS2_DEV_CONFIG_GEN_SET_2L_FD_HD 0x0 +#define UHS2_DEV_CONFIG_GEN_SET_CFG_COMPLETE (0x1 << 31) + +/* PHY Caps and Settings registers */ +#define UHS2_DEV_CONFIG_PHY_CAPS (UHS2_DEV_CONFIG_REG + 0x002) +#define UHS2_DEV_CONFIG_PHY_MINOR_MASK 0xF +#define UHS2_DEV_CONFIG_PHY_MAJOR_POS 4 +#define UHS2_DEV_CONFIG_PHY_MAJOR_MASK 0x3 +#define UHS2_DEV_CONFIG_CAN_HIBER_POS 15 +#define UHS2_DEV_CONFIG_CAN_HIBER_MASK 0x1 +#define UHS2_DEV_CONFIG_PHY_CAPS1 (UHS2_DEV_CONFIG_REG + 0x003) +#define UHS2_DEV_CONFIG_N_LSS_SYN_MASK 0xF +#define UHS2_DEV_CONFIG_N_LSS_DIR_POS 4 +#define UHS2_DEV_CONFIG_N_LSS_DIR_MASK 0xF + +#define UHS2_DEV_CONFIG_PHY_SET (UHS2_DEV_CONFIG_REG + 0x00A) +#define UHS2_DEV_CONFIG_PHY_SET_SPEED_POS 6 +#define UHS2_DEV_CONFIG_PHY_SET_SPEED_A 0x0 +#define UHS2_DEV_CONFIG_PHY_SET_SPEED_B 0x1 + +/* LINK-TRAN Caps and Settings registers */ +#define UHS2_DEV_CONFIG_LINK_TRAN_CAPS (UHS2_DEV_CONFIG_REG + 0x004) +#define UHS2_DEV_CONFIG_LT_MINOR_MASK 0xF +#define UHS2_DEV_CONFIG_LT_MAJOR_POS 4 +#define UHS2_DEV_CONFIG_LT_MAJOR_MASK 0x3 +#define UHS2_DEV_CONFIG_N_FCU_POS 8 +#define UHS2_DEV_CONFIG_N_FCU_MASK 0xFF +#define UHS2_DEV_CONFIG_DEV_TYPE_POS 16 +#define UHS2_DEV_CONFIG_DEV_TYPE_MASK 0x7 +#define UHS2_DEV_CONFIG_MAX_BLK_LEN_POS 20 +#define UHS2_DEV_CONFIG_MAX_BLK_LEN_MASK 0xFFF +#define UHS2_DEV_CONFIG_LINK_TRAN_CAPS1 (UHS2_DEV_CONFIG_REG + 0x005) +#define UHS2_DEV_CONFIG_N_DATA_GAP_MASK 0xFF + +#define UHS2_DEV_CONFIG_LINK_TRAN_SET (UHS2_DEV_CONFIG_REG + 0x00C) +#define UHS2_DEV_CONFIG_LT_SET_MAX_BLK_LEN 0x200 +#define UHS2_DEV_CONFIG_LT_SET_MAX_RETRY_POS 16 + +/* Preset register */ +#define UHS2_DEV_CONFIG_PRESET (UHS2_DEV_CONFIG_REG + 0x040) + +#define UHS2_DEV_INT_REG 0x100 + +#define UHS2_DEV_STATUS_REG 0x180 + +#define UHS2_DEV_CMD_REG 0x200 +#define UHS2_DEV_CMD_FULL_RESET (UHS2_DEV_CMD_REG + 0x000) +#define UHS2_DEV_CMD_GO_DORMANT_STATE (UHS2_DEV_CMD_REG + 0x001) +#define UHS2_DEV_CMD_DORMANT_HIBER (0x1 << 7) +#define UHS2_DEV_CMD_DEVICE_INIT (UHS2_DEV_CMD_REG + 0x002) +#define UHS2_DEV_CMD_ENUMERATE (UHS2_DEV_CMD_REG + 0x003) +#define UHS2_DEV_CMD_TRANS_ABORT (UHS2_DEV_CMD_REG + 0x004) + +#define UHS2_RCLK_MAX 52000000 +#define UHS2_RCLK_MIN 26000000 + +#endif /* LINUX_MMC_UHS2_H */ From patchwork Fri Jul 10 11:08:19 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Chuang X-Patchwork-Id: 11656255 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 1CBA613B6 for ; Fri, 10 Jul 2020 11:07:46 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0126D2078D for ; Fri, 10 Jul 2020 11:07:46 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="mkPU8GVR" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727851AbgGJLHp (ORCPT ); Fri, 10 Jul 2020 07:07:45 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40878 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727772AbgGJLHo (ORCPT ); Fri, 10 Jul 2020 07:07:44 -0400 Received: from mail-pf1-x441.google.com (mail-pf1-x441.google.com [IPv6:2607:f8b0:4864:20::441]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 945D2C08C5CE; Fri, 10 Jul 2020 04:07:44 -0700 (PDT) Received: by mail-pf1-x441.google.com with SMTP id x72so2397535pfc.6; Fri, 10 Jul 2020 04:07:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=XOFeEnxeFd3DTgaPl4GKh005ARvuiNKhOn7oW5FdfWA=; b=mkPU8GVR/yDq0XPj/516OIDXgA96qCnU4BWC7k2KfShqtnBia8e1z9CMjuca2lE1e+ N95N12QLmfteMfdRPlCDnEG2Bbv8PoINu7Yf9cwjsExFnK4KK50HsheboxiA5/wnRcqE +DCPagF7PKOKzpc/mSkXZXCwv33dxV99ZU0aYyvPQuSUjVzaS9FZJKU/mNrhjG+DVQ5I 5VC2Z8Rvx0eZiCobwODBQ94hlgjU73cdHJ2558KMAtqMGNnX5oiSAa0ijumyVg/5llX1 ejOr5WTJXiVTjYrVgJxSFrpdcot4MYtiprK1ffXfkZSVDxantUTqmmDlVrm67ksqoufC H9yg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=XOFeEnxeFd3DTgaPl4GKh005ARvuiNKhOn7oW5FdfWA=; b=uIHHnMwlZu+N6Ia7S/RGfsUZcj7azmJCFBJea9+1Ht9TLuw0xw4i+Gos4agOIPAWjR fxW8MPv8gaWIgCjHisI+oDvsI0IqYQyy3iUfN2R61FQvUgswQO2eqtcapyZKiBDoRbb3 X62hTXZKaJIOraZcwHpVv+o4wOt2/RIxRHBcdQDWUjruiwVjAUEqhmRay2u9j6mdhncd D2hJlAPfrXeMnlvatm114d79R2Dj2VWNbNbYZjYjaavdIR0vzzfuAikIrQlzoMGYo1YU vpBZbvd9jgBgszMlvWlsSJksPdt4x0nb2+eC+dI7chX4dah2gLsNMIenhiTbe1PC+vix lceQ== X-Gm-Message-State: AOAM533InLDXuhkCmYFhzaKJV0BU12eht7PGtKiIcFDzMFwCluLTJly0 +V7YfeJOb4DCyqS3PULlYeE6Edqd X-Google-Smtp-Source: ABdhPJwXOI8A1cjuOAhhHZ9joN+0ndyfu3R4Ng9Xxtc9ejEveyqoNyn5igxbGK8yKXhEM1Maqp67jg== X-Received: by 2002:a62:ce46:: with SMTP id y67mr58779108pfg.118.1594379264093; Fri, 10 Jul 2020 04:07:44 -0700 (PDT) Received: from gli-arch.genesyslogic.com.tw (60-251-58-169.HINET-IP.hinet.net. [60.251.58.169]) by smtp.gmail.com with ESMTPSA id k3sm5463656pjl.15.2020.07.10.04.07.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 10 Jul 2020 04:07:43 -0700 (PDT) From: Ben Chuang To: adrian.hunter@intel.com, ulf.hansson@linaro.org Cc: linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, ben.chuang@genesyslogic.com.tw, takahiro.akashi@linaro.org, greg.tu@genesyslogic.com.tw, Ben Chuang Subject: [RFC PATCH V3 02/21] mmc: core: UHS-II support, modify power-up sequence Date: Fri, 10 Jul 2020 19:08:19 +0800 Message-Id: <20200710110819.28965-1-benchuanggli@gmail.com> X-Mailer: git-send-email 2.27.0 MIME-Version: 1.0 Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org From: AKASHI Takahiro According to Fig. 3-35 in "SD Host Controller Simplified Spec. Ver4.20": - Prepare vdd1, vdd2 and ios.timing for using after/in step (2) - chip_select is not used in UHS-II, used to return to the legacy flow Signed-off-by: Ben Chuang Signed-off-by: AKASHI Takahiro --- drivers/mmc/core/core.c | 62 ++++++++++++++++++++++++------------ drivers/mmc/core/regulator.c | 14 ++++++++ 2 files changed, 56 insertions(+), 20 deletions(-) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 8d2b808e9b58..85c83c82ad0c 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1315,33 +1315,51 @@ void mmc_power_up(struct mmc_host *host, u32 ocr) if (host->ios.power_mode == MMC_POWER_ON) return; - mmc_pwrseq_pre_power_on(host); + if (host->flags & MMC_UHS2_SUPPORT) { + /* TODO: handle 'ocr' parameter */ + host->ios.vdd = fls(host->ocr_avail) - 1; + host->ios.vdd2 = fls(host->ocr_avail_uhs2) - 1; + if (mmc_host_is_spi(host)) + host->ios.chip_select = MMC_CS_HIGH; + else + host->ios.chip_select = MMC_CS_DONTCARE; + host->ios.timing = MMC_TIMING_UHS2; + } else { + mmc_pwrseq_pre_power_on(host); - host->ios.vdd = fls(ocr) - 1; - host->ios.power_mode = MMC_POWER_UP; - /* Set initial state and call mmc_set_ios */ - mmc_set_initial_state(host); + host->ios.vdd = fls(ocr) - 1; + host->ios.power_mode = MMC_POWER_UP; + /* Set initial state and call mmc_set_ios */ + mmc_set_initial_state(host); - mmc_set_initial_signal_voltage(host); + mmc_set_initial_signal_voltage(host); - /* - * This delay should be sufficient to allow the power supply - * to reach the minimum voltage. - */ - mmc_delay(host->ios.power_delay_ms); - - mmc_pwrseq_post_power_on(host); + /* + * This delay should be sufficient to allow the power supply + * to reach the minimum voltage. + */ + mmc_delay(host->ios.power_delay_ms); + mmc_pwrseq_post_power_on(host); + } host->ios.clock = host->f_init; - host->ios.power_mode = MMC_POWER_ON; + mmc_set_ios(host); - /* - * This delay must be at least 74 clock sizes, or 1 ms, or the - * time required to reach a stable voltage. - */ - mmc_delay(host->ios.power_delay_ms); + if (host->flags & MMC_UHS2_SUPPORT) + /* + * This delay should be sufficient to allow the power supply + * to reach the minimum voltage. + */ + /* TODO: avoid an immediate value */ + mmc_delay(10); + else + /* + * This delay must be at least 74 clock sizes, or 1 ms, or the + * time required to reach a stable voltage. + */ + mmc_delay(host->ios.power_delay_ms); } void mmc_power_off(struct mmc_host *host) @@ -2307,7 +2325,11 @@ void mmc_start_host(struct mmc_host *host) if (!(host->caps2 & MMC_CAP2_NO_PRESCAN_POWERUP)) { mmc_claim_host(host); - mmc_power_up(host, host->ocr_avail); + + /* Power up here will make UHS2 init ugly. */ + if (!(host->caps & MMC_CAP_UHS2)) + mmc_power_up(host, host->ocr_avail); + mmc_release_host(host); } diff --git a/drivers/mmc/core/regulator.c b/drivers/mmc/core/regulator.c index 96b1d15045d6..05556225d9ac 100644 --- a/drivers/mmc/core/regulator.c +++ b/drivers/mmc/core/regulator.c @@ -247,6 +247,7 @@ int mmc_regulator_get_supply(struct mmc_host *mmc) mmc->supply.vmmc = devm_regulator_get_optional(dev, "vmmc"); mmc->supply.vqmmc = devm_regulator_get_optional(dev, "vqmmc"); + mmc->supply.vmmc2 = devm_regulator_get_optional(dev, "vmmc2"); if (IS_ERR(mmc->supply.vmmc)) { if (PTR_ERR(mmc->supply.vmmc) == -EPROBE_DEFER) @@ -266,6 +267,19 @@ int mmc_regulator_get_supply(struct mmc_host *mmc) dev_dbg(dev, "No vqmmc regulator found\n"); } + if (IS_ERR(mmc->supply.vmmc2)) { + if (PTR_ERR(mmc->supply.vmmc2) == -EPROBE_DEFER) + return -EPROBE_DEFER; + dev_dbg(dev, "No vmmc2 regulator found\n"); + } else { + ret = mmc_regulator_get_ocrmask(mmc->supply.vmmc2); + if (ret > 0) + mmc->ocr_avail_uhs2 = ret; + else + dev_warn(dev, "Failed getting UHS2 OCR mask: %d\n", + ret); + } + return 0; } EXPORT_SYMBOL_GPL(mmc_regulator_get_supply); From patchwork Fri Jul 10 11:08:38 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Chuang X-Patchwork-Id: 11656257 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id ED8E7618 for ; Fri, 10 Jul 2020 11:07:57 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id D47D22076A for ; Fri, 10 Jul 2020 11:07:57 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="VWqB2c/2" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727944AbgGJLH5 (ORCPT ); Fri, 10 Jul 2020 07:07:57 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40910 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726496AbgGJLHz (ORCPT ); Fri, 10 Jul 2020 07:07:55 -0400 Received: from mail-pf1-x441.google.com (mail-pf1-x441.google.com [IPv6:2607:f8b0:4864:20::441]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 595EBC08C5DC; Fri, 10 Jul 2020 04:07:55 -0700 (PDT) Received: by mail-pf1-x441.google.com with SMTP id 1so2392694pfn.9; Fri, 10 Jul 2020 04:07:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=ti/RasPzpDQfCkU80y2QxpiPoAPRKGJkYJCcdL+0vLs=; b=VWqB2c/2mD7N1CybHi64Z60T58eMyCTiWHXE8zz0z9JBKZDY5XwX1tpqaq+i9EYfCP 1EpnQonma3W/bIwCu1unJEghezBdiUwX3/2UkMfe/++zgyFLq64DKoevEDW6xhqe08D9 tcvj6bMqcHaAY9M8Vo1q6tSAW9b+xt5y662KQkj8qIWYgtFcuUv5DCtBrkuv4lFJx34r nWTiIlsvWNuNJPWhmtZUJy5c1QdPhhtN9vXq1WV9TOwCxUfMAIC6a5EaXjskUUN4XHBL 71lA/nmBaZKU2VykKgTwOEfifooqU5xxcIKq7YETToMwaYvXiyYpYtmRxq47gEtkV8m0 kMuw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=ti/RasPzpDQfCkU80y2QxpiPoAPRKGJkYJCcdL+0vLs=; b=UOBFXekIGJTQJRhthTJwJJYM3/fEyM29zGtPuaQ+Qyoy+6iF+eWNwcpVpZt8zp+nUU e60cluVw3qD/AGqaJWwBZwefYasHxQ0enwQTE/iW+ynZRdhFxutQaYiuO/WnudKP9sNs hTLzXYQKSGYyyT5QyXxJOCKAJsd/158NAdN/ssjpZ/k3XY9F0lb/O9YQeL94hEDm2WIv jXsAYzhUl7WYZSfJlAJTnO2tq3SsqjtPBdFQHnXr23ygSwLzUpDH1GzDrnQe2P197BAj iqQrCegwjZaZzwMSxcXr6cN4BcWQOmG6VBfvS48Ph8ZTatVbYTqy0u3F3zVsiaKhPaEm 99/g== X-Gm-Message-State: AOAM531ehw4PQqJvFNTVvfaR6x6S5WiS9hy4QJxm4C9ZiI/nBfW5a9+j eLjlrJtpUxD62lM9bfAvzsI= X-Google-Smtp-Source: ABdhPJyTIgSD1QxyuKdo/hOw3kz38HcVnjtV13TNHThPCBsGsx7wn4iheuKlWK8i42JthGjl+OLDNA== X-Received: by 2002:a63:5fcc:: with SMTP id t195mr48796424pgb.56.1594379274962; Fri, 10 Jul 2020 04:07:54 -0700 (PDT) Received: from gli-arch.genesyslogic.com.tw (60-251-58-169.HINET-IP.hinet.net. [60.251.58.169]) by smtp.gmail.com with ESMTPSA id g3sm5581621pfq.19.2020.07.10.04.07.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 10 Jul 2020 04:07:54 -0700 (PDT) From: Ben Chuang To: adrian.hunter@intel.com, ulf.hansson@linaro.org Cc: linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, ben.chuang@genesyslogic.com.tw, takahiro.akashi@linaro.org, greg.tu@genesyslogic.com.tw, Ben Chuang Subject: [RFC PATCH V3 03/21] mmc: core: UHS-II support, skip set_chip_select() Date: Fri, 10 Jul 2020 19:08:38 +0800 Message-Id: <20200710110838.29018-1-benchuanggli@gmail.com> X-Mailer: git-send-email 2.27.0 MIME-Version: 1.0 Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org From: AKASHI Takahiro mmc_set_chip_select() should be called only in UHS-I mode, and not for UHS-II mode. Signed-off-by: Ben Chuang Signed-off-by: AKASHI Takahiro --- drivers/mmc/core/core.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 85c83c82ad0c..c6540d56646b 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -898,8 +898,10 @@ static inline void mmc_set_ios(struct mmc_host *host) */ void mmc_set_chip_select(struct mmc_host *host, int mode) { - host->ios.chip_select = mode; - mmc_set_ios(host); + if (!(host->flags & MMC_UHS2_INITIALIZED)) { + host->ios.chip_select = mode; + mmc_set_ios(host); + } } /* From patchwork Fri Jul 10 11:08:48 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Chuang X-Patchwork-Id: 11656259 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id A4280618 for ; Fri, 10 Jul 2020 11:08:08 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 707CC2078B for ; Fri, 10 Jul 2020 11:08:08 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="bIxqegoo" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727955AbgGJLIH (ORCPT ); Fri, 10 Jul 2020 07:08:07 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40938 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726725AbgGJLIG (ORCPT ); Fri, 10 Jul 2020 07:08:06 -0400 Received: from mail-pl1-x642.google.com (mail-pl1-x642.google.com [IPv6:2607:f8b0:4864:20::642]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DBBB7C08C5CE; Fri, 10 Jul 2020 04:08:05 -0700 (PDT) Received: by mail-pl1-x642.google.com with SMTP id x8so2107633plm.10; Fri, 10 Jul 2020 04:08:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=vfUx15GR7O9nIZG475DM65r/5oMnn9qDrYaUxktKuL4=; b=bIxqegooV1M02fhdbgORJPbQq6Lj78R12LLQWFm91KtvLyN7UpKI4ilpKgysOccyzJ tPBR55xQElA4IlDMMbsf2flS2o2/vthjKOM7fOtIAiSHpni3YPC1U6Cw4yLpRjnIphGQ unwXXJA8zM9bah8rMjqMxCZTgkZunvA+0v/LzRlC6ctbU9k0eRELq8BTldDz1qd3xKLH 9CN6zqye+vsTFkxNS0tKAU1pTSDVCsTeH5wiZOnbOV07llq60KOCnnTtXdmVlSyR9q2+ x7khLrGZHRnAfPyb8oSOEgoPoVpAvPJlL34H13/Kcya2RHBf85guJTyLNsWTAo8I8qlo uASg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=vfUx15GR7O9nIZG475DM65r/5oMnn9qDrYaUxktKuL4=; b=JmX1wzDlVPtAcw3hb1bdMyRj2lXl1Oa//odUuRs8WsN7vSjlKZDu0/Zybr5pbrBmO7 Ze0cNmBspdI44wLBsZqS+v/Ha5YGXU/hbuNeBIkrUWlRVqFvTlA7h5j6IuUfITYGxDg0 zxbg09CKw3FFBPvt001eU746yVX2dLmxh8WfQ5QDQ84fYUBXoJ+wm/cyAK6SPT8CKI+g ZGCbH9aKiWCGcp7kx4FgOxZyWnBJ4XpDSvnXyPVlFxL3+Sqc+PNhS1N0w7tQcuTRmocA x+A0K1Gl7iBAlU3VVyB1GtRtCUc4sC2T79OQE5K3WyZd0qq4Lk8ByKHHrMYATx+HzhUa 7KfQ== X-Gm-Message-State: AOAM530Mq6PX6vrxnocfcDhpSYSctCqEnv/2D5Dh54gicCvlXBFBoEE9 EsYBQxRXDi4qxYP+v4WLLHb9X52r X-Google-Smtp-Source: ABdhPJw0zey3vGrBHyilPwk4ImIvbzkvVYjqzJcGJVMSd/IQnCPTa2vSekMR1GvFX6PRZFOBfjvtaw== X-Received: by 2002:a17:90a:fc90:: with SMTP id ci16mr4908652pjb.1.1594379285131; Fri, 10 Jul 2020 04:08:05 -0700 (PDT) Received: from gli-arch.genesyslogic.com.tw (60-251-58-169.HINET-IP.hinet.net. [60.251.58.169]) by smtp.gmail.com with ESMTPSA id f14sm5336890pjq.36.2020.07.10.04.08.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 10 Jul 2020 04:08:04 -0700 (PDT) From: Ben Chuang To: adrian.hunter@intel.com, ulf.hansson@linaro.org Cc: linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, ben.chuang@genesyslogic.com.tw, takahiro.akashi@linaro.org, greg.tu@genesyslogic.com.tw, Ben Chuang Subject: [RFC PATCH V3 04/21] mmc: core: UHS-II support, try to select UHS-II interface Date: Fri, 10 Jul 2020 19:08:48 +0800 Message-Id: <20200710110848.29114-1-benchuanggli@gmail.com> X-Mailer: git-send-email 2.27.0 MIME-Version: 1.0 Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org From: Ben Chuang The flow of "interface selection and initialization" was a bit modified for UHS-II card. This commit follows the sequence defined in SD specification (Part 1). See section 7.2.3 in "UHS-II Simplified Addendum." Signed-off-by: Ben Chuang Signed-off-by: AKASHI Takahiro --- drivers/mmc/core/Makefile | 2 +- drivers/mmc/core/bus.c | 5 +- drivers/mmc/core/core.c | 33 +- drivers/mmc/core/sd.c | 26 ++ drivers/mmc/core/uhs2.c | 800 ++++++++++++++++++++++++++++++++++++++ drivers/mmc/core/uhs2.h | 20 + 6 files changed, 882 insertions(+), 4 deletions(-) create mode 100644 drivers/mmc/core/uhs2.c create mode 100644 drivers/mmc/core/uhs2.h diff --git a/drivers/mmc/core/Makefile b/drivers/mmc/core/Makefile index 95ffe008ebdf..e2a90dc98afc 100644 --- a/drivers/mmc/core/Makefile +++ b/drivers/mmc/core/Makefile @@ -8,7 +8,7 @@ mmc_core-y := core.o bus.o host.o \ mmc.o mmc_ops.o sd.o sd_ops.o \ sdio.o sdio_ops.o sdio_bus.o \ sdio_cis.o sdio_io.o sdio_irq.o \ - slot-gpio.o regulator.o + slot-gpio.o regulator.o uhs2.o mmc_core-$(CONFIG_OF) += pwrseq.o obj-$(CONFIG_PWRSEQ_SIMPLE) += pwrseq_simple.o obj-$(CONFIG_PWRSEQ_SD8787) += pwrseq_sd8787.o diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c index 70207f11a654..66d3e942f3fc 100644 --- a/drivers/mmc/core/bus.c +++ b/drivers/mmc/core/bus.c @@ -350,8 +350,9 @@ int mmc_add_card(struct mmc_card *card) } else { pr_info("%s: new %s%s%s%s%s%s card at address %04x\n", mmc_hostname(card->host), - mmc_card_uhs(card) ? "ultra high speed " : - (mmc_card_hs(card) ? "high speed " : ""), + mmc_card_uhs2(card) ? "ultra high speed 2 " : + (mmc_card_uhs(card) ? "ultra high speed 1 " : + (mmc_card_hs(card) ? "high speed " : "")), mmc_card_hs400(card) ? "HS400 " : (mmc_card_hs200(card) ? "HS200 " : ""), mmc_card_hs400es(card) ? "Enhanced strobe " : "", diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index c6540d56646b..e2534f3446ce 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -31,6 +31,7 @@ #include #include #include +#include #define CREATE_TRACE_POINTS #include @@ -41,6 +42,7 @@ #include "host.h" #include "sdio_bus.h" #include "pwrseq.h" +#include "uhs2.h" #include "mmc_ops.h" #include "sd_ops.h" @@ -51,6 +53,7 @@ #define SD_DISCARD_TIMEOUT_MS (250) static const unsigned freqs[] = { 400000, 300000, 200000, 100000 }; +static const unsigned int uhs2_freqs[] = { 52000000, 26000000 }; /* * Enabling software CRCs on the data blocks can be a significant (30%) @@ -2165,9 +2168,10 @@ static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq) if (!mmc_attach_sdio(host)) return 0; - if (!(host->caps2 & MMC_CAP2_NO_SD)) + if (!(host->caps2 & MMC_CAP2_NO_SD)) { if (!mmc_attach_sd(host)) return 0; + } if (!(host->caps2 & MMC_CAP2_NO_MMC)) if (!mmc_attach_mmc(host)) @@ -2300,6 +2304,33 @@ void mmc_rescan(struct work_struct *work) goto out; } + if (host->caps & MMC_CAP_UHS2) { + /* + * Start to try UHS-II initialization from 52MHz to 26MHz + * (RCLK range) per spec. + */ + for (i = 0; i < ARRAY_SIZE(uhs2_freqs); i++) { + unsigned int freq = uhs2_freqs[i]; + int err; + + err = mmc_uhs2_rescan_try_freq(host, + max(freq, host->f_min)); + if (!err) { + mmc_release_host(host); + goto out; + } + + if (err == UHS2_PHY_INIT_ERR) + /* UHS2 IF detect or Lane Sync error. + * Try legacy interface. + */ + break; + + if (freq <= host->f_min) + break; + } + } + for (i = 0; i < ARRAY_SIZE(freqs); i++) { unsigned int freq = freqs[i]; if (freq > host->f_max) { diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 5a2210c25aa7..c5b071bd98b3 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -901,6 +901,20 @@ int mmc_sd_setup_card(struct mmc_host *host, struct mmc_card *card, err = mmc_read_switch(card); if (err) return err; + if (host->flags & MMC_UHS2_INITIALIZED) { + u8 status[64]; + /* + * send CMD6 to set Maximum Power Consumption + * to get better performance + */ + err = mmc_sd_switch(card, 0, 3, + SD_SET_CURRENT_LIMIT_1000, status); + if (!err) { + err = mmc_sd_switch(card, 1, 3, + SD_SET_CURRENT_LIMIT_1000, + status); + } + } } /* @@ -1043,6 +1057,11 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, if (err) goto free_card; + /* For UHS2, skip the UHS-I initialization. */ + if ((host->flags & MMC_UHS2_SUPPORT) && + (host->flags & MMC_UHS2_INITIALIZED)) + goto done; + /* * If the card has not been power cycled, it may still be using 1.8V * signaling. Detect that situation and try to initialize a UHS-I (1.8V) @@ -1334,6 +1353,13 @@ int mmc_attach_sd(struct mmc_host *host) rocr = mmc_select_voltage(host, ocr); + /* + * Some cards have zero value of rocr in UHS-II mode. Assign host's ocr + * value to rocr. + */ + if ((host->flags & MMC_UHS2_INITIALIZED) && !rocr) + rocr = host->ocr_avail; + /* * Can we support the voltage(s) of the card(s)? */ diff --git a/drivers/mmc/core/uhs2.c b/drivers/mmc/core/uhs2.c new file mode 100644 index 000000000000..a3b20ac6f315 --- /dev/null +++ b/drivers/mmc/core/uhs2.c @@ -0,0 +1,800 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * linux/drivers/mmc/core/uhs2.c - UHS-II driver + * + * Copyright (C) 2014 Intel Corp, All Rights Reserved. + * Copyright (C) 2020 Genesys Logic, Inc. + * Authors: Ben Chuang + * Copyright (C) 2020 Linaro Limited + * Author: AKASHI Takahiro + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "uhs2.h" +#include "mmc_ops.h" +#include "sd_ops.h" +#include "core.h" + +#define DBG(f, x...) \ + pr_warn("[%s()]: " f, __func__, ## x) + +/** + * uhs2_cmd_assemble - assemble and build up uhs2 command + * @cmd: MMC command + * @uhs2_cmd: UHS2 command + * @header: Value of packet header + * @arg: Argument of packet + * @payload: Payload of packet + * @plen: Payload length + * @resp: Buffer for response + * @resp_len: Response buffer length + * + * resp is inputted outside which should be a variable created by caller + * so caller should handle it. For SD command, there is no uhs2_resp and + * response should be stored in resp of mmc_command. + */ +static void uhs2_cmd_assemble(struct mmc_command *cmd, + struct uhs2_command *uhs2_cmd, + u16 header, u16 arg, + u32 *payload, u8 plen, u8 *resp, u8 resp_len) +{ + uhs2_cmd->header = header; + uhs2_cmd->arg = arg; + uhs2_cmd->payload = payload; + uhs2_cmd->payload_len = plen * sizeof(u32); + uhs2_cmd->packet_len = uhs2_cmd->payload_len + 4; + + cmd->uhs2_cmd = uhs2_cmd; + cmd->uhs2_resp = resp; + cmd->uhs2_resp_len = resp_len; + + pr_debug("%s: uhs2_cmd: header=0x%x arg=0x%x\n", + __func__, uhs2_cmd->header, uhs2_cmd->arg); + pr_debug("%s: payload_len=%d packet_len=%d resp_len=%d\n", + __func__, uhs2_cmd->payload_len, uhs2_cmd->packet_len, + cmd->uhs2_resp_len); +} + +static int uhs2_dev_init(struct mmc_host *host) +{ + struct mmc_command cmd = {0}; + struct uhs2_command uhs2_cmd = {}; + u32 cnt; + u32 dap, gap, gap1; + u16 header = 0, arg = 0; + u32 payload[1]; + u8 plen = 1; + u8 gd = 0, cf = 1; + u8 resp[6] = {0}; + u8 resp_len = 6; + int err; + + dap = host->uhs2_caps.dap; + gap = host->uhs2_caps.gap; + + header = UHS2_NATIVE_PACKET | UHS2_PACKET_TYPE_CCMD; + arg = ((UHS2_DEV_CMD_DEVICE_INIT & 0xFF) << 8) | + UHS2_NATIVE_CMD_WRITE | + UHS2_NATIVE_CMD_PLEN_4B | + (UHS2_DEV_CMD_DEVICE_INIT >> 8); + + /* need this for some cards */ + cmd.busy_timeout = 1000; + + for (cnt = 0; cnt < 30; cnt++) { + payload[0] = ((dap & 0xF) << 12) | + (cf << 11) | + ((gd & 0xF) << 4) | + (gap & 0xF); + + uhs2_cmd_assemble(&cmd, &uhs2_cmd, header, arg, + payload, plen, resp, resp_len); + + DBG("Begin DEVICE_INIT, header=0x%x, arg=0x%x, payload=0x%x.\n", + header, arg, payload[0]); + + DBG("Sending DEVICE_INIT. Count = %d\n", cnt); + err = mmc_wait_for_cmd(host, &cmd, 0); + + if (err) { + pr_err("%s: %s: UHS2 CMD send fail, err= 0x%x!\n", + mmc_hostname(host), __func__, err); + return -EIO; + } + + if (IS_ENABLED(CONFIG_MMC_DEBUG)) { + int i; + + pr_warn("%s: DEVICE_INIT response is: ", + mmc_hostname(host)); + for (i = 0; i < resp_len; i++) + pr_warn("0x%x ", resp[i]); + pr_warn("\n"); + } + + if (resp[3] != (UHS2_DEV_CMD_DEVICE_INIT & 0xFF)) { + pr_err("%s: DEVICE_INIT response is wrong!\n", + mmc_hostname(host)); + return -EIO; + } + + if (resp[5] & 0x8) { + DBG("CF is set, device is initialized!\n"); + host->group_desc = gd; + break; + } + gap1 = resp[4] & 0x0F; + if (gap == gap1) + gd++; + } + if (cnt == 30) { + pr_err("%s: DEVICE_INIT fail, already 30 times!\n", + mmc_hostname(host)); + return -EIO; + } + + return 0; +} + +static int uhs2_enum(struct mmc_host *host) +{ + struct mmc_command cmd = {0}; + struct uhs2_command uhs2_cmd = {}; + u16 header = 0, arg = 0; + u32 payload[1]; + u8 plen = 1; + u8 id_f = 0xF, id_l = 0x0; + u8 resp[8] = {0}; + u8 resp_len = 8; + int err; + + header = UHS2_NATIVE_PACKET | UHS2_PACKET_TYPE_CCMD; + arg = ((UHS2_DEV_CMD_ENUMERATE & 0xFF) << 8) | + UHS2_NATIVE_CMD_WRITE | + UHS2_NATIVE_CMD_PLEN_4B | + (UHS2_DEV_CMD_ENUMERATE >> 8); + + payload[0] = (id_f << 4) | id_l; + + DBG("Begin ENUMERATE, header=0x%x, arg=0x%x, payload=0x%x.\n", + header, arg, payload[0]); + uhs2_cmd_assemble(&cmd, &uhs2_cmd, header, arg, payload, plen, + resp, resp_len); + + err = mmc_wait_for_cmd(host, &cmd, 0); + if (err) { + pr_err("%s: %s: UHS2 CMD send fail, err= 0x%x!\n", + mmc_hostname(host), __func__, err); + return -EIO; + } + + if (IS_ENABLED(CONFIG_MMC_DEBUG)) { + int i; + + pr_warn("%s: ENUMERATE response is: ", mmc_hostname(host)); + for (i = 0; i < resp_len; i++) + pr_warn("0x%x ", resp[i]); + pr_warn("\n"); + } + + if (resp[3] != (UHS2_DEV_CMD_ENUMERATE & 0xFF)) { + pr_err("%s: ENUMERATE response is wrong!\n", + mmc_hostname(host)); + return -EIO; + } + + id_f = (resp[4] >> 4) & 0xF; + id_l = resp[4] & 0xF; + DBG("id_f = %d, id_l = %d.\n", id_f, id_l); + DBG("Enumerate Cmd Completed. No. of Devices connected = %d\n", + id_l - id_f + 1); + host->uhs2_dev_prop.node_id = id_f; + + return 0; +} + +static int uhs2_config_read(struct mmc_host *host) +{ + struct mmc_command cmd = {0}; + struct uhs2_command uhs2_cmd = {}; + u16 header = 0, arg = 0; + u32 cap; + int err; + + DBG("INQUIRY_CFG: read Generic Caps.\n"); + header = UHS2_NATIVE_PACKET | + UHS2_PACKET_TYPE_CCMD | + host->uhs2_dev_prop.node_id; + arg = ((UHS2_DEV_CONFIG_GEN_CAPS & 0xFF) << 8) | + UHS2_NATIVE_CMD_READ | + UHS2_NATIVE_CMD_PLEN_4B | + (UHS2_DEV_CONFIG_GEN_CAPS >> 8); + + DBG("Begin INQUIRY_CFG, header=0x%x, arg=0x%x.\n", + header, arg); + /* There is no payload because per spec, there should be + * no payload field for read CCMD. + * Plen is set in arg. Per spec, plen for read CCMD + * represents the len of read data which is assigned in payload + * of following RES (p136). + */ + uhs2_cmd_assemble(&cmd, &uhs2_cmd, header, arg, NULL, 0, NULL, 0); + + err = mmc_wait_for_cmd(host, &cmd, 0); + if (err) { + pr_err("%s: %s: UHS2 CMD send fail, err= 0x%x!\n", + mmc_hostname(host), __func__, err); + return -EIO; + } + + if (IS_ENABLED(CONFIG_MMC_DEBUG)) { + int i; + + pr_warn("%s: INQUIRY_CFG generic response is: ", + mmc_hostname(host)); + for (i = 0; i < 2; i++) + pr_warn("0x%x ", cmd.resp[i]); + pr_warn("\n"); + } + + cap = cmd.resp[0]; + DBG("Device Generic Caps (0-31) is: 0x%x.\n", cap); + host->uhs2_dev_prop.n_lanes = (cap >> UHS2_DEV_CONFIG_N_LANES_POS) & + UHS2_DEV_CONFIG_N_LANES_MASK; + host->uhs2_dev_prop.dadr_len = (cap >> UHS2_DEV_CONFIG_DADR_POS) & + UHS2_DEV_CONFIG_DADR_MASK; + host->uhs2_dev_prop.app_type = (cap >> UHS2_DEV_CONFIG_APP_POS) & + UHS2_DEV_CONFIG_APP_MASK; + + DBG("INQUIRY_CFG: read PHY Caps.\n"); + arg = ((UHS2_DEV_CONFIG_PHY_CAPS & 0xFF) << 8) | + UHS2_NATIVE_CMD_READ | + UHS2_NATIVE_CMD_PLEN_8B | + (UHS2_DEV_CONFIG_PHY_CAPS >> 8); + + DBG("Begin INQUIRY_CFG, header=0x%x, arg=0x%x.\n", + header, arg); + uhs2_cmd_assemble(&cmd, &uhs2_cmd, header, arg, NULL, 0, NULL, 0); + + err = mmc_wait_for_cmd(host, &cmd, 0); + if (err) { + pr_err("%s: %s: UHS2 CMD send fail, err= 0x%x!\n", + mmc_hostname(host), __func__, err); + return -EIO; + } + + if (IS_ENABLED(CONFIG_MMC_DEBUG)) { + int i; + + pr_warn("%s: INQUIRY_CFG PHY response is: ", + mmc_hostname(host)); + for (i = 0; i < 2; i++) + pr_warn("0x%x ", cmd.resp[i]); + pr_warn("\n"); + } + + cap = cmd.resp[0]; + DBG("Device PHY Caps (0-31) is: 0x%x.\n", cap); + host->uhs2_dev_prop.phy_minor_rev = cap & + UHS2_DEV_CONFIG_PHY_MINOR_MASK; + host->uhs2_dev_prop.phy_major_rev = (cap >> + UHS2_DEV_CONFIG_PHY_MAJOR_POS) & + UHS2_DEV_CONFIG_PHY_MAJOR_MASK; + host->uhs2_dev_prop.can_hibernate = (cap >> + UHS2_DEV_CONFIG_CAN_HIBER_POS) & + UHS2_DEV_CONFIG_CAN_HIBER_MASK; + + cap = cmd.resp[1]; + DBG("Device PHY Caps (32-63) is: 0x%x.\n", cap); + host->uhs2_dev_prop.n_lss_sync = cap & UHS2_DEV_CONFIG_N_LSS_SYN_MASK; + host->uhs2_dev_prop.n_lss_dir = (cap >> + UHS2_DEV_CONFIG_N_LSS_DIR_POS) & + UHS2_DEV_CONFIG_N_LSS_DIR_MASK; + if (host->uhs2_dev_prop.n_lss_sync == 0) + host->uhs2_dev_prop.n_lss_sync = 16 << 2; + else + host->uhs2_dev_prop.n_lss_sync <<= 2; + + if (host->uhs2_dev_prop.n_lss_dir == 0) + host->uhs2_dev_prop.n_lss_dir = 16 << 3; + else + host->uhs2_dev_prop.n_lss_dir <<= 3; + + DBG("INQUIRY_CFG: read LINK-TRAN Caps.\n"); + arg = ((UHS2_DEV_CONFIG_LINK_TRAN_CAPS & 0xFF) << 8) | + UHS2_NATIVE_CMD_READ | + UHS2_NATIVE_CMD_PLEN_8B | + (UHS2_DEV_CONFIG_LINK_TRAN_CAPS >> 8); + + DBG("Begin INQUIRY_CFG, header=0x%x, arg=0x%x.\n", + header, arg); + uhs2_cmd_assemble(&cmd, &uhs2_cmd, header, arg, NULL, 0, NULL, 0); + + err = mmc_wait_for_cmd(host, &cmd, 0); + if (err) { + pr_err("%s: %s: UHS2 CMD send fail, err= 0x%x!\n", + mmc_hostname(host), __func__, err); + return -EIO; + } + + if (IS_ENABLED(CONFIG_MMC_DEBUG)) { + int i; + + pr_warn("%s: INQUIRY_CFG Link-Tran response is: ", + mmc_hostname(host)); + for (i = 0; i < 2; i++) + pr_warn("0x%x ", cmd.resp[i]); + pr_warn("\n"); + } + + cap = cmd.resp[0]; + DBG("Device LINK-TRAN Caps (0-31) is: 0x%x.\n", cap); + host->uhs2_dev_prop.link_minor_rev = cap & + UHS2_DEV_CONFIG_LT_MINOR_MASK; + host->uhs2_dev_prop.link_major_rev = (cap >> + UHS2_DEV_CONFIG_LT_MAJOR_POS) & + UHS2_DEV_CONFIG_LT_MAJOR_MASK; + host->uhs2_dev_prop.n_fcu = (cap >> UHS2_DEV_CONFIG_N_FCU_POS) & + UHS2_DEV_CONFIG_N_FCU_MASK; + host->uhs2_dev_prop.dev_type = (cap >> UHS2_DEV_CONFIG_DEV_TYPE_POS) & + UHS2_DEV_CONFIG_DEV_TYPE_MASK; + host->uhs2_dev_prop.maxblk_len = (cap >> + UHS2_DEV_CONFIG_MAX_BLK_LEN_POS) & + UHS2_DEV_CONFIG_MAX_BLK_LEN_MASK; + + cap = cmd.resp[1]; + DBG("Device LINK-TRAN Caps (32-63) is: 0x%x.\n", cap); + host->uhs2_dev_prop.n_data_gap = cap & UHS2_DEV_CONFIG_N_DATA_GAP_MASK; + if (host->uhs2_dev_prop.n_fcu == 0) + host->uhs2_dev_prop.n_fcu = 256; + + return 0; +} + +static int uhs2_config_write(struct mmc_host *host) +{ + struct mmc_command cmd = {0}; + struct uhs2_command uhs2_cmd = {}; + u16 header = 0, arg = 0; + u32 nTry; + u32 payload[2]; + u8 nMinDataGap; + u8 plen; + int err; + u8 resp[5] = {0}; + u8 resp_len = 5; + /* + * must long enough for RECV_SW_DIR == 2; + * need lss_dir at least 4 for GL9755 device + * max compitable g_lss_dir = 0 + */ + u32 g_lss_dir = 0; + + DBG("SET_COMMON_CFG: write Generic Settings.\n"); + header = UHS2_NATIVE_PACKET | + UHS2_PACKET_TYPE_CCMD | host->uhs2_dev_prop.node_id; + arg = ((UHS2_DEV_CONFIG_GEN_SET & 0xFF) << 8) | + UHS2_NATIVE_CMD_WRITE | + UHS2_NATIVE_CMD_PLEN_8B | + (UHS2_DEV_CONFIG_GEN_SET >> 8); + + if (host->uhs2_dev_prop.n_lanes == UHS2_DEV_CONFIG_2L_HD_FD && + host->uhs2_caps.n_lanes == UHS2_DEV_CONFIG_2L_HD_FD) { + /* Support HD */ + DBG("Both Host and device support 2L-HD.\n"); + host->flags |= MMC_UHS2_2L_HD; + host->uhs2_caps.n_lanes_set = UHS2_DEV_CONFIG_GEN_SET_2L_FD_HD; + host->uhs2_dev_prop.n_lanes_set = + UHS2_DEV_CONFIG_GEN_SET_2L_FD_HD; + nMinDataGap = 1; + } else { + /* Only support 2L-FD so far */ + host->flags &= ~MMC_UHS2_2L_HD; + host->uhs2_caps.n_lanes_set = UHS2_DEV_CONFIG_GEN_SET_2L_FD_HD; + host->uhs2_dev_prop.n_lanes_set = + UHS2_DEV_CONFIG_GEN_SET_2L_FD_HD; + nMinDataGap = 3; + } + + plen = 2; + payload[0] = host->uhs2_dev_prop.n_lanes_set << + UHS2_DEV_CONFIG_N_LANES_POS; + payload[1] = 0; + payload[0] = cpu_to_be32(payload[0]); + payload[1] = cpu_to_be32(payload[1]); + + DBG("Begin SET_COMMON_CFG, header=0x%x, arg=0x%x\n", header, arg); + DBG("UHS2 write Generic Settings %08x %08x\n", + payload[0], payload[1]); + DBG("flags=%08x dev_prop.n_lanes_set=%x host_caps.n_lanes_set=%x\n", + host->flags, + host->uhs2_dev_prop.n_lanes_set, + host->uhs2_caps.n_lanes_set); + + /* + * There is no payload because per spec, there should be + * no payload field for read CCMD. + * Plen is set in arg. Per spec, plen for read CCMD + * represents the len of read data which is assigned in payload + * of following RES (p136). + */ + uhs2_cmd_assemble(&cmd, &uhs2_cmd, header, arg, payload, plen, NULL, 0); + + err = mmc_wait_for_cmd(host, &cmd, 0); + if (err) { + pr_err("%s: %s: UHS2 CMD send fail, err= 0x%x!\n", + mmc_hostname(host), __func__, err); + return -EIO; + } + + DBG("SET_COMMON_CFG: PHY Settings.\n"); + arg = ((UHS2_DEV_CONFIG_PHY_SET & 0xFF) << 8) | + UHS2_NATIVE_CMD_WRITE | + UHS2_NATIVE_CMD_PLEN_8B | + (UHS2_DEV_CONFIG_PHY_SET >> 8); + + for (nTry = 0; nTry < 2; nTry++) { + plen = 2; + + if (host->uhs2_caps.speed_range == + UHS2_DEV_CONFIG_PHY_SET_SPEED_B) { + host->flags |= MMC_UHS2_SPEED_B; + host->uhs2_dev_prop.speed_range_set = + UHS2_DEV_CONFIG_PHY_SET_SPEED_B; + DBG("set dev_prop.speed_range_set to SPEED_B\n"); + } else { + host->uhs2_dev_prop.speed_range_set = + UHS2_DEV_CONFIG_PHY_SET_SPEED_A; + host->flags &= ~MMC_UHS2_SPEED_B; + DBG("set dev_prop.speed_range_set to SPEED_A\n"); + } + + payload[0] = host->uhs2_dev_prop.speed_range_set << + UHS2_DEV_CONFIG_PHY_SET_SPEED_POS; + + host->uhs2_dev_prop.n_lss_sync_set = + (min(host->uhs2_dev_prop.n_lss_sync, + host->uhs2_caps.n_lss_sync) >> 2) & + UHS2_DEV_CONFIG_N_LSS_SYN_MASK; + host->uhs2_caps.n_lss_sync_set = + host->uhs2_dev_prop.n_lss_sync_set; + + if (nTry) { + host->uhs2_dev_prop.n_lss_dir_set = + (max(host->uhs2_dev_prop.n_lss_dir, + host->uhs2_caps.n_lss_dir) >> 3) & + UHS2_DEV_CONFIG_N_LSS_DIR_MASK; + host->uhs2_caps.n_lss_dir_set = + host->uhs2_dev_prop.n_lss_dir_set; + payload[1] = (host->uhs2_dev_prop.n_lss_dir_set << + UHS2_DEV_CONFIG_N_LSS_DIR_POS) | + host->uhs2_dev_prop.n_lss_sync_set; + } else { + host->uhs2_caps.n_lss_dir_set = + (host->uhs2_dev_prop.n_lss_dir >> 3) & + UHS2_DEV_CONFIG_N_LSS_DIR_MASK; + host->uhs2_dev_prop.n_lss_dir_set = + ((host->uhs2_caps.n_lss_dir >> 3) + 1) & + UHS2_DEV_CONFIG_N_LSS_DIR_MASK; + } + + if (!g_lss_dir) { + host->uhs2_dev_prop.n_lss_dir_set = 0; + } else { + host->uhs2_dev_prop.n_lss_dir_set = + max((u8)g_lss_dir, + host->uhs2_dev_prop.n_lss_dir_set); + } + + payload[1] = (host->uhs2_dev_prop.n_lss_dir_set << + UHS2_DEV_CONFIG_N_LSS_DIR_POS) | + host->uhs2_dev_prop.n_lss_sync_set; + payload[0] = cpu_to_be32(payload[0]); + payload[1] = cpu_to_be32(payload[1]); + + DBG("UHS2 SET PHY Settings %08x %08x\n", + payload[0], payload[1]); + DBG("host->flags=%08x dev_prop.speed_range_set=%x\n", + host->flags, + host->uhs2_dev_prop.speed_range_set); + DBG("dev_prop.n_lss_sync_set=%x host_caps.n_lss_sync_set=%x\n", + host->uhs2_dev_prop.n_lss_sync_set, + host->uhs2_caps.n_lss_sync_set); + DBG("dev_prop.n_lss_dir_set=%x host_caps.n_lss_dir_set=%x\n", + host->uhs2_dev_prop.n_lss_dir_set, + host->uhs2_caps.n_lss_dir_set); + + DBG("Begin SET_COMMON_CFG header=0x%x arg=0x%x\n", + header, arg); + DBG("\t\tpayload[0]=0x%x payload[1]=0x%x\n", + payload[0], payload[1]); + + resp_len = 4; + memset(resp, 0, sizeof(resp)); + + uhs2_cmd_assemble(&cmd, &uhs2_cmd, header, arg, + payload, plen, resp, resp_len); + + err = mmc_wait_for_cmd(host, &cmd, 0); + if (err) { + pr_err("%s: %s: UHS2 CMD send fail, err= 0x%x!\n", + mmc_hostname(host), __func__, err); + return -EIO; + } + + if (!(resp[2] & 0x80)) + break; + + DBG("%s: %s: UHS2 SET PHY Settings fail, res= 0x%x!\n", + mmc_hostname(host), __func__, resp[2]); + } + + DBG("SET_COMMON_CFG: LINK-TRAN Settings.\n"); + arg = ((UHS2_DEV_CONFIG_LINK_TRAN_SET & 0xFF) << 8) | + UHS2_NATIVE_CMD_WRITE | + UHS2_NATIVE_CMD_PLEN_8B | + (UHS2_DEV_CONFIG_LINK_TRAN_SET >> 8); + + plen = 2; + + if (host->uhs2_dev_prop.app_type == UHS2_DEV_CONFIG_APP_SD_MEM) + host->uhs2_dev_prop.maxblk_len_set = + UHS2_DEV_CONFIG_LT_SET_MAX_BLK_LEN; + else + host->uhs2_dev_prop.maxblk_len_set = + min(host->uhs2_dev_prop.maxblk_len, + host->uhs2_caps.maxblk_len); + host->uhs2_caps.maxblk_len_set = host->uhs2_dev_prop.maxblk_len_set; + + host->uhs2_dev_prop.n_fcu_set = + min(host->uhs2_dev_prop.n_fcu, + host->uhs2_caps.n_fcu); + host->uhs2_caps.n_fcu_set = host->uhs2_dev_prop.n_fcu_set; + + host->uhs2_dev_prop.n_data_gap_set = + max(nMinDataGap, host->uhs2_dev_prop.n_data_gap); + + host->uhs2_caps.n_data_gap_set = host->uhs2_dev_prop.n_data_gap_set; + + host->uhs2_caps.max_retry_set = 3; + host->uhs2_dev_prop.max_retry_set = host->uhs2_caps.max_retry_set; + + payload[0] = (host->uhs2_dev_prop.maxblk_len_set << + UHS2_DEV_CONFIG_MAX_BLK_LEN_POS) | + (host->uhs2_dev_prop.max_retry_set << + UHS2_DEV_CONFIG_LT_SET_MAX_RETRY_POS) | + (host->uhs2_dev_prop.n_fcu_set << + UHS2_DEV_CONFIG_N_FCU_POS); + payload[1] = host->uhs2_dev_prop.n_data_gap_set; + payload[0] = cpu_to_be32(payload[0]); + payload[1] = cpu_to_be32(payload[1]); + + DBG("Begin SET_COMMON_CFG header=0x%x arg=0x%x\n", header, arg); + DBG("\t\tpayload[0]=0x%x payload[1]=0x%x\n", payload[0], payload[1]); + + uhs2_cmd_assemble(&cmd, &uhs2_cmd, header, arg, payload, plen, NULL, 0); + + err = mmc_wait_for_cmd(host, &cmd, 0); + if (err) { + pr_err("%s: %s: UHS2 CMD send fail, err= 0x%x!\n", + mmc_hostname(host), __func__, err); + return -EIO; + } + + DBG("SET_COMMON_CFG: Set Config Completion.\n"); + arg = ((UHS2_DEV_CONFIG_GEN_SET & 0xFF) << 8) | + UHS2_NATIVE_CMD_WRITE | + UHS2_NATIVE_CMD_PLEN_8B | + (UHS2_DEV_CONFIG_GEN_SET >> 8); + + plen = 2; + payload[0] = 0; + payload[1] = UHS2_DEV_CONFIG_GEN_SET_CFG_COMPLETE; + payload[0] = cpu_to_be32(payload[0]); + payload[1] = cpu_to_be32(payload[1]); + + DBG("Begin SET_COMMON_CFG, header=0x%x, arg=0x%x, payload[0] = 0x%x.\n", + header, arg, payload[0]); + resp_len = 5; + memset(resp, 0, sizeof(resp)); + uhs2_cmd_assemble(&cmd, &uhs2_cmd, header, arg, payload, plen, + resp, resp_len); + + err = mmc_wait_for_cmd(host, &cmd, 0); + if (err) { + pr_err("%s: %s: UHS2 CMD send fail, err= 0x%x!\n", + mmc_hostname(host), __func__, err); + return -EIO; + } + + /* Set host Config Setting registers */ + if (host->ops->uhs2_set_reg(host, SET_CONFIG)) { + pr_err("%s: %s: UHS2 SET_CONFIG fail!\n", + mmc_hostname(host), __func__); + return -EIO; + } + + return 0; +} + +static int uhs2_go_dormant(struct mmc_host *host, bool hibernate) +{ + struct mmc_command cmd = {0}; + struct uhs2_command uhs2_cmd = {}; + u16 header = 0, arg = 0; + u32 payload[1]; + u8 plen = 1; + int err; + + /* Disable Normal INT */ + if (host->ops->uhs2_set_reg(host, DISABLE_INT)) { + pr_err("%s: %s: UHS2 DISABLE_INT fail!\n", + mmc_hostname(host), __func__); + return -EIO; + } + + header = UHS2_NATIVE_PACKET | UHS2_PACKET_TYPE_CCMD | + host->uhs2_dev_prop.node_id; + + arg = ((UHS2_DEV_CMD_GO_DORMANT_STATE & 0xFF) << 8) | + UHS2_NATIVE_CMD_WRITE | + UHS2_NATIVE_CMD_PLEN_4B | + (UHS2_DEV_CMD_GO_DORMANT_STATE >> 8); + + if (hibernate) + payload[0] = UHS2_DEV_CMD_DORMANT_HIBER; + + DBG("Begin GO_DORMANT_STATE, header=0x%x, arg=0x%x, payload=0x%x.\n", + header, arg, payload[0]); + uhs2_cmd_assemble(&cmd, &uhs2_cmd, header, arg, payload, plen, NULL, 0); + + err = mmc_wait_for_cmd(host, &cmd, 0); + if (err) { + pr_err("%s: %s: UHS2 CMD send fail, err= 0x%x!\n", + mmc_hostname(host), __func__, err); + return -EIO; + } + + /* Check Dormant State in Present */ + if (host->ops->uhs2_set_reg(host, CHECK_DORMANT)) { + pr_err("%s: %s: UHS2 GO_DORMANT_STATE fail!\n", + mmc_hostname(host), __func__); + return -EIO; + } + + host->ops->uhs2_disable_clk(host); + + return 0; +} + +static int uhs2_change_speed(struct mmc_host *host) +{ + int err; + + /* Change Speed Range */ + if (host->ops->uhs2_set_reg(host, SET_SPEED_B)) { + pr_err("%s: %s: UHS2 SET_SPEED fail!\n", + mmc_hostname(host), __func__); + return -EIO; + } + + err = uhs2_go_dormant(host, false); + if (err) { + pr_err("%s: %s: UHS2 GO_DORMANT_STATE fail, err= 0x%x!\n", + mmc_hostname(host), __func__, err); + return -EIO; + } + + /* restore sd clock */ + mdelay(5); + host->ops->uhs2_enable_clk(host); + + /* Enable Normal INT */ + if (host->ops->uhs2_set_reg(host, ENABLE_INT)) { + pr_err("%s: %s: UHS2 ENABLE_INT fail!\n", + mmc_hostname(host), __func__); + return -EIO; + } + + if (host->ops->uhs2_detect_init(host)) { + pr_err("%s: %s: uhs2_detect_init() fail!\n", + mmc_hostname(host), __func__); + return -EIO; + } + + return 0; +} + +/** + * mmc_uhs2_rescan_try_freq - select UHS2 interface + * @host: MMC host + * @freq: Bus speed + * + * Try to select UHS2 interface and initialize the bus for a given + * frequency, @freq. + * + * Return: 0 on success, non-zero error on failure + */ +int mmc_uhs2_rescan_try_freq(struct mmc_host *host, unsigned int freq) +{ + int err = -EIO; + + host->flags |= MMC_UHS2_SUPPORT; + host->f_init = freq; + + pr_debug("%s: %s: trying to init card at %u Hz\n", + mmc_hostname(host), __func__, host->f_init); + + mmc_power_up(host, 0); + if (host->ops->uhs2_detect_init(host)) { + pr_err("%s: fail to detect UHS2!\n", mmc_hostname(host)); + err = UHS2_PHY_INIT_ERR; + goto init_fail; + } + + if (uhs2_dev_init(host)) { + pr_err("%s: UHS2 DEVICE_INIT fail!\n", mmc_hostname(host)); + goto init_fail; + } + + if (uhs2_enum(host)) { + pr_err("%s: UHS2 ENUMERATE fail!\n", mmc_hostname(host)); + goto init_fail; + } + + if (uhs2_config_read(host)) { + pr_err("%s: UHS2 INQUIRY_CONFIG fail!\n", mmc_hostname(host)); + goto init_fail; + } + + if (uhs2_config_write(host)) { + pr_err("%s: UHS2 SET_COMMON_CONFIG fail!\n", + mmc_hostname(host)); + goto init_fail; + } + + mmc_delay(10); + + /* Change to Speed Range B if it is supported */ + if (host->flags & MMC_UHS2_SPEED_B) + if (uhs2_change_speed(host)) { + pr_err("%s: UHS2 uhs2_change_speed() fail!\n", + mmc_hostname(host)); + goto init_fail; + } + + host->flags |= MMC_UHS2_INITIALIZED; + + mmc_send_if_cond(host, host->ocr_avail); + + /* On market, only can some SD cards support UHS-II so only call SD + * attach process here. + */ + if (!(host->caps2 & MMC_CAP2_NO_SD)) { + err = mmc_attach_sd(host); + if (!err) + return 0; + } else { + err = -EIO; + } + +init_fail: + mmc_power_off(host); + if (host->flags & MMC_UHS2_INITIALIZED) + host->flags &= ~MMC_UHS2_INITIALIZED; + host->flags &= ~MMC_UHS2_SUPPORT; + + return err; +} +EXPORT_SYMBOL_GPL(mmc_uhs2_rescan_try_freq); diff --git a/drivers/mmc/core/uhs2.h b/drivers/mmc/core/uhs2.h new file mode 100644 index 000000000000..e3389d4dda3b --- /dev/null +++ b/drivers/mmc/core/uhs2.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * driver/mmc/core/uhs2.h - UHS-II driver + * + * Header file for UHS-II packets, Host Controller registers and I/O + * accessors. + * + * Copyright (C) 2014 Intel Corp, All Rights Reserved. + */ +#ifndef MMC_UHS2_H +#define MMC_UHS2_H + +#include +#include + +#define UHS2_PHY_INIT_ERR 1 + +int mmc_uhs2_rescan_try_freq(struct mmc_host *host, unsigned int freq); + +#endif /* MMC_UHS2_H */ From patchwork Fri Jul 10 11:08:58 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Chuang X-Patchwork-Id: 11656261 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id E22A7618 for ; Fri, 10 Jul 2020 11:08:19 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C833D2077D for ; Fri, 10 Jul 2020 11:08:19 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="E+n7ZdWp" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727995AbgGJLIS (ORCPT ); Fri, 10 Jul 2020 07:08:18 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40964 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726725AbgGJLIQ (ORCPT ); Fri, 10 Jul 2020 07:08:16 -0400 Received: from mail-pl1-x641.google.com (mail-pl1-x641.google.com [IPv6:2607:f8b0:4864:20::641]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 87227C08C5CE; Fri, 10 Jul 2020 04:08:16 -0700 (PDT) Received: by mail-pl1-x641.google.com with SMTP id 72so2128723ple.0; Fri, 10 Jul 2020 04:08:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=MBX+zLWZoUU7YT17yBn/8lBjP/8tmr8iWyHaBASouus=; b=E+n7ZdWpw4sKWwQtuC6WSFtvBrgcNYj/pWuRfB1lveg4e7Hpzv3o+a27EhPaBs1NxF mpDlH3xJ2P1vgVyjoDuA8sjh1RdKVvmCr9W+qy7UWYpiFYyhUN/uZmBjO5ukLdNq/H4J KC+BaRZzzmNQkPGA9CbB0ibnI2jjIQX/MDwc34qR2eazOoQlIzBmfy5Scjc7tUD9AV15 PbK3wH/YxMSE+1cej08SqfG4pBeKWFQfCP5mKENsNeH6JDMT8BdA/Vm7VMZJTThVtXVc 2MgbnrQxn2thSZps8BpZ9IeVgdeH6mGS+7O6TnUf14dhFK5oangsHBIws3sOqQ/4mSFy Rfug== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=MBX+zLWZoUU7YT17yBn/8lBjP/8tmr8iWyHaBASouus=; b=T6IHwAXsCYiH12USh7w19ZnjYvpk7WME3QfYFJmU+4MmemZ+qKdr/y/wl1/ttMWvgS dkaYk8P45OogtVeO7Pw79xDgSoeK2QXLA6oZubpl8gCwOh7FpXgtb/StXSOpkqXZiEi+ xzYgBGtLsSvxXKSzWvtlej9EyHsrUqcdxFw0eN1N/F9yfR01FGajTP0TZIqL0pwB3YzA tJn+AVItlKdo6i3xUAvifOjVfLat7W21vwEeMU3BUoCE0ZbdrVzHjAedD5XFYCCprKwQ 9nidvFjx+BehIw3saWlxiKqsbpPfs2zpSrZT8kTtiXpHY9147xhAB3XhG+Htd6kXbXh0 5wcQ== X-Gm-Message-State: AOAM531xiJdVaxIH2cr8pyfVMa8TsdfJZA4L5yuRaivjE2Cn8ZhLLqDq FGese+vDbLziNsk77Cyd254= X-Google-Smtp-Source: ABdhPJxvP3R+7/6xKd+Ze0bdorOQUhuD5VNFY8wm13WbCL/3Kudo8U1XNgXX38/+8AysaMYEAyMfVQ== X-Received: by 2002:a17:902:a708:: with SMTP id w8mr16567900plq.128.1594379296110; Fri, 10 Jul 2020 04:08:16 -0700 (PDT) Received: from gli-arch.genesyslogic.com.tw (60-251-58-169.HINET-IP.hinet.net. [60.251.58.169]) by smtp.gmail.com with ESMTPSA id y80sm5498959pfb.165.2020.07.10.04.08.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 10 Jul 2020 04:08:15 -0700 (PDT) From: Ben Chuang To: adrian.hunter@intel.com, ulf.hansson@linaro.org Cc: linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, ben.chuang@genesyslogic.com.tw, takahiro.akashi@linaro.org, greg.tu@genesyslogic.com.tw, Ben Chuang Subject: [RFC PATCH V3 05/21] mmc: core: UHS-II support, skip TMODE setup in some cases Date: Fri, 10 Jul 2020 19:08:58 +0800 Message-Id: <20200710110858.29166-1-benchuanggli@gmail.com> X-Mailer: git-send-email 2.27.0 MIME-Version: 1.0 Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org From: AKASHI Takahiro UHS-II's data command packet has TMODE fields in which parameters for data transaction, like Duplex Mode(DM) and Length Mode(LM), are specified. In some cases, we don't need to initialize them and so set uhs2_tmode0_flag to 1 in order to skip them in generating a packet. (The code will be added in the next commit.) Signed-off-by: Ben Chuang Signed-off-by: AKASHI Takahiro --- drivers/mmc/core/block.c | 7 ++++++- drivers/mmc/core/sd_ops.c | 3 +++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c index 7896952de1ac..212f872d60bc 100644 --- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c @@ -56,6 +56,7 @@ #include "mmc_ops.h" #include "quirks.h" #include "sd_ops.h" +#include "uhs2.h" MODULE_ALIAS("mmc:block"); #ifdef MODULE_PARAM_PREFIX @@ -1526,6 +1527,9 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq, struct request *req = mmc_queue_req_to_req(mqrq); struct mmc_blk_data *md = mq->blkdata; bool do_rel_wr, do_data_tag; + bool do_multi; + + do_multi = (card->host->flags & MMC_UHS2_INITIALIZED) ? true : false; mmc_blk_data_prep(mq, mqrq, disable_multi, &do_rel_wr, &do_data_tag); @@ -1536,7 +1540,7 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq, brq->cmd.arg <<= 9; brq->cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; - if (brq->data.blocks > 1 || do_rel_wr) { + if (brq->data.blocks > 1 || do_rel_wr || do_multi) { /* SPI multiblock writes terminate using a special * token, not a STOP_TRANSMISSION request. */ @@ -1549,6 +1553,7 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq, brq->mrq.stop = NULL; readcmd = MMC_READ_SINGLE_BLOCK; writecmd = MMC_WRITE_BLOCK; + brq->cmd.uhs2_tmode0_flag = 1; } brq->cmd.opcode = rq_data_dir(req) == READ ? readcmd : writecmd; diff --git a/drivers/mmc/core/sd_ops.c b/drivers/mmc/core/sd_ops.c index 22bf528294b9..f58bb50872f6 100644 --- a/drivers/mmc/core/sd_ops.c +++ b/drivers/mmc/core/sd_ops.c @@ -235,6 +235,7 @@ int mmc_app_send_scr(struct mmc_card *card) cmd.opcode = SD_APP_SEND_SCR; cmd.arg = 0; cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; + cmd.uhs2_tmode0_flag = 1; data.blksz = 8; data.blocks = 1; @@ -282,6 +283,7 @@ int mmc_sd_switch(struct mmc_card *card, int mode, int group, cmd.arg &= ~(0xF << (group * 4)); cmd.arg |= value << (group * 4); cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; + cmd.uhs2_tmode0_flag = 1; data.blksz = 64; data.blocks = 1; @@ -323,6 +325,7 @@ int mmc_app_sd_status(struct mmc_card *card, void *ssr) cmd.opcode = SD_APP_SD_STATUS; cmd.arg = 0; cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_ADTC; + cmd.uhs2_tmode0_flag = 1; data.blksz = 64; data.blocks = 1; From patchwork Fri Jul 10 11:09:25 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Chuang X-Patchwork-Id: 11656263 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 1AF3413B6 for ; Fri, 10 Jul 2020 11:08:45 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 00F542078D for ; Fri, 10 Jul 2020 11:08:45 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="vQwHVP5j" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726757AbgGJLIo (ORCPT ); Fri, 10 Jul 2020 07:08:44 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41036 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726725AbgGJLIn (ORCPT ); Fri, 10 Jul 2020 07:08:43 -0400 Received: from mail-pj1-x1042.google.com (mail-pj1-x1042.google.com [IPv6:2607:f8b0:4864:20::1042]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 555F3C08C5CE; Fri, 10 Jul 2020 04:08:43 -0700 (PDT) Received: by mail-pj1-x1042.google.com with SMTP id k5so2466122pjg.3; Fri, 10 Jul 2020 04:08:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=F8O0SJiIJfP0hcr2bPL6Gp5kFAhLJphHNCRKgoNomCk=; b=vQwHVP5jS8iJIiVElm2NjGIXswygyZQ5FK2mQ7LBQRXpkVv6Chz3k/KwVJRxtRjwaB IREZXtd4S22b2xucTAx0qqXNqBh8lScaRfkJduXQ+KXGAkWRm+S2IBP1ixALTxnLm8zX mM6LGr7Wpjm0QUgydiNwA6tJAFvop5LJgscZza1CzKjSrajuN2o2TqnNEWnetwE+Afxa SsCF8+gxL9qNPpoXMpaX1n2mw/yIT6DpD8bMOWRnW26ne2QKUvrJXi+bjOh4lk/Es+GR i71ii8Ls+31UQK+sJzKRLD8OlSSAo2XFOaHFRDnpSbQI5OxAKMqoj+OZvXqEyyrPdgAs ix9Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=F8O0SJiIJfP0hcr2bPL6Gp5kFAhLJphHNCRKgoNomCk=; b=sfVCNnos9j0UwPhC/Iwx551jZurjR/4UFUiETtd6y28XPs6uRVkE6AvBQnb0SMloR9 /meJjs5ILhLDbNkweUNpzYHLuN5MuXOK0OahnXa7L66dPOE+1T4FsT+0+9MT9t7jhHno LN56TYW+IIo4qsELN+MaGoE5+zUhagov5jn1tWMoAp0e/AzomzZm3F5rZC7FN5OxX4TV msR35tO/HsyctvCYWbzo6DZ/hXA4ARmUDvL4IRFGkyNGixqHarXHvOS85bq41ytjp69u cBqczXVnhncW2Vp5tycs3DMDcBsm/lqvg3fu2mJLh6ITuzD0UT3mEhXt+22oKa6g0nvd /dZA== X-Gm-Message-State: AOAM531IU2E4XmwUPuL8iWdZzE1jrb5PPDJXTecPITdeKbYJ2bUseTMK iP8aalcdM/lie9OPy1F8rfo= X-Google-Smtp-Source: ABdhPJxdnXqTMaGuW7C48Nbs5ksP4+DEfMF6SarUMfxCAkZTK8hhxJvracW5aDAKNrNBOE2pX2Upjg== X-Received: by 2002:a17:90b:2350:: with SMTP id ms16mr5242120pjb.127.1594379322892; Fri, 10 Jul 2020 04:08:42 -0700 (PDT) Received: from gli-arch.genesyslogic.com.tw ([122.146.30.3]) by smtp.gmail.com with ESMTPSA id u14sm6014851pfk.211.2020.07.10.04.08.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 10 Jul 2020 04:08:42 -0700 (PDT) From: Ben Chuang To: adrian.hunter@intel.com, ulf.hansson@linaro.org Cc: linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, ben.chuang@genesyslogic.com.tw, takahiro.akashi@linaro.org, greg.tu@genesyslogic.com.tw, Ben Chuang Subject: [RFC PATCH V3 06/21] mmc: core: UHS-II support, generate UHS-II SD command packet Date: Fri, 10 Jul 2020 19:09:25 +0800 Message-Id: <20200710110925.29231-1-benchuanggli@gmail.com> X-Mailer: git-send-email 2.27.0 MIME-Version: 1.0 Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org From: AKASHI Takahiro In SD-TRAN protocol, legacy SD commands should be "encapsulated" in SD packets as described in SD specification. Please see section 7.1 and 7.2.1 in "UHS-II Simplified Addendum." Signed-off-by: Ben Chuang Signed-off-by: AKASHI Takahiro --- drivers/mmc/core/core.c | 18 +++++++++++ drivers/mmc/core/uhs2.c | 70 +++++++++++++++++++++++++++++++++++++++++ drivers/mmc/core/uhs2.h | 1 + 3 files changed, 89 insertions(+) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index e2534f3446ce..dfe3a6df7645 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -337,6 +337,8 @@ static int mmc_mrq_prep(struct mmc_host *host, struct mmc_request *mrq) int mmc_start_request(struct mmc_host *host, struct mmc_request *mrq) { + struct uhs2_command uhs2_cmd; + u32 payload[4]; /* for maximum size */ int err; init_completion(&mrq->cmd_completion); @@ -354,6 +356,13 @@ int mmc_start_request(struct mmc_host *host, struct mmc_request *mrq) if (err) return err; + if (host->flags & MMC_UHS2_SUPPORT && + host->flags & MMC_UHS2_INITIALIZED) { + uhs2_cmd.payload = payload; + mrq->cmd->uhs2_cmd = &uhs2_cmd; + uhs2_prepare_sd_cmd(host, mrq); + } + led_trigger_event(host->led, LED_FULL); __mmc_start_request(host, mrq); @@ -433,6 +442,8 @@ EXPORT_SYMBOL(mmc_wait_for_req_done); */ int mmc_cqe_start_req(struct mmc_host *host, struct mmc_request *mrq) { + struct uhs2_command uhs2_cmd; + u32 payload[4]; /* for maximum size */ int err; /* @@ -453,6 +464,13 @@ int mmc_cqe_start_req(struct mmc_host *host, struct mmc_request *mrq) if (err) goto out_err; + if (host->flags & MMC_UHS2_SUPPORT && + host->flags & MMC_UHS2_INITIALIZED) { + uhs2_cmd.payload = payload; + mrq->cmd->uhs2_cmd = &uhs2_cmd; + uhs2_prepare_sd_cmd(host, mrq); + } + err = host->cqe_ops->cqe_request(host, mrq); if (err) goto out_err; diff --git a/drivers/mmc/core/uhs2.c b/drivers/mmc/core/uhs2.c index a3b20ac6f315..6e26de429726 100644 --- a/drivers/mmc/core/uhs2.c +++ b/drivers/mmc/core/uhs2.c @@ -798,3 +798,73 @@ int mmc_uhs2_rescan_try_freq(struct mmc_host *host, unsigned int freq) return err; } EXPORT_SYMBOL_GPL(mmc_uhs2_rescan_try_freq); + +/** + * uhs2_prepare_sd_cmd - prepare for SD command packet + * @host: MMC host + * @mrq: MMC request + * + * Initialize and fill in a header and a payload of SD command packet. + * The caller should allocate uhs2_command in host->cmd->uhs2_cmd in + * advance. + * + * Return: 0 on success, non-zero error on failure + */ +int uhs2_prepare_sd_cmd(struct mmc_host *host, struct mmc_request *mrq) +{ + struct mmc_command *cmd; + struct uhs2_command *uhs2_cmd; + u16 header = 0, arg = 0; + u32 *payload; + u8 plen = 0; + + cmd = mrq->cmd; + header = host->uhs2_dev_prop.node_id; + if ((cmd->flags & MMC_CMD_MASK) == MMC_CMD_ADTC) + header |= UHS2_PACKET_TYPE_DCMD; + else + header |= UHS2_PACKET_TYPE_CCMD; + + arg = cmd->opcode << UHS2_SD_CMD_INDEX_POS; + + uhs2_cmd = cmd->uhs2_cmd; + payload = uhs2_cmd->payload; + plen = 2; /* at the maximum */ + + if ((cmd->flags & MMC_CMD_MASK) == MMC_CMD_ADTC && + !cmd->uhs2_tmode0_flag) { + if (host->flags & MMC_UHS2_2L_HD) + arg |= UHS2_DCMD_2L_HD_MODE; + + arg |= UHS2_DCMD_LM_TLEN_EXIST; + + if (cmd->data->blocks == 1 && + cmd->data->blksz != 512 && + cmd->opcode != MMC_READ_SINGLE_BLOCK && + cmd->opcode != MMC_WRITE_BLOCK) { + arg |= UHS2_DCMD_TLUM_BYTE_MODE; + payload[1] = uhs2_dcmd_convert_msb(cmd->data->blksz); + } else { + payload[1] = uhs2_dcmd_convert_msb(cmd->data->blocks); + } + + if (cmd->opcode == SD_IO_RW_EXTENDED) { + arg &= ~(UHS2_DCMD_LM_TLEN_EXIST | + UHS2_DCMD_TLUM_BYTE_MODE | + UHS2_NATIVE_DCMD_DAM_IO); + payload[1] = 0; + plen = 1; + } + } else { + plen = 1; + } + + payload[0] = uhs2_dcmd_convert_msb(cmd->arg); + pr_debug("%s: %s: sd_cmd->arg = 0x%x, payload[0]= 0x%x.\n", + mmc_hostname(host), __func__, cmd->arg, payload[0]); + + uhs2_cmd_assemble(cmd, uhs2_cmd, header, arg, payload, plen, NULL, 0); + + return 0; +} +EXPORT_SYMBOL_GPL(uhs2_prepare_sd_cmd); diff --git a/drivers/mmc/core/uhs2.h b/drivers/mmc/core/uhs2.h index e3389d4dda3b..48486ba21062 100644 --- a/drivers/mmc/core/uhs2.h +++ b/drivers/mmc/core/uhs2.h @@ -16,5 +16,6 @@ #define UHS2_PHY_INIT_ERR 1 int mmc_uhs2_rescan_try_freq(struct mmc_host *host, unsigned int freq); +int uhs2_prepare_sd_cmd(struct mmc_host *host, struct mmc_request *mrq); #endif /* MMC_UHS2_H */ From patchwork Fri Jul 10 11:09:37 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Chuang X-Patchwork-Id: 11656265 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 88DAD13B6 for ; Fri, 10 Jul 2020 11:08:57 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 6FE2A2078D for ; Fri, 10 Jul 2020 11:08:57 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="rtoPGOCQ" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728025AbgGJLI4 (ORCPT ); Fri, 10 Jul 2020 07:08:56 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41064 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726725AbgGJLIy (ORCPT ); Fri, 10 Jul 2020 07:08:54 -0400 Received: from mail-pg1-x542.google.com (mail-pg1-x542.google.com [IPv6:2607:f8b0:4864:20::542]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 84127C08C5CE; Fri, 10 Jul 2020 04:08:54 -0700 (PDT) Received: by mail-pg1-x542.google.com with SMTP id k27so2395331pgm.2; Fri, 10 Jul 2020 04:08:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=tErlLbdtCWDGv/vKwdRdEOml4K+SgK9V6YiS5pXmAGk=; b=rtoPGOCQCl8nBYC27b28IX042RFJzQXF7gcoKuoh66Q41+udmEwxjWuAqt8+VyJrQY 9xmhqI/5q9DEftOclJP0yuilarwfXpABksX4mf9NW7CeVDr5hnqySm4iJaa0pWnJrra+ NBU+gVNKCFsbTkPZFta7DpNNq8wuMDp32wBkbep0fFLuqSJUZBNRNvg3qhNKiE19APr5 HDdlkbafU3q/t2o2nV+EAJkCxIituZZ516DF1Q8OdCVM6O1K+weGxCn3c30T9oYoWa2A vcQecjZOgMsRkMyPRBQHD97hTGxqtCyax1x2faS1k+tiye71UgiTdIaYBy2mszi7sWB4 1Wtw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=tErlLbdtCWDGv/vKwdRdEOml4K+SgK9V6YiS5pXmAGk=; b=jsW6Hjl+AgVng6Z65VFI2ActWhdx/qZo4INhtqHxgMcfFrs/czLVvAAXwtaIaTyflV 8Wtwi3ek6OUsvR4H3c4vglz1ae0c8ggZWLghVV7bWGDmFms2T+Ire5FYmtWpOOjZgCDO 25Hp3wJ7JEK4AyM2aYDtLDfqvwSG5TYeAvDhiOqaPBC0RhfV4WWzf79yEV6toVVVq1Ns 4pr0E3lCd+vcjs6fsL31uWRHiwLbth8ZXt6xpZ0fxl3ESe0H7fiUBIo4huhHwy0S8oOu Or5d2SZs5zuj1Td/1cTIputvEGjcx5JQSBG3DYFnGGtmp1RsDzH5/eLfc6caEXiUnTkw iqQQ== X-Gm-Message-State: AOAM532tlZ3mgu07m37+mZi9+IsSKmoHoIU1ek8VbvqSbNVjEhS8Uxlq HCwjT15l9z6nPCg/vxpXf5o= X-Google-Smtp-Source: ABdhPJwuvAeLacUnNNBD4q38sBZjlHgfaYBiCTzmMUKSt2GojtyM91d7broEU4sA0x+Yl6XOx+CN6A== X-Received: by 2002:a62:f202:: with SMTP id m2mr51534273pfh.157.1594379334138; Fri, 10 Jul 2020 04:08:54 -0700 (PDT) Received: from gli-arch.genesyslogic.com.tw (60-251-58-169.HINET-IP.hinet.net. [60.251.58.169]) by smtp.gmail.com with ESMTPSA id v2sm5395427pje.19.2020.07.10.04.08.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 10 Jul 2020 04:08:53 -0700 (PDT) From: Ben Chuang To: adrian.hunter@intel.com, ulf.hansson@linaro.org Cc: linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, ben.chuang@genesyslogic.com.tw, takahiro.akashi@linaro.org, greg.tu@genesyslogic.com.tw, Ben Chuang Subject: [RFC PATCH V3 07/21] mmc: core: UHS-II support, set APP_CMD bit if necessary Date: Fri, 10 Jul 2020 19:09:37 +0800 Message-Id: <20200710110937.29283-1-benchuanggli@gmail.com> X-Mailer: git-send-email 2.27.0 MIME-Version: 1.0 Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org From: AKASHI Takahiro In UHS-II mode, MMC_APP_CMD command need not to be sent. Instead, APP_CMD bit in a packet should be set. Signed-off-by: Ben Chuang Signed-off-by: AKASHI Takahiro --- drivers/mmc/core/sd_ops.c | 9 +++++++++ drivers/mmc/core/uhs2.c | 4 ++++ 2 files changed, 13 insertions(+) diff --git a/drivers/mmc/core/sd_ops.c b/drivers/mmc/core/sd_ops.c index f58bb50872f6..9dc296356928 100644 --- a/drivers/mmc/core/sd_ops.c +++ b/drivers/mmc/core/sd_ops.c @@ -26,6 +26,15 @@ int mmc_app_cmd(struct mmc_host *host, struct mmc_card *card) if (WARN_ON(card && card->host != host)) return -EINVAL; + /* UHS2 packet has APP bit so only set APP_CMD flag here. + * Will set the APP bit when assembling UHS2 packet. + */ + if (host->flags & MMC_UHS2_SUPPORT && + host->flags & MMC_UHS2_INITIALIZED) { + host->flags |= MMC_UHS2_APP_CMD; + return 0; + } + cmd.opcode = MMC_APP_CMD; if (card) { diff --git a/drivers/mmc/core/uhs2.c b/drivers/mmc/core/uhs2.c index 6e26de429726..2fbd7b6d9dea 100644 --- a/drivers/mmc/core/uhs2.c +++ b/drivers/mmc/core/uhs2.c @@ -826,6 +826,10 @@ int uhs2_prepare_sd_cmd(struct mmc_host *host, struct mmc_request *mrq) header |= UHS2_PACKET_TYPE_CCMD; arg = cmd->opcode << UHS2_SD_CMD_INDEX_POS; + if (host->flags & MMC_UHS2_APP_CMD) { + arg |= UHS2_SD_CMD_APP; + host->flags &= ~MMC_UHS2_APP_CMD; + } uhs2_cmd = cmd->uhs2_cmd; payload = uhs2_cmd->payload; From patchwork Fri Jul 10 11:10:10 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Chuang X-Patchwork-Id: 11656267 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 2E629618 for ; Fri, 10 Jul 2020 11:09:29 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 110172077D for ; Fri, 10 Jul 2020 11:09:29 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="ndy1tJ6F" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727059AbgGJLJ2 (ORCPT ); Fri, 10 Jul 2020 07:09:28 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41150 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726725AbgGJLJ1 (ORCPT ); Fri, 10 Jul 2020 07:09:27 -0400 Received: from mail-pg1-x542.google.com (mail-pg1-x542.google.com [IPv6:2607:f8b0:4864:20::542]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 87B33C08C5CE; Fri, 10 Jul 2020 04:09:27 -0700 (PDT) Received: by mail-pg1-x542.google.com with SMTP id l63so2374060pge.12; Fri, 10 Jul 2020 04:09:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=ge6tP7aJVA2/arYXridWtv60L0GDRBud+3BiIv4iGwU=; b=ndy1tJ6FUeK9nFenN0cCeY/pzoN2bM+a5uOvvfZkluarKIZJG3/oGA5L0cfIPvpEeA 8r0CQvAXwFoZu3qtfitdpGhilU2/uSFamt9n+8IYg4wIrIUuY8iKeODTpG2O9jC0BKdF SMDEdNzXc7QaOlIz+1CImLRK8PmLURkQfxuGjQb4htN7/4o1BrA+0rA2cCuSI6014DAo AJa6nU7TIN6tocfIOzGYbM4scQVfUVVjT+BVCWSdwJ9IzJySvAfjk93zhrz6lLGycwSB juNIXBoNql4x9kkRUz8MTVpaaLQSYnjar7ffF7eALDVnoMINkArMCTSDULNLv1eRqgfH r1lA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=ge6tP7aJVA2/arYXridWtv60L0GDRBud+3BiIv4iGwU=; b=B/wGM8z82haGLI/kD0zAxTHo/LxI+3j0IUsE2U8y0eTg+Ib/FPO7ZyIUZy0gC9J9jX BZ9bt6hQqtQl7aTVwaeEgqHrq4fLz0iL0hQJ31r6TGIFOv8NxFqilEUqFrlbQZtc+Xzg 5ijwsEdz4vBmptrLurPrPoPjQE8+nzlfeubtO+7tGe4CNjkWOKenZYTgpQ2syTXNYu2Z AjriYvFDSCoLSSKNF4okmeqt9rDxI1f0of0tW/wOZxwn0EDIIWAte9hwtiG+oulbtG5o qilxz/BB5A4TVCBTYAxAtISH5jBrPezMRDIdPga3N3MKsBVRArYAAX7RHkB89qnpFARp nPLA== X-Gm-Message-State: AOAM532fbeyUH59fz+EK7NWsz8cBNM7hSUDzkePzaujicNitNrmZ/Pos QceAHkZKP2YhKFI5zZoP1jo= X-Google-Smtp-Source: ABdhPJzSpMVwQrKH6DooHAi6R2iQnhUlH8zT3quDLCPYiMmXpHoaYLoepA6KUHMqrdV4ZULbKsQMnA== X-Received: by 2002:a62:4e44:: with SMTP id c65mr26530826pfb.283.1594379367138; Fri, 10 Jul 2020 04:09:27 -0700 (PDT) Received: from gli-arch.genesyslogic.com.tw (60-251-58-169.HINET-IP.hinet.net. [60.251.58.169]) by smtp.gmail.com with ESMTPSA id m1sm5211496pjy.0.2020.07.10.04.09.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 10 Jul 2020 04:09:26 -0700 (PDT) From: Ben Chuang To: adrian.hunter@intel.com, ulf.hansson@linaro.org Cc: linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, ben.chuang@genesyslogic.com.tw, takahiro.akashi@linaro.org, greg.tu@genesyslogic.com.tw, Ben Chuang Subject: [RFC PATCH V3 08/21] mmc: sdhci: add a kernel configuration for enabling UHS-II support Date: Fri, 10 Jul 2020 19:10:10 +0800 Message-Id: <20200710111010.29345-1-benchuanggli@gmail.com> X-Mailer: git-send-email 2.27.0 MIME-Version: 1.0 Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org From: AKASHI Takahiro This kernel configuration, CONFIG_MMC_SDHCI_UHS2, will be used in the following commits to indicate UHS-II specific code in sdhci controllers. Signed-off-by: Ben Chuang Signed-off-by: AKASHI Takahiro --- drivers/mmc/host/Kconfig | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 3b706af35ec3..ffeef38264c0 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -89,6 +89,15 @@ config MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER This is the case for the Nintendo Wii SDHCI. +config MMC_SDHCI_UHS2 + tristate "UHS2 support on SDHCI controller" + depends on MMC_SDHCI + help + This option is selected by SDHCI controller drivers that want to + support UHS2-capable devices. + + If you have a controller with this feature, say Y or M here. + config MMC_SDHCI_PCI tristate "SDHCI support on PCI bus" depends on MMC_SDHCI && PCI From patchwork Fri Jul 10 11:10:21 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Chuang X-Patchwork-Id: 11656269 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C2CB013B6 for ; Fri, 10 Jul 2020 11:09:41 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 999742078D for ; Fri, 10 Jul 2020 11:09:41 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="QUzNqglx" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726965AbgGJLJl (ORCPT ); Fri, 10 Jul 2020 07:09:41 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41182 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726725AbgGJLJk (ORCPT ); Fri, 10 Jul 2020 07:09:40 -0400 Received: from mail-pj1-x1042.google.com (mail-pj1-x1042.google.com [IPv6:2607:f8b0:4864:20::1042]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8408FC08C5CE; Fri, 10 Jul 2020 04:09:40 -0700 (PDT) Received: by mail-pj1-x1042.google.com with SMTP id ch3so2467966pjb.5; Fri, 10 Jul 2020 04:09:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=xrjk59egYvJ8GHaDhNEmPkttWVMBNW7KFE/O0I7RbgU=; b=QUzNqglxDyl3W9xbqV8HFvms4cTt5/YRCkZS92phePxV51mPGY+TrJlA9ypsn4OmZC lCJ+pedP1VdzY6ARlSGgCFTdM6VUCNZVNed1X1SFPiKUTE+si9US1A/mLiVb34Mbswkv V94vIPJnktj/GfcL+SDqgaE2jkT5L9gUaPzby5zkQduwJkJa0oeih8lJUVQjsVizxAHX 4AZ5pLZUUeiIr+irJkUpIXV6QxsMSnUoRRDr/CDol15FoC+stLiLtvANhvSQ6iQULYx9 jHNOAdd7NWylU00scfEoMWeR0uOL3pbmXARwa2i2b0x3fqmTL0etScB8irDGnkn+Dznm Km5g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=xrjk59egYvJ8GHaDhNEmPkttWVMBNW7KFE/O0I7RbgU=; b=DXFgI+1wXrKbpxuO4nWn8maA2j++386XiSH/IvciVG6FbOWGJPLr6bFo/0CXrHnPvs W2c2Dg0C9BzZnM2JDsdRpVWulqQzFQ8IpyPWhcVFABp/D0RZAEYocP+MRwmirMivyBmC nqNNJS8FchnGL2rzGwS2VPHah1hCBP5GHIy7ffKyoUBJgwESBD8AhTLL5OwARsgkD1os 7ahQhlx+br2SaGpskaMTOyMjG+gQ5IIpttxyLk/gnZfSZuzajuHLH78R6jTcdNXPNW3C JNUVmzMpxS7Ion0wwxyoSN9O0L2zPGVkwBs5Ij7H69+bsQhGR3ABaFEIQ7KLUBJmEANM iKBg== X-Gm-Message-State: AOAM531z0bIpLqSMFkzi6yYt7PJb4V+gyQ4xEluVQkAeXzxeocS5BMjt UICY8Jn+Mw9d7smft5b7DW4= X-Google-Smtp-Source: ABdhPJw/a5gbf91VCcLli/FguBYGyagoU4SbODthswhegCQysjUdJGCPBFwA+LM4Fwyh2fZukwLeyQ== X-Received: by 2002:a17:90a:d507:: with SMTP id t7mr5164493pju.193.1594379379647; Fri, 10 Jul 2020 04:09:39 -0700 (PDT) Received: from gli-arch.genesyslogic.com.tw (60-251-58-169.HINET-IP.hinet.net. [60.251.58.169]) by smtp.gmail.com with ESMTPSA id y65sm5630152pfb.75.2020.07.10.04.09.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 10 Jul 2020 04:09:39 -0700 (PDT) From: Ben Chuang To: adrian.hunter@intel.com, ulf.hansson@linaro.org Cc: linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, ben.chuang@genesyslogic.com.tw, takahiro.akashi@linaro.org, greg.tu@genesyslogic.com.tw, Ben Chuang Subject: [RFC PATCH V3 09/21] mmc: sdhci: add UHS-II related definitions in headers Date: Fri, 10 Jul 2020 19:10:21 +0800 Message-Id: <20200710111021.29397-1-benchuanggli@gmail.com> X-Mailer: git-send-email 2.27.0 MIME-Version: 1.0 Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org From: AKASHI Takahiro Add UHS-II related definitions in shdci.h and sdhci-uhs2.h. Signed-off-by: Ben Chuang Signed-off-by: AKASHI Takahiro --- drivers/mmc/host/sdhci-uhs2.h | 215 ++++++++++++++++++++++++++++++++++ drivers/mmc/host/sdhci.h | 91 +++++++++++++- 2 files changed, 305 insertions(+), 1 deletion(-) create mode 100644 drivers/mmc/host/sdhci-uhs2.h diff --git a/drivers/mmc/host/sdhci-uhs2.h b/drivers/mmc/host/sdhci-uhs2.h new file mode 100644 index 000000000000..a7f53f95d69a --- /dev/null +++ b/drivers/mmc/host/sdhci-uhs2.h @@ -0,0 +1,215 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * linux/drivers/mmc/host/sdhci-uhs2.h - Secure Digital Host Controller + * Interface driver + * + * Header file for Host Controller UHS2 related registers and I/O accessors. + * + * Copyright (C) 2014 Intel Corp, All Rights Reserved. + */ +#ifndef __SDHCI_UHS2_H +#define __SDHCI_UHS2_H + +#include +#include +#include + +/* + * UHS-II Controller registers + * 0x74 preset in sdhci.h + * 0x80 + * 0x84-0xB4 + * 0xB8-0xCF + * 0xE0-0xE7 + */ +/* UHS2 */ +#define SDHCI_UHS2_BLOCK_SIZE 0x80 +#define SDHCI_UHS2_MAKE_BLKSZ(dma, blksz) \ + ((((dma) & 0x7) << 12) | ((blksz) & 0xFFF)) + +#define SDHCI_UHS2_BLOCK_COUNT 0x84 + +#define SDHCI_UHS2_CMD_PACKET 0x88 +#define SDHCI_UHS2_CMD_PACK_MAX_LEN 20 + +#define SDHCI_UHS2_TRANS_MODE 0x9C +#define SDHCI_UHS2_TRNS_DMA 0x0001 +#define SDHCI_UHS2_TRNS_BLK_CNT_EN 0x0002 +#define SDHCI_UHS2_TRNS_DATA_TRNS_WRT 0x0010 +#define SDHCI_UHS2_TRNS_BLK_BYTE_MODE 0x0020 +#define SDHCI_UHS2_TRNS_RES_R5 0x0040 +#define SDHCI_UHS2_TRNS_RES_ERR_CHECK_EN 0x0080 +#define SDHCI_UHS2_TRNS_RES_INT_DIS 0x0100 +#define SDHCI_UHS2_TRNS_WAIT_EBSY 0x4000 +#define SDHCI_UHS2_TRNS_2L_HD 0x8000 + +#define SDHCI_UHS2_COMMAND 0x9E +#define SDHCI_UHS2_COMMAND_SUB_CMD 0x0004 +#define SDHCI_UHS2_COMMAND_DATA 0x0020 +#define SDHCI_UHS2_COMMAND_TRNS_ABORT 0x0040 +#define SDHCI_UHS2_COMMAND_CMD12 0x0080 +#define SDHCI_UHS2_COMMAND_DORMANT 0x00C0 +#define SDHCI_UHS2_COMMAND_PACK_LEN_MASK 0x1F00 +#define SDHCI_UHS2_COMMAND_PACK_LEN_SHIFT 8 + +#define SDHCI_UHS2_RESPONSE 0xA0 +#define SDHCI_UHS2_RESPONSE_MAX_LEN 20 + +#define SDHCI_UHS2_MSG_SELECT 0xB4 +#define SDHCI_UHS2_MSG_SELECT_CURR 0x0 +#define SDHCI_UHS2_MSG_SELECT_ONE 0x1 +#define SDHCI_UHS2_MSG_SELECT_TWO 0x2 +#define SDHCI_UHS2_MSG_SELECT_THREE 0x3 + +#define SDHCI_UHS2_MSG 0xB8 + +#define SDHCI_UHS2_DEV_INT_STATUS 0xBC + +#define SDHCI_UHS2_DEV_SELECT 0xBE +#define SDHCI_UHS2_DEV_SELECT_DEV_SEL_MASK 0x0F +#define SDHCI_UHS2_DEV_SELECT_INT_MSG_EN 0x80 + +#define SDHCI_UHS2_DEV_INT_CODE 0xBF + +#define SDHCI_UHS2_SW_RESET 0xC0 +#define SDHCI_UHS2_SW_RESET_FULL 0x0001 +#define SDHCI_UHS2_SW_RESET_SD 0x0002 + +#define SDHCI_UHS2_TIMER_CTRL 0xC2 +#define SDHCI_UHS2_TIMER_CTRL_DEADLOCK_SHIFT 4 + +#define SDHCI_UHS2_ERR_INT_STATUS 0xC4 +#define SDHCI_UHS2_ERR_INT_STATUS_EN 0xC8 +#define SDHCI_UHS2_ERR_INT_SIG_EN 0xCC +#define SDHCI_UHS2_ERR_INT_STATUS_HEADER 0x00000001 +#define SDHCI_UHS2_ERR_INT_STATUS_RES 0x00000002 +#define SDHCI_UHS2_ERR_INT_STATUS_RETRY_EXP 0x00000004 +#define SDHCI_UHS2_ERR_INT_STATUS_CRC 0x00000008 +#define SDHCI_UHS2_ERR_INT_STATUS_FRAME 0x00000010 +#define SDHCI_UHS2_ERR_INT_STATUS_TID 0x00000020 +#define SDHCI_UHS2_ERR_INT_STATUS_UNRECOVER 0x00000080 +#define SDHCI_UHS2_ERR_INT_STATUS_EBUSY 0x00000100 +#define SDHCI_UHS2_ERR_INT_STATUS_ADMA 0x00008000 +#define SDHCI_UHS2_ERR_INT_STATUS_RES_TIMEOUT 0x00010000 +#define SDHCI_UHS2_ERR_INT_STATUS_DEADLOCK_TIMEOUT 0x00020000 +#define SDHCI_UHS2_ERR_INT_STATUS_VENDOR 0x08000000 +#define SDHCI_UHS2_ERR_INT_STATUS_MASK \ + (SDHCI_UHS2_ERR_INT_STATUS_HEADER | \ + SDHCI_UHS2_ERR_INT_STATUS_RES | \ + SDHCI_UHS2_ERR_INT_STATUS_RETRY_EXP | \ + SDHCI_UHS2_ERR_INT_STATUS_CRC | \ + SDHCI_UHS2_ERR_INT_STATUS_FRAME | \ + SDHCI_UHS2_ERR_INT_STATUS_TID | \ + SDHCI_UHS2_ERR_INT_STATUS_UNRECOVER | \ + SDHCI_UHS2_ERR_INT_STATUS_EBUSY | \ + SDHCI_UHS2_ERR_INT_STATUS_ADMA | \ + SDHCI_UHS2_ERR_INT_STATUS_RES_TIMEOUT | \ + SDHCI_UHS2_ERR_INT_STATUS_DEADLOCK_TIMEOUT) +#define SDHCI_UHS2_ERR_INT_STATUS_CMD_MASK \ + (SDHCI_UHS2_ERR_INT_STATUS_HEADER | \ + SDHCI_UHS2_ERR_INT_STATUS_RES | \ + SDHCI_UHS2_ERR_INT_STATUS_FRAME | \ + SDHCI_UHS2_ERR_INT_STATUS_TID | \ + SDHCI_UHS2_ERR_INT_STATUS_RES_TIMEOUT) +/* CRC Error occurs during a packet receiving */ +#define SDHCI_UHS2_ERR_INT_STATUS_DATA_MASK \ + (SDHCI_UHS2_ERR_INT_STATUS_RETRY_EXP | \ + SDHCI_UHS2_ERR_INT_STATUS_CRC | \ + SDHCI_UHS2_ERR_INT_STATUS_UNRECOVER | \ + SDHCI_UHS2_ERR_INT_STATUS_EBUSY | \ + SDHCI_UHS2_ERR_INT_STATUS_ADMA | \ + SDHCI_UHS2_ERR_INT_STATUS_DEADLOCK_TIMEOUT) + +#define SDHCI_UHS2_SET_PTR 0xE0 +#define SDHCI_UHS2_GEN_SET_POWER_LOW 0x0001 +#define SDHCI_UHS2_GEN_SET_N_LANES_POS 8 +#define SDHCI_UHS2_GEN_SET_2L_FD_HD 0x0 +#define SDHCI_UHS2_GEN_SET_2D1U_FD 0x2 +#define SDHCI_UHS2_GEN_SET_1D2U_FD 0x3 +#define SDHCI_UHS2_GEN_SET_2D2U_FD 0x4 + +#define SDHCI_UHS2_PHY_SET_SPEED_POS 6 +#define SDHCI_UHS2_PHY_SET_HIBER_EN 0x00008000 +#define SDHCI_UHS2_PHY_SET_N_LSS_SYN_MASK 0x000F0000 +#define SDHCI_UHS2_PHY_SET_N_LSS_SYN_POS 16 +#define SDHCI_UHS2_PHY_SET_N_LSS_DIR_MASK 0x00F00000 +#define SDHCI_UHS2_PHY_SET_N_LSS_DIR_POS 20 + +#define SDHCI_UHS2_TRAN_SET_N_FCU_MASK 0x0000FF00 +#define SDHCI_UHS2_TRAN_SET_N_FCU_POS 8 +#define SDHCI_UHS2_TRAN_SET_RETRY_CNT_MASK 0x00030000 +#define SDHCI_UHS2_TRAN_SET_RETRY_CNT_POS 16 + +#define SDHCI_UHS2_TRAN_SET_1_N_DAT_GAP_MASK 0x000000FF + +#define SDHCI_UHS2_HOST_CAPS_PTR 0xE2 +#define SDHCI_UHS2_HOST_CAPS_GEN_OFFSET 0 +#define SDHCI_UHS2_HOST_CAPS_GEN_DAP_MASK 0x0000000F +#define SDHCI_UHS2_HOST_CAPS_GEN_GAP_MASK 0x000000F0 +#define SDHCI_UHS2_HOST_CAPS_GEN_GAP(gap) ((gap) * 360) +#define SDHCI_UHS2_HOST_CAPS_GEN_GAP_SHIFT 4 +#define SDHCI_UHS2_HOST_CAPS_GEN_LANE_MASK 0x00003F00 +#define SDHCI_UHS2_HOST_CAPS_GEN_LANE_SHIFT 8 +#define SDHCI_UHS2_HOST_CAPS_GEN_2L_HD_FD 1 +#define SDHCI_UHS2_HOST_CAPS_GEN_2D1U_FD 2 +#define SDHCI_UHS2_HOST_CAPS_GEN_1D2U_FD 4 +#define SDHCI_UHS2_HOST_CAPS_GEN_2D2U_FD 8 +#define SDHCI_UHS2_HOST_CAPS_GEN_ADDR_64 0x00004000 +#define SDHCI_UHS2_HOST_CAPS_GEN_BOOT 0x00008000 +#define SDHCI_UHS2_HOST_CAPS_GEN_DEV_TYPE_MASK 0x00030000 +#define SDHCI_UHS2_HOST_CAPS_GEN_DEV_TYPE_SHIFT 16 +#define SDHCI_UHS2_HOST_CAPS_GEN_DEV_TYPE_RMV 0 +#define SDHCI_UHS2_HOST_CAPS_GEN_DEV_TYPE_EMB 1 +#define SDHCI_UHS2_HOST_CAPS_GEN_DEV_TYPE_EMB_RMV 2 +#define SDHCI_UHS2_HOST_CAPS_GEN_NUM_DEV_MASK 0x003C0000 +#define SDHCI_UHS2_HOST_CAPS_GEN_NUM_DEV_SHIFT 18 +#define SDHCI_UHS2_HOST_CAPS_GEN_BUS_TOPO_MASK 0x00C00000 +#define SDHCI_UHS2_HOST_CAPS_GEN_BUS_TOPO_SHIFT 22 +#define SDHCI_UHS2_HOST_CAPS_GEN_BUS_TOPO_P2P 0 +#define SDHCI_UHS2_HOST_CAPS_GEN_BUS_TOPO_RING 1 +#define SDHCI_UHS2_HOST_CAPS_GEN_BUS_TOPO_HUB 2 +#define SDHCI_UHS2_HOST_CAPS_GEN_BUS_TOPO_HUB_RING 3 + +#define SDHCI_UHS2_HOST_CAPS_PHY_OFFSET 4 +#define SDHCI_UHS2_HOST_CAPS_PHY_REV_MASK 0x0000003F +#define SDHCI_UHS2_HOST_CAPS_PHY_RANGE_MASK 0x000000C0 +#define SDHCI_UHS2_HOST_CAPS_PHY_RANGE_SHIFT 6 +#define SDHCI_UHS2_HOST_CAPS_PHY_RANGE_A 0 +#define SDHCI_UHS2_HOST_CAPS_PHY_RANGE_B 1 +#define SDHCI_UHS2_HOST_CAPS_PHY_N_LSS_SYN_MASK 0x000F0000 +#define SDHCI_UHS2_HOST_CAPS_PHY_N_LSS_SYN_SHIFT 16 +#define SDHCI_UHS2_HOST_CAPS_PHY_N_LSS_DIR_MASK 0x00F00000 +#define SDHCI_UHS2_HOST_CAPS_PHY_N_LSS_DIR_SHIFT 20 +#define SDHCI_UHS2_HOST_CAPS_TRAN_OFFSET 8 +#define SDHCI_UHS2_HOST_CAPS_TRAN_LINK_REV_MASK 0x0000003F +#define SDHCI_UHS2_HOST_CAPS_TRAN_N_FCU_MASK 0x0000FF00 +#define SDHCI_UHS2_HOST_CAPS_TRAN_N_FCU_SHIFT 8 +#define SDHCI_UHS2_HOST_CAPS_TRAN_HOST_TYPE_MASK 0x00070000 +#define SDHCI_UHS2_HOST_CAPS_TRAN_HOST_TYPE_SHIFT 16 +#define SDHCI_UHS2_HOST_CAPS_TRAN_BLK_LEN_MASK 0xFFF00000 +#define SDHCI_UHS2_HOST_CAPS_TRAN_BLK_LEN_SHIFT 20 + +#define SDHCI_UHS2_HOST_CAPS_TRAN_1_OFFSET 12 +#define SDHCI_UHS2_HOST_CAPS_TRAN_1_N_DATA_GAP_MASK 0x000000FF + +#define SDHCI_UHS2_TEST_PTR 0xE4 +#define SDHCI_UHS2_TEST_ERR_HEADER 0x00000001 +#define SDHCI_UHS2_TEST_ERR_RES 0x00000002 +#define SDHCI_UHS2_TEST_ERR_RETRY_EXP 0x00000004 +#define SDHCI_UHS2_TEST_ERR_CRC 0x00000008 +#define SDHCI_UHS2_TEST_ERR_FRAME 0x00000010 +#define SDHCI_UHS2_TEST_ERR_TID 0x00000020 +#define SDHCI_UHS2_TEST_ERR_UNRECOVER 0x00000080 +#define SDHCI_UHS2_TEST_ERR_EBUSY 0x00000100 +#define SDHCI_UHS2_TEST_ERR_ADMA 0x00008000 +#define SDHCI_UHS2_TEST_ERR_RES_TIMEOUT 0x00010000 +#define SDHCI_UHS2_TEST_ERR_DEADLOCK_TIMEOUT 0x00020000 +#define SDHCI_UHS2_TEST_ERR_VENDOR 0x08000000 + +#define SDHCI_UHS2_EMBED_CTRL 0xE6 +#define SDHCI_UHS2_VENDOR 0xE8 + +void sdhci_uhs2_reset(struct sdhci_host *host, u16 mask); +void sdhci_uhs2_clear_set_irqs(struct sdhci_host *host, u32 clear, u32 set); + +#endif /* __SDHCI_UHS2_H */ diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 0008bbd27127..ecf55394ea46 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -43,8 +43,27 @@ #define SDHCI_TRNS_READ 0x10 #define SDHCI_TRNS_MULTI 0x20 +/* + * Defined in Host Version 4.10. + * 1 - R5 (SDIO) + * 0 - R1 (Memory) + */ +#define SDHCI_TRNS_RES_TYPE 0x40 +#define SDHCI_TRNS_RES_ERR_CHECK 0x80 +#define SDHCI_TRNS_RES_INT_DIS 0x0100 + #define SDHCI_COMMAND 0x0E #define SDHCI_CMD_RESP_MASK 0x03 + +/* + * Host Version 4.10 adds this bit to distinguish a main command or + * sub command. + * CMD53(SDIO) - main command + * CMD52(SDIO) - sub command which doesn't have data block or doesn't + * indicate busy. + */ +#define SDHCI_CMD_SUB_CMD 0x04 + #define SDHCI_CMD_CRC 0x08 #define SDHCI_CMD_INDEX 0x10 #define SDHCI_CMD_DATA 0x20 @@ -60,11 +79,19 @@ #define SDHCI_RESPONSE 0x10 +#define SDHCI_RESPONSE_CM_TRAN_ABORT_OFFSET 0x10 +#define SDHCI_RESPONSE_CM_TRAN_ABORT_SIZE 4 +#define SDHCI_RESPONSE_SD_TRAN_ABORT_OFFSET 0x18 +#define SDHCI_RESPONSE_SD_TRAN_ABORT_SIZE 8 + #define SDHCI_BUFFER 0x20 #define SDHCI_PRESENT_STATE 0x24 #define SDHCI_CMD_INHIBIT 0x00000001 #define SDHCI_DATA_INHIBIT 0x00000002 + +#define SDHCI_DATA_HIGH_LVL_MASK 0x000000F0 + #define SDHCI_DOING_WRITE 0x00000100 #define SDHCI_DOING_READ 0x00000200 #define SDHCI_SPACE_AVAILABLE 0x00000400 @@ -80,6 +107,13 @@ #define SDHCI_DATA_0_LVL_MASK 0x00100000 #define SDHCI_CMD_LVL 0x01000000 +#define SDHCI_HOST_REGULATOR_STABLE 0x02000000 +#define SDHCI_CMD_NOT_ISSUE_ERR 0x08000000 +#define SDHCI_SUB_CMD_STATUS 0x10000000 +#define SDHCI_UHS2_IN_DORMANT_STATE 0x20000000 +#define SDHCI_UHS2_LANE_SYNC 0x40000000 +#define SDHCI_UHS2_IF_DETECT 0x80000000 + #define SDHCI_HOST_CONTROL 0x28 #define SDHCI_CTRL_LED 0x01 #define SDHCI_CTRL_4BITBUS 0x02 @@ -100,6 +134,11 @@ #define SDHCI_POWER_300 0x0C #define SDHCI_POWER_330 0x0E +/* VDD2 - UHS2 */ +#define SDHCI_VDD2_POWER_ON 0x10 +#define SDHCI_VDD2_POWER_180 0xA0 +#define SDHCI_VDD2_POWER_120 0x80 + #define SDHCI_BLOCK_GAP_CONTROL 0x2A #define SDHCI_WAKE_UP_CONTROL 0x2B @@ -110,7 +149,7 @@ #define SDHCI_CLOCK_CONTROL 0x2C #define SDHCI_DIVIDER_SHIFT 8 #define SDHCI_DIVIDER_HI_SHIFT 6 -#define SDHCI_DIV_MASK 0xFF +#define SDHCI_DIV_MASK 0xFF #define SDHCI_DIV_MASK_LEN 8 #define SDHCI_DIV_HI_MASK 0x300 #define SDHCI_PROG_CLOCK_MODE 0x0020 @@ -139,6 +178,10 @@ #define SDHCI_INT_CARD_REMOVE 0x00000080 #define SDHCI_INT_CARD_INT 0x00000100 #define SDHCI_INT_RETUNE 0x00001000 + +/* Host Version 4.10 */ +#define SDHCI_INT_FX_EVENT 0x00002000 + #define SDHCI_INT_CQE 0x00004000 #define SDHCI_INT_ERROR 0x00008000 #define SDHCI_INT_TIMEOUT 0x00010000 @@ -152,6 +195,9 @@ #define SDHCI_INT_AUTO_CMD_ERR 0x01000000 #define SDHCI_INT_ADMA_ERROR 0x02000000 +/* Host Version 4.0 */ +#define SDHCI_INT_RESPONSE_ERROR 0x08000000 + #define SDHCI_INT_NORMAL_MASK 0x00007FFF #define SDHCI_INT_ERROR_MASK 0xFFFF8000 @@ -178,6 +224,9 @@ #define SDHCI_AUTO_CMD_END_BIT 0x00000008 #define SDHCI_AUTO_CMD_INDEX 0x00000010 +/* Host Version 4.10 */ +#define SDHCI_ACMD_RESPONSE_ERROR 0x0020 + #define SDHCI_HOST_CONTROL2 0x3E #define SDHCI_CTRL_UHS_MASK 0x0007 #define SDHCI_CTRL_UHS_SDR12 0x0000 @@ -186,6 +235,7 @@ #define SDHCI_CTRL_UHS_SDR104 0x0003 #define SDHCI_CTRL_UHS_DDR50 0x0004 #define SDHCI_CTRL_HS400 0x0005 /* Non-standard */ +#define SDHCI_CTRL_UHS_2 0x0007 /* UHS-2 */ #define SDHCI_CTRL_VDD_180 0x0008 #define SDHCI_CTRL_DRV_TYPE_MASK 0x0030 #define SDHCI_CTRL_DRV_TYPE_B 0x0000 @@ -194,9 +244,12 @@ #define SDHCI_CTRL_DRV_TYPE_D 0x0030 #define SDHCI_CTRL_EXEC_TUNING 0x0040 #define SDHCI_CTRL_TUNED_CLK 0x0080 +#define SDHCI_CTRL_UHS2_INTERFACE_EN 0x0100 /* UHS-2 */ +#define SDHCI_CTRL_ADMA2_LEN_MODE 0x0400 #define SDHCI_CMD23_ENABLE 0x0800 #define SDHCI_CTRL_V4_MODE 0x1000 #define SDHCI_CTRL_64BIT_ADDR 0x2000 +#define SDHCI_CTRL_ASYNC_INT_EN 0x4000 #define SDHCI_CTRL_PRESET_VAL_ENABLE 0x8000 #define SDHCI_CAPABILITIES 0x40 @@ -217,11 +270,13 @@ #define SDHCI_CAN_VDD_180 0x04000000 #define SDHCI_CAN_64BIT_V4 0x08000000 #define SDHCI_CAN_64BIT 0x10000000 +#define SDHCI_CAN_ASYNC_INT 0x20000000 #define SDHCI_CAPABILITIES_1 0x44 #define SDHCI_SUPPORT_SDR50 0x00000001 #define SDHCI_SUPPORT_SDR104 0x00000002 #define SDHCI_SUPPORT_DDR50 0x00000004 +#define SDHCI_SUPPORT_UHS2 0x00000008 /* UHS-2 support */ #define SDHCI_DRIVER_TYPE_A 0x00000010 #define SDHCI_DRIVER_TYPE_C 0x00000020 #define SDHCI_DRIVER_TYPE_D 0x00000040 @@ -230,19 +285,28 @@ #define SDHCI_RETUNING_MODE_MASK GENMASK(15, 14) #define SDHCI_CLOCK_MUL_MASK GENMASK(23, 16) #define SDHCI_CAN_DO_ADMA3 0x08000000 +#define SDHCI_SUPPORT_VDD2_180 0x10000000 /* UHS-2 1.8V VDD2 */ +#define SDHCI_RSVD_FOR_VDD2 0x20000000 /* Rsvd for future VDD2 */ #define SDHCI_SUPPORT_HS400 0x80000000 /* Non-standard */ #define SDHCI_MAX_CURRENT 0x48 +#define SDHCI_MAX_CURRENT_1 0x4C #define SDHCI_MAX_CURRENT_LIMIT GENMASK(7, 0) #define SDHCI_MAX_CURRENT_330_MASK GENMASK(7, 0) #define SDHCI_MAX_CURRENT_300_MASK GENMASK(15, 8) #define SDHCI_MAX_CURRENT_180_MASK GENMASK(23, 16) +#define SDHCI_MAX_CURRENT_VDD2_180_MASK GENMASK(7, 0) /* UHS2 */ #define SDHCI_MAX_CURRENT_MULTIPLIER 4 /* 4C-4F reserved for more max current */ #define SDHCI_SET_ACMD12_ERROR 0x50 +/* Host Version 4.10 */ +#define SDHCI_SET_ACMD_RESPONSE_ERROR 0x20 #define SDHCI_SET_INT_ERROR 0x52 +/* Host Version 4.10 */ +#define SDHCI_SET_INT_TUNING_ERROR 0x0400 +#define SDHCI_SET_INT_RESPONSE_ERROR 0x0800 #define SDHCI_ADMA_ERROR 0x54 @@ -259,10 +323,16 @@ #define SDHCI_PRESET_FOR_SDR104 0x6C #define SDHCI_PRESET_FOR_DDR50 0x6E #define SDHCI_PRESET_FOR_HS400 0x74 /* Non-standard */ + +/* TODO: 0x74 is used for UHS2 in 4.10. How about HS400? */ +/* UHS2 */ +#define SDHCI_PRESET_FOR_UHS2 0x74 #define SDHCI_PRESET_DRV_MASK GENMASK(15, 14) #define SDHCI_PRESET_CLKGEN_SEL BIT(10) #define SDHCI_PRESET_SDCLK_FREQ_MASK GENMASK(9, 0) +#define SDHCI_ADMA3_ADDRESS 0x78 + #define SDHCI_SLOT_INT_STATUS 0xFC #define SDHCI_HOST_VERSION 0xFE @@ -653,6 +723,25 @@ struct sdhci_ops { void (*dump_vendor_regs)(struct sdhci_host *host); }; +struct sdhci_uhs2_ops { + /* UHS-2 support */ + void (*reset)(struct sdhci_host *host, u16 mask); + void (*set_timeout)(struct sdhci_host *host); + void (*set_transfer_mode)(struct sdhci_host *host, + struct mmc_command *cmd); + void (*send_command)(struct sdhci_host *host, + struct mmc_command *cmd); + void (*finish_command)(struct sdhci_host *host); + void (*do_set_ios)(struct sdhci_host *host, struct mmc_ios *ios); + int (*do_detect_init)(struct sdhci_host *host); + int (*do_set_reg)(struct sdhci_host *host, enum uhs2_act act); + void (*irq)(struct sdhci_host *host); + int (*add_host)(struct sdhci_host *host, u32 caps1); + void (*remove_host)(struct sdhci_host *host, int dead); +}; + +extern struct sdhci_uhs2_ops sdhci_uhs2_ops; + #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS static inline void sdhci_writel(struct sdhci_host *host, u32 val, int reg) From patchwork Fri Jul 10 11:10:34 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Chuang X-Patchwork-Id: 11656271 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id A3462618 for ; Fri, 10 Jul 2020 11:09:52 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 89F442078B for ; Fri, 10 Jul 2020 11:09:52 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="JjzbtFfd" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726828AbgGJLJw (ORCPT ); Fri, 10 Jul 2020 07:09:52 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41214 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726369AbgGJLJv (ORCPT ); Fri, 10 Jul 2020 07:09:51 -0400 Received: from mail-pj1-x1041.google.com (mail-pj1-x1041.google.com [IPv6:2607:f8b0:4864:20::1041]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8B9E1C08C5CE; Fri, 10 Jul 2020 04:09:51 -0700 (PDT) Received: by mail-pj1-x1041.google.com with SMTP id md7so2472867pjb.1; Fri, 10 Jul 2020 04:09:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=PXSanc4gimjYlUQVCO8YZAntIkVCDxhB7ClBTFnZorw=; b=JjzbtFfd0S1t2JHxMXH1vT3ZeUndEh+jspq5zoDSJ8cp4TLYqUJxdkA0MOsdcRGieG DKhW+1Unk9xcAqCbc7UYTcyfmdzzD9P7DBJhUP8Gc4ZR16FiubtfODz4RREbEXovvMQe bG9imrqQpFhFle+JCcvi0AMkgkRS1fCRH83O/J2fDdVk9L5qn2QsnhLHa8rk87brxWbs oyBKc3fv+KYlG45JhgP/6XzB6TlSnOrlNFN2fF27dOCq1aoWHoRbWn387HDK/Z5RsHKk Gr9t6+vnIw7Qd253wqhukcS+lqH83Up3db+uojDVF9a2xlXLLN++mAvkfg/FCV5Qxr2S zDXg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=PXSanc4gimjYlUQVCO8YZAntIkVCDxhB7ClBTFnZorw=; b=bZOqj+wcGueKQZNqsYb7h7RRz+2yby70QhlSoGQ2gvpII19/kAJM4nrRvfWKabw9p2 wKBT5bKFuN4s/q+xYCVCeXacRa6Ceg/1dEMSpheJfipiPv3ZaX2AExntSHBWykAGSao2 Wym6puBMJLR+/HPhUMPUMCjtq1olJuaxLsxuL1W1Itzw5DkEZ2/MoFo9h4YZGv82DSEl u3YxhqKYyXDG1FCAeLNl0I8P1ETRu8MKp6RiERh3JIkekEoj/GrTNUnLIf21xqxD+dOU 7vDueb91zmBKPD6Oyf+8SVQ32RVhGLi3zx5txApz/C3gSZXoMLtxSaqRmZas2nC+Q5KJ 2U0w== X-Gm-Message-State: AOAM532jxREmjB1pBCXUYc9Bb/VdILn3ED3eVV1fm/0PDaVqEsYmyMKh qaihp0Y3btwoWZ2wxzfoNEA= X-Google-Smtp-Source: ABdhPJz6NVHLu0FfmzD2WI/1w5266CSAJ4wTlZf2lvMvF2WEIqfMcJgXC26WssCLV6no267l9DXpHw== X-Received: by 2002:a17:90b:188d:: with SMTP id mn13mr5227812pjb.229.1594379391202; Fri, 10 Jul 2020 04:09:51 -0700 (PDT) Received: from gli-arch.genesyslogic.com.tw (60-251-58-169.HINET-IP.hinet.net. [60.251.58.169]) by smtp.gmail.com with ESMTPSA id b4sm5619415pfo.137.2020.07.10.04.09.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 10 Jul 2020 04:09:50 -0700 (PDT) From: Ben Chuang To: adrian.hunter@intel.com, ulf.hansson@linaro.org Cc: linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, ben.chuang@genesyslogic.com.tw, takahiro.akashi@linaro.org, greg.tu@genesyslogic.com.tw, Ben Chuang Subject: [RFC PATCH V3 10/21] mmc: sdhci: UHS-II support, dump UHS-II registers Date: Fri, 10 Jul 2020 19:10:34 +0800 Message-Id: <20200710111034.29456-1-benchuanggli@gmail.com> X-Mailer: git-send-email 2.27.0 MIME-Version: 1.0 Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org From: AKASHI Takahiro Dump UHS-II specific registers, if available, in sdhci_dumpregs() for informative/debugging use. Signed-off-by: Ben Chuang Signed-off-by: AKASHI Takahiro --- drivers/mmc/host/sdhci.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 37b1158c1c0c..c2f6923d296c 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -111,6 +111,30 @@ void sdhci_dumpregs(struct sdhci_host *host) } } + if (IS_ENABLED(CONFIG_MMC_SDHCI_UHS2) && + host->mmc && host->mmc->flags & MMC_UHS2_SUPPORT) { + SDHCI_DUMP("==================== UHS2 ==================\n"); + SDHCI_DUMP("Blk Size: 0x%08x | Blk Cnt: 0x%08x\n", + sdhci_readw(host, SDHCI_UHS2_BLOCK_SIZE), + sdhci_readl(host, SDHCI_UHS2_BLOCK_COUNT)); + SDHCI_DUMP("Cmd: 0x%08x | Trn mode: 0x%08x\n", + sdhci_readw(host, SDHCI_UHS2_COMMAND), + sdhci_readw(host, SDHCI_UHS2_TRANS_MODE)); + SDHCI_DUMP("Int Stat: 0x%08x | Dev Sel : 0x%08x\n", + sdhci_readw(host, SDHCI_UHS2_DEV_INT_STATUS), + sdhci_readb(host, SDHCI_UHS2_DEV_SELECT)); + SDHCI_DUMP("Dev Int Code: 0x%08x\n", + sdhci_readb(host, SDHCI_UHS2_DEV_INT_CODE)); + SDHCI_DUMP("Reset: 0x%08x | Timer: 0x%08x\n", + sdhci_readw(host, SDHCI_UHS2_SW_RESET), + sdhci_readw(host, SDHCI_UHS2_TIMER_CTRL)); + SDHCI_DUMP("ErrInt: 0x%08x | ErrIntEn: 0x%08x\n", + sdhci_readl(host, SDHCI_UHS2_ERR_INT_STATUS), + sdhci_readl(host, SDHCI_UHS2_ERR_INT_STATUS_EN)); + SDHCI_DUMP("ErrSigEn: 0x%08x\n", + sdhci_readl(host, SDHCI_UHS2_ERR_INT_SIG_EN)); + } + if (host->ops->dump_vendor_regs) host->ops->dump_vendor_regs(host); From patchwork Fri Jul 10 11:10:44 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Chuang X-Patchwork-Id: 11656273 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 3260A13B6 for ; Fri, 10 Jul 2020 11:10:04 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 182022078B for ; Fri, 10 Jul 2020 11:10:04 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="pvyejGdj" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727827AbgGJLKC (ORCPT ); Fri, 10 Jul 2020 07:10:02 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41240 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726369AbgGJLKB (ORCPT ); Fri, 10 Jul 2020 07:10:01 -0400 Received: from mail-pg1-x543.google.com (mail-pg1-x543.google.com [IPv6:2607:f8b0:4864:20::543]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8FD0EC08C5CE; Fri, 10 Jul 2020 04:10:01 -0700 (PDT) Received: by mail-pg1-x543.google.com with SMTP id e18so2392210pgn.7; Fri, 10 Jul 2020 04:10:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=BZxklyfbFjwycZmQoHtOvFDmfd5AMpO1Q2JX3/+fCok=; b=pvyejGdj/dmYs6plL0dYgkkAZTOXDXjujnAdH+JWsZRUGjbXUu3Uko24HxPrJBdqat aB0rXNsWAr7Pioc9nxQvES150TJJ5D4I2thRjwS/lV8ySMmsGlMdOC6alGQHR8ROPHqz zTCTccVQAnuFuEkzlaASPefmTcfvEy7md2P6n1D8TFBePCnpzBlh48yhhDQFtu8jJ3KZ T2tLkQF4jFsrQjIzzi4QuSmnJ4FynFkYEJYyY/iUcrq4BaSWes2ZyppOwHPFVdzN3AZu +ryS9ripmNncd44fjqOYrZeVUIky0Z4Wzb2kEU91pQiN5xGvJbkogLeZiYlbDUGwVdaD aLLA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=BZxklyfbFjwycZmQoHtOvFDmfd5AMpO1Q2JX3/+fCok=; b=O1MbiOJ1ZPGCNodSWtZ29R8KPrYKtzlIqbdaNUJ3Bfi5KWAsPnj+46DWJpaDvNwtAW Rhsqgxre7aCQomPKO1sPintoGy7q4BNVT3BjFII+R/8SsdzNO7d17ZHoOVcFo3jvJ0+P paJQLOtkN56ft+2nu9I1RcROTjPAaSMUQM7reiE7h9RxjElOPlfd1Y0dRZ/yJO0fj725 hwW+oRKU9LtOx+8Ty9J6a/YEE91PAN/FzuVP/xDrM6aX/HjrFbeU9qhJLMRmahLhOV0y C+tSxf0CkvLh9JSmdPa3Z0mQPynz4TM2gj+9bGLZ1K7TaByQZ7/UxzidtVOfVm3Pd3Vc VMbA== X-Gm-Message-State: AOAM533d11zrvQDQt3bLzbFGUYW9XLf+LW7VB1jVNXdvSwuTtES3B9h8 bBePWpTrR5PR4/qZtMCZUstSv0/w X-Google-Smtp-Source: ABdhPJxXFtlTLad17FUpQo+DemvmoR9Qd6xH7xe2ehhYdAG8Du9ZkfDrBj/K04SfqGHpRScVG7wmTQ== X-Received: by 2002:a63:e00c:: with SMTP id e12mr58217885pgh.413.1594379401209; Fri, 10 Jul 2020 04:10:01 -0700 (PDT) Received: from gli-arch.genesyslogic.com.tw (60-251-58-169.HINET-IP.hinet.net. [60.251.58.169]) by smtp.gmail.com with ESMTPSA id x8sm5437293pfn.61.2020.07.10.04.09.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 10 Jul 2020 04:10:00 -0700 (PDT) From: Ben Chuang To: adrian.hunter@intel.com, ulf.hansson@linaro.org Cc: linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, ben.chuang@genesyslogic.com.tw, takahiro.akashi@linaro.org, greg.tu@genesyslogic.com.tw, Ben Chuang Subject: [RFC PATCH V3 11/21] mmc: sdhci: UHS-II support, export host operations to core Date: Fri, 10 Jul 2020 19:10:44 +0800 Message-Id: <20200710111044.29509-1-benchuanggli@gmail.com> X-Mailer: git-send-email 2.27.0 MIME-Version: 1.0 Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org From: AKASHI Takahiro Export sdhci-specific UHS-II operations to core. Signed-off-by: Ben Chuang Signed-off-by: AKASHI Takahiro --- drivers/mmc/host/sdhci.c | 70 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index c2f6923d296c..aaf41954511a 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -2977,6 +2977,70 @@ static void sdhci_card_event(struct mmc_host *mmc) spin_unlock_irqrestore(&host->lock, flags); } +#if IS_ENABLED(CONFIG_MMC_SDHCI_UHS2) +static int sdhci_uhs2_detect_init(struct mmc_host *mmc) +{ + struct sdhci_host *host = mmc_priv(mmc); + int ret; + + if (sdhci_uhs2_ops.do_detect_init) + ret = sdhci_uhs2_ops.do_detect_init(host); + else + return 0; + + return ret; +} + +static int sdhci_uhs2_set_reg(struct mmc_host *mmc, enum uhs2_act act) +{ + struct sdhci_host *host = mmc_priv(mmc); + int ret; + + if (sdhci_uhs2_ops.do_set_reg) + ret = sdhci_uhs2_ops.do_set_reg(host, act); + else + ret = 0; + + return ret; +} + +static void sdhci_uhs2_disable_clk(struct mmc_host *mmc) +{ + struct sdhci_host *host = mmc_priv(mmc); + u16 clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); + + clk &= ~SDHCI_CLOCK_CARD_EN; + sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); +} + +static void sdhci_uhs2_enable_clk(struct mmc_host *mmc) +{ + struct sdhci_host *host = mmc_priv(mmc); + u16 clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); + ktime_t timeout; + + clk |= SDHCI_CLOCK_CARD_EN; + sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); + + /* Wait max 20 ms */ + timeout = ktime_add_ms(ktime_get(), 20); + while (1) { + bool timedout = ktime_after(ktime_get(), timeout); + + clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); + if (clk & SDHCI_CLOCK_INT_STABLE) + break; + if (timedout) { + pr_err("%s: Internal clock never stabilised.\n", + mmc_hostname(host->mmc)); + sdhci_dumpregs(host); + return; + } + udelay(10); + } +} +#endif /* CONFIG_MMC_SDHCI_UHS2 */ + static const struct mmc_host_ops sdhci_ops = { .request = sdhci_request, .post_req = sdhci_post_req, @@ -2992,6 +3056,12 @@ static const struct mmc_host_ops sdhci_ops = { .execute_tuning = sdhci_execute_tuning, .card_event = sdhci_card_event, .card_busy = sdhci_card_busy, +#if IS_ENABLED(CONFIG_MMC_SDHCI_UHS2) + .uhs2_detect_init = sdhci_uhs2_detect_init, + .uhs2_set_reg = sdhci_uhs2_set_reg, + .uhs2_disable_clk = sdhci_uhs2_disable_clk, + .uhs2_enable_clk = sdhci_uhs2_enable_clk, +#endif /* CONFIG_MMC_SDHCI_UHS2 */ }; /*****************************************************************************\ From patchwork Fri Jul 10 11:10:54 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Chuang X-Patchwork-Id: 11656275 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 5AFA313B6 for ; Fri, 10 Jul 2020 11:10:13 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 2C36F2077D for ; Fri, 10 Jul 2020 11:10:13 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="K4kGwKJn" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726496AbgGJLKM (ORCPT ); Fri, 10 Jul 2020 07:10:12 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41268 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726369AbgGJLKM (ORCPT ); Fri, 10 Jul 2020 07:10:12 -0400 Received: from mail-pf1-x442.google.com (mail-pf1-x442.google.com [IPv6:2607:f8b0:4864:20::442]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DBF24C08C5CE; Fri, 10 Jul 2020 04:10:11 -0700 (PDT) Received: by mail-pf1-x442.google.com with SMTP id x72so2400011pfc.6; Fri, 10 Jul 2020 04:10:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=KoXphThq6G2JWBwLp5RLDjsZp2uZzGStShxeoA6seBE=; b=K4kGwKJn223tYrkGCMY8U3TsgdkXXZZ64nkoF+2xjEnUKoqGWUSptgxTIz7OC5ooP9 dmQAwQXwAD5wD2fGjpISCdv8qeNYP85K/82LfxZMBxC5eNkpXbWbm/igE8GXUSGCX4RL B13v8f1Eoai4HR7h5qcH76IWQvvMekPJvaeEhqqnx1B/Uq9x1/WDYS/K4oHnttYFd2SP K/4ZblY1u9i9fjVhYe5E2xEl0Dq8x34eA2bUOk2rAoIpO9nSuwebT/PaLU5fU3KlxEYX myptCxQiC4Eg72Wyzw/F67Y4PMl8SmpJxk+pomkcxu6a0jLaiX0hy48ACHD/Qf47HzxZ InCQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=KoXphThq6G2JWBwLp5RLDjsZp2uZzGStShxeoA6seBE=; b=qRQ3yeZarV+wjpm4cMROa1zt79Q3DAu/1cEiDep66WNOO1mv+tksi2xwkCFMWtwJLL CK6aDvVOU4Oe4r3wfx0fQJsk52gGTeRgkz3D3QJZ4OcgBgVEivzVaTfDmvQDrzxhc0mg AT55ei2ZBGOJgx9Q05Tb53auR85tzRKQ6J8K0Bbm0YqRC4+cNaAQwQaBpQGdciJej+Fo 0FIJmSWSUO8CB5/9cBljGkZoM7oQyPBABaJmedB7IVpLkJRWQSaSOSiSnHN6mv1YNLUa /LU7foHoT6JrXOak2gTDULX8hSgWyuHflj0bONGThcq/lbyYB7cB8THhfCPgi3wn8YA+ 7JnQ== X-Gm-Message-State: AOAM530qloUahKC07XzuGc4JRc7h0G++CHkhEHYFWzp1aGF7Vw1Zpy2o 1OD1cWcRFY2ASgdp75E5d6A= X-Google-Smtp-Source: ABdhPJyseJm7HX+hSqhMnBvBKgj5eO87JpHUC6nK9w8DLYSBIzTdNBMrhlbJaKqhN+r+QWktY3sVIQ== X-Received: by 2002:a62:75c8:: with SMTP id q191mr53142041pfc.321.1594379411383; Fri, 10 Jul 2020 04:10:11 -0700 (PDT) Received: from gli-arch.genesyslogic.com.tw (60-251-58-169.HINET-IP.hinet.net. [60.251.58.169]) by smtp.gmail.com with ESMTPSA id u19sm6306680pfk.98.2020.07.10.04.10.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 10 Jul 2020 04:10:11 -0700 (PDT) From: Ben Chuang To: adrian.hunter@intel.com, ulf.hansson@linaro.org Cc: linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, ben.chuang@genesyslogic.com.tw, takahiro.akashi@linaro.org, greg.tu@genesyslogic.com.tw, Ben Chuang Subject: [RFC PATCH V3 12/21] mmc: sdhci: UHS-II support, add hooks for additional operations Date: Fri, 10 Jul 2020 19:10:54 +0800 Message-Id: <20200710111054.29562-1-benchuanggli@gmail.com> X-Mailer: git-send-email 2.27.0 MIME-Version: 1.0 Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org From: Ben Chuang In this commit, UHS-II related operations will be called via a function pointer array, sdhci_uhs2_ops, in order to make UHS-II support as a kernel module. This array will be initialized only if CONFIG_MMC_SDHCI_UHS2 is enabled and when the UHS-II module is loaded. Otherwise, all the functions stay void. Signed-off-by: Ben Chuang Signed-off-by: AKASHI Takahiro --- drivers/mmc/host/sdhci.c | 152 ++++++++++++++++++++++++++++++++++----- 1 file changed, 136 insertions(+), 16 deletions(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index aaf41954511a..5511649946b9 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -32,8 +32,12 @@ #include #include #include +#include +#include #include "sdhci.h" +#include "sdhci-uhs2.h" +#include "sdhci-pci.h" #define DRIVER_NAME "sdhci" @@ -45,6 +49,11 @@ #define MAX_TUNING_LOOP 40 +#if IS_ENABLED(CONFIG_MMC_SDHCI_UHS2) +struct sdhci_uhs2_ops sdhci_uhs2_ops; +EXPORT_SYMBOL_GPL(sdhci_uhs2_ops); +#endif + static unsigned int debug_quirks = 0; static unsigned int debug_quirks2; @@ -1041,8 +1050,11 @@ EXPORT_SYMBOL_GPL(sdhci_set_data_timeout_irq); void __sdhci_set_timeout(struct sdhci_host *host, struct mmc_command *cmd) { + u8 count; + bool too_big = false; - u8 count = sdhci_calc_timeout(host, cmd, &too_big); + + count = sdhci_calc_timeout(host, cmd, &too_big); if (too_big && host->quirks2 & SDHCI_QUIRK2_DISABLE_HW_TIMEOUT) { @@ -1053,6 +1065,11 @@ void __sdhci_set_timeout(struct sdhci_host *host, struct mmc_command *cmd) } sdhci_writeb(host, count, SDHCI_TIMEOUT_CONTROL); + + if (IS_ENABLED(CONFIG_MMC_SDHCI_UHS2) && + host->mmc->flags & MMC_UHS2_SUPPORT && + sdhci_uhs2_ops.set_timeout) + sdhci_uhs2_ops.set_timeout(host); } EXPORT_SYMBOL_GPL(__sdhci_set_timeout); @@ -1191,7 +1208,14 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd) sdhci_set_transfer_irqs(host); - sdhci_set_block_info(host, data); + if (IS_ENABLED(CONFIG_MMC_SDHCI_UHS2) && + host->mmc->flags & MMC_UHS2_SUPPORT && + host->mmc->flags & MMC_UHS2_INITIALIZED) { + sdhci_writew(host, data->blksz, SDHCI_UHS2_BLOCK_SIZE); + sdhci_writew(host, data->blocks, SDHCI_UHS2_BLOCK_COUNT); + } else { + sdhci_set_block_info(host, data); + } } #if IS_ENABLED(CONFIG_MMC_SDHCI_EXTERNAL_DMA) @@ -1439,6 +1463,13 @@ static void sdhci_set_transfer_mode(struct sdhci_host *host, u16 mode = 0; struct mmc_data *data = cmd->data; + if (IS_ENABLED(CONFIG_MMC_SDHCI_UHS2) && + host->mmc->flags & MMC_UHS2_SUPPORT) { + if (sdhci_uhs2_ops.set_transfer_mode) + sdhci_uhs2_ops.set_transfer_mode(host, cmd); + return; + } + if (data == NULL) { if (host->quirks2 & SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD) { @@ -1570,6 +1601,12 @@ static void __sdhci_finish_data(struct sdhci_host *host, bool sw_data_timeout) else data->bytes_xfered = data->blksz * data->blocks; + if (IS_ENABLED(CONFIG_MMC_SDHCI_UHS2) && + host->mmc->flags & MMC_UHS2_INITIALIZED) { + __sdhci_finish_mrq(host, data->mrq); + return; + } + /* * Need to send CMD12 if - * a) open-ended multiblock transfer not using auto CMD12 (no CMD23) @@ -1654,7 +1691,8 @@ static bool sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) sdhci_prepare_data(host, cmd); } - sdhci_writel(host, cmd->arg, SDHCI_ARGUMENT); + if (!IS_ENABLED(CONFIG_MMC_SDHCI_UHS2)) + sdhci_writel(host, cmd->arg, SDHCI_ARGUMENT); sdhci_set_transfer_mode(host, cmd); @@ -1699,6 +1737,17 @@ static bool sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) if (host->use_external_dma) sdhci_external_dma_pre_transfer(host, cmd); + if (IS_ENABLED(CONFIG_MMC_SDHCI_UHS2) && + (host->mmc->flags & MMC_UHS2_SUPPORT)) { + if (sdhci_uhs2_ops.send_command) + sdhci_uhs2_ops.send_command(host, cmd); + + return true; + } + + if (IS_ENABLED(CONFIG_MMC_SDHCI_UHS2)) + sdhci_writel(host, cmd->arg, SDHCI_ARGUMENT); + sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND); return true; @@ -1780,13 +1829,20 @@ static void sdhci_finish_command(struct sdhci_host *host) { struct mmc_command *cmd = host->cmd; - host->cmd = NULL; + if (IS_ENABLED(CONFIG_MMC_SDHCI_UHS2) && + host->mmc->flags & MMC_UHS2_SUPPORT) { + if (sdhci_uhs2_ops.finish_command) + sdhci_uhs2_ops.finish_command(host); + } else { + host->cmd = NULL; - if (cmd->flags & MMC_RSP_PRESENT) { - if (cmd->flags & MMC_RSP_136) { - sdhci_read_rsp_136(host, cmd); - } else { - cmd->resp[0] = sdhci_readl(host, SDHCI_RESPONSE); + if (cmd->flags & MMC_RSP_PRESENT) { + if (cmd->flags & MMC_RSP_136) { + sdhci_read_rsp_136(host, cmd); + } else { + cmd->resp[0] = sdhci_readl(host, + SDHCI_RESPONSE); + } } } @@ -1809,6 +1865,7 @@ static void sdhci_finish_command(struct sdhci_host *host) } else if (!(host->quirks & SDHCI_QUIRK_NO_BUSY_IRQ) && cmd == host->data_cmd) { /* Command complete before busy is ended */ + host->cmd = NULL; return; } } @@ -1828,6 +1885,8 @@ static void sdhci_finish_command(struct sdhci_host *host) if (!cmd->data) __sdhci_finish_mrq(host, cmd->mrq); } + + host->cmd = NULL; } static u16 sdhci_get_preset_value(struct sdhci_host *host) @@ -1855,6 +1914,11 @@ static u16 sdhci_get_preset_value(struct sdhci_host *host) case MMC_TIMING_MMC_HS400: preset = sdhci_readw(host, SDHCI_PRESET_FOR_HS400); break; +#if IS_ENABLED(CONFIG_MMC_SDHCI_UHS2) + case MMC_TIMING_UHS2: + preset = sdhci_readw(host, SDHCI_PRESET_FOR_UHS2); + break; +#endif default: pr_warn("%s: Invalid UHS-I mode selected\n", mmc_hostname(host->mmc)); @@ -2095,7 +2159,6 @@ void sdhci_set_power_noreg(struct sdhci_host *host, unsigned char mode, sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); pwr |= SDHCI_POWER_ON; - sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON) @@ -2261,6 +2324,7 @@ void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) { struct sdhci_host *host = mmc_priv(mmc); u8 ctrl; + u16 ctrl_2; if (ios->power_mode == MMC_POWER_UNDEFINED) return; @@ -2287,6 +2351,10 @@ void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) sdhci_enable_preset_value(host, false); if (!ios->clock || ios->clock != host->clock) { + if (IS_ENABLED(CONFIG_MMC_SDHCI_UHS2) && + ios->timing == MMC_TIMING_UHS2) + host->timing = ios->timing; + host->ops->set_clock(host, ios->clock); host->clock = ios->clock; @@ -2308,6 +2376,18 @@ void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) else sdhci_set_power(host, ios->power_mode, ios->vdd); + /* 4.0 host support */ + if (host->version >= SDHCI_SPEC_400) { + /* UHS2 Support */ + if (IS_ENABLED(CONFIG_MMC_SDHCI_UHS2) && + host->mmc->flags & MMC_UHS2_SUPPORT && + host->mmc->caps & MMC_CAP_UHS2) { + if (sdhci_uhs2_ops.do_set_ios) + sdhci_uhs2_ops.do_set_ios(host, ios); + return; + } + } + if (host->ops->platform_send_init_74_clocks) host->ops->platform_send_init_74_clocks(host, ios->power_mode); @@ -2331,7 +2411,7 @@ void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) } if (host->version >= SDHCI_SPEC_300) { - u16 clk, ctrl_2; + u16 clk; if (!host->preset_enabled) { sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); @@ -3173,11 +3253,19 @@ static bool sdhci_request_done(struct sdhci_host *host) /* This is to force an update */ host->ops->set_clock(host, host->clock); - /* Spec says we should do both at the same time, but Ricoh - controllers do not like that. */ - sdhci_do_reset(host, SDHCI_RESET_CMD); - sdhci_do_reset(host, SDHCI_RESET_DATA); - + if (IS_ENABLED(CONFIG_MMC_SDHCI_UHS2) && + host->mmc->flags & MMC_UHS2_INITIALIZED) { + if (sdhci_uhs2_ops.reset) + sdhci_uhs2_ops.reset(host, + SDHCI_UHS2_SW_RESET_SD); + } else { + /* + * Spec says we should do both at the same time, but + * Ricoh controllers do not like that. + */ + sdhci_do_reset(host, SDHCI_RESET_CMD); + sdhci_do_reset(host, SDHCI_RESET_DATA); + } host->pending_reset = false; } @@ -3532,6 +3620,13 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) SDHCI_INT_BUS_POWER); sdhci_writel(host, mask, SDHCI_INT_STATUS); + if (IS_ENABLED(CONFIG_MMC_SDHCI_UHS2) && + intmask & SDHCI_INT_ERROR && + host->mmc->flags & MMC_UHS2_SUPPORT) { + if (sdhci_uhs2_ops.irq) + sdhci_uhs2_ops.irq(host); + } + if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) { u32 present = sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT; @@ -4717,6 +4812,14 @@ int sdhci_setup_host(struct sdhci_host *host) /* This may alter mmc->*_blk_* parameters */ sdhci_allocate_bounce_buffer(host); + if (IS_ENABLED(CONFIG_MMC_SDHCI_UHS2) && + host->version >= SDHCI_SPEC_400 && + sdhci_uhs2_ops.add_host) { + ret = sdhci_uhs2_ops.add_host(host, host->caps1); + if (ret) + goto unreg; + } + return 0; unreg: @@ -4738,6 +4841,8 @@ void sdhci_cleanup_host(struct sdhci_host *host) { struct mmc_host *mmc = host->mmc; + /* FIXME: Do we have to do some cleanup for UHS2 here? */ + if (!IS_ERR(mmc->supply.vqmmc)) regulator_disable(mmc->supply.vqmmc); @@ -4766,6 +4871,14 @@ int __sdhci_add_host(struct sdhci_host *host) mmc->cqe_ops = NULL; } + if ((mmc->caps & MMC_CAP_UHS2) && !host->v4_mode) { + /* host doesn't want to enable UHS2 support */ + mmc->caps &= ~MMC_CAP_UHS2; + mmc->flags &= ~MMC_UHS2_SUPPORT; + + /* FIXME: Do we have to do some cleanup here? */ + } + host->complete_wq = alloc_workqueue("sdhci", flags, 0); if (!host->complete_wq) return -ENOMEM; @@ -4812,6 +4925,9 @@ int __sdhci_add_host(struct sdhci_host *host) unled: sdhci_led_unregister(host); unirq: + if (IS_ENABLED(CONFIG_MMC_SDHCI_UHS2) && + sdhci_uhs2_ops.remove_host) + sdhci_uhs2_ops.remove_host(host, 0); sdhci_do_reset(host, SDHCI_RESET_ALL); sdhci_writel(host, 0, SDHCI_INT_ENABLE); sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE); @@ -4869,6 +4985,10 @@ void sdhci_remove_host(struct sdhci_host *host, int dead) sdhci_led_unregister(host); + if (IS_ENABLED(CONFIG_MMC_SDHCI_UHS2) && + sdhci_uhs2_ops.remove_host) + sdhci_uhs2_ops.remove_host(host, dead); + if (!dead) sdhci_do_reset(host, SDHCI_RESET_ALL); From patchwork Fri Jul 10 11:11:04 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Chuang X-Patchwork-Id: 11656277 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 7D68A618 for ; Fri, 10 Jul 2020 11:10:22 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 63EC82078B for ; Fri, 10 Jul 2020 11:10:22 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="vJ9Ca77b" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726820AbgGJLKV (ORCPT ); Fri, 10 Jul 2020 07:10:21 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41294 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726369AbgGJLKV (ORCPT ); Fri, 10 Jul 2020 07:10:21 -0400 Received: from mail-pl1-x643.google.com (mail-pl1-x643.google.com [IPv6:2607:f8b0:4864:20::643]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7C65BC08C5CE; Fri, 10 Jul 2020 04:10:21 -0700 (PDT) Received: by mail-pl1-x643.google.com with SMTP id k5so2103219plk.13; Fri, 10 Jul 2020 04:10:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=dLfBKiqpz5EiKywgE0yB9WT/RYihQi2mbssOelfoHw0=; b=vJ9Ca77bH7p0DulTZ4e770baRLuddEbRx8xicTWnfaG9DjxAag0yOPpVlm/VIAs+XQ oDQ8AxlewBO2CA6Fq8DuWbFoJwLrsN2eOB70y1kHApbj4tk220c8ZrYNHM3QZmQUlho7 3As2hgljt3suLKzCfO/LQEANVuOQqGj4wilxVHDlW+o7xSzyvTowXlFzyf+N2QJKtYwF zpozqSCTO4Z83+xjKmufmrX6Vlpukc7mh4JnB4Q5Y4syrSwNW/c+xuY1qVhRqPTEwT7Y coub31+cfdlaCmaCJlrP/bWTzeellUELCq2x2YuDpgSE2MW8tDHQZnF/QqnZbFdL9uGV ALpw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=dLfBKiqpz5EiKywgE0yB9WT/RYihQi2mbssOelfoHw0=; b=KuFJTQ44mA+ScLaWAE3WTpzo6wPVNrcQwgqPX9fM2J5MPxhLVszTpMLAu02HbLt5lm pOJlfEU4pLeVqr9c5sdqKl40/MqDkiVKGpEvonc/MFFPAwmaYkmJpBB93EIxWqPNg/+B etdxvwKQ9dggKI5pkSu1Hz2pLTW5gwr0ZqYJYEQ7wcY9cPP4Aan+G5s0OR3zIaV9QBTB OrFarOMwA13PYB9+I7a2rBhC2uCIpkGSp9JehnwiFh54631Am+UZ7YuZ0/0jR2GkPVXU Sj3L33HUeARxajPhvFN6BOueZUkn2GJ8TGaoRDHST0vm14rwDXkMjXIZ6KKh/w6unm2z 8xqQ== X-Gm-Message-State: AOAM531vlCs/t9tRgcoHOrueZvk4qjfUaGcOJAM+TZQ8z1y31HixDq5Z h4VfEPaUKApXC0mOftSVD5fu1JC9 X-Google-Smtp-Source: ABdhPJwI9lWowh+owLufJVcE9e4ty10ucd5K10bYaioElYjSbv5+jab2lXM38QsdKGLNS7DPejD3eA== X-Received: by 2002:a17:90b:3809:: with SMTP id mq9mr5026522pjb.156.1594379421083; Fri, 10 Jul 2020 04:10:21 -0700 (PDT) Received: from gli-arch.genesyslogic.com.tw (60-251-58-169.HINET-IP.hinet.net. [60.251.58.169]) by smtp.gmail.com with ESMTPSA id q5sm5617263pfc.130.2020.07.10.04.10.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 10 Jul 2020 04:10:20 -0700 (PDT) From: Ben Chuang To: adrian.hunter@intel.com, ulf.hansson@linaro.org Cc: linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, ben.chuang@genesyslogic.com.tw, takahiro.akashi@linaro.org, greg.tu@genesyslogic.com.tw, Ben Chuang Subject: [RFC PATCH V3 13/21] mmc: sdhci: UHS-II support, skip signal_voltage_switch() Date: Fri, 10 Jul 2020 19:11:04 +0800 Message-Id: <20200710111104.29616-1-benchuanggli@gmail.com> X-Mailer: git-send-email 2.27.0 MIME-Version: 1.0 Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org From: AKASHI Takahiro sdhci_start_signal_voltage_switch() should be called only in UHS-I mode, and not for UHS-II mode. Signed-off-by: Ben Chuang Signed-off-by: AKASHI Takahiro --- drivers/mmc/host/sdhci.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 5511649946b9..7f2537648a08 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -2623,8 +2623,13 @@ int sdhci_start_signal_voltage_switch(struct mmc_host *mmc, /* * Signal Voltage Switching is only applicable for Host Controllers * v3.00 and above. + * But for UHS2, the signal voltage is supplied by vdd2 which is + * already 1.8v so no voltage switch required. */ - if (host->version < SDHCI_SPEC_300) + if (host->version < SDHCI_SPEC_300 || + (IS_ENABLED(CONFIG_MMC_SDHCI_UHS2) && + host->version >= SDHCI_SPEC_400 && + host->mmc->flags & MMC_UHS2_SUPPORT)) return 0; ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); From patchwork Fri Jul 10 11:11:21 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Chuang X-Patchwork-Id: 11656279 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 96FE013B6 for ; Fri, 10 Jul 2020 11:10:43 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7B4742077D for ; Fri, 10 Jul 2020 11:10:43 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="DaHGgEEG" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727098AbgGJLKm (ORCPT ); Fri, 10 Jul 2020 07:10:42 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41350 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726369AbgGJLKm (ORCPT ); Fri, 10 Jul 2020 07:10:42 -0400 Received: from mail-pl1-x62c.google.com (mail-pl1-x62c.google.com [IPv6:2607:f8b0:4864:20::62c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1557CC08C5CE; Fri, 10 Jul 2020 04:10:42 -0700 (PDT) Received: by mail-pl1-x62c.google.com with SMTP id w17so2108072ply.11; Fri, 10 Jul 2020 04:10:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=bgoBg0vT86NrsTuwHUuY0qnUVNcClhUjdRlVz8Y7TKE=; b=DaHGgEEGmlzpgsVxpafL78K63f9pg8pK4DQJ0e3sdMT6FZBcAGWs9J0qbf3jm6YWBE 7HJwFSW/t4BmyEDmuOGu58XH0gUxO/BVf+TUKsx/1buK1NPIGaMWNqpus/C9uOsZk6Zh A1jEgRnKGUbc/58IgVq67VvXpqcQ64pVI26KOaOqI5KqnCZmSrifUhPTXercRJuQErXH Ve+nvU5A2aMs8ro5YZsjyxSavNJNI0Prwog/nJJMUKUez7C4gMT9LQsMaZv2O1s5A9oT 7j8fA31ziMkvsLrq1mXIgVp8iaczoWZWwWt5geyHVBNIgnIF8L6rKEA9Gfi2mqvbfDOl dWRA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=bgoBg0vT86NrsTuwHUuY0qnUVNcClhUjdRlVz8Y7TKE=; b=p+48yTUtaBGsW+kUFqpLOEs2k3c8yn7M+QFk/Dl11HjmJHvMxrtWOLux9aJdcJjhyr 0L5EM2wn0nu3EzwylZXUPbJUolRHs83yuRg11OJzq/e5FPLK8rzYzYzR7AYqWcmJLeQh +2PRrOzS1UYithVjdkfkGGR2J9SvaQMT39siCt1CGGuwcbF2a7bLWbm5ztpkRP17HnSE J47mli8MkLR0n2fM6Dfl5r7fVJcNfT/igdX8onVv9vmMhySBvFJz0AMpYzddxsJKsv5a 8JU2sdkCvXrTPH4fEH+bcMdyYWy4oRV3EaIX+FdNfeyt0fRHU5y1sRfVuE09yvhDpb4k 45eA== X-Gm-Message-State: AOAM532F1jXlrET9paf3uo6PFAWJzs+Re4om20ALM9sHouHX8pC+HHY3 Oxca8JXI+ajymqgT1d9gZNk= X-Google-Smtp-Source: ABdhPJzDYSM4rpL4ZeqAOMHMe5vZeTQCKN7wlVZY5xSQgL1/S5yx6OECT09VkBYdQ9aM1Cjpw6222Q== X-Received: by 2002:a17:902:7d8f:: with SMTP id a15mr18410159plm.37.1594379441641; Fri, 10 Jul 2020 04:10:41 -0700 (PDT) Received: from gli-arch.genesyslogic.com.tw (60-251-58-169.HINET-IP.hinet.net. [60.251.58.169]) by smtp.gmail.com with ESMTPSA id v15sm5415890pgo.15.2020.07.10.04.10.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 10 Jul 2020 04:10:41 -0700 (PDT) From: Ben Chuang To: adrian.hunter@intel.com, ulf.hansson@linaro.org Cc: linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, ben.chuang@genesyslogic.com.tw, takahiro.akashi@linaro.org, greg.tu@genesyslogic.com.tw, Ben Chuang Subject: [RFC PATCH V3 14/21] mmc: sdhci: UHS-II support, handle vdd2 in case of power-off Date: Fri, 10 Jul 2020 19:11:21 +0800 Message-Id: <20200710111121.29671-1-benchuanggli@gmail.com> X-Mailer: git-send-email 2.27.0 MIME-Version: 1.0 Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org From: AKASHI Takahiro Configure a regulator for VDD2 in case of power-off. Signed-off-by: Ben Chuang Signed-off-by: AKASHI Takahiro --- drivers/mmc/host/sdhci.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 7f2537648a08..d38d734ec83f 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -2333,6 +2333,11 @@ void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) if (!IS_ERR(mmc->supply.vmmc) && ios->power_mode == MMC_POWER_OFF) mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0); + if (IS_ENABLED(CONFIG_MMC_SDHCI_UHS2) && + host->mmc->caps & MMC_CAP_UHS2 && + !IS_ERR(mmc->supply.vmmc2) && + ios->power_mode == MMC_POWER_OFF) + mmc_regulator_set_ocr(mmc, mmc->supply.vmmc2, 0); return; } From patchwork Fri Jul 10 11:11:40 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Chuang X-Patchwork-Id: 11656281 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 24DC9618 for ; Fri, 10 Jul 2020 11:11:08 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 05AD92076A for ; Fri, 10 Jul 2020 11:11:08 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="m608z0q3" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727976AbgGJLLH (ORCPT ); Fri, 10 Jul 2020 07:11:07 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41416 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726369AbgGJLLH (ORCPT ); Fri, 10 Jul 2020 07:11:07 -0400 Received: from mail-pl1-x641.google.com (mail-pl1-x641.google.com [IPv6:2607:f8b0:4864:20::641]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1E729C08C5CE; Fri, 10 Jul 2020 04:11:07 -0700 (PDT) Received: by mail-pl1-x641.google.com with SMTP id k4so2104815pld.12; Fri, 10 Jul 2020 04:11:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=g3VOa+Y0HTmbN1kJlGhfKpuHNVKRU2nXIafR93epWKM=; b=m608z0q3Dxy2rh5vH1gGrZfO2x7yIKk6ZWGZTzGMDJ9EAJtG64jdzVyuR72ci1PyDK sviN2r1yqZ9c4qZVmV+fg39bGWfLjbj+qIXBOm76dILQgVzsQMtkT2W30KUdUrLbrbkQ UcTStnHn7UJJTxkGJ95mH1mFicZGRUjdSJbRP1aWO8FJ00xMceUY+ArCg1oUIEK/5al4 FUiT0Uu6/uQ90Dn25DZvwERz9WdtvCgJz0EofahrhpDm5kZQadLjxpog8W9v2hQTsJk6 FGnrvbKcy/pMxKtZ+UU6pj+O4RAWYd22mPnD0rVjdOxCDrvYWlsEx8kMyXws13Kq+OVo /BZw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=g3VOa+Y0HTmbN1kJlGhfKpuHNVKRU2nXIafR93epWKM=; b=RE0ZnBnoA76YzN79MQpyICWO5xvMIRxmN/8pO4BTDytVHqH5fAk40rdCj99wIoCHV4 ppjWlCTAhPeQb/kEQ9YxqPfkAJCRPQKy/vzTiySAPGtQTHuGHuaTohrtiUoN4Czu9U7H SfwDtZOBLIWcj9vXX+uWyYsrRsaKWairbtz6U7jOQGTMqDwA3esUfYobaLYMNQaCYnOL EwCRDPrRn7nwhnlyZKC3mxAUzgRgIYoS9ni56jySX7JOu6HUB2XCB4tJNB5Y7xErI62H uneQAEfJV/aLl2uCIlHvFldHfTDznvZcDAUXm+P/ZGVB9SadRfmsdUJRPX+ONVjaqzlG wnig== X-Gm-Message-State: AOAM531HUYhABaC7BjhgA5AN6aBWDElTgQ4Q0AxOJva18KZTv4udYhkH eIQCUHo9BNryIBv9pL7dhr2G7Utf X-Google-Smtp-Source: ABdhPJwIJC1SSYNiZZSL03Zy9Nj63dzhvrE/+Bv1ETUo6pTvMwARn8QU77b8M3yL3g9+3XQXbvbm2w== X-Received: by 2002:a17:902:d715:: with SMTP id w21mr18325011ply.140.1594379466687; Fri, 10 Jul 2020 04:11:06 -0700 (PDT) Received: from gli-arch.genesyslogic.com.tw (60-251-58-169.HINET-IP.hinet.net. [60.251.58.169]) by smtp.gmail.com with ESMTPSA id h6sm5825010pfo.123.2020.07.10.04.11.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 10 Jul 2020 04:11:06 -0700 (PDT) From: Ben Chuang To: adrian.hunter@intel.com, ulf.hansson@linaro.org Cc: linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, ben.chuang@genesyslogic.com.tw, takahiro.akashi@linaro.org, greg.tu@genesyslogic.com.tw, Ben Chuang Subject: [RFC PATCH V3 15/21] mmc: sdhci: UHS-II support, modify set_power() to handle vdd2 Date: Fri, 10 Jul 2020 19:11:40 +0800 Message-Id: <20200710111140.29725-1-benchuanggli@gmail.com> X-Mailer: git-send-email 2.27.0 MIME-Version: 1.0 Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org From: AKASHI Takahiro VDD2 is used for powering UHS-II interface. Modify sdhci_set_power_and_bus_voltage(), sdhci_set_power_noreg() and sdhci_set_power_noreg() to handle VDD2. Signed-off-by: Ben Chuang Signed-off-by: AKASHI Takahiro --- drivers/mmc/host/sdhci-omap.c | 2 +- drivers/mmc/host/sdhci-pci-core.c | 4 +-- drivers/mmc/host/sdhci-pxav3.c | 4 +-- drivers/mmc/host/sdhci-xenon.c | 4 +-- drivers/mmc/host/sdhci.c | 42 ++++++++++++++++++++++++------- drivers/mmc/host/sdhci.h | 9 +++---- 6 files changed, 43 insertions(+), 22 deletions(-) diff --git a/drivers/mmc/host/sdhci-omap.c b/drivers/mmc/host/sdhci-omap.c index 1ec74c2d5c17..1926585debe5 100644 --- a/drivers/mmc/host/sdhci-omap.c +++ b/drivers/mmc/host/sdhci-omap.c @@ -678,7 +678,7 @@ static void sdhci_omap_set_clock(struct sdhci_host *host, unsigned int clock) } static void sdhci_omap_set_power(struct sdhci_host *host, unsigned char mode, - unsigned short vdd) + unsigned short vdd, unsigned short vdd2) { struct mmc_host *mmc = host->mmc; diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c index bb6802448b2f..40f5a24a8982 100644 --- a/drivers/mmc/host/sdhci-pci-core.c +++ b/drivers/mmc/host/sdhci-pci-core.c @@ -629,12 +629,12 @@ static int bxt_get_cd(struct mmc_host *mmc) #define SDHCI_INTEL_PWR_TIMEOUT_UDELAY 100 static void sdhci_intel_set_power(struct sdhci_host *host, unsigned char mode, - unsigned short vdd) + unsigned short vdd, unsigned short vdd2) { int cntr; u8 reg; - sdhci_set_power(host, mode, vdd); + sdhci_set_power(host, mode, vdd, -1); if (mode == MMC_POWER_OFF) return; diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c index e55037ceda73..457e9425339a 100644 --- a/drivers/mmc/host/sdhci-pxav3.c +++ b/drivers/mmc/host/sdhci-pxav3.c @@ -298,12 +298,12 @@ static void pxav3_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs) } static void pxav3_set_power(struct sdhci_host *host, unsigned char mode, - unsigned short vdd) + unsigned short vdd, unsigned short vdd2) { struct mmc_host *mmc = host->mmc; u8 pwr = host->pwr; - sdhci_set_power_noreg(host, mode, vdd); + sdhci_set_power_noreg(host, mode, vdd, -1); if (host->pwr == pwr) return; diff --git a/drivers/mmc/host/sdhci-xenon.c b/drivers/mmc/host/sdhci-xenon.c index 4703cd540c7f..2b0ebb91895a 100644 --- a/drivers/mmc/host/sdhci-xenon.c +++ b/drivers/mmc/host/sdhci-xenon.c @@ -214,12 +214,12 @@ static void xenon_set_uhs_signaling(struct sdhci_host *host, } static void xenon_set_power(struct sdhci_host *host, unsigned char mode, - unsigned short vdd) + unsigned short vdd, unsigned short vdd2) { struct mmc_host *mmc = host->mmc; u8 pwr = host->pwr; - sdhci_set_power_noreg(host, mode, vdd); + sdhci_set_power_noreg(host, mode, vdd, -1); if (host->pwr == pwr) return; diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index d38d734ec83f..ca3d4a506e01 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -2089,12 +2089,15 @@ void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) EXPORT_SYMBOL_GPL(sdhci_set_clock); static void sdhci_set_power_reg(struct sdhci_host *host, unsigned char mode, - unsigned short vdd) + unsigned short vdd, unsigned short vdd2) { struct mmc_host *mmc = host->mmc; mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, vdd); + if (mmc->caps & MMC_CAP_UHS2 && !IS_ERR(mmc->supply.vmmc2)) + mmc_regulator_set_ocr(mmc, mmc->supply.vmmc2, vdd2); + if (mode != MMC_POWER_OFF) sdhci_writeb(host, SDHCI_POWER_ON, SDHCI_POWER_CONTROL); else @@ -2102,7 +2105,7 @@ static void sdhci_set_power_reg(struct sdhci_host *host, unsigned char mode, } void sdhci_set_power_noreg(struct sdhci_host *host, unsigned char mode, - unsigned short vdd) + unsigned short vdd, unsigned short vdd2) { u8 pwr = 0; @@ -2133,6 +2136,20 @@ void sdhci_set_power_noreg(struct sdhci_host *host, unsigned char mode, } } + if (mode != MMC_POWER_OFF) { + if (vdd2 != (unsigned short)-1) { + switch (1 << vdd2) { + case MMC_VDD2_165_195: + pwr |= SDHCI_VDD2_POWER_180; + break; + default: + WARN(1, "%s: Invalid vdd2 %#x\n", + mmc_hostname(host->mmc), vdd2); + break; + } + } + } + if (host->pwr == pwr) return; @@ -2159,7 +2176,13 @@ void sdhci_set_power_noreg(struct sdhci_host *host, unsigned char mode, sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); pwr |= SDHCI_POWER_ON; + if (vdd2 != (unsigned short)-1) + pwr |= SDHCI_VDD2_POWER_ON; + + sdhci_writeb(host, pwr & 0xf, SDHCI_POWER_CONTROL); + mdelay(5); sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); + mdelay(5); if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON) sdhci_runtime_pm_bus_on(host); @@ -2175,12 +2198,12 @@ void sdhci_set_power_noreg(struct sdhci_host *host, unsigned char mode, EXPORT_SYMBOL_GPL(sdhci_set_power_noreg); void sdhci_set_power(struct sdhci_host *host, unsigned char mode, - unsigned short vdd) + unsigned short vdd, unsigned short vdd2) { if (IS_ERR(host->mmc->supply.vmmc)) - sdhci_set_power_noreg(host, mode, vdd); + sdhci_set_power_noreg(host, mode, vdd, vdd2); else - sdhci_set_power_reg(host, mode, vdd); + sdhci_set_power_reg(host, mode, vdd, vdd2); } EXPORT_SYMBOL_GPL(sdhci_set_power); @@ -2192,14 +2215,15 @@ EXPORT_SYMBOL_GPL(sdhci_set_power); */ void sdhci_set_power_and_bus_voltage(struct sdhci_host *host, unsigned char mode, - unsigned short vdd) + unsigned short vdd, + unsigned short vdd2) { if (!IS_ERR(host->mmc->supply.vmmc)) { struct mmc_host *mmc = host->mmc; mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, vdd); } - sdhci_set_power_noreg(host, mode, vdd); + sdhci_set_power_noreg(host, mode, vdd, -1); } EXPORT_SYMBOL_GPL(sdhci_set_power_and_bus_voltage); @@ -2377,9 +2401,9 @@ void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) } if (host->ops->set_power) - host->ops->set_power(host, ios->power_mode, ios->vdd); + host->ops->set_power(host, ios->power_mode, ios->vdd, -1); else - sdhci_set_power(host, ios->power_mode, ios->vdd); + sdhci_set_power(host, ios->power_mode, ios->vdd, -1); /* 4.0 host support */ if (host->version >= SDHCI_SPEC_400) { diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index ecf55394ea46..f6732f33f29f 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -689,7 +689,7 @@ struct sdhci_ops { void (*set_clock)(struct sdhci_host *host, unsigned int clock); void (*set_power)(struct sdhci_host *host, unsigned char mode, - unsigned short vdd); + unsigned short vdd, unsigned short vdd2); u32 (*irq)(struct sdhci_host *host, u32 intmask); @@ -852,13 +852,10 @@ u16 sdhci_calc_clk(struct sdhci_host *host, unsigned int clock, unsigned int *actual_clock); void sdhci_set_clock(struct sdhci_host *host, unsigned int clock); void sdhci_enable_clk(struct sdhci_host *host, u16 clk); -void sdhci_set_power(struct sdhci_host *host, unsigned char mode, - unsigned short vdd); void sdhci_set_power_and_bus_voltage(struct sdhci_host *host, unsigned char mode, - unsigned short vdd); -void sdhci_set_power_noreg(struct sdhci_host *host, unsigned char mode, - unsigned short vdd); + unsigned short vdd, + unsigned short vdd2); void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq); int sdhci_request_atomic(struct mmc_host *mmc, struct mmc_request *mrq); void sdhci_set_bus_width(struct sdhci_host *host, int width); From patchwork Fri Jul 10 11:12:15 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Chuang X-Patchwork-Id: 11656283 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 6B78713B6 for ; Fri, 10 Jul 2020 11:11:33 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 4D1A42077D for ; Fri, 10 Jul 2020 11:11:33 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="mStmS5OF" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726816AbgGJLLc (ORCPT ); Fri, 10 Jul 2020 07:11:32 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41478 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726369AbgGJLLc (ORCPT ); Fri, 10 Jul 2020 07:11:32 -0400 Received: from mail-pg1-x541.google.com (mail-pg1-x541.google.com [IPv6:2607:f8b0:4864:20::541]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1AEC0C08C5CE; Fri, 10 Jul 2020 04:11:32 -0700 (PDT) Received: by mail-pg1-x541.google.com with SMTP id k27so2398071pgm.2; Fri, 10 Jul 2020 04:11:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=hc0v8G3i487Ys5ZeJsDG4atE3X7Sxu4cwRpY1JcVqQw=; b=mStmS5OFyikPwV/iNnNUD8mZkeHhNxOpAFwn0mK2GxARssT4NT1EFEQfeP4Y5D/Ux7 Hn3a+v7gK7IcF3LNAEIpvmqiYuyDaZD6vjXxHlH6ohW/GO9/CtnB9PgFg6Rfav0XvQpC JZDtr9OZOungHrdyivKVn1JzQWmeUUjSL/OpgPHv6lk/LJT7pBapSG06VgUWyt/iHhkl Q7WLeg7LCKiS3xijxcJgoWihuKpaM9NLW4VxX7RNPq4Gw0uod0Tk2RQCVLkqTFfN/smz q+3nXWTYotUqFlBZ7nyfcGsxNbAP/u31273Sx4RUWkjwJ/T35QRJSWZD0Ad5O7+zy61E Qmiw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=hc0v8G3i487Ys5ZeJsDG4atE3X7Sxu4cwRpY1JcVqQw=; b=srr9cCDZhMD1i82qcrmC1gp0+Yg506WVfDQJ/injrYTK1ajZhY8W09Qg6jwlMeCRbO G4j1yT7Nvw7BiQo7C4PKEd6TS6mcTXFaQDDijZmdqWFIkN93E+jOidfE+PIKYfFUXwqY mytFqd8jbeFyF01CIFOz7oMTe1hpYJ28UnVo3Z/O8okSeQU9V/7t4CCV/7gCnStoAtuC +8f+VP2K9ieqscZ7Mr3fwdn9+I2igSloWqUtyr8AeUnXMBFBl2mb833UqtJ+phRsgga5 AIaNzN3Rip0zk5YODEJMUWn98lTNyC1ZKBjnPRMZgdoZvhW2W2sa+ctdRmCdmbzuwCSw hOiw== X-Gm-Message-State: AOAM5331sJa1ECwBRmc+ZRpNBJdN3vyduR5z86K6DureinoSRERXDViD l8oo9xPc112nLiGppyApNMIIuNTn X-Google-Smtp-Source: ABdhPJxfvNnpYGcvdrC8pfXFBjVoF3hfv0P7R5oPXnVmvum3BhU7en/mFrhuGdSpbEpiqeTsGfxeZw== X-Received: by 2002:a63:e018:: with SMTP id e24mr34282236pgh.175.1594379491736; Fri, 10 Jul 2020 04:11:31 -0700 (PDT) Received: from gli-arch.genesyslogic.com.tw (60-251-58-169.HINET-IP.hinet.net. [60.251.58.169]) by smtp.gmail.com with ESMTPSA id i63sm5602434pfc.22.2020.07.10.04.11.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 10 Jul 2020 04:11:31 -0700 (PDT) From: Ben Chuang To: adrian.hunter@intel.com, ulf.hansson@linaro.org Cc: linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, ben.chuang@genesyslogic.com.tw, takahiro.akashi@linaro.org, greg.tu@genesyslogic.com.tw, Ben Chuang Subject: [RFC PATCH V3 16/21] mmc: sdhci: UHS-II support, export helper functions to a module Date: Fri, 10 Jul 2020 19:12:15 +0800 Message-Id: <20200710111215.29779-1-benchuanggli@gmail.com> X-Mailer: git-send-email 2.27.0 MIME-Version: 1.0 Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org From: AKASHI Takahiro Those exported functions will be utilized in the following commit to implement UHS-II support as a kernel module. Signed-off-by: Ben Chuang Signed-off-by: AKASHI Takahiro --- drivers/mmc/host/sdhci.c | 14 ++++++++------ drivers/mmc/host/sdhci.h | 10 ++++++++++ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index ca3d4a506e01..5d84e61f6ad9 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -57,8 +57,6 @@ EXPORT_SYMBOL_GPL(sdhci_uhs2_ops); static unsigned int debug_quirks = 0; static unsigned int debug_quirks2; -static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable); - static bool sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd); void sdhci_dumpregs(struct sdhci_host *host) @@ -225,13 +223,14 @@ static void sdhci_runtime_pm_bus_on(struct sdhci_host *host) pm_runtime_get_noresume(host->mmc->parent); } -static void sdhci_runtime_pm_bus_off(struct sdhci_host *host) +void sdhci_runtime_pm_bus_off(struct sdhci_host *host) { if (!host->bus_on) return; host->bus_on = false; pm_runtime_put_noidle(host->mmc->parent); } +EXPORT_SYMBOL_GPL(sdhci_runtime_pm_bus_off); void sdhci_reset(struct sdhci_host *host, u8 mask) { @@ -1560,12 +1559,13 @@ static void __sdhci_finish_mrq(struct sdhci_host *host, struct mmc_request *mrq) sdhci_led_deactivate(host); } -static void sdhci_finish_mrq(struct sdhci_host *host, struct mmc_request *mrq) +void sdhci_finish_mrq(struct sdhci_host *host, struct mmc_request *mrq) { __sdhci_finish_mrq(host, mrq); queue_work(host->complete_wq, &host->complete_work); } +EXPORT_SYMBOL_GPL(sdhci_finish_mrq); static void __sdhci_finish_data(struct sdhci_host *host, bool sw_data_timeout) { @@ -1644,10 +1644,11 @@ static void __sdhci_finish_data(struct sdhci_host *host, bool sw_data_timeout) } } -static void sdhci_finish_data(struct sdhci_host *host) +void sdhci_finish_data(struct sdhci_host *host) { __sdhci_finish_data(host, false); } +EXPORT_SYMBOL_GPL(sdhci_finish_data); static bool sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) { @@ -2991,7 +2992,7 @@ int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode) } EXPORT_SYMBOL_GPL(sdhci_execute_tuning); -static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable) +void sdhci_enable_preset_value(struct sdhci_host *host, bool enable) { /* Host Controller v3.00 defines preset value registers */ if (host->version < SDHCI_SPEC_300) @@ -3019,6 +3020,7 @@ static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable) host->preset_enabled = enable; } } +EXPORT_SYMBOL_GPL(sdhci_enable_preset_value); static void sdhci_post_req(struct mmc_host *mmc, struct mmc_request *mrq, int err) diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index f6732f33f29f..927aaba28932 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -893,4 +893,14 @@ void sdhci_switch_external_dma(struct sdhci_host *host, bool en); void sdhci_set_data_timeout_irq(struct sdhci_host *host, bool enable); void __sdhci_set_timeout(struct sdhci_host *host, struct mmc_command *cmd); +/* sdhci_uhs2.c needed */ +void sdhci_enable_preset_value(struct sdhci_host *host, bool enable); +void sdhci_finish_data(struct sdhci_host *host); +void sdhci_set_power(struct sdhci_host *host, unsigned char mode, + unsigned short vdd, unsigned short vdd2); +void sdhci_set_power_noreg(struct sdhci_host *host, unsigned char mode, + unsigned short vdd, unsigned short vdd2); +void sdhci_runtime_pm_bus_off(struct sdhci_host *host); +void sdhci_finish_mrq(struct sdhci_host *host, struct mmc_request *mrq); + #endif /* __SDHCI_HW_H */ From patchwork Fri Jul 10 11:12:26 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Chuang X-Patchwork-Id: 11656285 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id DDFE2618 for ; Fri, 10 Jul 2020 11:11:45 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B6FEF2078D for ; Fri, 10 Jul 2020 11:11:45 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="G0fEUeEa" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726757AbgGJLLo (ORCPT ); Fri, 10 Jul 2020 07:11:44 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41510 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726369AbgGJLLn (ORCPT ); Fri, 10 Jul 2020 07:11:43 -0400 Received: from mail-pg1-x543.google.com (mail-pg1-x543.google.com [IPv6:2607:f8b0:4864:20::543]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 85DBFC08C5CE; Fri, 10 Jul 2020 04:11:43 -0700 (PDT) Received: by mail-pg1-x543.google.com with SMTP id k27so2398253pgm.2; Fri, 10 Jul 2020 04:11:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=WeKkb5Q08GvJxjOOUs9BTxSi1/QgqFy93CtcPDqFzG8=; b=G0fEUeEarz/UE/Wf1KVxas3LEeaEl90pTuYhSutwgbaVWAfX8M1mmcz4+5Ygknz2VG 1kfj6mIopdiYyyAT+leMwel8gL8FuAZveMMujxG5mkw+M4YoukieaFQZHZYnlF13Xn6E HFmtoTcy9UkI0rTFYISEJ10j5k/pxxtsd9Tci7eCfaWdAP5amdU6L6koniLW04FfI0hj hWV9JfgMX40sgSMqhCbHmirg34d0+w4fELi8uzh2bpFbJkomuSjIG43ac1MRSnTkUlsQ G2XdPYkFZRnWCFFs5wRgGJZsvvHM5naFTViUEn13mADxQLorC3V5XtIJZj0AT3mrnqcI ki7w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=WeKkb5Q08GvJxjOOUs9BTxSi1/QgqFy93CtcPDqFzG8=; b=L0Gw+CWkfSUbakXQgQXI21DNGciyVoWOhTqyPisJxw+Pf8Kr/Zs10eCdU4o6TFxnGv 9vFrvQRkRqLytLq5BZJIhoksVooRheaurhdYiWpC6AJmNCeldQl8yxKHVpvE9RzIwZhr GyV/HbeIRQJZUmKW3uQH7BHzUTkrd3P8l7P86yQdmiFMvp2CzIk9ZAdcqFCnXxv4YPKI ZDIw2HwH4W32QFEzs14Zj8QgdVmU19RX8WOUPgL932sPD/oD1vgQ+KKp9rVzwZIZW+zI tw8j9drRu+88PD7ftpFKNIBV2qW3zE6WOphnhPRgACatIQ7wgijkqL68uYFXUMoq4e+4 umwA== X-Gm-Message-State: AOAM530DKs1qwv1JV/WqGyKGmcdE9rcQ8OtINtewrxHtxiZzIDjKYmBV +NV5m3fP6UVwPOoUTNvyAoM= X-Google-Smtp-Source: ABdhPJx5zFRh5Ts0aDg2eE28VAjifIolasfKjwquJpHA8f4u376sh+8xxAVdMd6dgKSRzrYlLzuBsQ== X-Received: by 2002:a63:cd4d:: with SMTP id a13mr58367404pgj.49.1594379502887; Fri, 10 Jul 2020 04:11:42 -0700 (PDT) Received: from gli-arch.genesyslogic.com.tw (60-251-58-169.HINET-IP.hinet.net. [60.251.58.169]) by smtp.gmail.com with ESMTPSA id u8sm5336222pjn.24.2020.07.10.04.11.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 10 Jul 2020 04:11:42 -0700 (PDT) From: Ben Chuang To: adrian.hunter@intel.com, ulf.hansson@linaro.org Cc: linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, ben.chuang@genesyslogic.com.tw, takahiro.akashi@linaro.org, greg.tu@genesyslogic.com.tw, Ben Chuang Subject: [RFC PATCH V3 17/21] mmc: sdhci: UHS-II support, implement operations as a module Date: Fri, 10 Jul 2020 19:12:26 +0800 Message-Id: <20200710111226.29831-1-benchuanggli@gmail.com> X-Mailer: git-send-email 2.27.0 MIME-Version: 1.0 Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org From: AKASHI Takahiro All the UHS-II operations in struct sdhci_uhs2_ops are implemented here and exported as a kernel module. Signed-off-by: Ben Chuang Signed-off-by: AKASHI Takahiro --- drivers/mmc/host/Makefile | 1 + drivers/mmc/host/sdhci-uhs2.c | 794 ++++++++++++++++++++++++++++++++++ 2 files changed, 795 insertions(+) create mode 100644 drivers/mmc/host/sdhci-uhs2.c diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile index 4d5bcb0144a0..e51430d8f85d 100644 --- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_MMC_PXA) += pxamci.o obj-$(CONFIG_MMC_MXC) += mxcmmc.o obj-$(CONFIG_MMC_MXS) += mxs-mmc.o obj-$(CONFIG_MMC_SDHCI) += sdhci.o +obj-$(CONFIG_MMC_SDHCI_UHS2) += sdhci-uhs2.o obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.o sdhci-pci-y += sdhci-pci-core.o sdhci-pci-o2micro.o sdhci-pci-arasan.o \ sdhci-pci-dwc-mshc.o sdhci-pci-gli.o diff --git a/drivers/mmc/host/sdhci-uhs2.c b/drivers/mmc/host/sdhci-uhs2.c new file mode 100644 index 000000000000..3cb13071dd9d --- /dev/null +++ b/drivers/mmc/host/sdhci-uhs2.c @@ -0,0 +1,794 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * linux/drivers/mmc/host/sdhci_uhs2.c - Secure Digital Host Controller + * Interface driver + * + * Copyright (C) 2014 Intel Corp, All Rights Reserved. + * Copyright (C) 2020 Genesys Logic, Inc. + * Authors: Ben Chuang + * Copyright (C) 2020 Linaro Limited + * Author: AKASHI Takahiro + */ + +#include +#include +#include + +#include + +#include "sdhci.h" +#include "sdhci-uhs2.h" + +#define DRIVER_NAME "sdhci_uhs2" +#define DBG(f, x...) \ + pr_debug(DRIVER_NAME " [%s()]: " f, __func__, ## x) + +static void sdhci_clear_set_irqs(struct sdhci_host *host, u32 clear, u32 set) +{ + u32 ier; + + ier = sdhci_readl(host, SDHCI_INT_ENABLE); + ier &= ~clear; + ier |= set; + sdhci_writel(host, ier, SDHCI_INT_ENABLE); + sdhci_writel(host, ier, SDHCI_SIGNAL_ENABLE); +} + +/** + * sdhci_uhs2_clear_set_irqs - set Error Interrupt Status Enable register + * @host: SDHCI host + * @clear: bit-wise clear mask + * @set: bit-wise set mask + * + * Set/unset bits in UHS-II Error Interrupt Status Enable register + */ +void sdhci_uhs2_clear_set_irqs(struct sdhci_host *host, u32 clear, u32 set) +{ + u32 ier; + + ier = sdhci_readl(host, SDHCI_UHS2_ERR_INT_STATUS_EN); + ier &= ~clear; + ier |= set; + sdhci_writel(host, ier, SDHCI_UHS2_ERR_INT_STATUS_EN); + sdhci_writel(host, ier, SDHCI_UHS2_ERR_INT_SIG_EN); +} +EXPORT_SYMBOL_GPL(sdhci_uhs2_clear_set_irqs); + +/** + * sdhci_uhs2_reset - invoke SW reset + * @host: SDHCI host + * @mask: Control mask + * + * Invoke SW reset, depending on a bit in @mask and wait for completion. + */ +void sdhci_uhs2_reset(struct sdhci_host *host, u16 mask) +{ + unsigned long timeout; + + if (!(host->mmc->caps & MMC_CAP_UHS2)) + return; + + sdhci_writew(host, mask, SDHCI_UHS2_SW_RESET); + + if (mask & SDHCI_UHS2_SW_RESET_FULL) { + host->clock = 0; + /* Reset-all turns off SD Bus Power */ + if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON) + sdhci_runtime_pm_bus_off(host); + } + + /* Wait max 100 ms */ + timeout = 10000; + + /* hw clears the bit when it's done */ + while (sdhci_readw(host, SDHCI_UHS2_SW_RESET) & mask) { + if (timeout == 0) { + pr_err("%s: %s: Reset 0x%x never completed.\n", + __func__, mmc_hostname(host->mmc), (int)mask); + pr_err("%s: clean reset bit\n", + mmc_hostname(host->mmc)); + sdhci_writeb(host, 0, SDHCI_UHS2_SW_RESET); + return; + } + timeout--; + udelay(10); + } +} +EXPORT_SYMBOL_GPL(sdhci_uhs2_reset); + +static u8 sdhci_calc_timeout_uhs2(struct sdhci_host *host, u8 *cmd_res, + u8 *dead_lock) +{ + u8 count; + unsigned int cmd_res_timeout, dead_lock_timeout, current_timeout; + + /* + * If the host controller provides us with an incorrect timeout + * value, just skip the check and use 0xE. The hardware may take + * longer to time out, but that's much better than having a too-short + * timeout value. + */ + if (host->quirks & SDHCI_QUIRK_BROKEN_TIMEOUT_VAL) { + *cmd_res = 0xE; + *dead_lock = 0xE; + return 0xE; + } + + /* timeout in us */ + cmd_res_timeout = 5 * 1000; + dead_lock_timeout = 1 * 1000 * 1000; + + /* + * Figure out needed cycles. + * We do this in steps in order to fit inside a 32 bit int. + * The first step is the minimum timeout, which will have a + * minimum resolution of 6 bits: + * (1) 2^13*1000 > 2^22, + * (2) host->timeout_clk < 2^16 + * => + * (1) / (2) > 2^6 + */ + count = 0; + current_timeout = (1 << 13) * 1000 / host->timeout_clk; + while (current_timeout < cmd_res_timeout) { + count++; + current_timeout <<= 1; + if (count >= 0xF) + break; + } + + if (count >= 0xF) { + DBG("%s: Too large timeout 0x%x requested for CMD_RES!\n", + mmc_hostname(host->mmc), count); + count = 0xE; + } + *cmd_res = count; + + count = 0; + current_timeout = (1 << 13) * 1000 / host->timeout_clk; + while (current_timeout < dead_lock_timeout) { + count++; + current_timeout <<= 1; + if (count >= 0xF) + break; + } + + if (count >= 0xF) { + DBG("%s: Too large timeout 0x%x requested for DEADLOCK!\n", + mmc_hostname(host->mmc), count); + count = 0xE; + } + *dead_lock = count; + + return count; +} + +static void sdhci_uhs2_set_timeout(struct sdhci_host *host) +{ + u8 cmd_res, dead_lock; + + sdhci_calc_timeout_uhs2(host, &cmd_res, &dead_lock); + cmd_res |= dead_lock << SDHCI_UHS2_TIMER_CTRL_DEADLOCK_SHIFT; + sdhci_writeb(host, cmd_res, SDHCI_UHS2_TIMER_CTRL); +} + +static void sdhci_uhs2_set_transfer_mode(struct sdhci_host *host, + struct mmc_command *cmd) +{ + u16 mode; + struct mmc_data *data = cmd->data; + u16 arg; + + if (!data) { + /* clear Auto CMD settings for no data CMDs */ + arg = cmd->uhs2_cmd->arg; + if ((((arg & 0xF) << 8) | ((arg >> 8) & 0xFF)) == + UHS2_DEV_CMD_TRANS_ABORT) { + mode = 0; + } else { + mode = sdhci_readw(host, SDHCI_UHS2_TRANS_MODE); + if (cmd->opcode == MMC_STOP_TRANSMISSION || + cmd->opcode == MMC_ERASE) + mode |= SDHCI_UHS2_TRNS_WAIT_EBSY; + else + /* send status mode */ + if (cmd->opcode == MMC_SEND_STATUS) + mode = 0; + } + + if (IS_ENABLED(CONFIG_MMC_DEBUG)) + DBG("UHS2 no data trans mode is 0x%x.\n", mode); + + sdhci_writew(host, mode, SDHCI_UHS2_TRANS_MODE); + return; + } + + WARN_ON(!host->data); + + mode = SDHCI_UHS2_TRNS_BLK_CNT_EN | SDHCI_UHS2_TRNS_WAIT_EBSY; + if (data->flags & MMC_DATA_WRITE) + mode |= SDHCI_UHS2_TRNS_DATA_TRNS_WRT; + + if (data->blocks == 1 && + data->blksz != 512 && + cmd->opcode != MMC_READ_SINGLE_BLOCK && + cmd->opcode != MMC_WRITE_BLOCK) { + mode &= ~SDHCI_UHS2_TRNS_BLK_CNT_EN; + mode |= SDHCI_UHS2_TRNS_BLK_BYTE_MODE; + } + + if (host->flags & SDHCI_REQ_USE_DMA) + mode |= SDHCI_UHS2_TRNS_DMA; + + if ((host->mmc->flags & MMC_UHS2_2L_HD) && !cmd->uhs2_tmode0_flag) + mode |= SDHCI_UHS2_TRNS_2L_HD; + + sdhci_writew(host, mode, SDHCI_UHS2_TRANS_MODE); + + if (IS_ENABLED(CONFIG_MMC_DEBUG)) + DBG("UHS2 trans mode is 0x%x.\n", mode); +} + +static void sdhci_uhs2_send_command(struct sdhci_host *host, + struct mmc_command *cmd) +{ + int i, j; + int cmd_reg; + + if (host->mmc->flags & MMC_UHS2_INITIALIZED) { + if (!cmd->uhs2_cmd) { + pr_err("%s: fatal error, no uhs2_cmd!\n", + mmc_hostname(host->mmc)); + return; + } + } + + i = 0; + sdhci_writel(host, + ((u32)cmd->uhs2_cmd->arg << 16) | + (u32)cmd->uhs2_cmd->header, + SDHCI_UHS2_CMD_PACKET + i); + i += 4; + + /* + * Per spec, playload (config) should be MSB before sending out. + * But we don't need convert here because had set payload as + * MSB when preparing config read/write commands. + */ + for (j = 0; j < cmd->uhs2_cmd->payload_len / sizeof(u32); j++) { + sdhci_writel(host, *(cmd->uhs2_cmd->payload + j), + SDHCI_UHS2_CMD_PACKET + i); + i += 4; + } + + for ( ; i < SDHCI_UHS2_CMD_PACK_MAX_LEN; i += 4) + sdhci_writel(host, 0, SDHCI_UHS2_CMD_PACKET + i); + + if (IS_ENABLED(CONFIG_MMC_DEBUG)) { + DBG("UHS2 CMD packet_len = %d.\n", cmd->uhs2_cmd->packet_len); + for (i = 0; i < cmd->uhs2_cmd->packet_len; i++) + DBG("UHS2 CMD_PACKET[%d] = 0x%x.\n", i, + sdhci_readb(host, SDHCI_UHS2_CMD_PACKET + i)); + } + + cmd_reg = cmd->uhs2_cmd->packet_len << + SDHCI_UHS2_COMMAND_PACK_LEN_SHIFT; + if ((cmd->flags & MMC_CMD_MASK) == MMC_CMD_ADTC) + cmd_reg |= SDHCI_UHS2_COMMAND_DATA; + if (cmd->opcode == MMC_STOP_TRANSMISSION) + cmd_reg |= SDHCI_UHS2_COMMAND_CMD12; + + /* UHS2 Native ABORT */ + if ((cmd->uhs2_cmd->header & UHS2_NATIVE_PACKET) && + ((((cmd->uhs2_cmd->arg & 0xF) << 8) | + ((cmd->uhs2_cmd->arg >> 8) & 0xFF)) == UHS2_DEV_CMD_TRANS_ABORT)) + cmd_reg |= SDHCI_UHS2_COMMAND_TRNS_ABORT; + + /* UHS2 Native DORMANT */ + if ((cmd->uhs2_cmd->header & UHS2_NATIVE_PACKET) && + ((((cmd->uhs2_cmd->arg & 0xF) << 8) | + ((cmd->uhs2_cmd->arg >> 8) & 0xFF)) == + UHS2_DEV_CMD_GO_DORMANT_STATE)) + cmd_reg |= SDHCI_UHS2_COMMAND_DORMANT; + + DBG("0x%x is set to UHS2 CMD register.\n", cmd_reg); + + sdhci_writew(host, cmd_reg, SDHCI_UHS2_COMMAND); +} + +static void sdhci_uhs2_finish_command(struct sdhci_host *host) +{ + int i; + bool b_read_a0 = 0; + + if (host->mmc->flags & MMC_UHS2_INITIALIZED) { + u8 resp; + u8 ecode; + + resp = sdhci_readb(host, SDHCI_UHS2_RESPONSE + 2); + if (resp & UHS2_RES_NACK_MASK) { + ecode = (resp >> UHS2_RES_ECODE_POS) & + UHS2_RES_ECODE_MASK; + pr_err("%s: NACK is got, ECODE=0x%x.\n", + mmc_hostname(host->mmc), ecode); + } + b_read_a0 = 1; + } + + if (host->cmd->uhs2_resp && + host->cmd->uhs2_resp_len && + host->cmd->uhs2_resp_len <= 20) { + /* Get whole response of some native CCMD, like + * DEVICE_INIT, ENUMERATE. + */ + for (i = 0; i < host->cmd->uhs2_resp_len; i++) + host->cmd->uhs2_resp[i] = + sdhci_readb(host, + SDHCI_UHS2_RESPONSE + i); + } else { + /* Get SD CMD response and Payload for some read + * CCMD, like INQUIRY_CFG. + */ + /* Per spec (p136), payload field is divided into + * a unit of DWORD and transmission order within + * a DWORD is big endian. + */ + if (!b_read_a0) + sdhci_readl(host, SDHCI_UHS2_RESPONSE); + for (i = 4; i < 20; i += 4) { + host->cmd->resp[i / 4 - 1] = + (sdhci_readb(host, + SDHCI_UHS2_RESPONSE + i) << 24) | + (sdhci_readb(host, + SDHCI_UHS2_RESPONSE + i + 1) + << 16) | + (sdhci_readb(host, + SDHCI_UHS2_RESPONSE + i + 2) + << 8) | + sdhci_readb(host, SDHCI_UHS2_RESPONSE + i + 3); + } + } +} + +static void sdhci_uhs2_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) +{ + u8 cmd_res, dead_lock; + u16 ctrl_2; + unsigned long flags; + + spin_lock_irqsave(&host->lock, flags); + + /* UHS2 Timeout Control */ + sdhci_calc_timeout_uhs2(host, &cmd_res, &dead_lock); + + /* change to use calculate value */ + cmd_res |= dead_lock << SDHCI_UHS2_TIMER_CTRL_DEADLOCK_SHIFT; + + sdhci_uhs2_clear_set_irqs(host, + SDHCI_UHS2_ERR_INT_STATUS_RES_TIMEOUT | + SDHCI_UHS2_ERR_INT_STATUS_DEADLOCK_TIMEOUT, + 0); + sdhci_writeb(host, cmd_res, SDHCI_UHS2_TIMER_CTRL); + sdhci_uhs2_clear_set_irqs(host, 0, + SDHCI_UHS2_ERR_INT_STATUS_RES_TIMEOUT | + SDHCI_UHS2_ERR_INT_STATUS_DEADLOCK_TIMEOUT); + + /* UHS2 timing */ + ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); + if (ios->timing == MMC_TIMING_UHS2) + ctrl_2 |= SDHCI_CTRL_UHS_2 | SDHCI_CTRL_UHS2_INTERFACE_EN; + else + ctrl_2 &= ~(SDHCI_CTRL_UHS_2 | SDHCI_CTRL_UHS2_INTERFACE_EN); + sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); + + if (!(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN)) + sdhci_enable_preset_value(host, true); + + /* Set VDD2 */ + ios->vdd = fls(host->mmc->ocr_avail) - 1; + ios->vdd2 = fls(host->mmc->ocr_avail_uhs2) - 1; + + sdhci_set_power(host, ios->power_mode, ios->vdd, ios->vdd2); + udelay(100); + + host->timing = ios->timing; + sdhci_set_clock(host, host->clock); + + spin_unlock_irqrestore(&host->lock, flags); +} + +static int sdhci_uhs2_interface_detect(struct sdhci_host *host) +{ + int timeout = 100; + + udelay(200); /* wait for 200us before check */ + + while (!(sdhci_readl(host, SDHCI_PRESENT_STATE) & + SDHCI_UHS2_IF_DETECT)) { + if (timeout == 0) { + pr_warn("%s: not detect UHS2 interface in 200us.\n", + mmc_hostname(host->mmc)); + sdhci_dumpregs(host); + return -EIO; + } + timeout--; + mdelay(1); + } + + /* Enable UHS2 error interrupts */ + sdhci_uhs2_clear_set_irqs(host, SDHCI_INT_ALL_MASK, + SDHCI_UHS2_ERR_INT_STATUS_MASK); + + timeout = 150; + while (!(sdhci_readl(host, SDHCI_PRESENT_STATE) & + SDHCI_UHS2_LANE_SYNC)) { + if (timeout == 0) { + pr_warn("%s: UHS2 Lane sync fail in 150ms.\n", + mmc_hostname(host->mmc)); + sdhci_dumpregs(host); + return -EIO; + } + timeout--; + mdelay(1); + } + + DBG("%s: UHS2 Lane synchronized in UHS2 mode, PHY is initialized.\n", + mmc_hostname(host->mmc)); + return 0; +} + +static int sdhci_uhs2_init(struct sdhci_host *host) +{ + u16 caps_ptr = 0; + u32 caps_gen = 0; + u32 caps_phy = 0; + u32 caps_tran[2] = {0, 0}; + struct mmc_host *mmc = host->mmc; + + /* + * TODO: may add corresponding members in sdhci_host to + * keep these caps. + */ + caps_ptr = sdhci_readw(host, SDHCI_UHS2_HOST_CAPS_PTR); + if (caps_ptr < 0x100 || caps_ptr > 0x1FF) { + pr_err("%s: SDHCI_UHS2_HOST_CAPS_PTR(%d) is wrong.\n", + mmc_hostname(mmc), caps_ptr); + return -ENODEV; + } + caps_gen = sdhci_readl(host, + caps_ptr + SDHCI_UHS2_HOST_CAPS_GEN_OFFSET); + caps_phy = sdhci_readl(host, + caps_ptr + SDHCI_UHS2_HOST_CAPS_PHY_OFFSET); + caps_tran[0] = sdhci_readl(host, + caps_ptr + SDHCI_UHS2_HOST_CAPS_TRAN_OFFSET); + caps_tran[1] = sdhci_readl(host, + caps_ptr + + SDHCI_UHS2_HOST_CAPS_TRAN_1_OFFSET); + + /* General Caps */ + mmc->uhs2_caps.dap = caps_gen & SDHCI_UHS2_HOST_CAPS_GEN_DAP_MASK; + mmc->uhs2_caps.gap = (caps_gen & SDHCI_UHS2_HOST_CAPS_GEN_GAP_MASK) >> + SDHCI_UHS2_HOST_CAPS_GEN_GAP_SHIFT; + mmc->uhs2_caps.n_lanes = (caps_gen & SDHCI_UHS2_HOST_CAPS_GEN_LANE_MASK) + >> SDHCI_UHS2_HOST_CAPS_GEN_LANE_SHIFT; + mmc->uhs2_caps.addr64 = + (caps_gen & SDHCI_UHS2_HOST_CAPS_GEN_ADDR_64) ? 1 : 0; + mmc->uhs2_caps.card_type = + (caps_gen & SDHCI_UHS2_HOST_CAPS_GEN_DEV_TYPE_MASK) >> + SDHCI_UHS2_HOST_CAPS_GEN_DEV_TYPE_SHIFT; + + /* PHY Caps */ + mmc->uhs2_caps.phy_rev = caps_phy & SDHCI_UHS2_HOST_CAPS_PHY_REV_MASK; + mmc->uhs2_caps.speed_range = + (caps_phy & SDHCI_UHS2_HOST_CAPS_PHY_RANGE_MASK) + >> SDHCI_UHS2_HOST_CAPS_PHY_RANGE_SHIFT; + mmc->uhs2_caps.n_lss_sync = + (caps_phy & SDHCI_UHS2_HOST_CAPS_PHY_N_LSS_SYN_MASK) + >> SDHCI_UHS2_HOST_CAPS_PHY_N_LSS_SYN_SHIFT; + mmc->uhs2_caps.n_lss_dir = + (caps_phy & SDHCI_UHS2_HOST_CAPS_PHY_N_LSS_DIR_MASK) + >> SDHCI_UHS2_HOST_CAPS_PHY_N_LSS_DIR_SHIFT; + if (mmc->uhs2_caps.n_lss_sync == 0) + mmc->uhs2_caps.n_lss_sync = 16 << 2; + else + mmc->uhs2_caps.n_lss_sync <<= 2; + if (mmc->uhs2_caps.n_lss_dir == 0) + mmc->uhs2_caps.n_lss_dir = 16 << 3; + else + mmc->uhs2_caps.n_lss_dir <<= 3; + + /* LINK/TRAN Caps */ + mmc->uhs2_caps.link_rev = + caps_tran[0] & SDHCI_UHS2_HOST_CAPS_TRAN_LINK_REV_MASK; + mmc->uhs2_caps.n_fcu = + (caps_tran[0] & SDHCI_UHS2_HOST_CAPS_TRAN_N_FCU_MASK) + >> SDHCI_UHS2_HOST_CAPS_TRAN_N_FCU_SHIFT; + if (mmc->uhs2_caps.n_fcu == 0) + mmc->uhs2_caps.n_fcu = 256; + mmc->uhs2_caps.host_type = + (caps_tran[0] & SDHCI_UHS2_HOST_CAPS_TRAN_HOST_TYPE_MASK) + >> SDHCI_UHS2_HOST_CAPS_TRAN_HOST_TYPE_SHIFT; + mmc->uhs2_caps.maxblk_len = + (caps_tran[0] & SDHCI_UHS2_HOST_CAPS_TRAN_BLK_LEN_MASK) + >> SDHCI_UHS2_HOST_CAPS_TRAN_BLK_LEN_SHIFT; + mmc->uhs2_caps.n_data_gap = + caps_tran[1] & SDHCI_UHS2_HOST_CAPS_TRAN_1_N_DATA_GAP_MASK; + + return 0; +} + +static int sdhci_uhs2_do_detect_init(struct sdhci_host *host) +{ + unsigned long flags; + int ret = -EIO; + + DBG("%s: begin UHS2 init.\n", __func__); + spin_lock_irqsave(&host->lock, flags); + + if (sdhci_uhs2_interface_detect(host)) { + pr_warn("%s: cannot detect UHS2 interface.\n", + mmc_hostname(host->mmc)); + goto out; + } + + if (sdhci_uhs2_init(host)) { + pr_warn("%s: UHS2 init fail.\n", mmc_hostname(host->mmc)); + goto out; + } + + /* Init complete, do soft reset and enable UHS2 error irqs. */ + sdhci_uhs2_reset(host, SDHCI_UHS2_SW_RESET_SD); + sdhci_uhs2_clear_set_irqs(host, SDHCI_INT_ALL_MASK, + SDHCI_UHS2_ERR_INT_STATUS_MASK); + /* + * !!! SDHCI_INT_ENABLE and SDHCI_SIGNAL_ENABLE was cleared + * by SDHCI_UHS2_SW_RESET_SD + */ + sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); + sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); + + ret = 0; +out: + spin_unlock_irqrestore(&host->lock, flags); + return ret; +} + +static void sdhci_uhs2_set_config(struct sdhci_host *host) +{ + u32 value; + u16 sdhci_uhs2_set_ptr = sdhci_readw(host, SDHCI_UHS2_SET_PTR); + u16 sdhci_uhs2_gen_set_reg = (sdhci_uhs2_set_ptr + 0); + u16 sdhci_uhs2_phy_set_reg = (sdhci_uhs2_set_ptr + 4); + u16 sdhci_uhs2_tran_set_reg = (sdhci_uhs2_set_ptr + 8); + u16 sdhci_uhs2_tran_set_1_reg = (sdhci_uhs2_set_ptr + 12); + + /* Set Gen Settings */ + sdhci_writel(host, host->mmc->uhs2_caps.n_lanes_set << + SDHCI_UHS2_GEN_SET_N_LANES_POS, sdhci_uhs2_gen_set_reg); + + /* Set PHY Settings */ + value = (host->mmc->uhs2_caps.n_lss_dir_set << + SDHCI_UHS2_PHY_SET_N_LSS_DIR_POS) | + (host->mmc->uhs2_caps.n_lss_sync_set << + SDHCI_UHS2_PHY_SET_N_LSS_SYN_POS); + if (host->mmc->flags & MMC_UHS2_SPEED_B) + value |= 1 << SDHCI_UHS2_PHY_SET_SPEED_POS; + sdhci_writel(host, value, sdhci_uhs2_phy_set_reg); + + /* Set LINK-TRAN Settings */ + value = (host->mmc->uhs2_caps.max_retry_set << + SDHCI_UHS2_TRAN_SET_RETRY_CNT_POS) | + (host->mmc->uhs2_caps.n_fcu_set << + SDHCI_UHS2_TRAN_SET_N_FCU_POS); + sdhci_writel(host, value, sdhci_uhs2_tran_set_reg); + sdhci_writel(host, host->mmc->uhs2_caps.n_data_gap_set, + sdhci_uhs2_tran_set_1_reg); +} + +static int sdhci_uhs2_check_dormant(struct sdhci_host *host) +{ + int timeout = 100; + + while (!(sdhci_readl(host, SDHCI_PRESENT_STATE) & + SDHCI_UHS2_IN_DORMANT_STATE)) { + if (timeout == 0) { + pr_warn("%s: UHS2 IN_DORMANT fail in 100ms.\n", + mmc_hostname(host->mmc)); + sdhci_dumpregs(host); + return -EIO; + } + timeout--; + mdelay(1); + } + return 0; +} + +static int sdhci_uhs2_do_set_reg(struct sdhci_host *host, enum uhs2_act act) +{ + unsigned long flags; + int err = 0; + u16 sdhci_uhs2_set_ptr = sdhci_readw(host, SDHCI_UHS2_SET_PTR); + u16 sdhci_uhs2_phy_set_reg = (sdhci_uhs2_set_ptr + 4); + + DBG("Begin sdhci_uhs2_set_reg, act %d.\n", act); + spin_lock_irqsave(&host->lock, flags); + + switch (act) { + case SET_CONFIG: + sdhci_uhs2_set_config(host); + break; + case ENABLE_INT: + sdhci_clear_set_irqs(host, 0, SDHCI_INT_CARD_INT); + break; + case DISABLE_INT: + sdhci_clear_set_irqs(host, SDHCI_INT_CARD_INT, 0); + break; + case SET_SPEED_B: + sdhci_writeb(host, 1 << SDHCI_UHS2_PHY_SET_SPEED_POS, + sdhci_uhs2_phy_set_reg); + break; + case CHECK_DORMANT: + err = sdhci_uhs2_check_dormant(host); + break; + default: + pr_err("%s: input action %d is wrong!\n", + mmc_hostname(host->mmc), act); + err = -EIO; + break; + } + + spin_unlock_irqrestore(&host->lock, flags); + return err; +} + +static void sdhci_uhs2_irq(struct sdhci_host *host) +{ + u32 uhs2mask; + struct mmc_command *cmd = host->cmd; + + uhs2mask = sdhci_readl(host, SDHCI_UHS2_ERR_INT_STATUS); + DBG("*** %s got UHS2 interrupt: 0x%08x\n", + mmc_hostname(host->mmc), uhs2mask); + + sdhci_writel(host, uhs2mask & SDHCI_UHS2_ERR_INT_STATUS_MASK, + SDHCI_UHS2_ERR_INT_STATUS); + + if (!(uhs2mask & SDHCI_UHS2_ERR_INT_STATUS_MASK)) + return; + + if (uhs2mask & SDHCI_UHS2_ERR_INT_STATUS_CMD_MASK) { + if (!host->cmd) { + pr_err("%s: Got cmd interrupt 0x%08x but no cmd.\n", + mmc_hostname(host->mmc), + (unsigned int)uhs2mask); + sdhci_dumpregs(host); + return; + } + host->cmd->error = -EILSEQ; + if (uhs2mask & SDHCI_UHS2_ERR_INT_STATUS_RES_TIMEOUT) + host->cmd->error = -ETIMEDOUT; + } + + if (uhs2mask & SDHCI_UHS2_ERR_INT_STATUS_DATA_MASK) { + if (!host->data) { + pr_err("%s: Got data interrupt 0x%08x but no data.\n", + mmc_hostname(host->mmc), + (unsigned int)uhs2mask); + sdhci_dumpregs(host); + return; + } + + if (uhs2mask & SDHCI_UHS2_ERR_INT_STATUS_DEADLOCK_TIMEOUT) { + pr_err("%s: Got deadlock timeout interrupt 0x%08x\n", + mmc_hostname(host->mmc), + (unsigned int)uhs2mask); + host->data->error = -ETIMEDOUT; + } else if (uhs2mask & SDHCI_UHS2_ERR_INT_STATUS_ADMA) { + pr_err("%s: ADMA error = 0x %x\n", + mmc_hostname(host->mmc), + sdhci_readb(host, SDHCI_ADMA_ERROR)); + host->data->error = -EIO; + } else { + host->data->error = -EILSEQ; + } + } + + if (host->data && host->data->error) + sdhci_finish_data(host); + else + sdhci_finish_mrq(host, cmd->mrq); +} + +static int sdhci_uhs2_add_host(struct sdhci_host *host, u32 caps1) +{ + struct mmc_host *mmc; + u32 max_current_caps2; + + if (host->version < SDHCI_SPEC_400) + return 0; + + mmc = host->mmc; + + /* Support UHS2 */ + if (caps1 & SDHCI_SUPPORT_UHS2) { + mmc->caps |= MMC_CAP_UHS2; + mmc->flags |= MMC_UHS2_SUPPORT; + } + + max_current_caps2 = sdhci_readl(host, SDHCI_MAX_CURRENT_1); + + if ((caps1 & SDHCI_SUPPORT_VDD2_180) && + !max_current_caps2 && + !IS_ERR(mmc->supply.vmmc2)) { + /* UHS2 - VDD2 */ + int curr = regulator_get_current_limit(mmc->supply.vmmc2); + + if (curr > 0) { + /* convert to SDHCI_MAX_CURRENT format */ + curr = curr / 1000; /* convert to mA */ + curr = curr / SDHCI_MAX_CURRENT_MULTIPLIER; + curr = min_t(u32, curr, SDHCI_MAX_CURRENT_LIMIT); + max_current_caps2 = curr; + } + } + + if (caps1 & SDHCI_SUPPORT_VDD2_180) { + mmc->ocr_avail_uhs2 |= MMC_VDD2_165_195; + /* + * UHS2 doesn't require this. Only UHS-I bus needs to set + * max current. + */ + mmc->max_current_180_vdd2 = (max_current_caps2 & + SDHCI_MAX_CURRENT_VDD2_180_MASK) * + SDHCI_MAX_CURRENT_MULTIPLIER; + } else { + mmc->caps &= ~MMC_CAP_UHS2; + mmc->flags &= ~MMC_UHS2_SUPPORT; + } + + return 0; +} + +static void sdhci_uhs2_remove_host(struct sdhci_host *host, int dead) +{ + if (!(host->mmc) || !(host->mmc->flags & MMC_UHS2_SUPPORT)) + return; + + if (!dead) + sdhci_uhs2_reset(host, SDHCI_UHS2_SW_RESET_FULL); + + sdhci_writel(host, 0, SDHCI_UHS2_ERR_INT_STATUS_EN); + sdhci_writel(host, 0, SDHCI_UHS2_ERR_INT_SIG_EN); + host->mmc->flags &= ~MMC_UHS2_SUPPORT; + host->mmc->flags &= ~MMC_UHS2_INITIALIZED; +} + +static int __init sdhci_uhs2_host_init(void) +{ + sdhci_uhs2_ops.reset = sdhci_uhs2_reset; + sdhci_uhs2_ops.set_timeout = sdhci_uhs2_set_timeout; + sdhci_uhs2_ops.set_transfer_mode = sdhci_uhs2_set_transfer_mode; + sdhci_uhs2_ops.send_command = sdhci_uhs2_send_command; + sdhci_uhs2_ops.finish_command = sdhci_uhs2_finish_command; + sdhci_uhs2_ops.do_set_ios = sdhci_uhs2_do_set_ios; + sdhci_uhs2_ops.do_detect_init = sdhci_uhs2_do_detect_init; + sdhci_uhs2_ops.do_set_reg = sdhci_uhs2_do_set_reg; + sdhci_uhs2_ops.irq = sdhci_uhs2_irq; + sdhci_uhs2_ops.add_host = sdhci_uhs2_add_host; + sdhci_uhs2_ops.remove_host = sdhci_uhs2_remove_host; + + return 0; +} +module_init(sdhci_uhs2_host_init); + +static void __exit sdhci_uhs2_exit(void) +{ + struct sdhci_uhs2_ops nops = {}; + + sdhci_uhs2_ops = nops; +} +module_exit(sdhci_uhs2_exit); + +MODULE_AUTHOR("Intel, Genesys Logic, Linaro"); +MODULE_DESCRIPTION("MMC UHS-II Support"); +MODULE_LICENSE("GPL v2"); From patchwork Fri Jul 10 11:12:36 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Chuang X-Patchwork-Id: 11656287 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 7E07313B6 for ; Fri, 10 Jul 2020 11:12:15 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 641B92077D for ; Fri, 10 Jul 2020 11:12:15 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="TWFUzpMk" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728030AbgGJLLy (ORCPT ); Fri, 10 Jul 2020 07:11:54 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41536 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728010AbgGJLLx (ORCPT ); Fri, 10 Jul 2020 07:11:53 -0400 Received: from mail-pl1-x641.google.com (mail-pl1-x641.google.com [IPv6:2607:f8b0:4864:20::641]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A1AC6C08C5CE; Fri, 10 Jul 2020 04:11:53 -0700 (PDT) Received: by mail-pl1-x641.google.com with SMTP id x11so2116149plo.7; Fri, 10 Jul 2020 04:11:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=LNlz30IWOHI0EzUpbjw6GP+YcxLHXUvj3TU9mudyrqE=; b=TWFUzpMkGWdEJR/dntGvghD70r4RnseZlevMSVT2OkXokxRQRxOnIW2L+DZn89hDF9 exlyHvKx3g1QMGKjL5jO+YIsy2dySSJh+3CX3ZsgyVQlVT/4v4LW3TviUKuUn6pPim5q QvoZkSwSfFDHanr0rbYx4X3jLHpqpUHH438yPXC8tlZaVqj83zCBkbuYlYa57p/WgevE UZdrtdPnuAIDV9QZXBDcukGQ72rPFHX1uv4n56SNfezP5qPtqC9k7rMvEKGQqe14yE7f B4Ok65wV1CfcJSWLK9w1nKFnO61zIEaLIRZSH3laz3V9tvPYAqa0ckflwnCchJPCnvl8 tv1g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=LNlz30IWOHI0EzUpbjw6GP+YcxLHXUvj3TU9mudyrqE=; b=WTXpyVlL2fdf0iTy87SdLi793lJCFJdIvD2QMGkHVMbnCrJ8LiX7FLaNFeH5HX6yX9 e69QuS7HXHA7Ql86YvL5aqY3KiDPlLgfe2Mnbr6vQNTHSgD8eiumBRW0qVB/MctZKqsB KssrR+CJXdHMlF2XivHacvVLFJSmKb+LmnCj6UasO4POQh/jiCfW8Ytrr5xIbvJUn6BT H7Q2FmSHL6X9O1WZqP8O9C4hXW8pK5Bj7tcKo0Dt4IJfLRh5iv3kLERj4vFzAcMzOU6G Xs8bbfyWqpJSYHX4CWc9KsCwiYgIYwDaCzxYKCi24n0x/PcyJIFbitG7bVVRgHVv2/Gi +z9A== X-Gm-Message-State: AOAM533qCplmghn44SgV1fResg4234InYDSpIAbx2MwOf/Tfm+Gz1Yve 8ASLepASCs7BoirccYIuu6A= X-Google-Smtp-Source: ABdhPJzXMpnI3N2MmVSAmrIXDJg32JEDi0wJm3cFwqCUc+s/bm9ffzDOAN7dPvVGoLrWwlCDqTN6yw== X-Received: by 2002:a17:902:7c91:: with SMTP id y17mr26294187pll.103.1594379513255; Fri, 10 Jul 2020 04:11:53 -0700 (PDT) Received: from gli-arch.genesyslogic.com.tw (60-251-58-169.HINET-IP.hinet.net. [60.251.58.169]) by smtp.gmail.com with ESMTPSA id gv16sm5436756pjb.5.2020.07.10.04.11.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 10 Jul 2020 04:11:52 -0700 (PDT) From: Ben Chuang To: adrian.hunter@intel.com, ulf.hansson@linaro.org Cc: linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, ben.chuang@genesyslogic.com.tw, takahiro.akashi@linaro.org, greg.tu@genesyslogic.com.tw, Ben Chuang Subject: [RFC PATCH V3 18/21] mmc: sdhci-uhs2: add pre-detect_init hook Date: Fri, 10 Jul 2020 19:12:36 +0800 Message-Id: <20200710111236.29885-1-benchuanggli@gmail.com> X-Mailer: git-send-email 2.27.0 MIME-Version: 1.0 Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org From: Ben Chuang This "pre" hook for detect_init(), uhs2_pre_detect_init, will be required to enable UHS-II support, at least, on GL9755. Signed-off-by: Ben Chuang Signed-off-by: AKASHI Takahiro --- drivers/mmc/host/sdhci-uhs2.c | 3 +++ drivers/mmc/host/sdhci.h | 2 ++ 2 files changed, 5 insertions(+) diff --git a/drivers/mmc/host/sdhci-uhs2.c b/drivers/mmc/host/sdhci-uhs2.c index 3cb13071dd9d..3f7ebf5d18c5 100644 --- a/drivers/mmc/host/sdhci-uhs2.c +++ b/drivers/mmc/host/sdhci-uhs2.c @@ -525,6 +525,9 @@ static int sdhci_uhs2_do_detect_init(struct sdhci_host *host) DBG("%s: begin UHS2 init.\n", __func__); spin_lock_irqsave(&host->lock, flags); + if (host->ops && host->ops->uhs2_pre_detect_init) + host->ops->uhs2_pre_detect_init(host); + if (sdhci_uhs2_interface_detect(host)) { pr_warn("%s: cannot detect UHS2 interface.\n", mmc_hostname(host->mmc)); diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 927aaba28932..c825a8130bc1 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -721,6 +721,8 @@ struct sdhci_ops { void (*request_done)(struct sdhci_host *host, struct mmc_request *mrq); void (*dump_vendor_regs)(struct sdhci_host *host); + /* UHS-2 support */ + void (*uhs2_pre_detect_init)(struct sdhci_host *host); }; struct sdhci_uhs2_ops { From patchwork Fri Jul 10 11:12:47 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Chuang X-Patchwork-Id: 11656291 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 653FF13B6 for ; Fri, 10 Jul 2020 11:12:30 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 487CF2077D for ; Fri, 10 Jul 2020 11:12:30 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Os8uLJ7q" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726820AbgGJLMP (ORCPT ); Fri, 10 Jul 2020 07:12:15 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41564 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727785AbgGJLME (ORCPT ); Fri, 10 Jul 2020 07:12:04 -0400 Received: from mail-pf1-x441.google.com (mail-pf1-x441.google.com [IPv6:2607:f8b0:4864:20::441]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1456FC08C5CE; Fri, 10 Jul 2020 04:12:04 -0700 (PDT) Received: by mail-pf1-x441.google.com with SMTP id a14so2416531pfi.2; Fri, 10 Jul 2020 04:12:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=S7yVpx9Ygx5/VQ/WoaheeloIQ6g4ecPLVpX/LrJKnQ8=; b=Os8uLJ7qBc9aLgAmNWYB9sd2IUB6Gra0WHDPMxHgQNCdWVdwc9+dOuy2xVw7UtlBue tkQNyIFczI63sen2wg6m7gkIX+yHVokdBpiCWcXaPTdpqrCgpQhBxe6IKmq37OmgrMbG zJivl/E9SLAUmosgHOAIXiVhEXQJMHFWQY1ye9fzuTEX3hvCbKB6y8Svj2DSSt/azdEL vrU9t6inD0KxX1iGGd75xS/MhzvRY+nI7+A2FB1y0T2Kh7stONaEiMMdDYWj1xsl+3ew 7CZwDegcnQrUsczZ8qQTwkka4nMkSi9nyMqqZfON0jI4Ra1XWaq644vn8RE2yV0QAs5Y Rt9w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=S7yVpx9Ygx5/VQ/WoaheeloIQ6g4ecPLVpX/LrJKnQ8=; b=cX1uQ8CHJBqe96vrYSZn5y7TsXH9lWIQlT9gx4yCRRbzu23EOG0mf+WS/TVANKc85Y gh4Z9g/jQF/0tYyJiLBNSmtXNoFi74sWMhyrBtkngf8ELjNSagAmtWr5ia4Sr+mlFdQL DezDEEFxz09mHedPiEFTljcgJBzugQsELC4eK7InUD91EMHbxQyv8mu3yqpfMimdsyBR t6Amti6rjzJSERXj/xSvZTYkm0Mv5q+kusGxLSjk8YErw/bujb2bHFr7RWntF5GtSBG+ ItVjwbZGKjofa2CSmOyuQCJAaMCxhff0DLxp1UjVGotaYj+zQwuj4gDrE9QZFN46Pygf LBxQ== X-Gm-Message-State: AOAM531VYCthftH4wbADSQWUT95FrUqRzGnUWgtg46wr9vPC3B4Rjhl3 Ihl3Wy95gDIpF+RIsbZT5LE= X-Google-Smtp-Source: ABdhPJwk+ecIgJlHDMQzbxsodEXMOQGmZRDBOAjMNyfp/q/BE8CrQjcv+FHjPXZzeSJxmeF8tMfvoA== X-Received: by 2002:a63:d250:: with SMTP id t16mr56958474pgi.51.1594379523645; Fri, 10 Jul 2020 04:12:03 -0700 (PDT) Received: from gli-arch.genesyslogic.com.tw (60-251-58-169.HINET-IP.hinet.net. [60.251.58.169]) by smtp.gmail.com with ESMTPSA id x7sm5842904pfq.197.2020.07.10.04.12.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 10 Jul 2020 04:12:03 -0700 (PDT) From: Ben Chuang To: adrian.hunter@intel.com, ulf.hansson@linaro.org Cc: linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, ben.chuang@genesyslogic.com.tw, takahiro.akashi@linaro.org, greg.tu@genesyslogic.com.tw, Ben Chuang Subject: [RFC PATCH V3 19/21] mmc: core: add post-mmc_attach_sd hook Date: Fri, 10 Jul 2020 19:12:47 +0800 Message-Id: <20200710111247.29937-1-benchuanggli@gmail.com> X-Mailer: git-send-email 2.27.0 MIME-Version: 1.0 Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org From: AKASHI Takahiro This "post" hook for mmc_attach_sd() will be required to enable UHS-II support, at least, on GL9755. Signed-off-by: Ben Chuang Signed-off-by: AKASHI Takahiro --- drivers/mmc/core/sd.c | 6 ++++++ include/linux/mmc/host.h | 1 + 2 files changed, 7 insertions(+) diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index c5b071bd98b3..fd4cae4ed747 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -1381,6 +1381,12 @@ int mmc_attach_sd(struct mmc_host *host) goto remove_card; mmc_claim_host(host); + + /* TODO: Is this the right place? */ + if ((host->flags & MMC_UHS2_INITIALIZED) && + host->ops->uhs2_post_attach_sd) + host->ops->uhs2_post_attach_sd(host); + return 0; remove_card: diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 56bdb153ef16..e61e0ae62cff 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -180,6 +180,7 @@ struct mmc_host_ops { int (*uhs2_set_reg)(struct mmc_host *host, enum uhs2_act act); void (*uhs2_disable_clk)(struct mmc_host *host); void (*uhs2_enable_clk)(struct mmc_host *host); + void (*uhs2_post_attach_sd)(struct mmc_host *host); }; struct mmc_cqe_ops { From patchwork Fri Jul 10 11:12:57 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Chuang X-Patchwork-Id: 11656289 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 83805618 for ; Fri, 10 Jul 2020 11:12:29 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 6A6B4207BB for ; Fri, 10 Jul 2020 11:12:29 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Jfqafy0I" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727901AbgGJLMP (ORCPT ); Fri, 10 Jul 2020 07:12:15 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41592 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727826AbgGJLMO (ORCPT ); Fri, 10 Jul 2020 07:12:14 -0400 Received: from mail-pg1-x541.google.com (mail-pg1-x541.google.com [IPv6:2607:f8b0:4864:20::541]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2A73CC08C5CE; Fri, 10 Jul 2020 04:12:14 -0700 (PDT) Received: by mail-pg1-x541.google.com with SMTP id g67so2386957pgc.8; Fri, 10 Jul 2020 04:12:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=F8w87dZu+AXaxXmtJyyfj57eeIxgjjlo27WZMKJg5/8=; b=Jfqafy0IhQ1F7vYTGTPiFIM1vkS9YTFf+ErfGF8DVFPKsKv0VcUSK4F4oWjbpVx2eZ EtkvgMynMCCqCtpts2voU4hHe/uERNThBxWISEA4GPQd639QRecVLwj5de0c0H0gWn7p 5Nl6ltnzMEiXSU86lg+OitLUwzu0bsTnWS7/w20GUMdX+tI5wum0UVH8FYmGNIqnvNt3 L4rpUYJKWAMfhDDpLcTnPHWf14OKFgEXgo5SCyD6g/mQr8saf7xgRl7OOMIxnn1h5d60 U8irdVpLSXqluV0tPA5imk8MG/dvGVjLpplUTZcKfgp9bZmbSzlBMLAdAwkVbMAuy2nD HKIw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=F8w87dZu+AXaxXmtJyyfj57eeIxgjjlo27WZMKJg5/8=; b=KxqTw8pKEpapxUKBoHPfcc6nYI0X245MAGycjFsKT1VXXyxzYfocT642YzjGNMZn1D mAccKFB/PU1C0IN9UBiinPhx2/qg9uuCuj4sW3x/aJPGTPmmcv6TApg0pkaqu5cRxAvl gcJ/xfOopFiPWSFsDwOtnnYCsjX93iPY0tWsXZWOdJu99zoM61az94QyAxAbzwRzkTZt GEgjbG/++W7qy3Etd4H2uCFAacCE4MHop7ephRSVulHVo3uqxXPyyfK9fnEUKF6r7USz aUFFjZU8jL+51KzEMbmcmGhdXPZy/ExYMHCU6x3VJKu9BBYGY5i5quzl5pK2QRtIhcjz BTgQ== X-Gm-Message-State: AOAM533xSmTQhMOYH8rJGtpKbpwHG9P+oULn3me8ebIrnvHXi4omhJCw K31TG/EJzKpwgNQfd3qGqJY= X-Google-Smtp-Source: ABdhPJzwnZwvKSQKlNLwA/3ppBc4+nfB9rPPhw9n+Bd7qqbPRP9Tw35XqS7ggl1QKl9v9Vw1nV7cog== X-Received: by 2002:a63:5a60:: with SMTP id k32mr57460324pgm.73.1594379533769; Fri, 10 Jul 2020 04:12:13 -0700 (PDT) Received: from gli-arch.genesyslogic.com.tw (60-251-58-169.HINET-IP.hinet.net. [60.251.58.169]) by smtp.gmail.com with ESMTPSA id c30sm5386865pfj.213.2020.07.10.04.12.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 10 Jul 2020 04:12:13 -0700 (PDT) From: Ben Chuang To: adrian.hunter@intel.com, ulf.hansson@linaro.org Cc: linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, ben.chuang@genesyslogic.com.tw, takahiro.akashi@linaro.org, greg.tu@genesyslogic.com.tw, Ben Chuang Subject: [RFC PATCH V3 20/21] mmc: sdhci-uhs2: add post-mmc_attach_sd hook Date: Fri, 10 Jul 2020 19:12:57 +0800 Message-Id: <20200710111257.29992-1-benchuanggli@gmail.com> X-Mailer: git-send-email 2.27.0 MIME-Version: 1.0 Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org From: Ben Chuang This "post" hook for mmc_attach_sd(), uhs2_post_attach_sd, will be required to enable UHS-II support, at least, on GL9755. Signed-off-by: Ben Chuang Signed-off-by: AKASHI Takahiro --- drivers/mmc/host/sdhci.c | 9 +++++++++ drivers/mmc/host/sdhci.h | 1 + 2 files changed, 10 insertions(+) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 5d84e61f6ad9..a2cc5f758547 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -3155,6 +3155,14 @@ static void sdhci_uhs2_enable_clk(struct mmc_host *mmc) udelay(10); } } + +static void sdhci_uhs2_post_attach_sd(struct mmc_host *mmc) +{ + struct sdhci_host *host = mmc_priv(mmc); + + if (host->ops && host->ops->uhs2_post_attach_sd) + host->ops->uhs2_post_attach_sd(host); +} #endif /* CONFIG_MMC_SDHCI_UHS2 */ static const struct mmc_host_ops sdhci_ops = { @@ -3177,6 +3185,7 @@ static const struct mmc_host_ops sdhci_ops = { .uhs2_set_reg = sdhci_uhs2_set_reg, .uhs2_disable_clk = sdhci_uhs2_disable_clk, .uhs2_enable_clk = sdhci_uhs2_enable_clk, + .uhs2_post_attach_sd = sdhci_uhs2_post_attach_sd, #endif /* CONFIG_MMC_SDHCI_UHS2 */ }; diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index c825a8130bc1..d613ff8daaf6 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -723,6 +723,7 @@ struct sdhci_ops { void (*dump_vendor_regs)(struct sdhci_host *host); /* UHS-2 support */ void (*uhs2_pre_detect_init)(struct sdhci_host *host); + void (*uhs2_post_attach_sd)(struct sdhci_host *host); }; struct sdhci_uhs2_ops { From patchwork Fri Jul 10 11:13:12 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Chuang X-Patchwork-Id: 11656293 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D7A5513B6 for ; Fri, 10 Jul 2020 11:12:37 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id AB81F207BB for ; Fri, 10 Jul 2020 11:12:37 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="GicmT6qV" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728108AbgGJLMd (ORCPT ); Fri, 10 Jul 2020 07:12:33 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41632 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728051AbgGJLM3 (ORCPT ); Fri, 10 Jul 2020 07:12:29 -0400 Received: from mail-pl1-x641.google.com (mail-pl1-x641.google.com [IPv6:2607:f8b0:4864:20::641]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 00886C08C5CE; Fri, 10 Jul 2020 04:12:28 -0700 (PDT) Received: by mail-pl1-x641.google.com with SMTP id d10so2125455pll.3; Fri, 10 Jul 2020 04:12:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=l7RTKh+bZmJP85JGxF8cbqEPL7ohgIm/VkKorltZQs8=; b=GicmT6qVnPwNmyFD+RvB556xofUdcZ0CUZSmjnHihQ9WlaJQDLPyadjflzQy4UHVty BAJ6WXyjq/DmUQjSuAi+1cmmhaA5kG5DmXTKvic4yj981sZP65UdtXumzJ5nnC+Hjqli bJ5D2MT6UZFxfToZ5sX2hqPY/7zFYFu3mxdkJXt/HLtOEz3YNvAFxVuZ4VUD1dE11s8U zOhjgkCZLFcMmo+C2CmzNXI7INsaBnhN7HE7jduH1nYpU7PzRTZrYoQ2oHrtWKxNER83 vLJ/SAFBgKkpd8yMIZv14sO5PSFkDpLDRXgEZrqdLH1lClogoFw0M3kb4h2VupTdXGJY /KiQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=l7RTKh+bZmJP85JGxF8cbqEPL7ohgIm/VkKorltZQs8=; b=l/8g005xCSJ6LJm6aQKH/ptsBJatDjDu1qsav/QBiWNdRHBDLLUdRT7yQhA+IHTjqV KXAc8v+JWVCz/pcu8+FIMzPVDMLmzdoVk4OEZiHL7nNt6lq7KV6eKJzvG9nWwQa7DWXZ AaMjX65RyKWjQUfmww0StrSiJPCh+mvnue6eP3vemRdUr18kMIs6ZZ40CRaYiWs70Lze tckYz3Uldi6QOLUHTXwV+ysw1o3RCm2YwVTS0HgWP+qcvZZcq7V6HSbEKB+5wg+cp6Qr 3STPglkKUc/O4of+Scf7igWsbqGouTUgjiflfS7XAZMb6HdW+TY104X8fPlye7ehwdE/ 0xiQ== X-Gm-Message-State: AOAM531mYFQSu3lObQLaPAP42cx7lfMbFzb/tFAJ75GD3Z2P+Juv2RM7 fgZfAWhAu9O7PO5DIXhQhO2vWCEB X-Google-Smtp-Source: ABdhPJzJhF7vmftalvZ+YXUG0ixeh/Br6oqfQI4Zboy0wjJrq29tulvaNXLj9+Gyqdj8LiQXf9ExfQ== X-Received: by 2002:a17:90a:b901:: with SMTP id p1mr4727036pjr.134.1594379548474; Fri, 10 Jul 2020 04:12:28 -0700 (PDT) Received: from gli-arch.genesyslogic.com.tw (60-251-58-169.HINET-IP.hinet.net. [60.251.58.169]) by smtp.gmail.com with ESMTPSA id az13sm5046274pjb.34.2020.07.10.04.12.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 10 Jul 2020 04:12:28 -0700 (PDT) From: Ben Chuang To: adrian.hunter@intel.com, ulf.hansson@linaro.org Cc: linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, ben.chuang@genesyslogic.com.tw, takahiro.akashi@linaro.org, greg.tu@genesyslogic.com.tw, Ben Chuang Subject: [RFC PATCH V3 21/21] mmc: sdhci-pci-gli: enable UHS-II mode for GL9755 Date: Fri, 10 Jul 2020 19:13:12 +0800 Message-Id: <20200710111312.30046-1-benchuanggli@gmail.com> X-Mailer: git-send-email 2.27.0 MIME-Version: 1.0 Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org From: Ben Chuang Changes are: * Disable GL9755 overcurrent interrupt when power on/off on UHS-II. * Enable the internal clock when do reset on UHS-II mode. * Set ZC to 0x0 for Sandisk cards and set ZC to 0xB for others. * Increase timeout value before detecting UHS-II interface. * Add vendor settings fro UHS-II mode. Signed-off-by: Ben Chuang --- drivers/mmc/host/Kconfig | 1 + drivers/mmc/host/sdhci-pci-gli.c | 361 ++++++++++++++++++++++++++++++- 2 files changed, 361 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index ffeef38264c0..88e27d3a032b 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -102,6 +102,7 @@ config MMC_SDHCI_PCI tristate "SDHCI support on PCI bus" depends on MMC_SDHCI && PCI select MMC_CQHCI + select MMC_SDHCI_UHS2 select IOSF_MBI if X86 select MMC_SDHCI_IO_ACCESSORS help diff --git a/drivers/mmc/host/sdhci-pci-gli.c b/drivers/mmc/host/sdhci-pci-gli.c index ca0166d9bf82..16be8e47bf15 100644 --- a/drivers/mmc/host/sdhci-pci-gli.c +++ b/drivers/mmc/host/sdhci-pci-gli.c @@ -14,6 +14,7 @@ #include #include "sdhci.h" #include "sdhci-pci.h" +#include "sdhci-uhs2.h" /* Genesys Logic extra registers */ #define SDHCI_GLI_9750_WT 0x800 @@ -63,6 +64,42 @@ #define SDHCI_GLI_9750_TUNING_PARAMETERS_RX_DLY GENMASK(2, 0) #define GLI_9750_TUNING_PARAMETERS_RX_DLY_VALUE 0x1 +#define PCI_GLI_9755_WT 0x800 +#define PCI_GLI_9755_WT_EN BIT(0) +#define GLI_9755_WT_EN_ON 0x1 +#define GLI_9755_WT_EN_OFF 0x0 + +#define PCI_GLI_9755_PLLSSC 0x68 +#define PCI_GLI_9755_PLLSSC_RTL BIT(24) +#define GLI_9755_PLLSSC_RTL_VALUE 0x1 +#define PCI_GLI_9755_PLLSSC_TRANS_PASS BIT(27) +#define GLI_9755_PLLSSC_TRANS_PASS_VALUE 0x1 +#define PCI_GLI_9755_PLLSSC_RECV GENMASK(29, 28) +#define GLI_9755_PLLSSC_RECV_VALUE 0x3 +#define PCI_GLI_9755_PLLSSC_TRAN GENMASK(31, 30) +#define GLI_9755_PLLSSC_TRAN_VALUE 0x3 + +#define PCI_GLI_9755_UHS2_PLL 0x6C +#define PCI_GLI_9755_UHS2_PLL_SSC GENMASK(9, 8) +#define GLI_9755_UHS2_PLL_SSC_VALUE 0x0 +#define PCI_GLI_9755_UHS2_PLL_DELAY BIT(18) +#define GLI_9755_UHS2_PLL_DELAY_VALUE 0x1 +#define PCI_GLI_9755_UHS2_PLL_PDRST BIT(27) +#define GLI_9755_UHS2_PLL_PDRST_VALUE 0x1 + +#define PCI_GLI_9755_UHS2_SERDES 0x70 +#define PCI_GLI_9755_UHS2_SERDES_INTR GENMASK(2, 0) +#define GLI_9755_UHS2_SERDES_INTR_VALUE 0x3 +#define PCI_GLI_9755_UHS2_SERDES_ZC1 BIT(3) +#define GLI_9755_UHS2_SERDES_ZC1_VALUE 0x0 +#define PCI_GLI_9755_UHS2_SERDES_ZC2 GENMASK(7, 4) +#define GLI_9755_UHS2_SERDES_ZC2_DEFAULT 0xB +#define GLI_9755_UHS2_SERDES_ZC2_SANDISK 0x0 +#define PCI_GLI_9755_UHS2_SERDES_TRAN GENMASK(27, 24) +#define GLI_9755_UHS2_SERDES_TRAN_VALUE 0xC +#define PCI_GLI_9755_UHS2_SERDES_RECV GENMASK(31, 28) +#define GLI_9755_UHS2_SERDES_RECV_VALUE 0xF + #define SDHCI_GLI_9763E_CTRL_HS400 0x7 #define SDHCI_GLI_9763E_HS400_ES_REG 0x52C @@ -295,6 +332,324 @@ static void gli_pcie_enable_msi(struct sdhci_pci_slot *slot) slot->host->irq = pci_irq_vector(slot->chip->pdev, 0); } +static inline void gl9755_wt_on(struct pci_dev *pdev) +{ + u32 wt_value; + u32 wt_enable; + + pci_read_config_dword(pdev, PCI_GLI_9755_WT, &wt_value); + wt_enable = FIELD_GET(PCI_GLI_9755_WT_EN, wt_value); + + if (wt_enable == GLI_9755_WT_EN_ON) + return; + + wt_value &= ~PCI_GLI_9755_WT_EN; + wt_value |= FIELD_PREP(PCI_GLI_9755_WT_EN, GLI_9755_WT_EN_ON); + + pci_write_config_dword(pdev, PCI_GLI_9755_WT, wt_value); +} + +static inline void gl9755_wt_off(struct pci_dev *pdev) +{ + u32 wt_value; + u32 wt_enable; + + pci_read_config_dword(pdev, PCI_GLI_9755_WT, &wt_value); + wt_enable = FIELD_GET(PCI_GLI_9755_WT_EN, wt_value); + + if (wt_enable == GLI_9755_WT_EN_OFF) + return; + + wt_value &= ~PCI_GLI_9755_WT_EN; + wt_value |= FIELD_PREP(PCI_GLI_9755_WT_EN, GLI_9755_WT_EN_OFF); + + pci_write_config_dword(pdev, PCI_GLI_9755_WT, wt_value); +} + +static void gl9755_vendor_init(struct sdhci_host *host) +{ + struct sdhci_pci_slot *slot = sdhci_priv(host); + struct pci_dev *pdev = slot->chip->pdev; + u32 serdes; + u32 pllssc; + u32 uhs2_pll; + + gl9755_wt_on(pdev); + + pci_read_config_dword(pdev, PCI_GLI_9755_UHS2_SERDES, &serdes); + serdes &= ~PCI_GLI_9755_UHS2_SERDES_TRAN; + serdes |= FIELD_PREP(PCI_GLI_9755_UHS2_SERDES_TRAN, + GLI_9755_UHS2_SERDES_TRAN_VALUE); + serdes &= ~PCI_GLI_9755_UHS2_SERDES_RECV; + serdes |= FIELD_PREP(PCI_GLI_9755_UHS2_SERDES_RECV, + GLI_9755_UHS2_SERDES_RECV_VALUE); + serdes &= ~PCI_GLI_9755_UHS2_SERDES_INTR; + serdes |= FIELD_PREP(PCI_GLI_9755_UHS2_SERDES_INTR, + GLI_9755_UHS2_SERDES_INTR_VALUE); + serdes &= ~PCI_GLI_9755_UHS2_SERDES_ZC1; + serdes |= FIELD_PREP(PCI_GLI_9755_UHS2_SERDES_ZC1, + GLI_9755_UHS2_SERDES_ZC1_VALUE); + serdes &= ~PCI_GLI_9755_UHS2_SERDES_ZC2; + serdes |= FIELD_PREP(PCI_GLI_9755_UHS2_SERDES_ZC2, + GLI_9755_UHS2_SERDES_ZC2_DEFAULT); + pci_write_config_dword(pdev, PCI_GLI_9755_UHS2_SERDES, serdes); + + pci_read_config_dword(pdev, PCI_GLI_9755_UHS2_PLL, &uhs2_pll); + uhs2_pll &= ~PCI_GLI_9755_UHS2_PLL_SSC; + uhs2_pll |= FIELD_PREP(PCI_GLI_9755_UHS2_PLL_SSC, + GLI_9755_UHS2_PLL_SSC_VALUE); + uhs2_pll &= ~PCI_GLI_9755_UHS2_PLL_DELAY; + uhs2_pll |= FIELD_PREP(PCI_GLI_9755_UHS2_PLL_DELAY, + GLI_9755_UHS2_PLL_DELAY_VALUE); + uhs2_pll &= ~PCI_GLI_9755_UHS2_PLL_PDRST; + uhs2_pll |= FIELD_PREP(PCI_GLI_9755_UHS2_PLL_PDRST, + GLI_9755_UHS2_PLL_PDRST_VALUE); + pci_write_config_dword(pdev, PCI_GLI_9755_UHS2_PLL, uhs2_pll); + + pci_read_config_dword(pdev, PCI_GLI_9755_PLLSSC, &pllssc); + pllssc &= ~PCI_GLI_9755_PLLSSC_RTL; + pllssc |= FIELD_PREP(PCI_GLI_9755_PLLSSC_RTL, + GLI_9755_PLLSSC_RTL_VALUE); + pllssc &= ~PCI_GLI_9755_PLLSSC_TRANS_PASS; + pllssc |= FIELD_PREP(PCI_GLI_9755_PLLSSC_TRANS_PASS, + GLI_9755_PLLSSC_TRANS_PASS_VALUE); + pllssc &= ~PCI_GLI_9755_PLLSSC_RECV; + pllssc |= FIELD_PREP(PCI_GLI_9755_PLLSSC_RECV, + GLI_9755_PLLSSC_RECV_VALUE); + pllssc &= ~PCI_GLI_9755_PLLSSC_TRAN; + pllssc |= FIELD_PREP(PCI_GLI_9755_PLLSSC_TRAN, + GLI_9755_PLLSSC_TRAN_VALUE); + pci_write_config_dword(pdev, PCI_GLI_9755_PLLSSC, pllssc); + + gl9755_wt_off(pdev); +} + +static void gl9755_pre_detect_init(struct sdhci_host *host) +{ + /* GL9755 need more time on UHS2 detect flow */ + sdhci_writeb(host, 0xA7, SDHCI_UHS2_TIMER_CTRL); +} + +static void gl9755_post_attach_sd(struct sdhci_host *host) +{ + struct pci_dev *pdev; + struct sdhci_pci_chip *chip; + struct sdhci_pci_slot *slot; + u32 serdes; + + slot = sdhci_priv(host); + chip = slot->chip; + pdev = chip->pdev; + + gl9755_wt_on(pdev); + + pci_read_config_dword(pdev, PCI_GLI_9755_UHS2_SERDES, &serdes); + serdes &= ~PCI_GLI_9755_UHS2_SERDES_ZC1; + serdes &= ~PCI_GLI_9755_UHS2_SERDES_ZC2; + serdes |= FIELD_PREP(PCI_GLI_9755_UHS2_SERDES_ZC1, + GLI_9755_UHS2_SERDES_ZC1_VALUE); + + /* the manfid of sandisk card is 0x3 */ + if (host->mmc->card->cid.manfid == 0x3) + serdes |= FIELD_PREP(PCI_GLI_9755_UHS2_SERDES_ZC2, + GLI_9755_UHS2_SERDES_ZC2_SANDISK); + else + serdes |= FIELD_PREP(PCI_GLI_9755_UHS2_SERDES_ZC2, + GLI_9755_UHS2_SERDES_ZC2_DEFAULT); + + pci_write_config_dword(pdev, PCI_GLI_9755_UHS2_SERDES, serdes); + + gl9755_wt_off(pdev); +} + +static void gl9755_overcurrent_event_enable(struct sdhci_host *host, + bool enable) +{ + u32 mask; + + mask = sdhci_readl(host, SDHCI_SIGNAL_ENABLE); + if (enable) + mask |= SDHCI_INT_BUS_POWER; + else + mask &= ~SDHCI_INT_BUS_POWER; + + sdhci_writel(host, mask, SDHCI_SIGNAL_ENABLE); + + mask = sdhci_readl(host, SDHCI_INT_ENABLE); + if (enable) + mask |= SDHCI_INT_BUS_POWER; + else + mask &= ~SDHCI_INT_BUS_POWER; + + sdhci_writel(host, mask, SDHCI_INT_ENABLE); +} + +static void gl9755_set_power(struct sdhci_host *host, unsigned char mode, + unsigned short vdd, unsigned short vdd2) +{ + u8 pwr = 0; + + if (mode != MMC_POWER_OFF) { + switch (1 << vdd) { + case MMC_VDD_165_195: + /* + * Without a regulator, SDHCI does not support 2.0v + * so we only get here if the driver deliberately + * added the 2.0v range to ocr_avail. Map it to 1.8v + * for the purpose of turning on the power. + */ + case MMC_VDD_20_21: + pwr = SDHCI_POWER_180; + break; + case MMC_VDD_29_30: + case MMC_VDD_30_31: + pwr = SDHCI_POWER_300; + break; + case MMC_VDD_32_33: + case MMC_VDD_33_34: + pwr = SDHCI_POWER_330; + break; + default: + WARN(1, "%s: Invalid vdd %#x\n", + mmc_hostname(host->mmc), vdd); + break; + } + } + + if (mode != MMC_POWER_OFF) { + if (vdd2 != (unsigned short)-1) { + switch (1 << vdd2) { + case MMC_VDD2_165_195: + pwr |= SDHCI_VDD2_POWER_180; + break; + default: + WARN(1, "%s: Invalid vdd2 %#x\n", + mmc_hostname(host->mmc), vdd2); + break; + } + } + } + + if (host->pwr == pwr) + return; + + host->pwr = pwr; + + if (pwr == 0) { + gl9755_overcurrent_event_enable(host, false); + sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); + } else { + gl9755_overcurrent_event_enable(host, false); + sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); + + pwr |= SDHCI_POWER_ON; + if (vdd2 != (unsigned short)-1) + pwr |= SDHCI_VDD2_POWER_ON; + + sdhci_writeb(host, pwr & 0xf, SDHCI_POWER_CONTROL); + /* wait stable */ + mdelay(5); + sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); + /* wait stable */ + mdelay(5); + gl9755_overcurrent_event_enable(host, true); + } +} + +static bool sdhci_wait_clock_stable(struct sdhci_host *host) +{ + u16 clk = 0; + ktime_t timeout; + + /* Wait max 20 ms */ + timeout = ktime_add_ms(ktime_get(), 20); + while (1) { + bool timedout = ktime_after(ktime_get(), timeout); + + clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); + if (clk & SDHCI_CLOCK_INT_STABLE) + break; + if (timedout) { + pr_err("%s: Internal clock never stabilised.\n", + mmc_hostname(host->mmc)); + sdhci_dumpregs(host); + return false; + } + udelay(10); + } + return true; +} + +static void gl9755_uhs2_reset_sd_tran(struct sdhci_host *host) +{ + /* do this on UHS2 mode */ + if (host->mmc->flags & MMC_UHS2_INITIALIZED) { + sdhci_uhs2_reset(host, SDHCI_UHS2_SW_RESET_SD); + sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); + sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); + sdhci_uhs2_clear_set_irqs(host, + SDHCI_INT_ALL_MASK, + SDHCI_UHS2_ERR_INT_STATUS_MASK); + } +} + +static void sdhci_gl9755_reset(struct sdhci_host *host, u8 mask) +{ + ktime_t timeout; + u16 ctrl2; + u16 clk_ctrl; + + /* need internal clock */ + if (mask & SDHCI_RESET_ALL) { + ctrl2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); + clk_ctrl = sdhci_readw(host, SDHCI_CLOCK_CONTROL); + + if ((ctrl2 & SDHCI_CTRL_V4_MODE) && + (ctrl2 & SDHCI_CTRL_UHS2_INTERFACE_EN)) { + sdhci_writew(host, + SDHCI_CLOCK_INT_EN, + SDHCI_CLOCK_CONTROL); + } else { + sdhci_writew(host, + SDHCI_CLOCK_INT_EN, + SDHCI_CLOCK_CONTROL); + sdhci_wait_clock_stable(host); + sdhci_writew(host, + SDHCI_CTRL_V4_MODE, + SDHCI_HOST_CONTROL2); + } + } + + sdhci_writeb(host, mask, SDHCI_SOFTWARE_RESET); + + /* reset sd-tran on UHS2 mode if need to reset cmd/data */ + if ((mask & SDHCI_RESET_CMD) | (mask & SDHCI_RESET_DATA)) + gl9755_uhs2_reset_sd_tran(host); + + if (mask & SDHCI_RESET_ALL) + host->clock = 0; + + /* Wait max 100 ms */ + timeout = ktime_add_ms(ktime_get(), 100); + + /* hw clears the bit when it's done */ + while (1) { + bool timedout = ktime_after(ktime_get(), timeout); + + if (!(sdhci_readb(host, SDHCI_SOFTWARE_RESET) & mask)) + break; + if (timedout) { + pr_err("%s: Reset 0x%x never completed.\n", + mmc_hostname(host->mmc), (int)mask); + sdhci_dumpregs(host); + /* manual clear */ + sdhci_writeb(host, 0, SDHCI_SOFTWARE_RESET); + return; + } + udelay(10); + } +} + static int gli_probe_slot_gl9750(struct sdhci_pci_slot *slot) { struct sdhci_host *host = slot->host; @@ -313,6 +668,7 @@ static int gli_probe_slot_gl9755(struct sdhci_pci_slot *slot) gli_pcie_enable_msi(slot); slot->host->mmc->caps2 |= MMC_CAP2_NO_SDIO; sdhci_enable_v4_mode(host); + gl9755_vendor_init(host); return 0; } @@ -441,11 +797,14 @@ static int gli_probe_slot_gl9763e(struct sdhci_pci_slot *slot) static const struct sdhci_ops sdhci_gl9755_ops = { .set_clock = sdhci_set_clock, + .set_power = gl9755_set_power, .enable_dma = sdhci_pci_enable_dma, .set_bus_width = sdhci_set_bus_width, - .reset = sdhci_reset, + .reset = sdhci_gl9755_reset, .set_uhs_signaling = sdhci_set_uhs_signaling, .voltage_switch = sdhci_gli_voltage_switch, + .uhs2_pre_detect_init = gl9755_pre_detect_init, + .uhs2_post_attach_sd = gl9755_post_attach_sd, }; const struct sdhci_pci_fixes sdhci_gl9755 = {