From patchwork Thu Jul 22 04:00:56 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lai Jason X-Patchwork-Id: 484940 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.9 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNWANTED_LANGUAGE_BODY, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id DD0B5C07E9D for ; Thu, 22 Jul 2021 04:01:53 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B1A12608FC for ; Thu, 22 Jul 2021 04:01:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230381AbhGVDVR (ORCPT ); Wed, 21 Jul 2021 23:21:17 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43682 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230366AbhGVDVQ (ORCPT ); Wed, 21 Jul 2021 23:21:16 -0400 Received: from mail-pl1-x62f.google.com (mail-pl1-x62f.google.com [IPv6:2607:f8b0:4864:20::62f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 39857C061575; Wed, 21 Jul 2021 21:01:51 -0700 (PDT) Received: by mail-pl1-x62f.google.com with SMTP id p17so2993886plf.12; Wed, 21 Jul 2021 21:01: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=WfPohfF8CCjf5NRmHnHw+657LUcYbypd6xF6SZHF37I=; b=P029c22MDerUqTiWjwF8Mrf3LmxufU+EKl0bWZhACiC7GKGHDfiaI2/LIVRXtL+sTf C6q83vdCnEgJy02Tn/gZfC1uf8Zpx6MGHSKgO6BL4HQokeu6JUXwqgFbcHyKiTzUGa3L Xj3pKnrQARMpWNYveJ6hU52Brjocf+/odlHYSdCNS7rGnWd7/7zvnbGmvUAwGhSX3U7Z L2gSYcsIBhAd0dXqUfV26MG+9zcuKpcKAbVRYosAObnI6BaCs9N3cuOvjKzpydp8mWHV lhd+PIP2wLKp4j93RI9crNV0KdwfFCE18p/rz6kodfj9eji0ymN24fid8nlcszy+U8uj GaAw== 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=WfPohfF8CCjf5NRmHnHw+657LUcYbypd6xF6SZHF37I=; b=jeT2RanR0FldKa9lVH59E0X/HDcWS/DzeoF8X6eoONFQm9Bpt2lMwd5SEGAhypmD7M sZI2epc9VVPrTWPjzuwFMPxRqCdNTy0gfaSE5iDgt5fW1ouEP1dEwPB0/b/r4SOTKecK mjNzTGZNdAS4HnATlHdXbIbSj8VjPiOoA6ZDmvE8See8T0W2MGAbV2Co1R8RJZmNL0uT Mbob9YCAddsmSqbbc8Efjp0RHKw7kzn5YidcQCA5n4zg4cCV78YOI+cNE+f0foTP4tYV eakR8jfT3hoy2S3iRUlNT7Ykn/uXEc3YDY2KFiRqejvg+g5eI2Vs4TsVGH9jecSFninJ 1/LQ== X-Gm-Message-State: AOAM531O6jb3flFLE+KrhgZ7SMyzGvUPm78rML3YIc1v6SxBX1+IGJgV M0oQtq6O+bY+bbWRRkfozAHFe7Le4IjvHA== X-Google-Smtp-Source: ABdhPJwVbE6wTsDNuITv9ld/T5p7mxMu3nbjO/hLseUCDSmi/1VEcqPGfRdGwzLezcmXPge4cXfU7w== X-Received: by 2002:a63:e74c:: with SMTP id j12mr17896226pgk.121.1626926510663; Wed, 21 Jul 2021 21:01:50 -0700 (PDT) Received: from jason-z170xgaming7.mshome.net (218-35-143-223.cm.dynamic.apol.com.tw. [218.35.143.223]) by smtp.gmail.com with ESMTPSA id c19sm1663479pfp.184.2021.07.21.21.01.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 21 Jul 2021 21:01:50 -0700 (PDT) From: Jason Lai To: ulf.hansson@linaro.org, adrian.hunter@intel.com Cc: Ben Chuang , linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, greg.tu@genesyslogic.com.tw, jason.lai@genesyslogiv.com.tw, AKASHI Takahiro Subject: [RFC PATCH v3.2 01/29] mmc: add UHS-II related definitions in public headers Date: Thu, 22 Jul 2021 12:00:56 +0800 Message-Id: <20210722040124.7573-1-jasonlai.genesyslogic@gmail.com> X-Mailer: git-send-email 2.32.0 MIME-Version: 1.0 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 | 31 +++++ include/linux/mmc/uhs2.h | 268 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 306 insertions(+) create mode 100644 include/linux/mmc/uhs2.h -- 2.32.0 diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index f9ad35dd6012..4551a1280ee4 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 ab19245e9945..b698aa9cdb09 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 c7e7b43600e9..89a9e0e12f07 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -16,10 +16,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. */ @@ -63,6 +65,7 @@ struct mmc_ios { #define MMC_TIMING_MMC_HS400 10 #define MMC_TIMING_SD_EXP 11 #define MMC_TIMING_SD_EXP_1_2V 12 +#define MMC_TIMING_UHS2 13 unsigned char signal_voltage; /* signalling voltage (1.8V or 3.3V) */ @@ -190,6 +193,12 @@ struct mmc_host_ops { /* Initialize an SD express card, mandatory for MMC_CAP2_SD_EXP. */ int (*init_sd_express)(struct mmc_host *host, struct mmc_ios *ios); + + /* 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 { @@ -282,6 +291,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 */ }; @@ -302,10 +312,12 @@ 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 */ struct wakeup_source *ws; /* Enable consume of uevents */ 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 */ @@ -324,6 +336,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 */ @@ -357,6 +370,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 (1 << 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 */ @@ -403,6 +417,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 (1 << 0) +#define MMC_UHS2_INITIALIZED (1 << 1) +#define MMC_UHS2_2L_HD (1 << 2) +#define MMC_UHS2_APP_CMD (1 << 3) +#define MMC_UHS2_SPEED_B (1 << 4) +#define MMC_SUPPORT_ADMA3 (1 << 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 */ @@ -603,6 +628,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 Thu Jul 22 04:00:57 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lai Jason X-Patchwork-Id: 484199 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id A8F44C636C8 for ; Thu, 22 Jul 2021 04:01:59 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 8431361244 for ; Thu, 22 Jul 2021 04:01:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229905AbhGVDVW (ORCPT ); Wed, 21 Jul 2021 23:21:22 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43712 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229977AbhGVDVV (ORCPT ); Wed, 21 Jul 2021 23:21:21 -0400 Received: from mail-pj1-x102a.google.com (mail-pj1-x102a.google.com [IPv6:2607:f8b0:4864:20::102a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0B225C0613C1; Wed, 21 Jul 2021 21:01:57 -0700 (PDT) Received: by mail-pj1-x102a.google.com with SMTP id p4-20020a17090a9304b029016f3020d867so3686111pjo.3; Wed, 21 Jul 2021 21:01:57 -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:in-reply-to:references :mime-version:content-transfer-encoding; bh=TtTlmiOOwP/kifcL3jT81MRGQUXvmXHChazVkWTU6qM=; b=Qy7ys9tujk9AZ1EG3DwpC2b2wx7wIFQIDGYkUq5YV9czDjcN8Tbe/ZT6f+e5Npz1xs 8QeunHq0aGbxOykDJueV5O4kV/64flhSlUL3Nu7hgmtzByv/bglveFepc8lQhBROjMC/ u2TBkVC2JGPVlXCEqotbh5g321qft3NnmJsneV4ebxEOADQgLeEiOQtKUkErW7a0ywdm A5corv29xheef2oeyhZxg7Bglg5eqhomuTtk3WC8mlCYVqpf6ySPhnPuxuH9gRkAztif sY1APAYmE2bQVwU8Mevj3h/cne0ig0XA+VbS0xTGGYChvHeHddYwfVgLAs4OESsuMtAr uuXQ== 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:in-reply-to :references:mime-version:content-transfer-encoding; bh=TtTlmiOOwP/kifcL3jT81MRGQUXvmXHChazVkWTU6qM=; b=kd4kIXSAON6ZMosTqpHHFWI/dcBaxicBGFhQwCBcnhBilWjTrgU5Vd6VuJBaiUya9Q yzK7jeGBYYjpKzvjexQ0dwX4f9VMIWEgwhO6LyWHrMmAflOBSFLPKfBjveXuvunYlfoM 6ANatHwKxpUMUW3xkafiss6/m6x2ezqTdH+jhQtpLCFX8exiCRjSvgQuNDZ2ICduW7Ah RC3LwYOW7HY0C0rWGxw/y0o1L4vlov0iHMu+Te+xDQS6y/8BXy8YLtziD2Oao+tSJhnW CnD7+mKrHisUwKmDBxYsKziLYSQBSVy5Pxl6W+wEV+s1sA/6kaVx10d8wdhEvnU8b7jc 792g== X-Gm-Message-State: AOAM5326bhotGbc/89zR8Qx/jzD5kNyt//CXak92N+QTKdO0dV4pyUgi 2kajvCjfnans1590iTM3W4l0shIUb6zCOQ== X-Google-Smtp-Source: ABdhPJxg2Yto7mp3a7TrVIaYsjoCj9NFCmUhe5HMCNvlPjX/PnU4uhC+MYscZS/kVgqA67fOZOoNWQ== X-Received: by 2002:a17:902:db0c:b029:12b:8daa:cf8c with SMTP id m12-20020a170902db0cb029012b8daacf8cmr13852586plx.78.1626926516586; Wed, 21 Jul 2021 21:01:56 -0700 (PDT) Received: from jason-z170xgaming7.mshome.net (218-35-143-223.cm.dynamic.apol.com.tw. [218.35.143.223]) by smtp.gmail.com with ESMTPSA id c19sm1663479pfp.184.2021.07.21.21.01.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 21 Jul 2021 21:01:56 -0700 (PDT) From: Jason Lai To: ulf.hansson@linaro.org, adrian.hunter@intel.com Cc: linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, ben.chuang@genesyslogic.com.tw, greg.tu@genesyslogic.com.tw, jason.lai@genesyslogiv.com.tw, AKASHI Takahiro Subject: [RFC PATCH v3.2 02/29] mmc: core: UHS-II support, modify power-up sequence Date: Thu, 22 Jul 2021 12:00:57 +0800 Message-Id: <20210722040124.7573-2-jasonlai.genesyslogic@gmail.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210722040124.7573-1-jasonlai.genesyslogic@gmail.com> References: <20210722040124.7573-1-jasonlai.genesyslogic@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org 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 | 61 +++++++++++++++++++++++++----------- drivers/mmc/core/regulator.c | 14 +++++++++ 2 files changed, 56 insertions(+), 19 deletions(-) -- 2.32.0 diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index f194940c5974..722b61811f1e 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1318,33 +1318,52 @@ 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); + /* + * 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); + 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) @@ -2233,7 +2252,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 609201a467ef..629e25bc8cb7 100644 --- a/drivers/mmc/core/regulator.c +++ b/drivers/mmc/core/regulator.c @@ -249,6 +249,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) @@ -268,6 +269,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 Thu Jul 22 04:00:58 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lai Jason X-Patchwork-Id: 484939 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id E24FBC6377D for ; Thu, 22 Jul 2021 04:02:01 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id CDC14608FC for ; Thu, 22 Jul 2021 04:02:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230106AbhGVDVY (ORCPT ); Wed, 21 Jul 2021 23:21:24 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43722 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230166AbhGVDVX (ORCPT ); Wed, 21 Jul 2021 23:21:23 -0400 Received: from mail-pj1-x102e.google.com (mail-pj1-x102e.google.com [IPv6:2607:f8b0:4864:20::102e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B9D43C061575; Wed, 21 Jul 2021 21:01:58 -0700 (PDT) Received: by mail-pj1-x102e.google.com with SMTP id a17-20020a17090abe11b0290173ce472b8aso2384221pjs.2; Wed, 21 Jul 2021 21:01:58 -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:in-reply-to:references :mime-version:content-transfer-encoding; bh=HCiki6s3bkhDr8HEItmgJdP7VpsDfkf2iN/pIhh62EA=; b=FncgS1G79piW939Bxd70JAWZ8JZOH0CifGlRy1g7+k+j3wPx3dkb3ra583JuB8oWNA J7B4+9TOGs2ff8msj9H1NXmaU0kVrf+8M1uYGjDo/0YBTBaD7e8nBbAVlCKU791Pe+oh 2Dkx82WxfutR71Mrrv3bsSnxV/Tzj0ePzA9/nfpFF/Ml4D8cUrkKJa7CgcZ3NZzbbqHe wF9VVL9xM2M8w3vWkcLxsuQbw4xJavF0s4XAkF0ql+N1FpE0uctglb6ZPv0XANh6J71p CcuCpH5LnCEtxdwJtRJDOw84RqBHJFZ1LIDokeRM5Mle/PwZZphmmW7EbtBWtZ0jTxWu bIaw== 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:in-reply-to :references:mime-version:content-transfer-encoding; bh=HCiki6s3bkhDr8HEItmgJdP7VpsDfkf2iN/pIhh62EA=; b=iZ0W9qOyKICO7jeAGfb0hyZd6P4QCEo2fCbFyi/wlbX7/nqs7tSPl/CJrrsysj/tJH lhTfmn6noE548K8V1OZW+GmFIzkfH8CHXfPPwB2oyb4JFwgKQ+zcIunwaP3s1kWiyB7D O7GXgMNluqqIRovPhnnvz3QmsSmenroElcaD2WopgDLLucJ02R5A07+tIXLblkhE5ipm ChPrm7rk4MCGrBQ4TdmTubNs5cTGxIo9N67TpQXb6v1OWpGcw14apIEw7P7tiK3l9yFG zb77sgYgIMa4XbSixL7m/cwyk1gWktKX1Pbq8qe0e5KlWNZ6RJXNnL9qDvnsyJFNcSJL g4SA== X-Gm-Message-State: AOAM531nRxbUjj4yngwvY6yOhzXOStaxNP5f2/CgJuPGXBHq6TrLBrqZ 2ACRSSbYTRCRbhzI60AW9MA= X-Google-Smtp-Source: ABdhPJypAdbwOLhqudXCRiHkNrQh4VT+ulwNpjfrp2tOc7CWFz3DRS2p0hC/oBMSjNuusZKORdVIXg== X-Received: by 2002:a17:902:d681:b029:12b:381c:c86 with SMTP id v1-20020a170902d681b029012b381c0c86mr30345901ply.46.1626926518357; Wed, 21 Jul 2021 21:01:58 -0700 (PDT) Received: from jason-z170xgaming7.mshome.net (218-35-143-223.cm.dynamic.apol.com.tw. [218.35.143.223]) by smtp.gmail.com with ESMTPSA id c19sm1663479pfp.184.2021.07.21.21.01.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 21 Jul 2021 21:01:58 -0700 (PDT) From: Jason Lai To: ulf.hansson@linaro.org, adrian.hunter@intel.com Cc: linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, ben.chuang@genesyslogic.com.tw, greg.tu@genesyslogic.com.tw, jason.lai@genesyslogiv.com.tw, AKASHI Takahiro Subject: [RFC PATCH v3.2 03/29] mmc: core: UHS-II support, skip set_chip_select() Date: Thu, 22 Jul 2021 12:00:58 +0800 Message-Id: <20210722040124.7573-3-jasonlai.genesyslogic@gmail.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210722040124.7573-1-jasonlai.genesyslogic@gmail.com> References: <20210722040124.7573-1-jasonlai.genesyslogic@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org mmc_set_chip_select() should be called only in UHS-II 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(-) -- 2.32.0 diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 722b61811f1e..3da7b7e321a0 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -899,8 +899,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 Thu Jul 22 04:00:59 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lai Jason X-Patchwork-Id: 484198 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2C624C6377C for ; Thu, 22 Jul 2021 04:02:05 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0E7B76135C for ; Thu, 22 Jul 2021 04:02:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230313AbhGVDV1 (ORCPT ); Wed, 21 Jul 2021 23:21:27 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43730 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230252AbhGVDVZ (ORCPT ); Wed, 21 Jul 2021 23:21:25 -0400 Received: from mail-pj1-x1030.google.com (mail-pj1-x1030.google.com [IPv6:2607:f8b0:4864:20::1030]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EE274C061575; Wed, 21 Jul 2021 21:02:00 -0700 (PDT) Received: by mail-pj1-x1030.google.com with SMTP id j8-20020a17090aeb08b0290173bac8b9c9so2372673pjz.3; Wed, 21 Jul 2021 21:02:00 -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:in-reply-to:references :mime-version:content-transfer-encoding; bh=Mgc5WEIH5oQIGb5RdTTiLAUuDHSTPoj4mIY2qXWvnp8=; b=H7hlZri+NxVMqeOz53UM3m7EE2Z28+nYk5b4j36wqkc2wb4Fp8zD5x3HO7uKAQ8e5p ocMayqWRynmVdL7S9hPfyw5QllHsGizdqv7jjqRZw0wvc4rGoG+UCCU6ctZ68MqaKZ6m AwUv9iyLK8QoArwbvK731wbjKr5plGiFoKkfRemnLW+04LMWZ5HJhy8sXQ8l9yuyoFhF Naql3HE5IsHV5KeurTh8GjK1q8ULcJlSzQ0HtcbPThfyqAudgmyvLi8HJyNC1ezSHlx0 1Qo0Z/+h7TwuSZtM3oMy/m2bgpy/FNzxituwPyRvDad1PHIGWp90rglwJnnE+FHyvT/9 O14g== 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:in-reply-to :references:mime-version:content-transfer-encoding; bh=Mgc5WEIH5oQIGb5RdTTiLAUuDHSTPoj4mIY2qXWvnp8=; b=huHsoCPouDXtONClYgtH4C+Z3Q6jGNDrOKVQpfFGJdWBX9ECsSoVPbgFfzWxuh8RBf BbXI2vuOkpoSQBcmstkcJOG4Cb04fLZ1RrYrXrgN/fbpZpprbJmgTcm6wbZZPSkFl4pv tGkFB8rgcPJ34PsxMxaSLmHTmEwoEDQ2StMf3WyaIxwCFdi0cZqEvqqGLxplU4N4nuy4 q1eK2r772KrcD2j9BIuWcY36nvyPfE2xXtVE+516ey+7UhuzAjilnESbMQx4mWuz8TjZ 06sThc31FlVXH8L8DGVO0EQBqKoQ5MzPzPG1MNvu8MpendGWA+UHMoYCFPVERxKiVSRU d3Aw== X-Gm-Message-State: AOAM533iAgIjq2JeeZTr+GxFfertEV/e4r6+30rDFr+TNozTsZceCJsN dBbLEeSqrJsaVbod4miH8s4= X-Google-Smtp-Source: ABdhPJzw7qKBNPOFfbPIHIF4+z+DOdCgwhuHxzaOdHaG9dluygJ4x3AJ6GgQn3cE0GLKsTlThooKUQ== X-Received: by 2002:a63:4c0e:: with SMTP id z14mr39703933pga.427.1626926520246; Wed, 21 Jul 2021 21:02:00 -0700 (PDT) Received: from jason-z170xgaming7.mshome.net (218-35-143-223.cm.dynamic.apol.com.tw. [218.35.143.223]) by smtp.gmail.com with ESMTPSA id c19sm1663479pfp.184.2021.07.21.21.01.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 21 Jul 2021 21:02:00 -0700 (PDT) From: Jason Lai To: ulf.hansson@linaro.org, adrian.hunter@intel.com Cc: linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, ben.chuang@genesyslogic.com.tw, greg.tu@genesyslogic.com.tw, jason.lai@genesyslogiv.com.tw, AKASHI Takahiro Subject: [RFC PATCH v3.2 04/29] mmc: core: UHS-II support, try to select UHS-II interface Date: Thu, 22 Jul 2021 12:00:59 +0800 Message-Id: <20210722040124.7573-4-jasonlai.genesyslogic@gmail.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210722040124.7573-1-jasonlai.genesyslogic@gmail.com> References: <20210722040124.7573-1-jasonlai.genesyslogic@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org 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 | 809 ++++++++++++++++++++++++++++++++++++++ drivers/mmc/core/uhs2.h | 20 + 6 files changed, 891 insertions(+), 4 deletions(-) create mode 100644 drivers/mmc/core/uhs2.c create mode 100644 drivers/mmc/core/uhs2.h -- 2.32.0 diff --git a/drivers/mmc/core/Makefile b/drivers/mmc/core/Makefile index 6a907736cd7a..3d3a55bc7e45 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 4383c262b3f5..77cbadef30ce 100644 --- a/drivers/mmc/core/bus.c +++ b/drivers/mmc/core/bus.c @@ -362,8 +362,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 3da7b7e321a0..300812c69e13 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 @@ -42,6 +43,7 @@ #include "host.h" #include "sdio_bus.h" #include "pwrseq.h" +#include "uhs2.h" #include "mmc_ops.h" #include "sd_ops.h" @@ -52,6 +54,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%) @@ -2103,9 +2106,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)) @@ -2226,6 +2230,33 @@ void mmc_rescan(struct work_struct *work) if (mmc_card_sd_express(host)) { mmc_release_host(host); 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++) { diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 2c48d6504101..0a407ef1cfc0 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -937,6 +937,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); + } + } } /* @@ -1079,6 +1093,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) @@ -1370,6 +1389,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..acb46b5b57ef --- /dev/null +++ b/drivers/mmc/core/uhs2.c @@ -0,0 +1,809 @@ +// 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 gLssDir = 0 + */ + u32 gLssDir = 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 (!gLssDir) { + host->uhs2_dev_prop.n_lss_dir_set = 0; + } else { + host->uhs2_dev_prop.n_lss_dir_set = + max((u8)gLssDir, + 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->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->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->ops->uhs2_set_reg(host, CHECK_DORMANT)) { + pr_err("%s: %s: UHS2 GO_DORMANT_STATE fail!\n", + mmc_hostname(host), __func__); + return -EIO; + } + + if (host->ops->uhs2_disable_clk) + 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->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); + if (host->ops->uhs2_enable_clk) + host->ops->uhs2_enable_clk(host); + + /* Enable Normal INT */ + if (!host->ops->uhs2_set_reg || + 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->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->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 Thu Jul 22 04:01:00 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lai Jason X-Patchwork-Id: 484938 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9C35BC6377E for ; Thu, 22 Jul 2021 04:02:06 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 85254608FC for ; Thu, 22 Jul 2021 04:02:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230334AbhGVDV3 (ORCPT ); Wed, 21 Jul 2021 23:21:29 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43746 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230201AbhGVDV1 (ORCPT ); Wed, 21 Jul 2021 23:21:27 -0400 Received: from mail-pl1-x62a.google.com (mail-pl1-x62a.google.com [IPv6:2607:f8b0:4864:20::62a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9B9F9C061757; Wed, 21 Jul 2021 21:02:02 -0700 (PDT) Received: by mail-pl1-x62a.google.com with SMTP id e14so3002083plh.8; Wed, 21 Jul 2021 21:02:02 -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:in-reply-to:references :mime-version:content-transfer-encoding; bh=MlYdZedfzdwEWYsud6KArWcbSXHSw/yPGnBz1xgAeuA=; b=CWhUUvGUikR4GNhQp5D//oZZeD7oHwmvqqG4OyLkktg5JWAGz9CTmJeICFWqsXq8Z+ 8kKVJiG2DJCUbe1EjtGL/jyCUHRF3sTlkyJRR9iBj1+TjJTchis6XaLEgCsO3biOmt1S 6v9a1YuguvgW7k9WkhIv6c69M8QtX0jyiynZ3Ip4fR/+u6kJ1oNnn9/onF3SRuIADdZn l6TzjnVQpfuATSgddatjIMfBYkjH8SxD60H6ZszbluAAtOACdm0KqyDr4eyqCP7OYEt/ k9WA29DEsmYdDI3ZQejm2MZyqTVj5nPGk4R/M4W6hGaHJMczsPF/satN0IJURjGDr6mn 6AIw== 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:in-reply-to :references:mime-version:content-transfer-encoding; bh=MlYdZedfzdwEWYsud6KArWcbSXHSw/yPGnBz1xgAeuA=; b=EQd7Voh7Rke8epg+mLii1dxp9vPollbd/0XFKBklDknXiXVvfrU5DiFAqLb+caiJmS s2hnoOHQv7EjlSxWj5tH5KGKkcpB5gB2a+ihw94By+CrshNLU4WIADYLw3Wkw9Z7fnmm NdqRkm+6X+c5rF1wOf7DI50QquAFfXfPcDwMpLzFSNwHxzJyXZecvH5ZlJKlsb8ts94B WTrc7wBs7FxNMc21c2JmP110YBIwaR25k0/wQRQn4aOyXT30ScUGI6X/c6jUIM454m8j E0KZA27WOZtFT609eArLxZGg1HTT6ac6DIN/nS8M8APdk9nMLvH1KQdgxeMHc0rK5Fg1 DWNQ== X-Gm-Message-State: AOAM533LD3j245QbU6mz1eTTYXZH1nUa2VbphMfdCPQ90z2zbzDMlDWL KWS9gMZkg9WGLhEX/Vrm/A0= X-Google-Smtp-Source: ABdhPJzzObRrw2bYzX6SUT8P+jtBNpdWlM/kL2o29VHHPjTRQLySETBZeqEZ8Hb4tmuezSXwhcHnJQ== X-Received: by 2002:a63:5952:: with SMTP id j18mr21127123pgm.366.1626926522132; Wed, 21 Jul 2021 21:02:02 -0700 (PDT) Received: from jason-z170xgaming7.mshome.net (218-35-143-223.cm.dynamic.apol.com.tw. [218.35.143.223]) by smtp.gmail.com with ESMTPSA id c19sm1663479pfp.184.2021.07.21.21.02.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 21 Jul 2021 21:02:01 -0700 (PDT) From: Jason Lai To: ulf.hansson@linaro.org, adrian.hunter@intel.com Cc: linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, ben.chuang@genesyslogic.com.tw, greg.tu@genesyslogic.com.tw, jason.lai@genesyslogiv.com.tw, AKASHI Takahiro Subject: [RFC PATCH v3.2 05/29] mmc: core: UHS-II support, skip TMODE setup in some cases Date: Thu, 22 Jul 2021 12:01:00 +0800 Message-Id: <20210722040124.7573-5-jasonlai.genesyslogic@gmail.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210722040124.7573-1-jasonlai.genesyslogic@gmail.com> References: <20210722040124.7573-1-jasonlai.genesyslogic@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org 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(-) -- 2.32.0 diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c index 689eb9afeeed..d107578cdbff 100644 --- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c @@ -57,6 +57,7 @@ #include "mmc_ops.h" #include "quirks.h" #include "sd_ops.h" +#include "uhs2.h" MODULE_ALIAS("mmc:block"); #ifdef MODULE_PARAM_PREFIX @@ -1538,6 +1539,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); @@ -1548,7 +1552,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. */ @@ -1561,6 +1565,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 d61ff811218c..baa05a6a36c4 100644 --- a/drivers/mmc/core/sd_ops.c +++ b/drivers/mmc/core/sd_ops.c @@ -280,6 +280,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; @@ -327,6 +328,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; @@ -368,6 +370,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 Thu Jul 22 04:01:01 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lai Jason X-Patchwork-Id: 484197 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2E55BC63793 for ; Thu, 22 Jul 2021 04:02:09 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 188CF61241 for ; Thu, 22 Jul 2021 04:02:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230400AbhGVDVb (ORCPT ); Wed, 21 Jul 2021 23:21:31 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43740 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230300AbhGVDV3 (ORCPT ); Wed, 21 Jul 2021 23:21:29 -0400 Received: from mail-pl1-x631.google.com (mail-pl1-x631.google.com [IPv6:2607:f8b0:4864:20::631]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5BCDAC061575; Wed, 21 Jul 2021 21:02:04 -0700 (PDT) Received: by mail-pl1-x631.google.com with SMTP id y3so3012491plp.4; Wed, 21 Jul 2021 21:02: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:in-reply-to:references :mime-version:content-transfer-encoding; bh=grqvWstToZdU1j24UPoQskvD093nWq2s/JMON7jHKtg=; b=vaO9oiOAtYPhf6+JV5KVEKRwuWPcKfUfhofeZ9Em3FIM2J5JksGrexLpx4Q7WB7YIV HbR0k6gOwdU3ITgJUAU1TAXNnI4L3WLA8urVWPrYPPjWodPfak+6aPcSVrfYfP1k+1PE iGNAt3B4F79n/aMbg7ah2Or1X5kfdmUSuB6sE+t/ERb96zri3yuz0RfE7dd9CRwI9P+c 8WPXML6t8d5oT/GneMs7hJJ0t7OrO7t6KyEZ+0qLvoofFI8BYOxzRC7IJlTQecM01mh4 25UjZVz+8B8EPDc7JYymaE61lQjzmmwZNA3zkok7JKJmzRktIU6+DmXeT5Fm7ne+EuGc C6ZQ== 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:in-reply-to :references:mime-version:content-transfer-encoding; bh=grqvWstToZdU1j24UPoQskvD093nWq2s/JMON7jHKtg=; b=YOthoKGcucSpWc3xsLjE8QGiHCO8pO2AYpFKtZiJjUjZRhmspxFyiiKKX58rzzkBgD pvJyeC2k161EpWtRPWjojrAdxD9xlSTtxqbTmDt2Hws3rsVmWn+xhOBl1g+vCRk4wYxa SdRCpNPYIh/Q1NRvBjR3E7MrX0mE8yq2CFCB2zUJsXAIrbbPl3DzstGkEC4TV3DIkKht nUHAaEoGXcwIBbi+weQBOmtEMXCk9aipA29AnMxeX1nNmF1FC7RIE2dcVnweBR6uiwy5 ENiwUBTmoZ8atVx87Pyho+rD+DJiHbNNBijadISRwyqo6OEMlY/pkGzS4PSreTn+Oc72 khJQ== X-Gm-Message-State: AOAM531vRiLKaH3BymVKZmyqWghz4rbr9gNdShtjk9EM1CQbREBtGt0l nrbpD5UD44bDgZFtfxuTY1s= X-Google-Smtp-Source: ABdhPJy14stfb0YEBrNLc/Qb5dT9yVl22mgg0Dl5ZNMHcncwoxbPYqck1MvmS8IJUAGRN6NLGBIikg== X-Received: by 2002:a63:3704:: with SMTP id e4mr39032195pga.310.1626926523940; Wed, 21 Jul 2021 21:02:03 -0700 (PDT) Received: from jason-z170xgaming7.mshome.net (218-35-143-223.cm.dynamic.apol.com.tw. [218.35.143.223]) by smtp.gmail.com with ESMTPSA id c19sm1663479pfp.184.2021.07.21.21.02.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 21 Jul 2021 21:02:03 -0700 (PDT) From: Jason Lai To: ulf.hansson@linaro.org, adrian.hunter@intel.com Cc: linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, ben.chuang@genesyslogic.com.tw, greg.tu@genesyslogic.com.tw, jason.lai@genesyslogiv.com.tw, AKASHI Takahiro Subject: [RFC PATCH v3.2 06/29] mmc: core: UHS-II support, generate UHS-II SD command packet Date: Thu, 22 Jul 2021 12:01:01 +0800 Message-Id: <20210722040124.7573-6-jasonlai.genesyslogic@gmail.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210722040124.7573-1-jasonlai.genesyslogic@gmail.com> References: <20210722040124.7573-1-jasonlai.genesyslogic@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org 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(+) -- 2.32.0 diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 300812c69e13..d53722c21f29 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -338,6 +338,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); @@ -355,6 +357,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); @@ -434,6 +443,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; /* @@ -454,6 +465,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 acb46b5b57ef..1f6d0e0cf355 100644 --- a/drivers/mmc/core/uhs2.c +++ b/drivers/mmc/core/uhs2.c @@ -807,3 +807,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 Thu Jul 22 04:01:02 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lai Jason X-Patchwork-Id: 484937 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id DFBF5C07E9D for ; Thu, 22 Jul 2021 04:02:09 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C2D2861285 for ; Thu, 22 Jul 2021 04:02:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229889AbhGVDVc (ORCPT ); Wed, 21 Jul 2021 23:21:32 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43760 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230252AbhGVDVa (ORCPT ); Wed, 21 Jul 2021 23:21:30 -0400 Received: from mail-pj1-x1029.google.com (mail-pj1-x1029.google.com [IPv6:2607:f8b0:4864:20::1029]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1CCE1C061757; Wed, 21 Jul 2021 21:02:06 -0700 (PDT) Received: by mail-pj1-x1029.google.com with SMTP id j8-20020a17090aeb08b0290173bac8b9c9so2372918pjz.3; Wed, 21 Jul 2021 21:02:06 -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:in-reply-to:references :mime-version:content-transfer-encoding; bh=akS7G7fDQc5oV25QXxyh3Me7TqHga56qr6CDdV6HGtw=; b=JWnLRvtLH0VPMXgB74AG/X+a60TibxTftfCnqtAr8OO19cyL6NDKiKBABTBTsa4jsy rYleignu8hDrNmdP8ZRwrX9k/7c/T1jftkWm7+FqZR0FaI8+SvJP4A+Bf+dAk1ahctwL zqZYGu8NIS/ixGPTJrjxOgvhPtj0Sasz1NeFgr1XlsGfouYQ3d9tz2naVkAHIzErAK4d CjoO+RuW1i8pTSa+guFONfHSu6O5bVqt2BeCHuBtW4oy0+uK3GGdRJU9OXfpnSfDcKT2 mNkPkG4Doeiwt15rPiMJVKURGWJU+oQroDD003Fm5iex3BpUT6UuS6PEmqQXrtSqHiwk hiXg== 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:in-reply-to :references:mime-version:content-transfer-encoding; bh=akS7G7fDQc5oV25QXxyh3Me7TqHga56qr6CDdV6HGtw=; b=kp13kpiTu8JJ/oLnApUrkmiMAHUPbsX0ZgWy5j54MJVI3ecBCTpj3ROjeIpph+dbVX V2PEIAXdNSptNkeTlOaLGYo2PJMS/INFPIINWhr1zSAm+OnirmGWCqNL/F7cIRzpI1tH DBPGbThkQDIB27YgHGm7u52QREKtcZWpnVYNrz8PooWqHrCOEg5l7U6NgEaHjUxLfsex /8AJHg5IaMnm2FNOZau8F4HwmgZWJyn7azYZ0cXAybotdY3fQWrRPC49UUV4EbZ0qk/6 Z9OFuTqVFl0EIj5mthV56t9vAgrgux15MtHyZ980DtI3s7LwqUm+h2c1PoZARtXmYIL5 tmSQ== X-Gm-Message-State: AOAM533jc8y+V7UKdQTq+2QZqRqdaPy6YgxNLTBJOpyKWIxCZTgreI7v l5T7c5z/yVoojcIA1iqC9D0= X-Google-Smtp-Source: ABdhPJz5Y+1ld9SHZMbvb414AkqLe+C3TYkNqg1q/QqU0XRaDjsB8cHJJImBl9cEMWlWcVfVeAbrwg== X-Received: by 2002:a63:f00d:: with SMTP id k13mr39693451pgh.260.1626926525697; Wed, 21 Jul 2021 21:02:05 -0700 (PDT) Received: from jason-z170xgaming7.mshome.net (218-35-143-223.cm.dynamic.apol.com.tw. [218.35.143.223]) by smtp.gmail.com with ESMTPSA id c19sm1663479pfp.184.2021.07.21.21.02.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 21 Jul 2021 21:02:05 -0700 (PDT) From: Jason Lai To: ulf.hansson@linaro.org, adrian.hunter@intel.com Cc: linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, ben.chuang@genesyslogic.com.tw, greg.tu@genesyslogic.com.tw, jason.lai@genesyslogiv.com.tw, AKASHI Takahiro Subject: [RFC PATCH v3.2 07/29] mmc: core: UHS-II support, set APP_CMD bit if necessary Date: Thu, 22 Jul 2021 12:01:02 +0800 Message-Id: <20210722040124.7573-7-jasonlai.genesyslogic@gmail.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210722040124.7573-1-jasonlai.genesyslogic@gmail.com> References: <20210722040124.7573-1-jasonlai.genesyslogic@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org 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(+) -- 2.32.0 diff --git a/drivers/mmc/core/sd_ops.c b/drivers/mmc/core/sd_ops.c index baa05a6a36c4..279d676cd5e6 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 1f6d0e0cf355..c0d61e7d9e4b 100644 --- a/drivers/mmc/core/uhs2.c +++ b/drivers/mmc/core/uhs2.c @@ -835,6 +835,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 Thu Jul 22 04:01:03 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lai Jason X-Patchwork-Id: 484196 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9A171C6377C for ; Thu, 22 Jul 2021 04:02:13 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 85D49608FC for ; Thu, 22 Jul 2021 04:02:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230021AbhGVDVg (ORCPT ); Wed, 21 Jul 2021 23:21:36 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43774 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230340AbhGVDVd (ORCPT ); Wed, 21 Jul 2021 23:21:33 -0400 Received: from mail-pj1-x102a.google.com (mail-pj1-x102a.google.com [IPv6:2607:f8b0:4864:20::102a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 03C6AC061575; Wed, 21 Jul 2021 21:02:08 -0700 (PDT) Received: by mail-pj1-x102a.google.com with SMTP id my10so4365387pjb.1; Wed, 21 Jul 2021 21:02: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:in-reply-to:references :mime-version:content-transfer-encoding; bh=0z54twZ+AgT0+7a2useNZocEp9hbUYo5ZhqzjAiSPZU=; b=GqkjAGLTYo/CiiHjQcfJSEDwGAKjJTR8mxDyBTZ4gu42tlYkEscznirikuDRCqg4Lt fl0RghB/kOTBnks+DFqXFv1VBaiCqwkFAbUs7vZf0Oc1Mb5OHIyY6wxpdSSuK5fIyOcP Auu4fvKwnukZ1Rl4SNwP26M5CqH+rZ/vFGd8poggTghwQKvC7ZzUVqM70zJrrd1QdAP0 YDCKAE4kMwejcTjEZlkSnjlbTlgEbhkZJnREm/5MokRCIvAW8hK1l73/+vdmobQKk6Fx eH+8eo/GRopLlZvmvOpR5cZh7/0J5eGMX90veFwkw0OWw/MJ/dTQWU+te/clw9r2ppTH WawQ== 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:in-reply-to :references:mime-version:content-transfer-encoding; bh=0z54twZ+AgT0+7a2useNZocEp9hbUYo5ZhqzjAiSPZU=; b=tyBfiplPE1IQWDg3BSbN2Yq/esSO9t58PG8+mrMHgjMuiJ+hBbzvU2vr2GgpJg0v1J iEPmy8mGYMchoWujdyLAzp1mMxuNeI04Mn8YAR64KL0c9ZQUP2vKPgkZjcWYqJ6/OVMj QhdpfNwg1sSoao59AL1RvBmueexpObLnuNcY0GjITS1aXSNnNXfUTpgjzEZVJtiYFrk8 y2ySIrluMm2+uIR3Jmcx9V1fGqFKbI7jc+ceE97dBGFHu2Phv8fhlp0oHpetkEa0fDJy d4rU0WJxF6hklGJBkN7EUJN+lwi9KLThokEfVCFx56PKkObgJMswLfOgmPQdtty5wCyA UBAQ== X-Gm-Message-State: AOAM53010ueI9nY0NwNTGGvVwC3hENpAwFervHneBvcfprP3eF5TYig5 shi3RHFYJHa2VKjZ1YRdIM4= X-Google-Smtp-Source: ABdhPJyJm/V2f3KXD5bsjKlj6cYv4Ii88IMH/oWHjd5y2vjxoyIAFc0iXUmgtgCjpBCUXdB9WMQdDw== X-Received: by 2002:a17:902:ea0a:b029:12b:46f3:2db3 with SMTP id s10-20020a170902ea0ab029012b46f32db3mr30343550plg.21.1626926527620; Wed, 21 Jul 2021 21:02:07 -0700 (PDT) Received: from jason-z170xgaming7.mshome.net (218-35-143-223.cm.dynamic.apol.com.tw. [218.35.143.223]) by smtp.gmail.com with ESMTPSA id c19sm1663479pfp.184.2021.07.21.21.02.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 21 Jul 2021 21:02:07 -0700 (PDT) From: Jason Lai To: ulf.hansson@linaro.org, adrian.hunter@intel.com Cc: linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, ben.chuang@genesyslogic.com.tw, greg.tu@genesyslogic.com.tw, jason.lai@genesyslogiv.com.tw, AKASHI Takahiro Subject: [RFC PATCH v3.2 08/29] mmc: sdhci: add a kernel configuration for enabling UHS-II support Date: Thu, 22 Jul 2021 12:01:03 +0800 Message-Id: <20210722040124.7573-8-jasonlai.genesyslogic@gmail.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210722040124.7573-1-jasonlai.genesyslogic@gmail.com> References: <20210722040124.7573-1-jasonlai.genesyslogic@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org 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(+) -- 2.32.0 diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index a4d4c757eea0..684539a65692 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 Thu Jul 22 04:01:04 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lai Jason X-Patchwork-Id: 484936 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, UPPERCASE_50_75, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id A593BC6377D for ; Thu, 22 Jul 2021 04:02:17 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 8F2E361241 for ; Thu, 22 Jul 2021 04:02:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230200AbhGVDVj (ORCPT ); Wed, 21 Jul 2021 23:21:39 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43790 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229949AbhGVDVf (ORCPT ); Wed, 21 Jul 2021 23:21:35 -0400 Received: from mail-pj1-x1036.google.com (mail-pj1-x1036.google.com [IPv6:2607:f8b0:4864:20::1036]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 19324C0613C1; Wed, 21 Jul 2021 21:02:10 -0700 (PDT) Received: by mail-pj1-x1036.google.com with SMTP id pf12-20020a17090b1d8cb0290175c085e7a5so2406688pjb.0; Wed, 21 Jul 2021 21:02:10 -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:in-reply-to:references :mime-version:content-transfer-encoding; bh=kD9TsEhKbmduN4v9vmSX4kdrg5c7UgUUrX7cdsMF7gI=; b=IwOb9a7fKwGprr99/qvt3vQ1FHIGtmgXZdIpZBvK3sG2by8BlMY4hJT2LktA1CboLY ReZsb8NugOvePJ7CXwfnZuCW0yjFPR9c6OBkVTksrE/yucZvcNIGXze6JixSkx0fqFhh h6aYsHPg5k13lhzQ+xvxxbmoWKGTUprqk3xYJxKkjX9Ib6xsnVXTO8u5s1aH87doXBEx PH79tEmI7SJNVOxano4cBTFuiQfcxLW7rpFPhR2YudzajZ8gFj4u+HuLRaOXPM4Z99ya ymPUlDGjiR1UoaCl2BB/9PpCPznQH8dEtBotPMmI7JIZkIzakSfJXRDLoGFYKBcELIwS C6HQ== 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:in-reply-to :references:mime-version:content-transfer-encoding; bh=kD9TsEhKbmduN4v9vmSX4kdrg5c7UgUUrX7cdsMF7gI=; b=OEN76tVZW+Ur48kwcuHzj+7b6aiwIAsxM8X82JLpbSvC1yrkwqTs3RoSIoyV7q86v0 9FLN7noDYgiZfRixFMzA8HJvdLva23F8t4g+jsJdK8psWZjO06ehf5wHaPFvjtx9sCmh hz6XQuucBAVmi5zG6jvufNnnCMGituQh/VWsZch94/6a45JzCmfsephxIcWsClJgGhZn Tfg2ygzhKuusrZbWthn9QGYbITxayj6PR37XRmPKaXRzDxRSDfXz8DMKA4fcuYcRQYNn SNRfZ9RZjCmlVT3GCDW+P/AQGsoLK+czL1ypcSEKFCCQy6j/7zYrp8QoG92JkkdtzeeX HP+g== X-Gm-Message-State: AOAM532ZPGu9Q5uZW2RWOR6+OKB16p/TqykV0ke1oN7t9qmJ1MNB7A30 RiNUwCof+jWbRxX9acM9FH8= X-Google-Smtp-Source: ABdhPJyCN2rPa8LYJeVwHgruqUSA7r7wxl2kv0sDPE75usAkU6NyKH3BLws4mLqof2DaNp0o4JsuPQ== X-Received: by 2002:a62:e704:0:b029:32b:545c:b58 with SMTP id s4-20020a62e7040000b029032b545c0b58mr39698789pfh.53.1626926529630; Wed, 21 Jul 2021 21:02:09 -0700 (PDT) Received: from jason-z170xgaming7.mshome.net (218-35-143-223.cm.dynamic.apol.com.tw. [218.35.143.223]) by smtp.gmail.com with ESMTPSA id c19sm1663479pfp.184.2021.07.21.21.02.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 21 Jul 2021 21:02:09 -0700 (PDT) From: Jason Lai To: ulf.hansson@linaro.org, adrian.hunter@intel.com Cc: linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, ben.chuang@genesyslogic.com.tw, greg.tu@genesyslogic.com.tw, jason.lai@genesyslogiv.com.tw, AKASHI Takahiro Subject: [RFC PATCH v3.2 09/29] mmc: sdhci: add UHS-II related definitions in headers Date: Thu, 22 Jul 2021 12:01:04 +0800 Message-Id: <20210722040124.7573-9-jasonlai.genesyslogic@gmail.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210722040124.7573-1-jasonlai.genesyslogic@gmail.com> References: <20210722040124.7573-1-jasonlai.genesyslogic@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org 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 | 210 ++++++++++++++++++++++++++++++++++ drivers/mmc/host/sdhci.h | 73 +++++++++++- 2 files changed, 282 insertions(+), 1 deletion(-) create mode 100644 drivers/mmc/host/sdhci-uhs2.h -- 2.32.0 diff --git a/drivers/mmc/host/sdhci-uhs2.h b/drivers/mmc/host/sdhci-uhs2.h new file mode 100644 index 000000000000..3b157df9c89c --- /dev/null +++ b/drivers/mmc/host/sdhci-uhs2.h @@ -0,0 +1,210 @@ +/* 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 + +/* + * 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 BIT(0) +#define SDHCI_UHS2_TRNS_BLK_CNT_EN BIT(1) +#define SDHCI_UHS2_TRNS_DATA_TRNS_WRT BIT(4) +#define SDHCI_UHS2_TRNS_BLK_BYTE_MODE BIT(5) +#define SDHCI_UHS2_TRNS_RES_R5 BIT(6) +#define SDHCI_UHS2_TRNS_RES_ERR_CHECK_EN BIT(7) +#define SDHCI_UHS2_TRNS_RES_INT_DIS BIT(8) +#define SDHCI_UHS2_TRNS_WAIT_EBSY BIT(14) +#define SDHCI_UHS2_TRNS_2L_HD BIT(15) + +#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 GENMASK(12,8) +#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 GENMASK(3,0) +#define SDHCI_UHS2_DEV_SELECT_INT_MSG_EN BIT(7) + +#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 BIT(0) +#define SDHCI_UHS2_ERR_INT_STATUS_RES BIT(1) +#define SDHCI_UHS2_ERR_INT_STATUS_RETRY_EXP BIT(2) +#define SDHCI_UHS2_ERR_INT_STATUS_CRC BIT(3) +#define SDHCI_UHS2_ERR_INT_STATUS_FRAME BIT(4) +#define SDHCI_UHS2_ERR_INT_STATUS_TID BIT(5) +#define SDHCI_UHS2_ERR_INT_STATUS_UNRECOVER BIT(7) +#define SDHCI_UHS2_ERR_INT_STATUS_EBUSY BIT(8) +#define SDHCI_UHS2_ERR_INT_STATUS_ADMA BIT(15) +#define SDHCI_UHS2_ERR_INT_STATUS_RES_TIMEOUT BIT(16) +#define SDHCI_UHS2_ERR_INT_STATUS_DEADLOCK_TIMEOUT BIT(17) +#define SDHCI_UHS2_ERR_INT_STATUS_VENDOR BIT(27) +#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 BIT(12) +#define SDHCI_UHS2_PHY_SET_N_LSS_SYN_MASK GENMASK(19,16) +#define SDHCI_UHS2_PHY_SET_N_LSS_SYN_POS 16 +#define SDHCI_UHS2_PHY_SET_N_LSS_DIR_MASK GENMASK(23,20) +#define SDHCI_UHS2_PHY_SET_N_LSS_DIR_POS 20 + +#define SDHCI_UHS2_TRAN_SET_N_FCU_MASK GENMASK(15,8) +#define SDHCI_UHS2_TRAN_SET_N_FCU_POS 8 +#define SDHCI_UHS2_TRAN_SET_RETRY_CNT_MASK GENMASK(17,16) +#define SDHCI_UHS2_TRAN_SET_RETRY_CNT_POS 16 + +#define SDHCI_UHS2_TRAN_SET_1_N_DAT_GAP_MASK GENMASK(7,0) + +#define SDHCI_UHS2_HOST_CAPS_PTR 0xE2 +#define SDHCI_UHS2_HOST_CAPS_GEN_OFFSET 0 +#define SDHCI_UHS2_HOST_CAPS_GEN_DAP_MASK GENMASK(3,0) +#define SDHCI_UHS2_HOST_CAPS_GEN_GAP_MASK GENMASK(7,4) +#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 GENMASK(13,8) +#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 BIT(14) +#define SDHCI_UHS2_HOST_CAPS_GEN_BOOT BIT(15) +#define SDHCI_UHS2_HOST_CAPS_GEN_DEV_TYPE_MASK GENMASK(17,16) +#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 GENMASK(21,18) +#define SDHCI_UHS2_HOST_CAPS_GEN_NUM_DEV_SHIFT 18 +#define SDHCI_UHS2_HOST_CAPS_GEN_BUS_TOPO_MASK GENMASK(23,22) +#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 GENMASK(5,0) +#define SDHCI_UHS2_HOST_CAPS_PHY_RANGE_MASK GENMASK(7,6) +#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 GENMASK(19,16) +#define SDHCI_UHS2_HOST_CAPS_PHY_N_LSS_SYN_SHIFT 16 +#define SDHCI_UHS2_HOST_CAPS_PHY_N_LSS_DIR_MASK GENMASK(23,20) +#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 GENMASK(5,0) +#define SDHCI_UHS2_HOST_CAPS_TRAN_N_FCU_MASK GENMASK(15,8) +#define SDHCI_UHS2_HOST_CAPS_TRAN_N_FCU_SHIFT 8 +#define SDHCI_UHS2_HOST_CAPS_TRAN_HOST_TYPE_MASK GENMASK(18,16) +#define SDHCI_UHS2_HOST_CAPS_TRAN_HOST_TYPE_SHIFT 16 +#define SDHCI_UHS2_HOST_CAPS_TRAN_BLK_LEN_MASK GENMASK(31,20) +#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 GENMASK(7,0) + +#define SDHCI_UHS2_TEST_PTR 0xE4 +#define SDHCI_UHS2_TEST_ERR_HEADER BIT(0) +#define SDHCI_UHS2_TEST_ERR_RES BIT(1) +#define SDHCI_UHS2_TEST_ERR_RETRY_EXP BIT(2) +#define SDHCI_UHS2_TEST_ERR_CRC BIT(3) +#define SDHCI_UHS2_TEST_ERR_FRAME BIT(4) +#define SDHCI_UHS2_TEST_ERR_TID BIT(5) +#define SDHCI_UHS2_TEST_ERR_UNRECOVER BIT(7) +#define SDHCI_UHS2_TEST_ERR_EBUSY BIT(8) +#define SDHCI_UHS2_TEST_ERR_ADMA BIT(15) +#define SDHCI_UHS2_TEST_ERR_RES_TIMEOUT BIT(16) +#define SDHCI_UHS2_TEST_ERR_DEADLOCK_TIMEOUT BIT(17) +#define SDHCI_UHS2_TEST_ERR_VENDOR BIT(27) + +#define SDHCI_UHS2_EMBED_CTRL 0xE6 +#define SDHCI_UHS2_VENDOR 0xE8 + +#endif /* __SDHCI_UHS2_H */ diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 0770c036e2ff..d9d7a76cedc1 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 @@ -652,6 +722,7 @@ struct sdhci_ops { void (*request_done)(struct sdhci_host *host, struct mmc_request *mrq); void (*dump_vendor_regs)(struct sdhci_host *host); + void (*dump_uhs2_regs)(struct sdhci_host *host); }; #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS From patchwork Thu Jul 22 04:01:05 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lai Jason X-Patchwork-Id: 484195 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C5F65C636C8 for ; Thu, 22 Jul 2021 04:02:19 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id AFBDF61261 for ; Thu, 22 Jul 2021 04:02:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229821AbhGVDVm (ORCPT ); Wed, 21 Jul 2021 23:21:42 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43802 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229897AbhGVDVh (ORCPT ); Wed, 21 Jul 2021 23:21:37 -0400 Received: from mail-pl1-x629.google.com (mail-pl1-x629.google.com [IPv6:2607:f8b0:4864:20::629]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 200A3C061757; Wed, 21 Jul 2021 21:02:12 -0700 (PDT) Received: by mail-pl1-x629.google.com with SMTP id h1so2989097plf.6; Wed, 21 Jul 2021 21:02:12 -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:in-reply-to:references :mime-version:content-transfer-encoding; bh=7i6w2iKEOywQsc9e6JFf3HDymPwOIKAohMpUEWZ/YB4=; b=txIOFEOvIwVOt0pywrA1rab3Dq//asriiYMC2eC/YUubujszAgE7dyornRY1ezF3hp 8ZPsMFa7qheqOmh2Pw1d45X6BFAW61MKYYaslwE3LR3Dlb0MpmyqVkvZLu7McskEpZl2 rNVtglLhTE2yiLMXZK1zMgxlHagPXI50Cx+FXfAppnSu2hCgvCIrV4O/JQohyyg0nTNv oAs20rsymwKYgc7LJUJrOJszPkbBL56FAAdGd+33ZcSP0bw8HQDq8P4hc9aKq8AVOEkB mUEwuloSSbE7KZE37cKOplzz8bTW55Q8a++pv6B7xpGKO+9S4KRNLVC3YxEKwctRw3hJ S/ng== 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:in-reply-to :references:mime-version:content-transfer-encoding; bh=7i6w2iKEOywQsc9e6JFf3HDymPwOIKAohMpUEWZ/YB4=; b=OP59qvhRgqQVtP07pIVFf3ndafij6A9jlQX5M+1w7bRZS7asftwq6dmhlN6aAuylSG s1UcFYOQHYBbUxrWTd+pgnLS/a9iONHVB4TWqKTC9RO8R3VCGvX7+M9zA+phTnbtqG9C dPe8CWdqPRB0dbnn7ShvIynyFT3FtyUe7jLB+MhtQwaAPfhDM1B/552Vn4pX4LjiEC0G /OhXUtDqXhx0WEljcLnUuF6SxFJGAwNvyBommUR9OIr9gvy428Z/0Ej206dDNnf3BYdk z6XczzV3xgc6EYTiJ2XDgWxgTkoo83msCOA2HqSu2N7Ya8s4YZRFu+DPfWWKYnxe71qk sEIQ== X-Gm-Message-State: AOAM531LNBjelfQZOVxO/TxZl9UGtGDcwyZ9x1UABAKPuvX3jDgG61ac nlX2S9K7Pg1EO30u8Py9KYQ= X-Google-Smtp-Source: ABdhPJwR+K9Pm/a6U/tLgxfUvASpukIhQg5FbXvcT4dxFxuS5wau1y9PPBx0JnG364No3MprwWV3wg== X-Received: by 2002:a63:a18:: with SMTP id 24mr38958215pgk.309.1626926531719; Wed, 21 Jul 2021 21:02:11 -0700 (PDT) Received: from jason-z170xgaming7.mshome.net (218-35-143-223.cm.dynamic.apol.com.tw. [218.35.143.223]) by smtp.gmail.com with ESMTPSA id c19sm1663479pfp.184.2021.07.21.21.02.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 21 Jul 2021 21:02:11 -0700 (PDT) From: Jason Lai To: ulf.hansson@linaro.org, adrian.hunter@intel.com Cc: linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, ben.chuang@genesyslogic.com.tw, greg.tu@genesyslogic.com.tw, jason.lai@genesyslogiv.com.tw, AKASHI Takahiro Subject: [RFC PATCH v3.2 10/29] mmc: sdhci: add UHS-II module Date: Thu, 22 Jul 2021 12:01:05 +0800 Message-Id: <20210722040124.7573-10-jasonlai.genesyslogic@gmail.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210722040124.7573-1-jasonlai.genesyslogic@gmail.com> References: <20210722040124.7573-1-jasonlai.genesyslogic@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org This patch adds sdhci-uhs2.c as a module for UHS-II support. This is a skelton for further development in this patch series. Signed-off-by: Ben Chuang Signed-off-by: AKASHI Takahiro --- drivers/mmc/host/Makefile | 1 + drivers/mmc/host/sdhci-uhs2.c | 46 +++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 drivers/mmc/host/sdhci-uhs2.c -- 2.32.0 diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile index 14004cc09aaa..6522f130245f 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..f29d3a4ed43c --- /dev/null +++ b/drivers/mmc/host/sdhci-uhs2.c @@ -0,0 +1,46 @@ +// 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 "sdhci.h" +#include "sdhci-uhs2.h" + +#define DRIVER_NAME "sdhci_uhs2" +#define DBG(f, x...) \ + pr_debug(DRIVER_NAME " [%s()]: " f, __func__, ## x) + +/*****************************************************************************\ + * * + * Driver init/exit * + * * +\*****************************************************************************/ + +static int sdhci_uhs2_host_ops_init(struct sdhci_host *host) +{ + return 0; +} + +static int __init sdhci_uhs2_mod_init(void) +{ + return 0; +} +module_init(sdhci_uhs2_mod_init); + +static void __exit sdhci_uhs2_exit(void) +{ +} +module_exit(sdhci_uhs2_exit); + +MODULE_AUTHOR("Intel, Genesys Logic, Linaro"); +MODULE_DESCRIPTION("MMC UHS-II Support"); +MODULE_LICENSE("GPL v2"); From patchwork Thu Jul 22 04:01:06 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lai Jason X-Patchwork-Id: 484194 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5EE98C6377C for ; Thu, 22 Jul 2021 04:02:20 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 4E22D61279 for ; Thu, 22 Jul 2021 04:02:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230048AbhGVDVn (ORCPT ); Wed, 21 Jul 2021 23:21:43 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43790 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230097AbhGVDVj (ORCPT ); Wed, 21 Jul 2021 23:21:39 -0400 Received: from mail-pj1-x1032.google.com (mail-pj1-x1032.google.com [IPv6:2607:f8b0:4864:20::1032]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D94BFC0613D5; Wed, 21 Jul 2021 21:02:13 -0700 (PDT) Received: by mail-pj1-x1032.google.com with SMTP id ds11-20020a17090b08cbb0290172f971883bso2389461pjb.1; Wed, 21 Jul 2021 21:02:13 -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:in-reply-to:references :mime-version:content-transfer-encoding; bh=L5rS4U/NLgMc3Ohw7S7a9WvKYozCjHnEc5ftGhe5Wwk=; b=COSuwQL6O1qsP+f9cpXUJ+UoUtiWqIKftgmABdFHNrz3VMms71ThFP/nDl3B7S0QIL ge620lhhfAdzsZhp50+9fJnLw9mItep20oq5pwi4YRD3mBUkW5L/QNigmWR0zYyj+qjd Wk8IwoMszN0bbvnQMAIJCqPafTUANcZWVYudId5mSdJLrTDEZ0rEKEUG07Hw0kqcHH+0 YWhOo1cSQQNF64Zlq7LOF5kPHVFJahAox0LKTLvUccnATsc6lL4GCPJCEq6ePKbDlZO8 lQl2UDdCz5vpSdWuFw6CNdUVHRF6A7vpCzXVUiTcPD8EdMpha714HZMw/lZZwKc6WPeb QyWA== 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:in-reply-to :references:mime-version:content-transfer-encoding; bh=L5rS4U/NLgMc3Ohw7S7a9WvKYozCjHnEc5ftGhe5Wwk=; b=brspVy0fSQtGXtvsSWEr2ygbNxOzkKcCaMWvJlawNH6xT1Rlk+qCMiGheM9izZZmrG cwkofLyQE6uP045xLfTvF/566l294204eVjaUyqO0/tZAOFxVu6ntsrsfycHhngblBfq RowJ0YOjKOXT969NeqppP9eVAAqTDGHoCZkO6wTW6sJm9Sp5r8oedR3hoJSAhx3kHNYx XyZfXtRmJogMEacILdj15cnKNeo4FGIRzNUkIgo1vFuUJkABFVx2ZfjtGwq/72XkluC+ UEpHQKSLK4e6A75cznXA6FXTIUE23t9EzHb4F5Ay+YTcDEfNDH20hhcmVLCB+bOrnDyA XZUQ== X-Gm-Message-State: AOAM531OVL1qV8jmmNZrACPU+1t6H6p/iaspCucDXYHIW+KMpB0AFIqd GinUW18hlX56iN4NiRkPs2k= X-Google-Smtp-Source: ABdhPJzWg2yvkM53M0PJWsBqcBapIRTpblCRgcU4vfu5M5js39khQl0q/LB4vXI4yl5z63rMvjPwCA== X-Received: by 2002:aa7:800b:0:b029:330:455f:57a8 with SMTP id j11-20020aa7800b0000b0290330455f57a8mr39101331pfi.7.1626926533507; Wed, 21 Jul 2021 21:02:13 -0700 (PDT) Received: from jason-z170xgaming7.mshome.net (218-35-143-223.cm.dynamic.apol.com.tw. [218.35.143.223]) by smtp.gmail.com with ESMTPSA id c19sm1663479pfp.184.2021.07.21.21.02.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 21 Jul 2021 21:02:13 -0700 (PDT) From: Jason Lai To: ulf.hansson@linaro.org, adrian.hunter@intel.com Cc: linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, ben.chuang@genesyslogic.com.tw, greg.tu@genesyslogic.com.tw, jason.lai@genesyslogiv.com.tw, AKASHI Takahiro Subject: [RFC PATCH v3.2 11/29] mmc: sdhci-uhs2: dump UHS-II registers Date: Thu, 22 Jul 2021 12:01:06 +0800 Message-Id: <20210722040124.7573-11-jasonlai.genesyslogic@gmail.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210722040124.7573-1-jasonlai.genesyslogic@gmail.com> References: <20210722040124.7573-1-jasonlai.genesyslogic@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org 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-uhs2.c | 30 ++++++++++++++++++++++++++++++ drivers/mmc/host/sdhci-uhs2.h | 4 ++++ drivers/mmc/host/sdhci.c | 3 +++ 3 files changed, 37 insertions(+) -- 2.32.0 diff --git a/drivers/mmc/host/sdhci-uhs2.c b/drivers/mmc/host/sdhci-uhs2.c index f29d3a4ed43c..08905ed081fb 100644 --- a/drivers/mmc/host/sdhci-uhs2.c +++ b/drivers/mmc/host/sdhci-uhs2.c @@ -18,6 +18,36 @@ #define DRIVER_NAME "sdhci_uhs2" #define DBG(f, x...) \ pr_debug(DRIVER_NAME " [%s()]: " f, __func__, ## x) +#define SDHCI_UHS2_DUMP(f, x...) \ + pr_err("%s: " DRIVER_NAME ": " f, mmc_hostname(host->mmc), ## x) + +void sdhci_uhs2_dump_regs(struct sdhci_host *host) +{ + if (!host->mmc || !(host->mmc->flags & MMC_UHS2_SUPPORT)) + return; + + SDHCI_UHS2_DUMP("==================== UHS2 ==================\n"); + SDHCI_UHS2_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_UHS2_DUMP("Cmd: 0x%08x | Trn mode: 0x%08x\n", + sdhci_readw(host, SDHCI_UHS2_COMMAND), + sdhci_readw(host, SDHCI_UHS2_TRANS_MODE)); + SDHCI_UHS2_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_UHS2_DUMP("Dev Int Code: 0x%08x\n", + sdhci_readb(host, SDHCI_UHS2_DEV_INT_CODE)); + SDHCI_UHS2_DUMP("Reset: 0x%08x | Timer: 0x%08x\n", + sdhci_readw(host, SDHCI_UHS2_SW_RESET), + sdhci_readw(host, SDHCI_UHS2_TIMER_CTRL)); + SDHCI_UHS2_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_UHS2_DUMP("ErrSigEn: 0x%08x\n", + sdhci_readl(host, SDHCI_UHS2_ERR_INT_SIG_EN)); +} +EXPORT_SYMBOL_GPL(sdhci_uhs2_dump_regs); /*****************************************************************************\ * * diff --git a/drivers/mmc/host/sdhci-uhs2.h b/drivers/mmc/host/sdhci-uhs2.h index 3b157df9c89c..b9529d32b58d 100644 --- a/drivers/mmc/host/sdhci-uhs2.h +++ b/drivers/mmc/host/sdhci-uhs2.h @@ -207,4 +207,8 @@ #define SDHCI_UHS2_EMBED_CTRL 0xE6 #define SDHCI_UHS2_VENDOR 0xE8 +struct sdhci_host; + +void sdhci_uhs2_dump_regs(struct sdhci_host *host); + #endif /* __SDHCI_UHS2_H */ diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index bf238ade1602..97e7e04e4614 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -110,6 +110,9 @@ void sdhci_dumpregs(struct sdhci_host *host) } } + if (host->ops->dump_uhs2_regs) + host->ops->dump_uhs2_regs(host); + if (host->ops->dump_vendor_regs) host->ops->dump_vendor_regs(host); From patchwork Thu Jul 22 04:01:07 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lai Jason X-Patchwork-Id: 484935 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id A24E8C63793 for ; Thu, 22 Jul 2021 04:02:21 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 8F41E61261 for ; Thu, 22 Jul 2021 04:02:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230123AbhGVDVo (ORCPT ); Wed, 21 Jul 2021 23:21:44 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43788 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230211AbhGVDVl (ORCPT ); Wed, 21 Jul 2021 23:21:41 -0400 Received: from mail-pj1-x102c.google.com (mail-pj1-x102c.google.com [IPv6:2607:f8b0:4864:20::102c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D3A93C0613C1; Wed, 21 Jul 2021 21:02:15 -0700 (PDT) Received: by mail-pj1-x102c.google.com with SMTP id j8-20020a17090aeb08b0290173bac8b9c9so2373415pjz.3; Wed, 21 Jul 2021 21:02:15 -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:in-reply-to:references :mime-version:content-transfer-encoding; bh=ejtiMK9VQCHj3pEZGWJNyT1NRRi8uOEqf+b459wT27E=; b=lzdFGf9tRsxC5x3Y01z7ioD454DrUWR6+9yNqGFqlCem94cI70zK/aQTOqUKJ96RBp N9Qbav1jwAYhYVsflz9+msxTl+09w08aEEKkZ8bEW+jMSEYOz3H/MhGhU5avCGcuKMHh E+oXPfpNJeJgYwlXetNjjgK8CrWLMVy2iiFvUwlxk8pBDWFVEeF4BHxopwAt7TncjjN5 sJzN8XXPwHu6k//vucudBd2j85+YxcCfI4nQtdaWkj0/NiqzR0/iA4HdlcznyDoL5DQC jkLEBy2EL0HG7T8DQ5bw7nclIQQIOOILIA7/1Xqtb6vQbfMOFfhlxhLIiR5bzaFBkEWC rDWg== 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:in-reply-to :references:mime-version:content-transfer-encoding; bh=ejtiMK9VQCHj3pEZGWJNyT1NRRi8uOEqf+b459wT27E=; b=RqYRzWSBWnHWg25a8oLVbH4XYK++PD4JA9aexTzZ/pgMlnpBBJo8M/6lUNMWXTJ5xi E0eQrVsFLd/d82EWfwMz2rgfi5ZtbrHDA92cXzSeq9/Ag3KZcU97pdOnGX7K4TlaxCDC nEuk31TUWv+w/BiEtFIn3JCpQAwNip/H1BLvoOL3nkxpRu/dUwwZgRyxRwCs5NkYnm0j uHmSi6DAJ04n2TLoyDbLoBGh9a1UnMzOirXCr4lCMixxX1ecVA5/BAsZZ+YHSZpCy4Fg D7dLW8A37C1E+AKYqsqmUyT1rOQ9O8rVQZ/j0J6A+WesGaIdx8O+fTZKXzlEbDxlqV+s qfSg== X-Gm-Message-State: AOAM532X+vKFYe62JA9JnkYUpT8cf15v9kNcBdM22xK7BlOaaW8GSzME Iuc4OBTlpLyUNC7joxLenAY= X-Google-Smtp-Source: ABdhPJxY+0tjP0htyvrV54Blv0ou7gs49wfJg3A9Pt8Ywoj/qan2+98oN42jaXRW+pCF60eI7tOzPw== X-Received: by 2002:a17:902:744a:b029:12b:af44:5b28 with SMTP id e10-20020a170902744ab029012baf445b28mr384673plt.84.1626926535453; Wed, 21 Jul 2021 21:02:15 -0700 (PDT) Received: from jason-z170xgaming7.mshome.net (218-35-143-223.cm.dynamic.apol.com.tw. [218.35.143.223]) by smtp.gmail.com with ESMTPSA id c19sm1663479pfp.184.2021.07.21.21.02.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 21 Jul 2021 21:02:15 -0700 (PDT) From: Jason Lai To: ulf.hansson@linaro.org, adrian.hunter@intel.com Cc: linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, ben.chuang@genesyslogic.com.tw, greg.tu@genesyslogic.com.tw, jason.lai@genesyslogiv.com.tw, AKASHI Takahiro Subject: [RFC PATCH v3.2 12/29] mmc: sdhci-uhs2: add reset function Date: Thu, 22 Jul 2021 12:01:07 +0800 Message-Id: <20210722040124.7573-12-jasonlai.genesyslogic@gmail.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210722040124.7573-1-jasonlai.genesyslogic@gmail.com> References: <20210722040124.7573-1-jasonlai.genesyslogic@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org Sdhci_uhs2_reset() does a UHS-II specific reset operation. Signed-off-by: Ben Chuang Signed-off-by: AKASHI Takahiro --- drivers/mmc/host/sdhci-uhs2.c | 49 +++++++++++++++++++++++++++++++++++ drivers/mmc/host/sdhci-uhs2.h | 1 + drivers/mmc/host/sdhci.c | 3 ++- drivers/mmc/host/sdhci.h | 1 + 4 files changed, 53 insertions(+), 1 deletion(-) -- 2.32.0 diff --git a/drivers/mmc/host/sdhci-uhs2.c b/drivers/mmc/host/sdhci-uhs2.c index 08905ed081fb..e2b9743fe17d 100644 --- a/drivers/mmc/host/sdhci-uhs2.c +++ b/drivers/mmc/host/sdhci-uhs2.c @@ -10,6 +10,7 @@ * Author: AKASHI Takahiro */ +#include #include #include "sdhci.h" @@ -49,6 +50,54 @@ void sdhci_uhs2_dump_regs(struct sdhci_host *host) } EXPORT_SYMBOL_GPL(sdhci_uhs2_dump_regs); +/*****************************************************************************\ + * * + * Low level functions * + * * +\*****************************************************************************/ + +/** + * 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); + /*****************************************************************************\ * * * Driver init/exit * diff --git a/drivers/mmc/host/sdhci-uhs2.h b/drivers/mmc/host/sdhci-uhs2.h index b9529d32b58d..7bb7a0d67109 100644 --- a/drivers/mmc/host/sdhci-uhs2.h +++ b/drivers/mmc/host/sdhci-uhs2.h @@ -210,5 +210,6 @@ struct sdhci_host; void sdhci_uhs2_dump_regs(struct sdhci_host *host); +void sdhci_uhs2_reset(struct sdhci_host *host, u16 mask); #endif /* __SDHCI_UHS2_H */ diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 97e7e04e4614..78db850dc1f3 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -194,13 +194,14 @@ static void sdhci_runtime_pm_bus_on(struct sdhci_host *host) pm_runtime_get_noresume(mmc_dev(host->mmc)); } -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(mmc_dev(host->mmc)); } +EXPORT_SYMBOL_GPL(sdhci_runtime_pm_bus_off); void sdhci_reset(struct sdhci_host *host, u8 mask) { diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index d9d7a76cedc1..b9932423db08 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -831,6 +831,7 @@ static inline void sdhci_read_caps(struct sdhci_host *host) __sdhci_read_caps(host, NULL, NULL, NULL); } +void sdhci_runtime_pm_bus_off(struct sdhci_host *host); 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); From patchwork Thu Jul 22 04:01:08 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lai Jason X-Patchwork-Id: 484934 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3E9A7C07E9D for ; Thu, 22 Jul 2021 04:02:36 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 2634C61222 for ; Thu, 22 Jul 2021 04:02:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230352AbhGVDVy (ORCPT ); Wed, 21 Jul 2021 23:21:54 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43802 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230169AbhGVDVn (ORCPT ); Wed, 21 Jul 2021 23:21:43 -0400 Received: from mail-pl1-x635.google.com (mail-pl1-x635.google.com [IPv6:2607:f8b0:4864:20::635]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C2CF7C061757; Wed, 21 Jul 2021 21:02:17 -0700 (PDT) Received: by mail-pl1-x635.google.com with SMTP id b12so2989371plh.10; Wed, 21 Jul 2021 21:02:17 -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:in-reply-to:references :mime-version:content-transfer-encoding; bh=k1ztdz3rUyfvAhBD7oREx/OD58dYkmWuDzT+QQUbx2M=; b=UcuJ5Jddv4aYiD4yK4pfO/FlWjt9fdTokv2sVHVZ9z1h7kGvUj1bzxLK6rcsfHrreE pc2HuImk4yMCUohtNiwybWChnOLdG5B5e2gaTTbDgI3XznR7AUjXJkf5JPKp2HXcyC3/ XLXarqrXG81u0k9wQJPtarC1sQpwCSlMN5+68NapQlvs+MfFE/pjY7IWxF7s5DWoLgNc rBEiORVr1KdyFrp2UZZm8Z7QByRinYmUoo0/xh7QzK5lqTR1UxpmkfYydQNg3Kdfbhrs G6sq8RJUpSteOCBKI6GWmBqx/BsMRI3UuddhZC23cz32C6DjIG3SBmbgqRGWzXAui53E peXg== 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:in-reply-to :references:mime-version:content-transfer-encoding; bh=k1ztdz3rUyfvAhBD7oREx/OD58dYkmWuDzT+QQUbx2M=; b=m+y2ATjcD+Xy8oW0q8r1sbCsCQLfa4yZhGPN6pHTI7fZJ76jqB6Sx2gVPWtW3BG8yy 0dBAqCuHwQihLSWX+VscL4IkJuZCrWgvfa1uMBOmHb3KHJL2wQX8+hZWJOcEuPSChfQr MqMlmbDg8s93KOpbMTCfJDjdZao6WbctcspkiYAobry6BXo/nM3IK3x1+jpOoAVA9C+v 9OrtKYuZyHyAfABiorMMrWZFV54GzxQcuymgkrh4Upb8h8AnKXYkVr82i0BZlFeP+T0l tpCdkG8h788Dd/vuUKJCa8LDX9OCd9MqLV9F9mVNZfTwZUpxSPrx2/z56MCf8szz089p 5w9Q== X-Gm-Message-State: AOAM533ERF7HJ2GjrciKT3uX2uRuGsPkBrlOfz0CqDLezR/zvYik1vwb EKuUnrvWLdCwyntzD0jO4JE= X-Google-Smtp-Source: ABdhPJzaxANSs7WNWViDXZyEEFec272tl1/MUCEHeKXAtTIWFCkE47c/x9UDSJtoK2WZD6JxgUkMfQ== X-Received: by 2002:a17:903:189:b029:12b:3fd7:d95d with SMTP id z9-20020a1709030189b029012b3fd7d95dmr30124708plg.24.1626926537256; Wed, 21 Jul 2021 21:02:17 -0700 (PDT) Received: from jason-z170xgaming7.mshome.net (218-35-143-223.cm.dynamic.apol.com.tw. [218.35.143.223]) by smtp.gmail.com with ESMTPSA id c19sm1663479pfp.184.2021.07.21.21.02.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 21 Jul 2021 21:02:17 -0700 (PDT) From: Jason Lai To: ulf.hansson@linaro.org, adrian.hunter@intel.com Cc: linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, ben.chuang@genesyslogic.com.tw, greg.tu@genesyslogic.com.tw, jason.lai@genesyslogiv.com.tw, AKASHI Takahiro Subject: [RFC PATCH v3.2 13/29] mmc: sdhci-uhs2: add set_power() to support vdd2 Date: Thu, 22 Jul 2021 12:01:08 +0800 Message-Id: <20210722040124.7573-13-jasonlai.genesyslogic@gmail.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210722040124.7573-1-jasonlai.genesyslogic@gmail.com> References: <20210722040124.7573-1-jasonlai.genesyslogic@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org This is a UHS-II version of sdhci's set_power operation. VDD2, as well as VDD, is handled here. Signed-off-by: Ben Chuang Signed-off-by: AKASHI Takahiro --- drivers/mmc/host/sdhci-uhs2.c | 80 +++++++++++++++++++++++++++++++++++ drivers/mmc/host/sdhci-uhs2.h | 2 + drivers/mmc/host/sdhci.c | 58 +++++++++++++++---------- drivers/mmc/host/sdhci.h | 2 + 4 files changed, 119 insertions(+), 23 deletions(-) -- 2.32.0 diff --git a/drivers/mmc/host/sdhci-uhs2.c b/drivers/mmc/host/sdhci-uhs2.c index e2b9743fe17d..2bf78cc4e9ed 100644 --- a/drivers/mmc/host/sdhci-uhs2.c +++ b/drivers/mmc/host/sdhci-uhs2.c @@ -98,6 +98,86 @@ void sdhci_uhs2_reset(struct sdhci_host *host, u16 mask) } EXPORT_SYMBOL_GPL(sdhci_uhs2_reset); +void sdhci_uhs2_set_power(struct sdhci_host *host, unsigned char mode, + unsigned short vdd) +{ + struct mmc_host *mmc = host->mmc; + u8 pwr; + + /* FIXME: check if flags & MMC_UHS2_SUPPORT? */ + if (!(host->mmc->caps & MMC_CAP_UHS2)) { + sdhci_set_power(host, mode, vdd); + return; + } + + if (mode != MMC_POWER_OFF) { + pwr = sdhci_get_vdd_value(vdd); + if (!pwr) + WARN(1, "%s: Invalid vdd %#x\n", + mmc_hostname(host->mmc), vdd); + + pwr |= SDHCI_VDD2_POWER_180; + } + + if (host->pwr == pwr) + return; + host ->pwr = pwr; + + if (pwr == 0) { + sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); + + if (!IS_ERR(host->mmc->supply.vmmc)) + mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0); + if (!IS_ERR_OR_NULL(host->mmc->supply.vmmc2)) + mmc_regulator_set_ocr(mmc, mmc->supply.vmmc2, 0); + + if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON) + sdhci_runtime_pm_bus_off(host); + } else { + if (!IS_ERR(host->mmc->supply.vmmc)) + mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, vdd); + if (!IS_ERR_OR_NULL(host->mmc->supply.vmmc2)) + /* support 1.8v only for now */ + mmc_regulator_set_ocr(mmc, mmc->supply.vmmc2, + fls(MMC_VDD2_165_195) - 1); + + /* + * Spec says that we should clear the power reg before setting + * a new value. Some controllers don't seem to like this though. + */ + if (!(host->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE)) + sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); + + /* + * At least the Marvell CaFe chip gets confused if we set the + * voltage and set turn on power at the same time, so set the + * voltage first. + */ + if (host->quirks & SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER) + sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); + + /* vdd first */ + pwr |= SDHCI_POWER_ON; + sdhci_writeb(host, pwr & 0xf, SDHCI_POWER_CONTROL); + mdelay(5); + + pwr |= SDHCI_VDD2_POWER_ON; + 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); + + /* + * Some controllers need an extra 10ms delay of 10ms before + * they can apply clock after applying power + */ + if (host->quirks & SDHCI_QUIRK_DELAY_AFTER_POWER) + mdelay(10); + } +} +EXPORT_SYMBOL_GPL(sdhci_uhs2_set_power); + /*****************************************************************************\ * * * Driver init/exit * diff --git a/drivers/mmc/host/sdhci-uhs2.h b/drivers/mmc/host/sdhci-uhs2.h index 7bb7a0d67109..3c19d8e44c36 100644 --- a/drivers/mmc/host/sdhci-uhs2.h +++ b/drivers/mmc/host/sdhci-uhs2.h @@ -211,5 +211,7 @@ struct sdhci_host; void sdhci_uhs2_dump_regs(struct sdhci_host *host); void sdhci_uhs2_reset(struct sdhci_host *host, u16 mask); +void sdhci_uhs2_set_power(struct sdhci_host *host, unsigned char mode, + unsigned short vdd); #endif /* __SDHCI_UHS2_H */ diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 78db850dc1f3..d944e5e0a30a 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -186,13 +186,14 @@ static void sdhci_disable_card_detection(struct sdhci_host *host) sdhci_set_card_detection(host, false); } -static void sdhci_runtime_pm_bus_on(struct sdhci_host *host) +void sdhci_runtime_pm_bus_on(struct sdhci_host *host) { if (host->bus_on) return; host->bus_on = true; pm_runtime_get_noresume(mmc_dev(host->mmc)); } +EXPORT_SYMBOL_GPL(sdhci_runtime_pm_bus_on); void sdhci_runtime_pm_bus_off(struct sdhci_host *host) { @@ -2018,36 +2019,47 @@ static void sdhci_set_power_reg(struct sdhci_host *host, unsigned char mode, sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); } +unsigned short sdhci_get_vdd_value(unsigned short vdd) +{ + u8 pwr; + + 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: + pwr = 0; + } + + return pwr; +} +EXPORT_SYMBOL_GPL(sdhci_get_vdd_value); + void sdhci_set_power_noreg(struct sdhci_host *host, unsigned char mode, unsigned short vdd) { 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: + pwr = sdhci_get_vdd_value(vdd); + if (!pwr) WARN(1, "%s: Invalid vdd %#x\n", mmc_hostname(host->mmc), vdd); - break; - } } if (host->pwr == pwr) diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index b9932423db08..2b5b8295cf92 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -831,6 +831,7 @@ static inline void sdhci_read_caps(struct sdhci_host *host) __sdhci_read_caps(host, NULL, NULL, NULL); } +void sdhci_runtime_pm_bus_on(struct sdhci_host *host); void sdhci_runtime_pm_bus_off(struct sdhci_host *host); u16 sdhci_calc_clk(struct sdhci_host *host, unsigned int clock, unsigned int *actual_clock); @@ -841,6 +842,7 @@ void sdhci_set_power(struct sdhci_host *host, unsigned char mode, void sdhci_set_power_and_bus_voltage(struct sdhci_host *host, unsigned char mode, unsigned short vdd); +unsigned short sdhci_get_vdd_value(unsigned short vdd); void sdhci_set_power_noreg(struct sdhci_host *host, unsigned char mode, unsigned short vdd); void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq); From patchwork Thu Jul 22 04:01:09 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lai Jason X-Patchwork-Id: 484933 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id E1EB7C6377D for ; Thu, 22 Jul 2021 04:02:37 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id CB9D1608FC for ; Thu, 22 Jul 2021 04:02:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229890AbhGVDWA (ORCPT ); Wed, 21 Jul 2021 23:22:00 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43800 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230136AbhGVDVo (ORCPT ); Wed, 21 Jul 2021 23:21:44 -0400 Received: from mail-pj1-x1031.google.com (mail-pj1-x1031.google.com [IPv6:2607:f8b0:4864:20::1031]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6A485C061575; Wed, 21 Jul 2021 21:02:19 -0700 (PDT) Received: by mail-pj1-x1031.google.com with SMTP id gx2so4343514pjb.5; Wed, 21 Jul 2021 21:02:19 -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:in-reply-to:references :mime-version:content-transfer-encoding; bh=p64ymEfbWIOXlBU2XpyW8YH+kA6dtacSu0XJepOqP6o=; b=o36SZHRyhDW8cRhM8Kb/a2tz61RRancNXporAGJjhwLEnOvRF/4dYJZZyE8KoT4qrI BkDM2eT+QOXHswKseFyID6tPjcDhHFEOogh6VBRHaj63Xg/5H5oQu8F47C/9nKaqE3Lm bXfqz2TlEp/JHOYHqLCDTqxWY5iMDeo4cgJPGXjI45Q/9lO7yHm9LuE/yLKYf/TcDbU4 Kc3ePo1lUgmjnI5itPw9Je2ipZ1agayVH1PR4mCcXxibP/mS5ysf3A/UcyBgsq7OgY61 CqtmylDwaQCGBbhzXxEXIOqxpKB04zb5XJjvzn4Z96vReDbi5kJmL0loPextW4nup9w8 5KQQ== 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:in-reply-to :references:mime-version:content-transfer-encoding; bh=p64ymEfbWIOXlBU2XpyW8YH+kA6dtacSu0XJepOqP6o=; b=bpPFjq33jJQgLHlmUPJA+rF/jtE3GnQzJQdO9XGJDZbdJtFjqa9xAM9iPzZAVCMWj9 HYzMUIUPtClOwvDndmaScqjWJBYJMcuRs+g+hx61Y3Tppgnp0Vh7MSlLsNhvGe+b894S VMmwpoA6akzE6a9xK3eceMF8MC7dFeoRKp1klUkx7CuT+Ra8IB+P3+Wc+EcjzRIjjMOg GWvRCrejoyDLEQtekIBPA/KX7bHo+d0sGmfOuu/1bYrjIFhTz62I2+EVgdtouofg4Fo+ 1EAHTHUs41UZLRDoPNnA9IbB0bPilqP5ulLu8GaiAxury9pXrTMsxyYCUc8leSUyyF9c TjhQ== X-Gm-Message-State: AOAM533UwrjkTPstc9l/dSsddmpM1b1VuMR3RwyuMg+1qCbhN3k71WXZ fItTpBURY8EOk8RtTX9cfaA= X-Google-Smtp-Source: ABdhPJysyTXxFH//02lY03MLSMoI5M1YP/Pc54A3QNv3ZGjmC0Sja2Gc9rjf/cgboqftYxDM5yeXug== X-Received: by 2002:a62:3344:0:b029:25e:a0a8:1c51 with SMTP id z65-20020a6233440000b029025ea0a81c51mr39851727pfz.58.1626926539031; Wed, 21 Jul 2021 21:02:19 -0700 (PDT) Received: from jason-z170xgaming7.mshome.net (218-35-143-223.cm.dynamic.apol.com.tw. [218.35.143.223]) by smtp.gmail.com with ESMTPSA id c19sm1663479pfp.184.2021.07.21.21.02.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 21 Jul 2021 21:02:18 -0700 (PDT) From: Jason Lai To: ulf.hansson@linaro.org, adrian.hunter@intel.com Cc: linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, ben.chuang@genesyslogic.com.tw, greg.tu@genesyslogic.com.tw, jason.lai@genesyslogiv.com.tw, AKASHI Takahiro Subject: [RFC PATCH v3.2 14/29] mmc: sdhci-uhs2: skip signal_voltage_switch() Date: Thu, 22 Jul 2021 12:01:09 +0800 Message-Id: <20210722040124.7573-14-jasonlai.genesyslogic@gmail.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210722040124.7573-1-jasonlai.genesyslogic@gmail.com> References: <20210722040124.7573-1-jasonlai.genesyslogic@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org For UHS2, the signal voltage is supplied by vdd2 which is already 1.8v, so no voltage switch required. Signed-off-by: Ben Chuang Signed-off-by: AKASHI Takahiro --- drivers/mmc/host/sdhci-uhs2.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) -- 2.32.0 diff --git a/drivers/mmc/host/sdhci-uhs2.c b/drivers/mmc/host/sdhci-uhs2.c index 2bf78cc4e9ed..1eca89359351 100644 --- a/drivers/mmc/host/sdhci-uhs2.c +++ b/drivers/mmc/host/sdhci-uhs2.c @@ -178,6 +178,29 @@ void sdhci_uhs2_set_power(struct sdhci_host *host, unsigned char mode, } EXPORT_SYMBOL_GPL(sdhci_uhs2_set_power); +/*****************************************************************************\ + * * + * MMC callbacks * + * * +\*****************************************************************************/ + +static int sdhci_uhs2_start_signal_voltage_switch(struct mmc_host *mmc, + struct mmc_ios *ios) +{ + struct sdhci_host *host = mmc_priv(mmc); + + /* + * For UHS2, the signal voltage is supplied by vdd2 which is + * already 1.8v so no voltage switch required. + */ + if (IS_ENABLED(CONFIG_MMC_SDHCI_UHS2) && + host->version >= SDHCI_SPEC_400 && + host->mmc->flags & MMC_UHS2_SUPPORT) + return 0; + + return sdhci_start_signal_voltage_switch(mmc, ios); +} + /*****************************************************************************\ * * * Driver init/exit * @@ -186,6 +209,9 @@ EXPORT_SYMBOL_GPL(sdhci_uhs2_set_power); static int sdhci_uhs2_host_ops_init(struct sdhci_host *host) { + host->mmc_host_ops.start_signal_voltage_switch = + sdhci_uhs2_start_signal_voltage_switch; + return 0; } From patchwork Thu Jul 22 04:01:10 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lai Jason X-Patchwork-Id: 484193 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 00793C6377E for ; Thu, 22 Jul 2021 04:02:39 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id DE8C461222 for ; Thu, 22 Jul 2021 04:02:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230268AbhGVDWB (ORCPT ); Wed, 21 Jul 2021 23:22:01 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43826 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230201AbhGVDVq (ORCPT ); Wed, 21 Jul 2021 23:21:46 -0400 Received: from mail-pl1-x630.google.com (mail-pl1-x630.google.com [IPv6:2607:f8b0:4864:20::630]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 57AD2C0613C1; Wed, 21 Jul 2021 21:02:21 -0700 (PDT) Received: by mail-pl1-x630.google.com with SMTP id y3so3013123plp.4; Wed, 21 Jul 2021 21:02: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:in-reply-to:references :mime-version:content-transfer-encoding; bh=CQfXFdO5AEIdfPufawPvgOpW6II+HeJ1KkO9+iMXy5s=; b=IdlQMfton5ZPJks2yC6JdkJWks1ukLPO7xQFbAEzBKz/VRo3YhyBC4zb5xF7jMrSzB LhcyVlUckRU0G9MQ9RMwvckGShxysJCqGV7XPBTVkaojMNSzr/V54+T+pA/iVT8lXcD+ kNmW44RqdhfOJUsHxH/S7O6xp6RDlxzKebO4Z0bULyr5jXEqUH1mxuucLU2j4fGCsGr3 2Mvze2hNG/OeEc2zIZqGFWxsBwotRE4e83E0WA+r4TLiyDe9Sht1LgWldiAHMZIRRY/M 79GGfCUxR9bD0DOfauxGqAmJ21D9r/QuTouAEqzwVQdnIwatJGIggQZ2fPv0uikMLQ4a 7HHA== 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:in-reply-to :references:mime-version:content-transfer-encoding; bh=CQfXFdO5AEIdfPufawPvgOpW6II+HeJ1KkO9+iMXy5s=; b=UknSLOFzgN0WEZcM4JRmIMV4W8CZ8a6LusGfAgcDLIpUKsriW5/ZeLzAqKK+JbOKcH dpw54nAurI30Y1d2wVv+g1WvzsKGt0EDtqu51UKJLpYLQ1lg97rdk2NqGdwuPIekx2xG Ccb8emTXX8NMNNDcanZU5BT+tm8Cdh7XmCiEhgPvtri2clfNwOLT3+BWfqZjK8b1Do3l G/VywuwfMP1UsChKRcjRd7RuREPRoxm6gYg/Q2pRDRBGuJGVnb+oO7k0sO2NDOUFZ3we pU0He9xZsf/a/GDiPSb1OeUC3ABglG0quVwbNZ1LYG/YIsLQB8Vad/15WZPqw87juGTK 5+9g== X-Gm-Message-State: AOAM532WqCwm2c3izlqYppz7ADnS9gn4tDdppQr0a1de6+ZWiErEDQmE m+idPewyFzRJl4LmxuE9nbk= X-Google-Smtp-Source: ABdhPJzMe7vGkNEmv+sRfdgqQ9q9YzeTSh7yKMJWvS426JSLU13gVa+/4EopqHpAl60tHOmzNjS1ww== X-Received: by 2002:a63:dd46:: with SMTP id g6mr15211013pgj.347.1626926540968; Wed, 21 Jul 2021 21:02:20 -0700 (PDT) Received: from jason-z170xgaming7.mshome.net (218-35-143-223.cm.dynamic.apol.com.tw. [218.35.143.223]) by smtp.gmail.com with ESMTPSA id c19sm1663479pfp.184.2021.07.21.21.02.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 21 Jul 2021 21:02:20 -0700 (PDT) From: Jason Lai To: ulf.hansson@linaro.org, adrian.hunter@intel.com Cc: linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, ben.chuang@genesyslogic.com.tw, greg.tu@genesyslogic.com.tw, jason.lai@genesyslogiv.com.tw, AKASHI Takahiro Subject: [RFC PATCH v3.2 15/29] mmc: sdhci-uhs2: add set_timeout() Date: Thu, 22 Jul 2021 12:01:10 +0800 Message-Id: <20210722040124.7573-15-jasonlai.genesyslogic@gmail.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210722040124.7573-1-jasonlai.genesyslogic@gmail.com> References: <20210722040124.7573-1-jasonlai.genesyslogic@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org This is a UHS-II version of sdhci's set_timeout() operation. Signed-off-by: Ben Chuang Signed-off-by: AKASHI Takahiro --- drivers/mmc/host/sdhci-uhs2.c | 85 +++++++++++++++++++++++++++++++++++ drivers/mmc/host/sdhci-uhs2.h | 1 + 2 files changed, 86 insertions(+) -- 2.32.0 diff --git a/drivers/mmc/host/sdhci-uhs2.c b/drivers/mmc/host/sdhci-uhs2.c index 1eca89359351..d9e98c097bfe 100644 --- a/drivers/mmc/host/sdhci-uhs2.c +++ b/drivers/mmc/host/sdhci-uhs2.c @@ -178,6 +178,91 @@ void sdhci_uhs2_set_power(struct sdhci_host *host, unsigned char mode, } EXPORT_SYMBOL_GPL(sdhci_uhs2_set_power); +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); +} + +void sdhci_uhs2_set_timeout(struct sdhci_host *host, struct mmc_command *cmd) +{ + __sdhci_set_timeout(host, cmd); + + if (host->mmc->flags & MMC_UHS2_SUPPORT) + __sdhci_uhs2_set_timeout(host); +} +EXPORT_SYMBOL_GPL(sdhci_uhs2_set_timeout); + /*****************************************************************************\ * * * MMC callbacks * diff --git a/drivers/mmc/host/sdhci-uhs2.h b/drivers/mmc/host/sdhci-uhs2.h index 3c19d8e44c36..efe70577bc74 100644 --- a/drivers/mmc/host/sdhci-uhs2.h +++ b/drivers/mmc/host/sdhci-uhs2.h @@ -213,5 +213,6 @@ void sdhci_uhs2_dump_regs(struct sdhci_host *host); void sdhci_uhs2_reset(struct sdhci_host *host, u16 mask); void sdhci_uhs2_set_power(struct sdhci_host *host, unsigned char mode, unsigned short vdd); +void sdhci_uhs2_set_timeout(struct sdhci_host *host, struct mmc_command *cmd); #endif /* __SDHCI_UHS2_H */ From patchwork Thu Jul 22 04:01:11 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lai Jason X-Patchwork-Id: 484192 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.5 required=3.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_INVALID, DKIM_SIGNED, FREEMAIL_FORGED_FROMDOMAIN, FREEMAIL_FROM,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 973B4C63797 for ; Thu, 22 Jul 2021 04:02:40 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 800C561222 for ; Thu, 22 Jul 2021 04:02:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230463AbhGVDWD (ORCPT ); Wed, 21 Jul 2021 23:22:03 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43848 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230292AbhGVDVs (ORCPT ); Wed, 21 Jul 2021 23:21:48 -0400 Received: from mail-pl1-x634.google.com (mail-pl1-x634.google.com [IPv6:2607:f8b0:4864:20::634]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3A7EDC0613D3; Wed, 21 Jul 2021 21:02:23 -0700 (PDT) Received: by mail-pl1-x634.google.com with SMTP id n11so3013453plc.2; Wed, 21 Jul 2021 21:02:23 -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:in-reply-to:references :mime-version:content-transfer-encoding; bh=GTJnDJdPb/p/1p06j3Be3mQ1PFh0Arrmq+qmboZAUS0=; b=Oc/ast9lhQOzssCj4tsEBIqUHwi9PMcThoGlNYEOCyK44kinVKg2AW7+4eHxpQSW9J hGYqKMxT7qSud/69EhsRgHaYcbBeyfqEP6canZX+S+sDVnwWXEYL9cPQA8coCQgxwZGH ufgAyGMITfw/bFAJGZ1H7Om4oqPBJZXfFcyC2Epez0siW5vq0+yW06jxIJVlpr/Wp50i O1KYFZpd9mA6Oyva/yLE9N0kvVqMY/bLwYrAnddI6SiPXi1Ih2Ms0v07dGB8moV9mKU4 83GoS9zq+hoVSUzqHbyPs3YJ125NQVqNyxvjhgLIiOmdy9+8yRCo1xfxRV4juQ+VOqVY XTJQ== 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:in-reply-to :references:mime-version:content-transfer-encoding; bh=GTJnDJdPb/p/1p06j3Be3mQ1PFh0Arrmq+qmboZAUS0=; b=kt4bx/oLglM/YUNOzhmXRr6KcI+QeJmuf9RYoSPIqYDj4QxebV6dsMsvqg0eAHafE6 3Ow0Yl7p0+m5PxYAQ3U3WJMUzNOEIWMLLd20pdahHgnCJftY5yIiaLAvcK6mSVWXj+Fp B/dOuyixiqot/xOKfiqFZzu0+JrO+1W1JniCOot6T1OHL1Jyr8+1T/A7u95cEHv6PVaN MxSOmbYTd08H8xj83ZcT+S2WISiI/gebkQpiSgeFGBVWetDQ1vJ6illOYm06CP02ObIi OIwrwN8Ili7LJuDcR49jy8MLo12opg3PigrVQyXrpDmDueGkgo4yNiWebp8QjkbRjLNn SrDg== X-Gm-Message-State: AOAM532m4wK4EH7naSgTe+MXNawVhj32O/Tlwr4KvqQN1tDOHIyD43cr rFhCGPklQ+rnmICprZXE1lU= X-Google-Smtp-Source: ABdhPJwuliBjmBxfAhRyu6nw+RBhpikcPxS3s8XN88chSnR7LrqK8J45DXcs1e8BQcHuW9AZVhyF7g== X-Received: by 2002:a17:90a:f186:: with SMTP id bv6mr6913912pjb.25.1626926542768; Wed, 21 Jul 2021 21:02:22 -0700 (PDT) Received: from jason-z170xgaming7.mshome.net (218-35-143-223.cm.dynamic.apol.com.tw. [218.35.143.223]) by smtp.gmail.com with ESMTPSA id c19sm1663479pfp.184.2021.07.21.21.02.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 21 Jul 2021 21:02:22 -0700 (PDT) From: Jason Lai To: ulf.hansson@linaro.org, adrian.hunter@intel.com Cc: linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, ben.chuang@genesyslogic.com.tw, greg.tu@genesyslogic.com.tw, jason.lai@genesyslogiv.com.tw, AKASHI Takahiro Subject: [RFC PATCH v3.2 16/29] mmc: sdhci-uhs2: add set_ios() Date: Thu, 22 Jul 2021 12:01:11 +0800 Message-Id: <20210722040124.7573-16-jasonlai.genesyslogic@gmail.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210722040124.7573-1-jasonlai.genesyslogic@gmail.com> References: <20210722040124.7573-1-jasonlai.genesyslogic@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org This is a sdhci version of mmc's set_ios operation. It covers both UHS-I and UHS-II. Signed-off-by: Ben Chuang Signed-off-by: AKASHI Takahiro --- drivers/mmc/host/sdhci-uhs2.c | 100 ++++++++++++++++++++++++++++++++++ drivers/mmc/host/sdhci-uhs2.h | 1 + drivers/mmc/host/sdhci.c | 40 +++++++++----- drivers/mmc/host/sdhci.h | 2 + 4 files changed, 128 insertions(+), 15 deletions(-) -- 2.32.0 diff --git a/drivers/mmc/host/sdhci-uhs2.c b/drivers/mmc/host/sdhci-uhs2.c index d9e98c097bfe..637464748cc4 100644 --- a/drivers/mmc/host/sdhci-uhs2.c +++ b/drivers/mmc/host/sdhci-uhs2.c @@ -263,6 +263,74 @@ void sdhci_uhs2_set_timeout(struct sdhci_host *host, struct mmc_command *cmd) } EXPORT_SYMBOL_GPL(sdhci_uhs2_set_timeout); +/** + * 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); + +static void __sdhci_uhs2_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) +{ + struct sdhci_host *host = mmc_priv(mmc); + u8 cmd_res, dead_lock; + u16 ctrl_2; + unsigned long flags; + + /* FIXME: why lock? */ + 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); + + if (host->ops->set_power) + host->ops->set_power(host, ios->power_mode, ios->vdd); + else + sdhci_set_power(host, ios->power_mode, ios->vdd); + udelay(100); + + host->timing = ios->timing; + sdhci_set_clock(host, host->clock); + + spin_unlock_irqrestore(&host->lock, flags); +} + /*****************************************************************************\ * * * MMC callbacks * @@ -286,6 +354,37 @@ static int sdhci_uhs2_start_signal_voltage_switch(struct mmc_host *mmc, return sdhci_start_signal_voltage_switch(mmc, ios); } +void sdhci_uhs2_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) +{ + struct sdhci_host *host = mmc_priv(mmc); + + if (!(host->version >= SDHCI_SPEC_400) || + !(host->mmc->flags & MMC_UHS2_SUPPORT && + host->mmc->caps & MMC_CAP_UHS2)) { + sdhci_set_ios(mmc, ios); + return; + } + + if (ios->power_mode == MMC_POWER_UNDEFINED) + return; + + if (host->flags & SDHCI_DEVICE_DEAD) { + if (!IS_ERR(mmc->supply.vmmc) && + ios->power_mode == MMC_POWER_OFF) + mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0); + if (!IS_ERR_OR_NULL(mmc->supply.vmmc2) && + ios->power_mode == MMC_POWER_OFF) + mmc_regulator_set_ocr(mmc, mmc->supply.vmmc2, 0); + return; + } + + /* FIXME: host->timing = ios->timing */ + + sdhci_set_ios_common(mmc, ios); + + __sdhci_uhs2_set_ios(mmc, ios); +} + /*****************************************************************************\ * * * Driver init/exit * @@ -296,6 +395,7 @@ static int sdhci_uhs2_host_ops_init(struct sdhci_host *host) { host->mmc_host_ops.start_signal_voltage_switch = sdhci_uhs2_start_signal_voltage_switch; + host->mmc_host_ops.set_ios = sdhci_uhs2_set_ios; return 0; } diff --git a/drivers/mmc/host/sdhci-uhs2.h b/drivers/mmc/host/sdhci-uhs2.h index efe70577bc74..c1ff4ac1ab7a 100644 --- a/drivers/mmc/host/sdhci-uhs2.h +++ b/drivers/mmc/host/sdhci-uhs2.h @@ -214,5 +214,6 @@ void sdhci_uhs2_reset(struct sdhci_host *host, u16 mask); void sdhci_uhs2_set_power(struct sdhci_host *host, unsigned char mode, unsigned short vdd); void sdhci_uhs2_set_timeout(struct sdhci_host *host, struct mmc_command *cmd); +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.c b/drivers/mmc/host/sdhci.c index d944e5e0a30a..d60a1fdd1385 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -47,8 +47,6 @@ 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) @@ -1837,6 +1835,9 @@ static u16 sdhci_get_preset_value(struct sdhci_host *host) case MMC_TIMING_MMC_HS400: preset = sdhci_readw(host, SDHCI_PRESET_FOR_HS400); break; + case MMC_TIMING_UHS2: + preset = sdhci_readw(host, SDHCI_PRESET_FOR_UHS2); + break; default: pr_warn("%s: Invalid UHS-I mode selected\n", mmc_hostname(host->mmc)); @@ -2250,20 +2251,9 @@ void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing) } EXPORT_SYMBOL_GPL(sdhci_set_uhs_signaling); -void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) +void sdhci_set_ios_common(struct mmc_host *mmc, struct mmc_ios *ios) { struct sdhci_host *host = mmc_priv(mmc); - u8 ctrl; - - if (ios->power_mode == MMC_POWER_UNDEFINED) - return; - - if (host->flags & SDHCI_DEVICE_DEAD) { - if (!IS_ERR(mmc->supply.vmmc) && - ios->power_mode == MMC_POWER_OFF) - mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0); - return; - } /* * Reset the chip on each power off. @@ -2300,6 +2290,25 @@ void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) host->ops->set_power(host, ios->power_mode, ios->vdd); else sdhci_set_power(host, ios->power_mode, ios->vdd); +} +EXPORT_SYMBOL_GPL(sdhci_set_ios_common); + +void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) +{ + struct sdhci_host *host = mmc_priv(mmc); + u8 ctrl; + + if (ios->power_mode == MMC_POWER_UNDEFINED) + return; + + if (host->flags & SDHCI_DEVICE_DEAD) { + if (!IS_ERR(mmc->supply.vmmc) && + ios->power_mode == MMC_POWER_OFF) + mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0); + return; + } + + sdhci_set_ios_common(mmc, ios); if (host->ops->platform_send_init_74_clocks) host->ops->platform_send_init_74_clocks(host, ios->power_mode); @@ -2870,7 +2879,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) @@ -2898,6 +2907,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 2b5b8295cf92..e84ebddb20d8 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -851,6 +851,8 @@ void sdhci_set_bus_width(struct sdhci_host *host, int width); void sdhci_reset(struct sdhci_host *host, u8 mask); void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing); int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode); +void sdhci_enable_preset_value(struct sdhci_host *host, bool enable); +void sdhci_set_ios_common(struct mmc_host *mmc, struct mmc_ios *ios); void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios); int sdhci_start_signal_voltage_switch(struct mmc_host *mmc, struct mmc_ios *ios); From patchwork Thu Jul 22 04:01:12 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lai Jason X-Patchwork-Id: 484932 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.5 required=3.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_INVALID, DKIM_SIGNED, FREEMAIL_FORGED_FROMDOMAIN, FREEMAIL_FROM,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id E21B1C07E9D for ; Thu, 22 Jul 2021 04:02:43 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C9B2861279 for ; Thu, 22 Jul 2021 04:02:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230252AbhGVDWE (ORCPT ); Wed, 21 Jul 2021 23:22:04 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43860 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230310AbhGVDVu (ORCPT ); Wed, 21 Jul 2021 23:21:50 -0400 Received: from mail-pl1-x635.google.com (mail-pl1-x635.google.com [IPv6:2607:f8b0:4864:20::635]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 25703C06179A; Wed, 21 Jul 2021 21:02:25 -0700 (PDT) Received: by mail-pl1-x635.google.com with SMTP id y3so3013217plp.4; Wed, 21 Jul 2021 21:02:25 -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:in-reply-to:references :mime-version:content-transfer-encoding; bh=Syp+0S37AQCBW6PlS3KzFfSj2fIUsGEfeocJuZhdlqQ=; b=Zt7n2VRG/RfevCZ6MzOUveEX14cXRf37Gc1onen4TOPHDW7zshDETp9v6TsAwQxRT1 IdiDQAXYegh70pmkDP8IIY9ItTv8K083wRzaum0J9G9xWuHg64bzlUSyjk05ZSdgrpRN 1J7PrDuQfuRDlwwlNVe8DDYcSh680BPFQimvvXheJ2bSNjOJ+mWCqQAhTe69+GmNQ4wJ c992t8OBkcClCQhogy/8xkB+odKwI1NiMNLVCxa/OWOKgl5elOpUanVyv5GD9/jqKp5L r/rgqeuUfgosIf8GxpVluodpXqqOoQdTybyGjmyr8xgcmHrN/YSrUbe7AKDp/SaA3lTm b6zw== 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:in-reply-to :references:mime-version:content-transfer-encoding; bh=Syp+0S37AQCBW6PlS3KzFfSj2fIUsGEfeocJuZhdlqQ=; b=hQiJnvl4euDxQmYA1aA8wEWArkoSu0z1sdYcRIakQemR2GrO5/Lo33ruizG5e+pp+E W77fmIaJTZWN94Dbq9BKQpMQh+hiRxZFutwdWjFciz28xLPvdnS42Za1jg+/5ASC4POl 0P0+vRinb+nKxFrmr3yARxVWVFLu2WJStS4QmGVAEQqTMmcwQkQt+Sai3YKJasPz13Hj 8Byi4865CiXJ2nin57A3M7PPOD7SHZgiU+QdEX0m/S6jfik4TWKUyAB5yhbDc2/FoyIZ 1ywd7T1aqqWTOJaxdN41Y7uS/2j4R5PnPynnCpgZg3gKbHx4fcRqvjqGbvdX/foKzZ0c dHwQ== X-Gm-Message-State: AOAM532vkS3qaayGmlurgHTtWv41o7QvVzWDSIJs2oU813jk7PpxyXRo hSLohea2O1hVSEeapDSxkms= X-Google-Smtp-Source: ABdhPJzSBKi3BCtE019e5sLt9VJvHP+XBkbbbfz+7i6lnlYEaOkVkDWj8c+wVZljftuofcxVYZWN1Q== X-Received: by 2002:a17:902:7794:b029:12b:8d54:870 with SMTP id o20-20020a1709027794b029012b8d540870mr14095467pll.70.1626926544653; Wed, 21 Jul 2021 21:02:24 -0700 (PDT) Received: from jason-z170xgaming7.mshome.net (218-35-143-223.cm.dynamic.apol.com.tw. [218.35.143.223]) by smtp.gmail.com with ESMTPSA id c19sm1663479pfp.184.2021.07.21.21.02.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 21 Jul 2021 21:02:24 -0700 (PDT) From: Jason Lai To: ulf.hansson@linaro.org, adrian.hunter@intel.com Cc: linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, ben.chuang@genesyslogic.com.tw, greg.tu@genesyslogic.com.tw, jason.lai@genesyslogiv.com.tw, AKASHI Takahiro Subject: [RFC PATCH v3.2 17/29] mmc: sdhci-uhs2: add detect_init() to detect the interface Date: Thu, 22 Jul 2021 12:01:12 +0800 Message-Id: <20210722040124.7573-17-jasonlai.genesyslogic@gmail.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210722040124.7573-1-jasonlai.genesyslogic@gmail.com> References: <20210722040124.7573-1-jasonlai.genesyslogic@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org Sdhci_uhs2_do_detect_init() is a sdhci version of mmc's uhs2_detect_init operation. After detected, the host's UHS-II capabilities will be set up here and interrupts will also be enabled. Signed-off-by: Ben Chuang Signed-off-by: AKASHI Takahiro --- drivers/mmc/host/sdhci-uhs2.c | 160 ++++++++++++++++++++++++++++++++++ 1 file changed, 160 insertions(+) -- 2.32.0 diff --git a/drivers/mmc/host/sdhci-uhs2.c b/drivers/mmc/host/sdhci-uhs2.c index 637464748cc4..994dff967e85 100644 --- a/drivers/mmc/host/sdhci-uhs2.c +++ b/drivers/mmc/host/sdhci-uhs2.c @@ -391,12 +391,172 @@ void sdhci_uhs2_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) * * \*****************************************************************************/ +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 mmc_host *mmc) +{ + struct sdhci_host *host = mmc_priv(mmc); + 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 int sdhci_uhs2_host_ops_init(struct sdhci_host *host) { host->mmc_host_ops.start_signal_voltage_switch = sdhci_uhs2_start_signal_voltage_switch; host->mmc_host_ops.set_ios = sdhci_uhs2_set_ios; + if (!host->mmc_host_ops.uhs2_detect_init) + host->mmc_host_ops.uhs2_detect_init = sdhci_uhs2_do_detect_init; + return 0; } From patchwork Thu Jul 22 04:01:13 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lai Jason X-Patchwork-Id: 484191 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-10.7 required=3.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_INVALID, DKIM_SIGNED, FREEMAIL_FORGED_FROMDOMAIN, FREEMAIL_FROM,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, UNWANTED_LANGUAGE_BODY,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id A75E0C6377E for ; Thu, 22 Jul 2021 04:02:46 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 993F161222 for ; Thu, 22 Jul 2021 04:02:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230367AbhGVDWG (ORCPT ); Wed, 21 Jul 2021 23:22:06 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43804 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230370AbhGVDVw (ORCPT ); Wed, 21 Jul 2021 23:21:52 -0400 Received: from mail-pj1-x1031.google.com (mail-pj1-x1031.google.com [IPv6:2607:f8b0:4864:20::1031]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EBAEEC06179E; Wed, 21 Jul 2021 21:02:26 -0700 (PDT) Received: by mail-pj1-x1031.google.com with SMTP id u9-20020a17090a1f09b029017554809f35so2352733pja.5; Wed, 21 Jul 2021 21:02:26 -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:in-reply-to:references :mime-version:content-transfer-encoding; bh=4E1R4sFAVMhjqGN0YC8B71uq5j/Oq2YJVzlAWihbNec=; b=Pq96KElRB891sL3oh229eket4TOuYtBX6m8VN9tj6wOsum4w1hFrJa4deMzoaShe2E le6J0np6YDc4pz71DW6ZA6ey8ngPgpNRxk2AvY6fUQRPW5X+BqwENeiQpoT4IzU3tkwe zOyayHd1zrlcTYExn4Eiy9XOD1838BdpWc2X05Zb+0RCkQcV8L6CHlbpVsdMcy7x3DfK J8ypiNOhAZAci6Yu3Z5REDo6D9KuTy9aLQYXEdU4xW/PSzo4/6d8+8qLuH19gnaBAAKa hr27YJxIDBYgxlzaMWH+BXN9XRzUscxgI3oYSCbiC2fy1VbrSB4NDjqM2WCU7NPQawaO PeqQ== 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:in-reply-to :references:mime-version:content-transfer-encoding; bh=4E1R4sFAVMhjqGN0YC8B71uq5j/Oq2YJVzlAWihbNec=; b=LmeZU4fRXiRvwpAwOG/9YYZa/AXvEHl/d9N6u56sRFqO1o5xtW79HqA8Osz6W6lPPS r08Ii8AJIlK6EuXrwJDrQDcE7Y/dX9BlaLiRQGBjB/OZN6LmxIATuTE+wwzO7PwyataM dJ6YIxc268eZXsslttSlq2hC6wk8H7oNVBFOzXL+fPHDnOm3qg0n2QUDwBsMNJ4jfGL4 ipQfHqMFNtuACRxzwHe1i9TOICcKpE28SFSRdNT5hLFHDWw11+SQo91RketPwRUcbRVI 13nIDWDc0VYFlAjNZ3pOpTbaM6tWjfNm6MzbwLxtnI2dev+zhFjMVCAvbxgc/iCk3Wcw IQvA== X-Gm-Message-State: AOAM530R8cnJqTiCbTEDxMdfK6pweOzgY47IcFpFyDflw9L5kSi9af2t gjst3SZERyAX/TuoNj/Oerw= X-Google-Smtp-Source: ABdhPJwQP26yCo/7Sfuz+wcyp46/mt03qdV41wSR5PhVno2OrdQL2UQ0K54vH8mjw8tPNNPhs61Gaw== X-Received: by 2002:a17:902:8648:b029:129:dda4:ddc2 with SMTP id y8-20020a1709028648b0290129dda4ddc2mr29974073plt.4.1626926546577; Wed, 21 Jul 2021 21:02:26 -0700 (PDT) Received: from jason-z170xgaming7.mshome.net (218-35-143-223.cm.dynamic.apol.com.tw. [218.35.143.223]) by smtp.gmail.com with ESMTPSA id c19sm1663479pfp.184.2021.07.21.21.02.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 21 Jul 2021 21:02:26 -0700 (PDT) From: Jason Lai To: ulf.hansson@linaro.org, adrian.hunter@intel.com Cc: linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, ben.chuang@genesyslogic.com.tw, greg.tu@genesyslogic.com.tw, jason.lai@genesyslogiv.com.tw, AKASHI Takahiro Subject: [RFC PATCH v3.2 18/29] mmc: sdhci-uhs2: add clock operations Date: Thu, 22 Jul 2021 12:01:13 +0800 Message-Id: <20210722040124.7573-18-jasonlai.genesyslogic@gmail.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210722040124.7573-1-jasonlai.genesyslogic@gmail.com> References: <20210722040124.7573-1-jasonlai.genesyslogic@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org This is a sdhci version of mmc's uhs2_[enable|disable]_clk operations. Signed-off-by: Ben Chuang Signed-off-by: AKASHI Takahiro --- drivers/mmc/host/sdhci-uhs2.c | 41 +++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) -- 2.32.0 diff --git a/drivers/mmc/host/sdhci-uhs2.c b/drivers/mmc/host/sdhci-uhs2.c index 994dff967e85..55362ace1857 100644 --- a/drivers/mmc/host/sdhci-uhs2.c +++ b/drivers/mmc/host/sdhci-uhs2.c @@ -11,6 +11,7 @@ */ #include +#include #include #include "sdhci.h" @@ -385,6 +386,42 @@ void sdhci_uhs2_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) __sdhci_uhs2_set_ios(mmc, ios); } +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); + } +} + /*****************************************************************************\ * * * Driver init/exit * @@ -556,6 +593,10 @@ static int sdhci_uhs2_host_ops_init(struct sdhci_host *host) if (!host->mmc_host_ops.uhs2_detect_init) host->mmc_host_ops.uhs2_detect_init = sdhci_uhs2_do_detect_init; + if (!host->mmc_host_ops.uhs2_disable_clk) + host->mmc_host_ops.uhs2_disable_clk = sdhci_uhs2_disable_clk; + if (!host->mmc_host_ops.uhs2_enable_clk) + host->mmc_host_ops.uhs2_enable_clk = sdhci_uhs2_enable_clk; return 0; } From patchwork Thu Jul 22 04:01:14 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lai Jason X-Patchwork-Id: 484931 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.5 required=3.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_INVALID, DKIM_SIGNED, FREEMAIL_FORGED_FROMDOMAIN, FREEMAIL_FROM,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B9C60C63798 for ; Thu, 22 Jul 2021 04:02:47 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B4E3961222 for ; Thu, 22 Jul 2021 04:02:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230514AbhGVDWL (ORCPT ); Wed, 21 Jul 2021 23:22:11 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43886 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230291AbhGVDVy (ORCPT ); Wed, 21 Jul 2021 23:21:54 -0400 Received: from mail-pj1-x1032.google.com (mail-pj1-x1032.google.com [IPv6:2607:f8b0:4864:20::1032]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C267DC061757; Wed, 21 Jul 2021 21:02:28 -0700 (PDT) Received: by mail-pj1-x1032.google.com with SMTP id cu14so4386527pjb.0; Wed, 21 Jul 2021 21:02: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:in-reply-to:references :mime-version:content-transfer-encoding; bh=0jPg7TYNoaxg7wBJUp7wcIlMPDK4HteHjTAZGWqphXY=; b=FDj+DeD8gEaBAZ38MeLLodcrNxM5NgsjsZAi6E6TtDquYuulPz/p9oHVrukvU7TGlL Or+cPt9EngcCx+79gqFIZ0v7fUYUFladM42rlHIRgQpk4HAqzwCSCXi+n0h7bLxGhuT3 mMuLAGA53Ur063GUckOLtHMZrPMoS0CEZqJuraflH3QRy/KFX3VcXY2lbTx07a525WA2 NSdToL9AM2DrbWtlfoEQYC6AWxVdIJ+YSXelqc9pSeOf6rq/93P+jBuyQ+1xxKaizj0T 2VD6vgfE4GC/8/G9yKJxTtn5XVeaAHWFrqtjiMj3xlLiLdYapTmaP0/WHaSK6r6AJ+/b oQFw== 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:in-reply-to :references:mime-version:content-transfer-encoding; bh=0jPg7TYNoaxg7wBJUp7wcIlMPDK4HteHjTAZGWqphXY=; b=G4UDGUfXzMsz+7ccjGzAP2Ks39gqacKaIYtvygvgQcQi25uCUxi25BY9e10wL/JWK3 WtbbXuXxIwSdwpORoqH0cRfmv/T1TlJ4SO8NhBXW6xboGyjCGi6zBgGQq95GKW77OuMh 0D3UskgwUJSgfuHxGZPG/1yqiEgaBvXk6QqCeSGN4WCTgKgQ7u0/8AupcahHFxTy1deg 8DGZd8nmzwb1wXw9K9zGfb5MGTTxzYMJtonbExz8qWAYHV/WQHWiubGKbvgeEYyhYO7O r2YsZ+GQGxd04N6GP2EJX/Bt0PU7xOdahtpNwF8Y+poh+5u/3N4f9s6JFFk84OQ9dHrw RjTg== X-Gm-Message-State: AOAM530wqGwDQMoE5pTjI+FvysGsNmnt+BK4jiGcN38qHXchJJtLqTEt tt6CSAHNQ/HsOzB0cVSbivM= X-Google-Smtp-Source: ABdhPJwv7m+5cLa9LtYY+t1c3fuFSOPt1YwAGNN811V6eCbizTnO1HgYHw3VgvXdqRkZG6/Xqpdf4Q== X-Received: by 2002:a17:90a:8e82:: with SMTP id f2mr7240104pjo.177.1626926548401; Wed, 21 Jul 2021 21:02:28 -0700 (PDT) Received: from jason-z170xgaming7.mshome.net (218-35-143-223.cm.dynamic.apol.com.tw. [218.35.143.223]) by smtp.gmail.com with ESMTPSA id c19sm1663479pfp.184.2021.07.21.21.02.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 21 Jul 2021 21:02:28 -0700 (PDT) From: Jason Lai To: ulf.hansson@linaro.org, adrian.hunter@intel.com Cc: linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, ben.chuang@genesyslogic.com.tw, greg.tu@genesyslogic.com.tw, jason.lai@genesyslogiv.com.tw, AKASHI Takahiro Subject: [RFC PATCH v3.2 19/29] mmc: sdhci-uhs2: add set_reg() to initialise the interface Date: Thu, 22 Jul 2021 12:01:14 +0800 Message-Id: <20210722040124.7573-19-jasonlai.genesyslogic@gmail.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210722040124.7573-1-jasonlai.genesyslogic@gmail.com> References: <20210722040124.7573-1-jasonlai.genesyslogic@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org This is a sdhci version of mmc's uhs2_set_reg operation. UHS-II interface (related registers) will be initialised here. Signed-off-by: Ben Chuang Signed-off-by: AKASHI Takahiro --- drivers/mmc/host/sdhci-uhs2.c | 103 ++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) -- 2.32.0 diff --git a/drivers/mmc/host/sdhci-uhs2.c b/drivers/mmc/host/sdhci-uhs2.c index 55362ace1857..d8afb99a9918 100644 --- a/drivers/mmc/host/sdhci-uhs2.c +++ b/drivers/mmc/host/sdhci-uhs2.c @@ -332,6 +332,68 @@ static void __sdhci_uhs2_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) spin_unlock_irqrestore(&host->lock, flags); } +/* TODO: move this function to sdhci.c */ +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); +} + +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; +} + /*****************************************************************************\ * * * MMC callbacks * @@ -422,6 +484,45 @@ static void sdhci_uhs2_enable_clk(struct mmc_host *mmc) } } +static int sdhci_uhs2_set_reg(struct mmc_host *mmc, enum uhs2_act act) +{ + struct sdhci_host *host = mmc_priv(mmc); + 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; +} + /*****************************************************************************\ * * * Driver init/exit * @@ -597,6 +698,8 @@ static int sdhci_uhs2_host_ops_init(struct sdhci_host *host) host->mmc_host_ops.uhs2_disable_clk = sdhci_uhs2_disable_clk; if (!host->mmc_host_ops.uhs2_enable_clk) host->mmc_host_ops.uhs2_enable_clk = sdhci_uhs2_enable_clk; + if (!host->mmc_host_ops.uhs2_set_reg) + host->mmc_host_ops.uhs2_set_reg = sdhci_uhs2_set_reg; return 0; } From patchwork Thu Jul 22 04:01:15 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lai Jason X-Patchwork-Id: 484930 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.5 required=3.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_INVALID, DKIM_SIGNED, FREEMAIL_FORGED_FROMDOMAIN, FREEMAIL_FROM,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B0C54C63793 for ; Thu, 22 Jul 2021 04:02:47 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id A7B5161279 for ; Thu, 22 Jul 2021 04:02:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230501AbhGVDWK (ORCPT ); Wed, 21 Jul 2021 23:22:10 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43800 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230407AbhGVDV5 (ORCPT ); Wed, 21 Jul 2021 23:21:57 -0400 Received: from mail-pl1-x631.google.com (mail-pl1-x631.google.com [IPv6:2607:f8b0:4864:20::631]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DC77BC0617A0; Wed, 21 Jul 2021 21:02:30 -0700 (PDT) Received: by mail-pl1-x631.google.com with SMTP id b2so3018906plx.1; Wed, 21 Jul 2021 21:02:30 -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:in-reply-to:references :mime-version:content-transfer-encoding; bh=W8kiq8rFUXyPUDCLJprquZZA1XIPutuhE48mQtXu7VA=; b=oYTUmvQ5Mdq/wu+1IcCbGZu9dEE/K+66FitxZSI5ACGtJMZCxstEEm+qxcX8zesJCR 6t07eN0Xh/3tEuBIJMYIya1N6uE3QeBJAZsXtUoA9jfSSL40Ayb8WzyZW1Ly0iGtf8KL FFAQT4qKMydvock92rbducKFYU/zOdlI4psweQcjV9qnqRDhZvifPMOBVFGUJRg3LOhQ l9yEbGQZ3C6tULXaNNpQTgKd6k1dV3wRKgxApnglzoJKhBbfhSSY5HGsTzz8Dtqs24WT 4q4LFM4SDCyfysm1xvJUYhVxo+35nVafNSdyoJOIJNGUHI3ez1LjC9kI7uNvhiAp52H0 KQcQ== 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:in-reply-to :references:mime-version:content-transfer-encoding; bh=W8kiq8rFUXyPUDCLJprquZZA1XIPutuhE48mQtXu7VA=; b=gVft/xZ31DJ0pfRMx/u4TSpRlk6rjjqaqjyZPMChSfa+yKGKyrDUyYO0L1LJ+u3aUl NUidTfriBuuNixNlhgNBwRXVg+KhdBwE8hVyGM2Jp4oezs1TEVMcqwvbeXj4Yj8S5cvq yoZHAumMHYzk28o7wbSBFrFiKgm31o/SsLNe0GkxaWtXcy4FXSMUGaFDcPuFme4Z0o+p 4gEqPq2V6FUfrWcXCKPQeIoHOSj0iq13tHbBnXA92uJjiiCFUkBziX49YFCQP4c/16tu PRbyIDEGIm4JEqlrDMYpyS49nztlWI19Jbwn8aRDK9g22BwRXuBGSas8+WaWLp9J/kTX zdow== X-Gm-Message-State: AOAM530NucxkN/gPvtDUayJE7sHdHliRVllD30btqyl580YRH9illeRE H+BvMcKXUKrC+i30jMMsA1k= X-Google-Smtp-Source: ABdhPJyOwl0mC7XO/OIDKRabI1c9uYeVm+Dv4BDxECclEVkUm+e0OVXz3wizqePJphwiYBtZp4pGHg== X-Received: by 2002:a63:d14c:: with SMTP id c12mr38883392pgj.412.1626926550241; Wed, 21 Jul 2021 21:02:30 -0700 (PDT) Received: from jason-z170xgaming7.mshome.net (218-35-143-223.cm.dynamic.apol.com.tw. [218.35.143.223]) by smtp.gmail.com with ESMTPSA id c19sm1663479pfp.184.2021.07.21.21.02.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 21 Jul 2021 21:02:30 -0700 (PDT) From: Jason Lai To: ulf.hansson@linaro.org, adrian.hunter@intel.com Cc: linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, ben.chuang@genesyslogic.com.tw, greg.tu@genesyslogic.com.tw, jason.lai@genesyslogiv.com.tw, AKASHI Takahiro Subject: [RFC PATCH v3.2 20/29] mmc: sdhci-uhs2: add request() and others Date: Thu, 22 Jul 2021 12:01:15 +0800 Message-Id: <20210722040124.7573-20-jasonlai.genesyslogic@gmail.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210722040124.7573-1-jasonlai.genesyslogic@gmail.com> References: <20210722040124.7573-1-jasonlai.genesyslogic@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org This is a sdhci version of mmc's request operation. It covers both UHS-I and UHS-II. Signed-off-by: Ben Chuang Signed-off-by: AKASHI Takahiro --- drivers/mmc/host/sdhci-uhs2.c | 529 ++++++++++++++++++++++++++++++++++ drivers/mmc/host/sdhci.c | 93 +++--- drivers/mmc/host/sdhci.h | 21 ++ 3 files changed, 610 insertions(+), 33 deletions(-) -- 2.32.0 diff --git a/drivers/mmc/host/sdhci-uhs2.c b/drivers/mmc/host/sdhci-uhs2.c index d8afb99a9918..36e52553977a 100644 --- a/drivers/mmc/host/sdhci-uhs2.c +++ b/drivers/mmc/host/sdhci-uhs2.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "sdhci.h" #include "sdhci-uhs2.h" @@ -394,6 +395,27 @@ static int sdhci_uhs2_check_dormant(struct sdhci_host *host) return 0; } +/* TODO: move them to a header */ +#if IS_REACHABLE(CONFIG_LEDS_CLASS) +static inline void sdhci_led_activate(struct sdhci_host *host) +{ +} + +static inline void sdhci_led_deactivate(struct sdhci_host *host) +{ +} +#else +static inline void sdhci_led_activate(struct sdhci_host *host) +{ + __sdhci_led_activate(host); +} + +static inline void sdhci_led_deactivate(struct sdhci_host *host) +{ + __sdhci_led_deactivate(host); +} +#endif + /*****************************************************************************\ * * * MMC callbacks * @@ -523,6 +545,512 @@ static int sdhci_uhs2_set_reg(struct mmc_host *mmc, enum uhs2_act act) return err; } +static bool sdhci_uhs2_send_command(struct sdhci_host *host, + struct mmc_command *cmd); +static bool sdhci_uhs2_send_command_retry(struct sdhci_host *host, + struct mmc_command *cmd, + unsigned long flags); + +void sdhci_uhs2_request(struct mmc_host *mmc, struct mmc_request *mrq) +{ + struct sdhci_host *host = mmc_priv(mmc); + struct mmc_command *cmd; + unsigned long flags; + bool present; + + /* FIXME: check more flags? */ + if (!host->mmc->flags & MMC_UHS2_SUPPORT) { + sdhci_request(mmc, mrq); + return; + } + + /* Firstly check card presence */ + present = mmc->ops->get_cd(mmc); + + spin_lock_irqsave(&host->lock, flags); + + sdhci_led_activate(host); + + if (sdhci_present_error(host, mrq->cmd, present)) + goto out_finish; + + cmd = sdhci_manual_cmd23(host, mrq) ? mrq->sbc : mrq->cmd; + + if (!sdhci_uhs2_send_command_retry(host, cmd, flags)) + goto out_finish; + + spin_unlock_irqrestore(&host->lock, flags); + + return; + +out_finish: + sdhci_finish_mrq(host, mrq); + spin_unlock_irqrestore(&host->lock, flags); +} +EXPORT_SYMBOL_GPL(sdhci_uhs2_request); + +int sdhci_uhs2_request_atomic(struct mmc_host *mmc, struct mmc_request *mrq) +{ + struct sdhci_host *host = mmc_priv(mmc); + struct mmc_command *cmd; + unsigned long flags; + int ret = 0; + + if (!host->mmc->flags & MMC_UHS2_SUPPORT) + return sdhci_request_atomic(mmc, mrq); + + spin_lock_irqsave(&host->lock, flags); + + if (sdhci_present_error(host, mrq->cmd, true)) { + sdhci_finish_mrq(host, mrq); + goto out_finish; + } + + cmd = sdhci_manual_cmd23(host, mrq) ? mrq->sbc : mrq->cmd; + + /* + * The HSQ may send a command in interrupt context without polling + * the busy signaling, which means we should return BUSY if controller + * has not released inhibit bits to allow HSQ trying to send request + * again in non-atomic context. So we should not finish this request + * here. + */ + if (!sdhci_uhs2_send_command(host, cmd)) + ret = -EBUSY; + else + sdhci_led_activate(host); + +out_finish: + spin_unlock_irqrestore(&host->lock, flags); + return ret; +} +EXPORT_SYMBOL_GPL(sdhci_uhs2_request_atomic); + +/*****************************************************************************\ + * * + * Core functions * + * * +\*****************************************************************************/ + +static void sdhci_uhs2_prepare_data(struct sdhci_host *host, + struct mmc_command *cmd) +{ + struct mmc_data *data = cmd->data; + + sdhci_initialize_data(host, data); + + sdhci_prepare_dma(host, data); + + sdhci_writew(host, data->blksz, SDHCI_UHS2_BLOCK_SIZE); + sdhci_writew(host, data->blocks, SDHCI_UHS2_BLOCK_COUNT); +} + +#if IS_ENABLED(CONFIG_MMC_SDHCI_EXTERNAL_DMA) +static void sdhci_uhs2_external_dma_prepare_data(struct sdhci_host *host, + struct mmc_command *cmd) +{ + if (!sdhci_external_dma_setup(host, cmd)) { + __sdhci_external_dma_prepare_data(host, cmd); + } else { + sdhci_external_dma_release(host); + pr_err("%s: Cannot use external DMA, switch to the DMA/PIO which standard SDHCI provides.\n", + mmc_hostname(host->mmc)); + sdhci_uhs2_prepare_data(host, cmd); + } +} +#else +static inline void sdhci_uhs2_external_dma_prepare_data(struct sdhci_host *host, + struct mmc_command *cmd) +{ + /* This should never happen */ + WARN_ON_ONCE(1); +} + +static inline void sdhci_external_dma_pre_transfer(struct sdhci_host *host, + struct mmc_command *cmd) +{ +} +#endif /* CONFIG_MMC_SDHCI_EXTERNAL_DMA */ + +static void sdhci_uhs2_finish_data(struct sdhci_host *host) +{ + struct mmc_data *data = host->data; + + __sdhci_finish_data_common(host); + + /* + * FIXME: Is this condition needed? + if (host->mmc->flags & MMC_UHS2_INITIALIZED) + */ + __sdhci_finish_mrq(host, data->mrq); +} + +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 bool sdhci_uhs2_send_command(struct sdhci_host *host, + struct mmc_command *cmd) +{ + int flags; + u32 mask; + unsigned long timeout; + + /* FIXME: Is this check necessary? */ + if (!(host->mmc->flags & MMC_UHS2_SUPPORT)) + return sdhci_send_command(host, cmd); + + WARN_ON(host->cmd); + + /* Initially, a command has no error */ + cmd->error = 0; + + if ((host->quirks2 & SDHCI_QUIRK2_STOP_WITH_TC) && + cmd->opcode == MMC_STOP_TRANSMISSION) + cmd->flags |= MMC_RSP_BUSY; + + mask = SDHCI_CMD_INHIBIT; + if (sdhci_data_line_cmd(cmd)) + mask |= SDHCI_DATA_INHIBIT; + + /* We shouldn't wait for data inihibit for stop commands, even + though they might use busy signaling */ + if (cmd->mrq->data && (cmd == cmd->mrq->data->stop)) + mask &= ~SDHCI_DATA_INHIBIT; + + if (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask) + return false; + + host->cmd = cmd; + host->data_timeout = 0; + if (sdhci_data_line_cmd(cmd)) { + WARN_ON(host->data_cmd); + host->data_cmd = cmd; + __sdhci_uhs2_set_timeout(host); + } + + if (cmd->data) { + if (host->use_external_dma) + sdhci_uhs2_external_dma_prepare_data(host, cmd); + else + sdhci_uhs2_prepare_data(host, cmd); + } + + sdhci_uhs2_set_transfer_mode(host, cmd); + + if ((cmd->flags & MMC_RSP_136) && (cmd->flags & MMC_RSP_BUSY)) { + WARN_ONCE(1, "Unsupported response type!\n"); + /* + * This does not happen in practice because 136-bit response + * commands never have busy waiting, so rather than complicate + * the error path, just remove busy waiting and continue. + */ + cmd->flags &= ~MMC_RSP_BUSY; + } + + if (!(cmd->flags & MMC_RSP_PRESENT)) + flags = SDHCI_CMD_RESP_NONE; + else if (cmd->flags & MMC_RSP_136) + flags = SDHCI_CMD_RESP_LONG; + else if (cmd->flags & MMC_RSP_BUSY) + flags = SDHCI_CMD_RESP_SHORT_BUSY; + else + flags = SDHCI_CMD_RESP_SHORT; + + if (cmd->flags & MMC_RSP_CRC) + flags |= SDHCI_CMD_CRC; + if (cmd->flags & MMC_RSP_OPCODE) + flags |= SDHCI_CMD_INDEX; + + /* CMD19 is special in that the Data Present Select should be set */ + if (cmd->data || cmd->opcode == MMC_SEND_TUNING_BLOCK || + cmd->opcode == MMC_SEND_TUNING_BLOCK_HS200) + flags |= SDHCI_CMD_DATA; + + timeout = jiffies; + if (host->data_timeout) + timeout += nsecs_to_jiffies(host->data_timeout); + else if (!cmd->data && cmd->busy_timeout > 9000) + timeout += DIV_ROUND_UP(cmd->busy_timeout, 1000) * HZ + HZ; + else + timeout += 10 * HZ; + sdhci_mod_timer(host, cmd->mrq, timeout); + + if (host->use_external_dma) + sdhci_external_dma_pre_transfer(host, cmd); + + __sdhci_uhs2_send_command(host, cmd); + + return true; +} + +static bool sdhci_uhs2_send_command_retry(struct sdhci_host *host, + struct mmc_command *cmd, + unsigned long flags) + __releases(host->lock) + __acquires(host->lock) +{ + struct mmc_command *deferred_cmd = host->deferred_cmd; + int timeout = 10; /* Approx. 10 ms */ + bool present; + + while (!sdhci_uhs2_send_command(host, cmd)) { + if (!timeout--) { + pr_err("%s: Controller never released inhibit bit(s).\n", + mmc_hostname(host->mmc)); + sdhci_dumpregs(host); + cmd->error = -EIO; + return false; + } + + spin_unlock_irqrestore(&host->lock, flags); + + usleep_range(1000, 1250); + + present = host->mmc->ops->get_cd(host->mmc); + + spin_lock_irqsave(&host->lock, flags); + + /* A deferred command might disappear, handle that */ + if (cmd == deferred_cmd && cmd != host->deferred_cmd) + return true; + + if (sdhci_present_error(host, cmd, present)) + return false; + } + + if (cmd == host->deferred_cmd) + host->deferred_cmd = NULL; + + return true; +} + +static void __sdhci_uhs2_finish_command(struct sdhci_host *host) +{ + struct mmc_command *cmd = host->cmd; + u8 resp; + u8 ecode; + bool bReadA0 = 0; + int i; + + if (host->mmc->flags & MMC_UHS2_INITIALIZED) { + 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); + } + bReadA0 = 1; + } + + if (cmd->uhs2_resp && + cmd->uhs2_resp_len && cmd->uhs2_resp_len <= 20) { + /* Get whole response of some native CCMD, like + * DEVICE_INIT, ENUMERATE. + */ + for (i = 0; i < cmd->uhs2_resp_len; i++) + 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 (!bReadA0) + sdhci_readl(host, SDHCI_UHS2_RESPONSE); + for (i = 4; i < 20; i += 4) { + 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_finish_command(struct sdhci_host *host) +{ + struct mmc_command *cmd = host->cmd; + + /* FIXME: Is this check necessary? */ + if (!(host->mmc->flags & MMC_UHS2_SUPPORT)) { + sdhci_finish_command(host); + return; + } + + __sdhci_uhs2_finish_command(host); + + host->cmd = NULL; + + if (cmd->mrq->cap_cmd_during_tfr && cmd == cmd->mrq->cmd) + mmc_command_done(host->mmc, cmd->mrq); + + /* + * The host can send and interrupt when the busy state has + * ended, allowing us to wait without wasting CPU cycles. + * The busy signal uses DAT0 so this is similar to waiting + * for data to complete. + * + * Note: The 1.0 specification is a bit ambiguous about this + * feature so there might be some problems with older + * controllers. + */ + if (cmd->flags & MMC_RSP_BUSY) { + if (cmd->data) { + DBG("Cannot wait for busy signal when also doing a data transfer"); + } else if (!(host->quirks & SDHCI_QUIRK_NO_BUSY_IRQ) && + cmd == host->data_cmd) { + /* Command complete before busy is ended */ + return; + } + } + + /* Finished CMD23, now send actual command. */ + if (cmd == cmd->mrq->sbc) { + if (!sdhci_uhs2_send_command(host, cmd->mrq->cmd)) { + WARN_ON(host->deferred_cmd); + host->deferred_cmd = cmd->mrq->cmd; + } + } else { + + /* Processed actual command. */ + if (host->data && host->data_early) + sdhci_uhs2_finish_data(host); + + if (!cmd->data) + __sdhci_finish_mrq(host, cmd->mrq); + } +} + /*****************************************************************************\ * * * Driver init/exit * @@ -691,6 +1219,7 @@ static int sdhci_uhs2_host_ops_init(struct sdhci_host *host) host->mmc_host_ops.start_signal_voltage_switch = sdhci_uhs2_start_signal_voltage_switch; host->mmc_host_ops.set_ios = sdhci_uhs2_set_ios; + host->mmc_host_ops.request = sdhci_uhs2_request; if (!host->mmc_host_ops.uhs2_detect_init) host->mmc_host_ops.uhs2_detect_init = sdhci_uhs2_do_detect_init; diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index d60a1fdd1385..731a60c4b131 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -47,8 +47,6 @@ static unsigned int debug_quirks = 0; static unsigned int debug_quirks2; -static bool sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd); - void sdhci_dumpregs(struct sdhci_host *host) { SDHCI_DUMP("============ SDHCI REGISTER DUMP ===========\n"); @@ -147,10 +145,13 @@ void sdhci_enable_v4_mode(struct sdhci_host *host) } EXPORT_SYMBOL_GPL(sdhci_enable_v4_mode); -static inline bool sdhci_data_line_cmd(struct mmc_command *cmd) +bool sdhci_data_line_cmd(struct mmc_command *cmd) { return cmd->data || cmd->flags & MMC_RSP_BUSY; } +EXPORT_SYMBOL_GPL(sdhci_data_line_cmd); + +/* TODO: move this as an inline function to a header */ static void sdhci_set_card_detection(struct sdhci_host *host, bool enable) { @@ -362,7 +363,7 @@ static void sdhci_reinit(struct sdhci_host *host) mmc_detect_change(host->mmc, msecs_to_jiffies(200)); } -static void __sdhci_led_activate(struct sdhci_host *host) +void __sdhci_led_activate(struct sdhci_host *host) { u8 ctrl; @@ -373,8 +374,9 @@ static void __sdhci_led_activate(struct sdhci_host *host) ctrl |= SDHCI_CTRL_LED; sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); } +EXPORT_SYMBOL_GPL(__sdhci_led_activate); -static void __sdhci_led_deactivate(struct sdhci_host *host) +void __sdhci_led_deactivate(struct sdhci_host *host) { u8 ctrl; @@ -385,6 +387,7 @@ static void __sdhci_led_deactivate(struct sdhci_host *host) ctrl &= ~SDHCI_CTRL_LED; sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); } +EXPORT_SYMBOL_GPL(__sdhci_led_deactivate); #if IS_REACHABLE(CONFIG_LEDS_CLASS) static void sdhci_led_control(struct led_classdev *led, @@ -463,14 +466,15 @@ static inline void sdhci_led_deactivate(struct sdhci_host *host) #endif -static void sdhci_mod_timer(struct sdhci_host *host, struct mmc_request *mrq, - unsigned long timeout) +void sdhci_mod_timer(struct sdhci_host *host, struct mmc_request *mrq, + unsigned long timeout) { if (sdhci_data_line_cmd(mrq->cmd)) mod_timer(&host->data_timer, timeout); else mod_timer(&host->timer, timeout); } +EXPORT_SYMBOL_GPL(sdhci_mod_timer); static void sdhci_del_timer(struct sdhci_host *host, struct mmc_request *mrq) { @@ -1042,8 +1046,7 @@ static void sdhci_set_timeout(struct sdhci_host *host, struct mmc_command *cmd) __sdhci_set_timeout(host, cmd); } -static void sdhci_initialize_data(struct sdhci_host *host, - struct mmc_data *data) +void sdhci_initialize_data(struct sdhci_host *host, struct mmc_data *data) { WARN_ON(host->data); @@ -1056,6 +1059,7 @@ static void sdhci_initialize_data(struct sdhci_host *host, host->data_early = 0; host->data->bytes_xfered = 0; } +EXPORT_SYMBOL_GPL(sdhci_initialize_data); static inline void sdhci_set_block_info(struct sdhci_host *host, struct mmc_data *data) @@ -1078,12 +1082,8 @@ static inline void sdhci_set_block_info(struct sdhci_host *host, } } -static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd) +void sdhci_prepare_dma(struct sdhci_host *host, struct mmc_data *data) { - struct mmc_data *data = cmd->data; - - sdhci_initialize_data(host, data); - if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) { struct scatterlist *sg; unsigned int length_mask, offset_mask; @@ -1168,6 +1168,16 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd) } sdhci_set_transfer_irqs(host); +} +EXPORT_SYMBOL_GPL(sdhci_prepare_dma); + +static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd) +{ + struct mmc_data *data = cmd->data; + + sdhci_initialize_data(host, data); + + sdhci_prepare_dma(host, data); sdhci_set_block_info(host, data); } @@ -1210,8 +1220,7 @@ static struct dma_chan *sdhci_external_dma_channel(struct sdhci_host *host, return data->flags & MMC_DATA_WRITE ? host->tx_chan : host->rx_chan; } -static int sdhci_external_dma_setup(struct sdhci_host *host, - struct mmc_command *cmd) +int sdhci_external_dma_setup(struct sdhci_host *host, struct mmc_command *cmd) { int ret, i; enum dma_transfer_direction dir; @@ -1263,8 +1272,9 @@ static int sdhci_external_dma_setup(struct sdhci_host *host, return ret; } +EXPORT_SYMBOL_GPL(sdhci_external_dma_setup); -static void sdhci_external_dma_release(struct sdhci_host *host) +void sdhci_external_dma_release(struct sdhci_host *host) { if (host->tx_chan) { dma_release_channel(host->tx_chan); @@ -1278,9 +1288,10 @@ static void sdhci_external_dma_release(struct sdhci_host *host) sdhci_switch_external_dma(host, false); } +EXPORT_SYMBOL_GPL(sdhci_external_dma_release); -static void __sdhci_external_dma_prepare_data(struct sdhci_host *host, - struct mmc_command *cmd) +void __sdhci_external_dma_prepare_data(struct sdhci_host *host, + struct mmc_command *cmd) { struct mmc_data *data = cmd->data; @@ -1291,6 +1302,7 @@ static void __sdhci_external_dma_prepare_data(struct sdhci_host *host, sdhci_set_block_info(host, data); } +EXPORT_SYMBOL(__sdhci_external_dma_prepare_data); static void sdhci_external_dma_prepare_data(struct sdhci_host *host, struct mmc_command *cmd) @@ -1305,8 +1317,8 @@ static void sdhci_external_dma_prepare_data(struct sdhci_host *host, } } -static void sdhci_external_dma_pre_transfer(struct sdhci_host *host, - struct mmc_command *cmd) +void sdhci_external_dma_pre_transfer(struct sdhci_host *host, + struct mmc_command *cmd) { struct dma_chan *chan; @@ -1317,6 +1329,7 @@ static void sdhci_external_dma_pre_transfer(struct sdhci_host *host, if (chan) dma_async_issue_pending(chan); } +EXPORT_SYMBOL_GPL(sdhci_external_dma_pre_transfer); #else @@ -1368,11 +1381,11 @@ static inline bool sdhci_auto_cmd23(struct sdhci_host *host, return mrq->sbc && (host->flags & SDHCI_AUTO_CMD23); } -static inline bool sdhci_manual_cmd23(struct sdhci_host *host, - struct mmc_request *mrq) +bool sdhci_manual_cmd23(struct sdhci_host *host, struct mmc_request *mrq) { return mrq->sbc && !(host->flags & SDHCI_AUTO_CMD23); } +EXPORT_SYMBOL_GPL(sdhci_manual_cmd23); static inline void sdhci_auto_cmd_select(struct sdhci_host *host, struct mmc_command *cmd, @@ -1484,7 +1497,7 @@ static void sdhci_set_mrq_done(struct sdhci_host *host, struct mmc_request *mrq) WARN_ON(i >= SDHCI_MAX_MRQS); } -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) { if (host->cmd && host->cmd->mrq == mrq) host->cmd = NULL; @@ -1508,15 +1521,17 @@ static void __sdhci_finish_mrq(struct sdhci_host *host, struct mmc_request *mrq) if (!sdhci_has_requests(host)) sdhci_led_deactivate(host); } +EXPORT_SYMBOL_GPL(__sdhci_finish_mrq); -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) +void __sdhci_finish_data_common(struct sdhci_host *host) { struct mmc_command *data_cmd = host->data_cmd; struct mmc_data *data = host->data; @@ -1549,6 +1564,14 @@ static void __sdhci_finish_data(struct sdhci_host *host, bool sw_data_timeout) data->bytes_xfered = 0; else data->bytes_xfered = data->blksz * data->blocks; +} +EXPORT_SYMBOL_GPL(__sdhci_finish_data_common); + +static void __sdhci_finish_data(struct sdhci_host *host, bool sw_data_timeout) +{ + struct mmc_data *data = host->data; + + __sdhci_finish_data_common(host); /* * Need to send CMD12 if - @@ -1587,12 +1610,13 @@ 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) +bool sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) { int flags; u32 mask; @@ -1634,8 +1658,6 @@ 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); - sdhci_set_transfer_mode(host, cmd); if ((cmd->flags & MMC_RSP_136) && (cmd->flags & MMC_RSP_BUSY)) { @@ -1679,13 +1701,16 @@ 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); + sdhci_writel(host, cmd->arg, SDHCI_ARGUMENT); + sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND); return true; } +EXPORT_SYMBOL_GPL(sdhci_send_command); -static bool sdhci_present_error(struct sdhci_host *host, - struct mmc_command *cmd, bool present) +bool sdhci_present_error(struct sdhci_host *host, + struct mmc_command *cmd, bool present) { if (!present || host->flags & SDHCI_DEVICE_DEAD) { cmd->error = -ENOMEDIUM; @@ -1694,6 +1719,7 @@ static bool sdhci_present_error(struct sdhci_host *host, return false; } +EXPORT_SYMBOL_GPL(sdhci_present_error); static bool sdhci_send_command_retry(struct sdhci_host *host, struct mmc_command *cmd, @@ -1756,7 +1782,7 @@ static void sdhci_read_rsp_136(struct sdhci_host *host, struct mmc_command *cmd) } } -static void sdhci_finish_command(struct sdhci_host *host) +void sdhci_finish_command(struct sdhci_host *host) { struct mmc_command *cmd = host->cmd; @@ -1809,6 +1835,7 @@ static void sdhci_finish_command(struct sdhci_host *host) __sdhci_finish_mrq(host, cmd->mrq); } } +EXPORT_SYMBOL_GPL(sdhci_finish_command); static u16 sdhci_get_preset_value(struct sdhci_host *host) { diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index e84ebddb20d8..6eeb74741da3 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -831,8 +831,29 @@ static inline void sdhci_read_caps(struct sdhci_host *host) __sdhci_read_caps(host, NULL, NULL, NULL); } +bool sdhci_data_line_cmd(struct mmc_command *cmd); void sdhci_runtime_pm_bus_on(struct sdhci_host *host); void sdhci_runtime_pm_bus_off(struct sdhci_host *host); +void sdhci_mod_timer(struct sdhci_host *host, struct mmc_request *mrq, + unsigned long timeout); +void sdhci_initialize_data(struct sdhci_host *host, struct mmc_data *data); +void sdhci_prepare_dma(struct sdhci_host *host, struct mmc_data *data); +#if IS_ENABLED(CONFIG_MMC_SDHCI_EXTERNAL_DMA) +int sdhci_external_dma_setup(struct sdhci_host *host, struct mmc_command *cmd); +void sdhci_external_dma_release(struct sdhci_host *host); +void __sdhci_external_dma_prepare_data(struct sdhci_host *host, + struct mmc_command *cmd); +void sdhci_external_dma_pre_transfer(struct sdhci_host *host, + struct mmc_command *cmd); +#endif +bool sdhci_manual_cmd23(struct sdhci_host *host, struct mmc_request *mrq); +void __sdhci_finish_mrq(struct sdhci_host *host, struct mmc_request *mrq); +void sdhci_finish_mrq(struct sdhci_host *host, struct mmc_request *mrq); +void __sdhci_finish_data_common(struct sdhci_host *host); +bool sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd); +void sdhci_finish_command(struct sdhci_host *host); +bool sdhci_present_error(struct sdhci_host *host, + struct mmc_command *cmd, bool present); 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); From patchwork Thu Jul 22 04:01:16 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lai Jason X-Patchwork-Id: 484189 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.5 required=3.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_INVALID, DKIM_SIGNED, FREEMAIL_FORGED_FROMDOMAIN, FREEMAIL_FROM,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D3710C63799 for ; Thu, 22 Jul 2021 04:02:50 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C3338608FC for ; Thu, 22 Jul 2021 04:02:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229897AbhGVDWL (ORCPT ); Wed, 21 Jul 2021 23:22:11 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43790 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230424AbhGVDWA (ORCPT ); Wed, 21 Jul 2021 23:22:00 -0400 Received: from mail-pj1-x1033.google.com (mail-pj1-x1033.google.com [IPv6:2607:f8b0:4864:20::1033]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A4804C0617A4; Wed, 21 Jul 2021 21:02:32 -0700 (PDT) Received: by mail-pj1-x1033.google.com with SMTP id p9so4336497pjl.3; Wed, 21 Jul 2021 21:02: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:in-reply-to:references :mime-version:content-transfer-encoding; bh=eFFpAwt1nYpMrpAEp6H8PERqKttQGMnFGGlR8JKGTsc=; b=lF8WQU+z7JVvryJee6LsiXH4JcfLUGDIQyLmpqEcrMSGgk+yJg1vBOVRHNoLPun8LC pQoJt+Rjs78ihYD5TkY+FfzZjX39iGTepY9EG5nYD0B5DUlpG9lW4A/D+eYFdt1EC2SV kI8EzoiYyGrUnTX/9JlyEn8b6zhbGCiuf4ViXyEHblUJfDWL5C96xRAHVKUlx+Yjt4Cu NUrkhMBIc6EfmERcvvk0nKDoXQefWqt0WG+F9IF0nSpNE/OJu2XxSnauucDUL3L1BcZI A4KGtYAOHQRN8krjy3T4UCU64IlSBR6b+J87YtV5BIqjl/mHDmI7NNV6SyKtQhJqc6ad v5Uw== 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:in-reply-to :references:mime-version:content-transfer-encoding; bh=eFFpAwt1nYpMrpAEp6H8PERqKttQGMnFGGlR8JKGTsc=; b=F/+qGglqBzqhp7VC74ouEE97Dk4hB8u8waa8v3kWC/2i3g0Left2W0LvwN8vOvGpEo Pk4hr6grjk6lHxRYIllzdvv2vY57W5/cB1IucfIydV+2fwxIDlqkl7J7d8fv2WOtgQ07 N/4lMeU1zWpmi5enBCySHZODXBNLQHLwtwgeiA0dwvWHQ7xcsU6GRP1KCv5nHHBmcu44 jGU5QPTUWB4iPKGq6EccXbIE4eu7f6VgF/hSEItf2lFuMjdI5gR3J6pyjrZ1FgA+98cx c5x8uM+Pwzs7ixBiqWDCd6B5yMyJpuBuPVFmSZcA3UFAc90QEia1ImghqtWbzHwAz1ng dBSQ== X-Gm-Message-State: AOAM5304IFp51xFN/hDJuU9n1zcF/s55kp51/UvaLk/xquvhYYYrd/nO 3CQ6yYwLbNgI24zXIt+Wd3I= X-Google-Smtp-Source: ABdhPJwWcY+c7GBZAEXDRyRASU8yesCBBWVegC8ZCgFeddWst3ejfqAtCWK51TyPcW85XEY4M1AwQw== X-Received: by 2002:a65:6894:: with SMTP id e20mr39018825pgt.350.1626926552167; Wed, 21 Jul 2021 21:02:32 -0700 (PDT) Received: from jason-z170xgaming7.mshome.net (218-35-143-223.cm.dynamic.apol.com.tw. [218.35.143.223]) by smtp.gmail.com with ESMTPSA id c19sm1663479pfp.184.2021.07.21.21.02.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 21 Jul 2021 21:02:31 -0700 (PDT) From: Jason Lai To: ulf.hansson@linaro.org, adrian.hunter@intel.com Cc: linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, ben.chuang@genesyslogic.com.tw, greg.tu@genesyslogic.com.tw, jason.lai@genesyslogiv.com.tw, AKASHI Takahiro Subject: [RFC PATCH v3.2 21/29] mmc: sdhci-uhs2: add irq() and others Date: Thu, 22 Jul 2021 12:01:16 +0800 Message-Id: <20210722040124.7573-21-jasonlai.genesyslogic@gmail.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210722040124.7573-1-jasonlai.genesyslogic@gmail.com> References: <20210722040124.7573-1-jasonlai.genesyslogic@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org This is a UHS-II version of sdhci's request() operation. It handles UHS-II related command interrupts and errors. Signed-off-by: Ben Chuang Signed-off-by: AKASHI Takahiro --- drivers/mmc/host/sdhci-uhs2.c | 247 ++++++++++++++++++++++++++++++++++ drivers/mmc/host/sdhci-uhs2.h | 3 + drivers/mmc/host/sdhci.c | 96 ++++++++++++- drivers/mmc/host/sdhci.h | 6 + 4 files changed, 347 insertions(+), 5 deletions(-) -- 2.32.0 diff --git a/drivers/mmc/host/sdhci-uhs2.c b/drivers/mmc/host/sdhci-uhs2.c index 36e52553977a..d50134e912f3 100644 --- a/drivers/mmc/host/sdhci-uhs2.c +++ b/drivers/mmc/host/sdhci-uhs2.c @@ -11,6 +11,7 @@ */ #include +#include #include #include #include @@ -670,6 +671,12 @@ static inline void sdhci_external_dma_pre_transfer(struct sdhci_host *host, struct mmc_command *cmd) { } + +static inline struct dma_chan *sdhci_external_dma_channel(struct sdhci_host *host, + struct mmc_data *data) +{ + return NULL; +} #endif /* CONFIG_MMC_SDHCI_EXTERNAL_DMA */ static void sdhci_uhs2_finish_data(struct sdhci_host *host) @@ -1051,6 +1058,246 @@ static void sdhci_uhs2_finish_command(struct sdhci_host *host) } } +/*****************************************************************************\ + * * + * Request done * + * * +\*****************************************************************************/ + +static bool sdhci_uhs2_request_done(struct sdhci_host *host) +{ + unsigned long flags; + struct mmc_request *mrq; + int i; + + /* FIXME: UHS2_INITIALIZED, instead? */ + if (!(host->mmc->flags & MMC_UHS2_SUPPORT)) + return sdhci_request_done(host); + + spin_lock_irqsave(&host->lock, flags); + + for (i = 0; i < SDHCI_MAX_MRQS; i++) { + mrq = host->mrqs_done[i]; + if (mrq) + break; + } + + if (!mrq) { + spin_unlock_irqrestore(&host->lock, flags); + return true; + } + + /* + * Always unmap the data buffers if they were mapped by + * sdhci_prepare_data() whenever we finish with a request. + * This avoids leaking DMA mappings on error. + */ + if (host->flags & SDHCI_REQ_USE_DMA) { + struct mmc_data *data = mrq->data; + + if (host->use_external_dma && data && + (mrq->cmd->error || data->error)) { + struct dma_chan *chan = sdhci_external_dma_channel(host, data); + + host->mrqs_done[i] = NULL; + spin_unlock_irqrestore(&host->lock, flags); + dmaengine_terminate_sync(chan); + spin_lock_irqsave(&host->lock, flags); + sdhci_set_mrq_done(host, mrq); + } + + sdhci_request_done_dma(host, mrq); + } + + /* + * The controller needs a reset of internal state machines + * upon error conditions. + */ + if (sdhci_needs_reset(host, mrq)) { + /* + * Do not finish until command and data lines are available for + * reset. Note there can only be one other mrq, so it cannot + * also be in mrqs_done, otherwise host->cmd and host->data_cmd + * would both be null. + */ + if (host->cmd || host->data_cmd) { + spin_unlock_irqrestore(&host->lock, flags); + return true; + } + + /* Some controllers need this kick or reset won't work here */ + if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET) + /* This is to force an update */ + host->ops->set_clock(host, host->clock); + + sdhci_uhs2_reset(host, SDHCI_UHS2_SW_RESET_SD); + host->pending_reset = false; + } + + host->mrqs_done[i] = NULL; + + spin_unlock_irqrestore(&host->lock, flags); + + if (host->ops->request_done) + host->ops->request_done(host, mrq); + else + mmc_request_done(host->mmc, mrq); + + return false; +} + +static void sdhci_uhs2_complete_work(struct work_struct *work) +{ + struct sdhci_host *host = container_of(work, struct sdhci_host, + complete_work); + + while (!sdhci_uhs2_request_done(host)) + ; +} + +/*****************************************************************************\ + * * + * Interrupt handling * + * * +\*****************************************************************************/ + +static void __sdhci_uhs2_irq(struct sdhci_host *host, u32 uhs2mask) +{ + struct mmc_command *cmd = host->cmd; + + DBG("*** %s got UHS2 error interrupt: 0x%08x\n", + mmc_hostname(host->mmc), uhs2mask); + + 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_uhs2_finish_data(host); + else + sdhci_finish_mrq(host, cmd->mrq); +} + +u32 sdhci_uhs2_irq(struct sdhci_host *host, u32 intmask) +{ + u32 mask = intmask, uhs2mask; + + if (!(host->mmc->flags & MMC_UHS2_SUPPORT)) + goto out; + + /* + * TODO: We should mask Normal Error Interrupt Status Register + * in UHS-2 mode so that we don't have to care SD mode errors. + */ + if (intmask & SDHCI_INT_ERROR) { + uhs2mask = sdhci_readl(host, SDHCI_UHS2_ERR_INT_STATUS); + if (!(uhs2mask & SDHCI_UHS2_ERR_INT_STATUS_MASK)) + goto cmd_irq; + + /* Clear error interrupts */ + sdhci_writel(host, uhs2mask & SDHCI_UHS2_ERR_INT_STATUS_MASK, + SDHCI_UHS2_ERR_INT_STATUS); + + /* Handle error interrupts */ + __sdhci_uhs2_irq(host, uhs2mask); + + /* Caller, shdci_irq(), doesn't have to care UHS-2 errors */ + intmask &= ~SDHCI_INT_ERROR; + mask &= SDHCI_INT_ERROR; + } + +cmd_irq: + /* + * TODO: Cleanup + * INT_RESPONSE is enough instead of INT_CMD_MASK, assuming that + * INT_ERROR and INT_CMD_MASK won't happen at the same time. + */ + if (intmask & SDHCI_INT_CMD_MASK) { + /* Clear command interrupt */ + sdhci_writel(host, intmask & SDHCI_INT_CMD_MASK, + SDHCI_INT_STATUS); + + /* Handle command interrupt */ + if (intmask & SDHCI_INT_RESPONSE) + sdhci_uhs2_finish_command(host); + + /* Caller, shdci_irq(), doesn't have to care UHS-2 command */ + intmask &= ~SDHCI_INT_CMD_MASK; + mask &= SDHCI_INT_CMD_MASK; + } + + /* Clear already-handled interrupts. */ + sdhci_writel(host, mask, SDHCI_INT_STATUS); + +out: + return intmask; +} +EXPORT_SYMBOL_GPL(sdhci_uhs2_irq); + +static irqreturn_t sdhci_uhs2_thread_irq(int irq, void *dev_id) +{ + struct sdhci_host *host = dev_id; + struct mmc_command *cmd; + unsigned long flags; + u32 isr; + + while (!sdhci_uhs2_request_done(host)) + ; + + spin_lock_irqsave(&host->lock, flags); + + isr = host->thread_isr; + host->thread_isr = 0; + + cmd = host->deferred_cmd; + if (cmd && !sdhci_uhs2_send_command_retry(host, cmd, flags)) + sdhci_finish_mrq(host, cmd->mrq); + + spin_unlock_irqrestore(&host->lock, flags); + + if (isr & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) { + struct mmc_host *mmc = host->mmc; + + mmc->ops->card_event(mmc); + mmc_detect_change(mmc, msecs_to_jiffies(200)); + } + + return IRQ_HANDLED; +} + /*****************************************************************************\ * * * Driver init/exit * diff --git a/drivers/mmc/host/sdhci-uhs2.h b/drivers/mmc/host/sdhci-uhs2.h index c1ff4ac1ab7a..b74af641d00e 100644 --- a/drivers/mmc/host/sdhci-uhs2.h +++ b/drivers/mmc/host/sdhci-uhs2.h @@ -215,5 +215,8 @@ void sdhci_uhs2_set_power(struct sdhci_host *host, unsigned char mode, unsigned short vdd); void sdhci_uhs2_set_timeout(struct sdhci_host *host, struct mmc_command *cmd); void sdhci_uhs2_clear_set_irqs(struct sdhci_host *host, u32 clear, u32 set); +void sdhci_uhs2_request(struct mmc_host *mmc, struct mmc_request *mrq); +int sdhci_uhs2_request_atomic(struct mmc_host *mmc, struct mmc_request *mrq); +u32 sdhci_uhs2_irq(struct sdhci_host *host, u32 intmask); #endif /* __SDHCI_UHS2_H */ diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 731a60c4b131..4a2046c22319 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1214,11 +1214,12 @@ static int sdhci_external_dma_init(struct sdhci_host *host) return ret; } -static struct dma_chan *sdhci_external_dma_channel(struct sdhci_host *host, - struct mmc_data *data) +struct dma_chan *sdhci_external_dma_channel(struct sdhci_host *host, + struct mmc_data *data) { return data->flags & MMC_DATA_WRITE ? host->tx_chan : host->rx_chan; } +EXPORT_SYMBOL_GPL(sdhci_external_dma_channel); int sdhci_external_dma_setup(struct sdhci_host *host, struct mmc_command *cmd) { @@ -1467,7 +1468,7 @@ static void sdhci_set_transfer_mode(struct sdhci_host *host, sdhci_writew(host, mode, SDHCI_TRANSFER_MODE); } -static bool sdhci_needs_reset(struct sdhci_host *host, struct mmc_request *mrq) +bool sdhci_needs_reset(struct sdhci_host *host, struct mmc_request *mrq) { return (!(host->flags & SDHCI_DEVICE_DEAD) && ((mrq->cmd && mrq->cmd->error) || @@ -1475,8 +1476,9 @@ static bool sdhci_needs_reset(struct sdhci_host *host, struct mmc_request *mrq) (mrq->data && mrq->data->stop && mrq->data->stop->error) || (host->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST))); } +EXPORT_SYMBOL_GPL(sdhci_needs_reset); -static void sdhci_set_mrq_done(struct sdhci_host *host, struct mmc_request *mrq) +void sdhci_set_mrq_done(struct sdhci_host *host, struct mmc_request *mrq) { int i; @@ -1496,6 +1498,7 @@ static void sdhci_set_mrq_done(struct sdhci_host *host, struct mmc_request *mrq) WARN_ON(i >= SDHCI_MAX_MRQS); } +EXPORT_SYMBOL_GPL(sdhci_set_mrq_done); void __sdhci_finish_mrq(struct sdhci_host *host, struct mmc_request *mrq) { @@ -3029,7 +3032,56 @@ static const struct mmc_host_ops sdhci_ops = { * * \*****************************************************************************/ -static bool sdhci_request_done(struct sdhci_host *host) +void sdhci_request_done_dma(struct sdhci_host *host, struct mmc_request *mrq) +{ + struct mmc_data *data = mrq->data; + + if (data && data->host_cookie == COOKIE_MAPPED) { + if (host->bounce_buffer) { + /* + * On reads, copy the bounced data into the + * sglist + */ + if (mmc_get_dma_dir(data) == DMA_FROM_DEVICE) { + unsigned int length = data->bytes_xfered; + + if (length > host->bounce_buffer_size) { + pr_err("%s: bounce buffer is %u bytes but DMA claims to have transferred %u bytes\n", + mmc_hostname(host->mmc), + host->bounce_buffer_size, + data->bytes_xfered); + /* Cap it down and continue */ + length = host->bounce_buffer_size; + } + dma_sync_single_for_cpu( + host->mmc->parent, + host->bounce_addr, + host->bounce_buffer_size, + DMA_FROM_DEVICE); + sg_copy_from_buffer(data->sg, + data->sg_len, + host->bounce_buffer, + length); + } else { + /* No copying, just switch ownership */ + dma_sync_single_for_cpu( + host->mmc->parent, + host->bounce_addr, + host->bounce_buffer_size, + mmc_get_dma_dir(data)); + } + } else { + /* Unmap the raw data */ + dma_unmap_sg(mmc_dev(host->mmc), data->sg, + data->sg_len, + mmc_get_dma_dir(data)); + } + data->host_cookie = COOKIE_UNMAPPED; + } +} +EXPORT_SYMBOL_GPL(sdhci_request_done_dma); + +bool sdhci_request_done(struct sdhci_host *host) { unsigned long flags; struct mmc_request *mrq; @@ -3140,6 +3192,39 @@ static bool sdhci_request_done(struct sdhci_host *host) } data->host_cookie = COOKIE_UNMAPPED; } + + sdhci_request_done_dma(host, mrq); + } + + /* + * The controller needs a reset of internal state machines + * upon error conditions. + */ + if (sdhci_needs_reset(host, mrq)) { + /* + * Do not finish until command and data lines are available for + * reset. Note there can only be one other mrq, so it cannot + * also be in mrqs_done, otherwise host->cmd and host->data_cmd + * would both be null. + */ + if (host->cmd || host->data_cmd) { + spin_unlock_irqrestore(&host->lock, flags); + return true; + } + + /* Some controllers need this kick or reset won't work here */ + if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET) + /* 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); + + host->pending_reset = false; } host->mrqs_done[i] = NULL; @@ -3153,6 +3238,7 @@ static bool sdhci_request_done(struct sdhci_host *host) return false; } +EXPORT_SYMBOL_GPL(sdhci_request_done); static void sdhci_complete_work(struct work_struct *work) { diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 6eeb74741da3..74572b54ec47 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -845,8 +845,12 @@ void __sdhci_external_dma_prepare_data(struct sdhci_host *host, struct mmc_command *cmd); void sdhci_external_dma_pre_transfer(struct sdhci_host *host, struct mmc_command *cmd); +struct dma_chan *sdhci_external_dma_channel(struct sdhci_host *host, + struct mmc_data *data); #endif bool sdhci_manual_cmd23(struct sdhci_host *host, struct mmc_request *mrq); +bool sdhci_needs_reset(struct sdhci_host *host, struct mmc_request *mrq); +void sdhci_set_mrq_done(struct sdhci_host *host, struct mmc_request *mrq); void __sdhci_finish_mrq(struct sdhci_host *host, struct mmc_request *mrq); void sdhci_finish_mrq(struct sdhci_host *host, struct mmc_request *mrq); void __sdhci_finish_data_common(struct sdhci_host *host); @@ -878,6 +882,8 @@ void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios); int sdhci_start_signal_voltage_switch(struct mmc_host *mmc, struct mmc_ios *ios); void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable); +void sdhci_request_done_dma(struct sdhci_host *host, struct mmc_request *mrq); +bool sdhci_request_done(struct sdhci_host *host); void sdhci_adma_write_desc(struct sdhci_host *host, void **desc, dma_addr_t addr, int len, unsigned int cmd); From patchwork Thu Jul 22 04:01:17 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lai Jason X-Patchwork-Id: 484929 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.5 required=3.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_INVALID, DKIM_SIGNED, FREEMAIL_FORGED_FROMDOMAIN, FREEMAIL_FROM,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1B1D7C636C8 for ; Thu, 22 Jul 2021 04:02:53 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0958261222 for ; Thu, 22 Jul 2021 04:02:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230399AbhGVDWN (ORCPT ); Wed, 21 Jul 2021 23:22:13 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43914 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230249AbhGVDWB (ORCPT ); Wed, 21 Jul 2021 23:22:01 -0400 Received: from mail-pj1-x102f.google.com (mail-pj1-x102f.google.com [IPv6:2607:f8b0:4864:20::102f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 71A4AC061575; Wed, 21 Jul 2021 21:02:34 -0700 (PDT) Received: by mail-pj1-x102f.google.com with SMTP id p4-20020a17090a9304b029016f3020d867so3687884pjo.3; Wed, 21 Jul 2021 21:02:34 -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:in-reply-to:references :mime-version:content-transfer-encoding; bh=Nmb7MQUj4yN2N+TKnPZpClMZdUK4ahExo7YxzodDXVQ=; b=eyD3kr1LZwlWLV/a6t2lr7RU2FUMzSy9+33qqWhUL+fJyVmrNIpxX7QtPRQN/9hC8M 5wOuXQrYehiOqyTh5+v6NrwelMfzQ73ne/G/qXcrTsSJ/x7DnB/PS7qLfanZ3Tt4wnMF 9biaMI1YF82FZpNpu50+c9b+Z+fJa0oqmxnIGLjw7ccLCvTI7CpwXBh4iSUy+IzSe1tb 84NZ9jmfm90w1L2eVPsns1AWX+ILv1IuDQlSuI2y4FhLziT3bJ1XydZC2X76ccUbbO6f UrSbHvjnHd/wuN1dlsnglPuNqdTuceuCoOJHMLiBgDOIAcVArhmVirkcLR2F2uaxAnyW 7zJQ== 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:in-reply-to :references:mime-version:content-transfer-encoding; bh=Nmb7MQUj4yN2N+TKnPZpClMZdUK4ahExo7YxzodDXVQ=; b=YjCsTAzvch17OKMUKRosIdzYAh4JG2k2yOmNhiEqxcLXVe617Sr0dIFEMPi8/MWQYd IrP9NrmF+N+Ke8rpSIeUvdbfYMAawAi2L0V3J9Xj+hub2rcswbqoa5o1vLdX7vL/q5zF NGvdsyaCs6e4M7wW77/hlCVFa9tlyjZy1jeHcY6dl/Dy6Gc7RLg6g/prj0vSu/RDBYMR DxmUhEyIzLxompCl0fqhlwovYSRgdrAF+hRWs4Gee5abukEgvbwAxhKMkw+GBQxoyA4N 3PR5eKSIHxKLTvlVGeVmvr6QrjGdhAfBBtdkslDvy3t/SH+zDNNGZTBurA9wFnOUziSY nacw== X-Gm-Message-State: AOAM531tmymNSho2wIcSO15MYZPu5+PjXPdG52DJ6D6i6xZFiCYHCJ6r 4rl+hQdd4eH43hzS63Pgrg4= X-Google-Smtp-Source: ABdhPJwnR70DRL9bJQhoBUPwEJ9jowGhD9oq7L4j5Z1uunpu2gGX+qzFW3B93iOmuhfLD/8WN7JG7A== X-Received: by 2002:a63:5259:: with SMTP id s25mr33377975pgl.397.1626926553948; Wed, 21 Jul 2021 21:02:33 -0700 (PDT) Received: from jason-z170xgaming7.mshome.net (218-35-143-223.cm.dynamic.apol.com.tw. [218.35.143.223]) by smtp.gmail.com with ESMTPSA id c19sm1663479pfp.184.2021.07.21.21.02.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 21 Jul 2021 21:02:33 -0700 (PDT) From: Jason Lai To: ulf.hansson@linaro.org, adrian.hunter@intel.com Cc: linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, ben.chuang@genesyslogic.com.tw, greg.tu@genesyslogic.com.tw, jason.lai@genesyslogiv.com.tw, AKASHI Takahiro Subject: [RFC PATCH v3.2 22/29] mmc: sdhci-uhs2: add add_host() and others to set up the driver Date: Thu, 22 Jul 2021 12:01:17 +0800 Message-Id: <20210722040124.7573-22-jasonlai.genesyslogic@gmail.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210722040124.7573-1-jasonlai.genesyslogic@gmail.com> References: <20210722040124.7573-1-jasonlai.genesyslogic@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org This is a UHS-II version of sdhci's add_host/remove_host operation. Any sdhci drivers which are capable of handling UHS-II cards must call those functions instead of the corresponding sdhci's. Signed-off-by: Ben Chuang Signed-off-by: AKASHI Takahiro --- drivers/mmc/host/sdhci-uhs2.c | 198 ++++++++++++++++++++++++++++++++++ drivers/mmc/host/sdhci-uhs2.h | 2 + drivers/mmc/host/sdhci.c | 24 +++-- drivers/mmc/host/sdhci.h | 10 ++ 4 files changed, 226 insertions(+), 8 deletions(-) -- 2.32.0 diff --git a/drivers/mmc/host/sdhci-uhs2.c b/drivers/mmc/host/sdhci-uhs2.c index d50134e912f3..5d3362ea138f 100644 --- a/drivers/mmc/host/sdhci-uhs2.c +++ b/drivers/mmc/host/sdhci-uhs2.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "sdhci.h" #include "sdhci-uhs2.h" @@ -406,6 +407,15 @@ static inline void sdhci_led_deactivate(struct sdhci_host *host) { } #else +static inline int sdhci_led_register(struct sdhci_host *host) +{ + return 0; +} + +static inline void sdhci_led_unregister(struct sdhci_host *host) +{ +} + static inline void sdhci_led_activate(struct sdhci_host *host) { __sdhci_led_activate(host); @@ -1298,6 +1308,194 @@ static irqreturn_t sdhci_uhs2_thread_irq(int irq, void *dev_id) return IRQ_HANDLED; } +/*****************************************************************************\ + * + * Device allocation/registration * + * * +\*****************************************************************************/ + +static int __sdhci_uhs2_add_host_v4(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; + + 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; + } + + return 0; +} + +static int sdhci_uhs2_host_ops_init(struct sdhci_host *host); + +static int __sdhci_uhs2_add_host(struct sdhci_host *host) +{ + unsigned int flags = WQ_UNBOUND | WQ_MEM_RECLAIM | WQ_HIGHPRI; + struct mmc_host *mmc = host->mmc; + int ret; + + if ((mmc->caps2 & MMC_CAP2_CQE) && + (host->quirks & SDHCI_QUIRK_BROKEN_CQE)) { + mmc->caps2 &= ~MMC_CAP2_CQE; + mmc->cqe_ops = NULL; + } + + /* overwrite ops */ + if (mmc->caps & MMC_CAP_UHS2) + sdhci_uhs2_host_ops_init(host); + + host->complete_wq = alloc_workqueue("sdhci", flags, 0); + if (!host->complete_wq) + return -ENOMEM; + + INIT_WORK(&host->complete_work, sdhci_uhs2_complete_work); + + timer_setup(&host->timer, sdhci_timeout_timer, 0); + timer_setup(&host->data_timer, sdhci_timeout_data_timer, 0); + + init_waitqueue_head(&host->buf_ready_int); + + sdhci_init(host, 0); + + ret = request_threaded_irq(host->irq, sdhci_irq, + sdhci_uhs2_thread_irq, + IRQF_SHARED, mmc_hostname(mmc), host); + if (ret) { + pr_err("%s: Failed to request IRQ %d: %d\n", + mmc_hostname(mmc), host->irq, ret); + goto unwq; + } + + ret = sdhci_led_register(host); + if (ret) { + pr_err("%s: Failed to register LED device: %d\n", + mmc_hostname(mmc), ret); + goto unirq; + } + + ret = mmc_add_host(mmc); + if (ret) + goto unled; + + pr_info("%s: SDHCI controller on %s [%s] using %s\n", + mmc_hostname(mmc), host->hw_name, dev_name(mmc_dev(mmc)), + host->use_external_dma ? "External DMA" : + (host->flags & SDHCI_USE_ADMA) ? + (host->flags & SDHCI_USE_64_BIT_DMA) ? "ADMA 64-bit" : "ADMA" : + (host->flags & SDHCI_USE_SDMA) ? "DMA" : "PIO"); + + sdhci_enable_card_detection(host); + + return 0; + +unled: + sdhci_led_unregister(host); +unirq: + sdhci_do_reset(host, SDHCI_RESET_ALL); + sdhci_writel(host, 0, SDHCI_INT_ENABLE); + sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE); + free_irq(host->irq, host); +unwq: + destroy_workqueue(host->complete_wq); + + return ret; +} + +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_INITIALIZED; +} + +int sdhci_uhs2_add_host(struct sdhci_host *host) +{ + struct mmc_host *mmc = host->mmc; + int ret; + + ret = sdhci_setup_host(host); + if (ret) + return ret; + + if (host->version >= SDHCI_SPEC_400) { + ret = __sdhci_uhs2_add_host_v4(host, host->caps1); + if (ret) + goto cleanup; + } + + if ((mmc->caps & MMC_CAP_UHS2) && !host->v4_mode) + /* host doesn't want to enable UHS2 support */ + /* FIXME: Do we have to do some cleanup here? */ + mmc->caps &= ~MMC_CAP_UHS2; + + ret = __sdhci_uhs2_add_host(host); + if (ret) + goto cleanup2; + + return 0; + +cleanup2: + /* + * TODO: Is this a right cleanup? + */ + if (host->version >= SDHCI_SPEC_400) + __sdhci_uhs2_remove_host(host, 0); +cleanup: + sdhci_cleanup_host(host); + + return ret; +} +EXPORT_SYMBOL_GPL(sdhci_uhs2_add_host); + +void sdhci_uhs2_remove_host(struct sdhci_host *host, int dead) +{ + __sdhci_uhs2_remove_host(host, dead); + + sdhci_uhs2_remove_host(host, dead); +} +EXPORT_SYMBOL_GPL(sdhci_uhs2_remove_host); + /*****************************************************************************\ * * * Driver init/exit * diff --git a/drivers/mmc/host/sdhci-uhs2.h b/drivers/mmc/host/sdhci-uhs2.h index b74af641d00e..34e140f21284 100644 --- a/drivers/mmc/host/sdhci-uhs2.h +++ b/drivers/mmc/host/sdhci-uhs2.h @@ -218,5 +218,7 @@ void sdhci_uhs2_clear_set_irqs(struct sdhci_host *host, u32 clear, u32 set); void sdhci_uhs2_request(struct mmc_host *mmc, struct mmc_request *mrq); int sdhci_uhs2_request_atomic(struct mmc_host *mmc, struct mmc_request *mrq); u32 sdhci_uhs2_irq(struct sdhci_host *host, u32 intmask); +int sdhci_uhs2_add_host(struct sdhci_host *host); +void sdhci_uhs2_remove_host(struct sdhci_host *host, int dead); #endif /* __SDHCI_UHS2_H */ diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 4a2046c22319..5356cd5f4907 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -175,10 +175,11 @@ static void sdhci_set_card_detection(struct sdhci_host *host, bool enable) sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); } -static void sdhci_enable_card_detection(struct sdhci_host *host) +void sdhci_enable_card_detection(struct sdhci_host *host) { sdhci_set_card_detection(host, true); } +EXPORT_SYMBOL_GPL(sdhci_enable_card_detection); static void sdhci_disable_card_detection(struct sdhci_host *host) { @@ -236,7 +237,7 @@ void sdhci_reset(struct sdhci_host *host, u8 mask) } EXPORT_SYMBOL_GPL(sdhci_reset); -static void sdhci_do_reset(struct sdhci_host *host, u8 mask) +void sdhci_do_reset(struct sdhci_host *host, u8 mask) { if (host->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET) { struct mmc_host *mmc = host->mmc; @@ -257,6 +258,7 @@ static void sdhci_do_reset(struct sdhci_host *host, u8 mask) host->preset_enabled = false; } } +EXPORT_SYMBOL_GPL(sdhci_do_reset); static void sdhci_set_default_irqs(struct sdhci_host *host) { @@ -320,7 +322,7 @@ static void sdhci_config_dma(struct sdhci_host *host) sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); } -static void sdhci_init(struct sdhci_host *host, int soft) +void sdhci_init(struct sdhci_host *host, int soft) { struct mmc_host *mmc = host->mmc; unsigned long flags; @@ -345,6 +347,7 @@ static void sdhci_init(struct sdhci_host *host, int soft) mmc->ops->set_ios(mmc, &mmc->ios); } } +EXPORT_SYMBOL_GPL(sdhci_init); static void sdhci_reinit(struct sdhci_host *host) { @@ -409,7 +412,7 @@ static void sdhci_led_control(struct led_classdev *led, spin_unlock_irqrestore(&host->lock, flags); } -static int sdhci_led_register(struct sdhci_host *host) +int sdhci_led_register(struct sdhci_host *host) { struct mmc_host *mmc = host->mmc; @@ -426,14 +429,16 @@ static int sdhci_led_register(struct sdhci_host *host) return led_classdev_register(mmc_dev(mmc), &host->led); } +EXPORT_SYMBOL_GPL(sdhci_led_register); -static void sdhci_led_unregister(struct sdhci_host *host) +void sdhci_led_unregister(struct sdhci_host *host) { if (host->quirks & SDHCI_QUIRK_NO_LED) return; led_classdev_unregister(&host->led); } +EXPORT_SYMBOL_GPL(sdhci_led_unregister); static inline void sdhci_led_activate(struct sdhci_host *host) { @@ -3249,7 +3254,7 @@ static void sdhci_complete_work(struct work_struct *work) ; } -static void sdhci_timeout_timer(struct timer_list *t) +void sdhci_timeout_timer(struct timer_list *t) { struct sdhci_host *host; unsigned long flags; @@ -3269,8 +3274,9 @@ static void sdhci_timeout_timer(struct timer_list *t) spin_unlock_irqrestore(&host->lock, flags); } +EXPORT_SYMBOL_GPL(sdhci_timeout_timer); -static void sdhci_timeout_data_timer(struct timer_list *t) +void sdhci_timeout_data_timer(struct timer_list *t) { struct sdhci_host *host; unsigned long flags; @@ -3300,6 +3306,7 @@ static void sdhci_timeout_data_timer(struct timer_list *t) spin_unlock_irqrestore(&host->lock, flags); } +EXPORT_SYMBOL_GPL(sdhci_timeout_data_timer); /*****************************************************************************\ * * @@ -3543,7 +3550,7 @@ static inline bool sdhci_defer_done(struct sdhci_host *host, data->host_cookie == COOKIE_MAPPED); } -static irqreturn_t sdhci_irq(int irq, void *dev_id) +irqreturn_t sdhci_irq(int irq, void *dev_id) { struct mmc_request *mrqs_done[SDHCI_MAX_MRQS] = {0}; irqreturn_t result = IRQ_NONE; @@ -3683,6 +3690,7 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) return result; } +EXPORT_SYMBOL_GPL(sdhci_irq); static irqreturn_t sdhci_thread_irq(int irq, void *dev_id) { diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 74572b54ec47..b1d856664b58 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -832,8 +832,15 @@ static inline void sdhci_read_caps(struct sdhci_host *host) } bool sdhci_data_line_cmd(struct mmc_command *cmd); +void sdhci_enable_card_detection(struct sdhci_host *host); void sdhci_runtime_pm_bus_on(struct sdhci_host *host); void sdhci_runtime_pm_bus_off(struct sdhci_host *host); +void sdhci_do_reset(struct sdhci_host *host, u8 mask); +void sdhci_init(struct sdhci_host *host, int soft); +#if IS_REACHABLE(CONFIG_LEDS_CLASS) +int sdhci_led_register(struct sdhci_host *host); +void sdhci_led_unregister(struct sdhci_host *host); +#endif void sdhci_mod_timer(struct sdhci_host *host, struct mmc_request *mrq, unsigned long timeout); void sdhci_initialize_data(struct sdhci_host *host, struct mmc_data *data); @@ -884,6 +891,9 @@ int sdhci_start_signal_voltage_switch(struct mmc_host *mmc, void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable); void sdhci_request_done_dma(struct sdhci_host *host, struct mmc_request *mrq); bool sdhci_request_done(struct sdhci_host *host); +void sdhci_timeout_timer(struct timer_list *t); +void sdhci_timeout_data_timer(struct timer_list *t); +irqreturn_t sdhci_irq(int irq, void *dev_id); void sdhci_adma_write_desc(struct sdhci_host *host, void **desc, dma_addr_t addr, int len, unsigned int cmd); From patchwork Thu Jul 22 04:01:18 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lai Jason X-Patchwork-Id: 484190 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.5 required=3.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_INVALID, DKIM_SIGNED, FREEMAIL_FORGED_FROMDOMAIN, FREEMAIL_FROM,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 17025C6379B for ; Thu, 22 Jul 2021 04:02:52 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 050FF61241 for ; Thu, 22 Jul 2021 04:02:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230527AbhGVDWN (ORCPT ); Wed, 21 Jul 2021 23:22:13 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43854 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230182AbhGVDWB (ORCPT ); Wed, 21 Jul 2021 23:22:01 -0400 Received: from mail-pl1-x636.google.com (mail-pl1-x636.google.com [IPv6:2607:f8b0:4864:20::636]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 34B46C0613C1; Wed, 21 Jul 2021 21:02:36 -0700 (PDT) Received: by mail-pl1-x636.google.com with SMTP id o8so2973500plg.11; Wed, 21 Jul 2021 21:02:36 -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:in-reply-to:references :mime-version:content-transfer-encoding; bh=zGhpNbXjKkULU4t1oSP9LihFc2uO9bsLN2xlTwKncGQ=; b=iNjg6RUphomtTC4PFaeGwZeYq19C02HLmnMgiVrvoa8C0aT9r5cwiGWa9ZQQsVGXZ4 Zt7pPOMQa58xuYVhiRhbu3xtGYMvN6H70HfnQmNTANWzKbAcg4kQRA/XQb6DQ/xYoGUt otOHBf1Mct6bI12EDL3p05rrIEsDVzTMrwlNCC3786Dy+R64T69yNxzLMUu+mE9kocJT yKXKwdU0xqRFbz1AA8QqFFUyLBN5xu/GjnuIbpR0fC4V0DI6WDxNKeJFNvdOAJvenvO7 XuuHJB6C5FkZjGDjKx5Y/snbYzK6MwxZ2Zx4T0xU0o5aYsCM8Y7uuBR0553pEbHl8geE hoKA== 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:in-reply-to :references:mime-version:content-transfer-encoding; bh=zGhpNbXjKkULU4t1oSP9LihFc2uO9bsLN2xlTwKncGQ=; b=e2BxYXsBik+0Yg/elyfQQ0/L1cnqnUTP8QUklSM0Kn14xOtX9DNGxYSxQdNCuEwqO1 GabDAGuCvNY+Xud6Emil/FZhUMjCz64XL96haEPjTFYVoxC+bBWx9G+uaXZdzXhjLDKi Q1RRR9skrWjdTVL39WGO3LWRTFodzAM9y3nl7qzZnaVC0RajDy43fktA/O+X4hVVx+El Git3i71bIa90YKTtgC/N0oqp24JUCu0heTA1f22BD2LKnBXvZglTbnOm/DMYhNGrMa95 bpMnNoLIYU8K27URbgraHsvLVZhZ8Gmhqww02KLi55ucHcv9cpz3qbG/tZ7LV1KSdJ9X /Cwg== X-Gm-Message-State: AOAM530lZCOKUvXPEdJIqmEpTmFYkM12FGPcwuCWKu33TVY5gb+0YFUj xMUq3gHV+KiCbfTrO0RsQCk= X-Google-Smtp-Source: ABdhPJwu259mPUixEt5btD46qtAMquPui9vw1tjjwsW4nQwZmas6RBzHfqtXs5cJRH26oT7XXQr6Iw== X-Received: by 2002:a63:f00d:: with SMTP id k13mr39695102pgh.260.1626926555791; Wed, 21 Jul 2021 21:02:35 -0700 (PDT) Received: from jason-z170xgaming7.mshome.net (218-35-143-223.cm.dynamic.apol.com.tw. [218.35.143.223]) by smtp.gmail.com with ESMTPSA id c19sm1663479pfp.184.2021.07.21.21.02.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 21 Jul 2021 21:02:35 -0700 (PDT) From: Jason Lai To: ulf.hansson@linaro.org, adrian.hunter@intel.com Cc: linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, ben.chuang@genesyslogic.com.tw, greg.tu@genesyslogic.com.tw, jason.lai@genesyslogiv.com.tw, AKASHI Takahiro Subject: [RFC PATCH v3.2 23/29] mmc: sdhci-uhs2: add pre-detect_init hook Date: Thu, 22 Jul 2021 12:01:18 +0800 Message-Id: <20210722040124.7573-23-jasonlai.genesyslogic@gmail.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210722040124.7573-1-jasonlai.genesyslogic@gmail.com> References: <20210722040124.7573-1-jasonlai.genesyslogic@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org 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 | 1 + 2 files changed, 4 insertions(+) -- 2.32.0 diff --git a/drivers/mmc/host/sdhci-uhs2.c b/drivers/mmc/host/sdhci-uhs2.c index 5d3362ea138f..3dd81c89d8f1 100644 --- a/drivers/mmc/host/sdhci-uhs2.c +++ b/drivers/mmc/host/sdhci-uhs2.c @@ -1631,6 +1631,9 @@ static int sdhci_uhs2_do_detect_init(struct mmc_host *mmc) 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 b1d856664b58..4e2cb73a63bd 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -723,6 +723,7 @@ struct sdhci_ops { struct mmc_request *mrq); void (*dump_vendor_regs)(struct sdhci_host *host); void (*dump_uhs2_regs)(struct sdhci_host *host); + void (*uhs2_pre_detect_init)(struct sdhci_host *host); }; #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS From patchwork Thu Jul 22 04:01:19 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lai Jason X-Patchwork-Id: 484188 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.5 required=3.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_INVALID, DKIM_SIGNED, FREEMAIL_FORGED_FROMDOMAIN, FREEMAIL_FROM,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4E969C6379C for ; Thu, 22 Jul 2021 04:02:53 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 3D93B61285 for ; Thu, 22 Jul 2021 04:02:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231130AbhGVDWO (ORCPT ); Wed, 21 Jul 2021 23:22:14 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43848 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230274AbhGVDWD (ORCPT ); Wed, 21 Jul 2021 23:22:03 -0400 Received: from mail-pl1-x633.google.com (mail-pl1-x633.google.com [IPv6:2607:f8b0:4864:20::633]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0A483C0613D5; Wed, 21 Jul 2021 21:02:38 -0700 (PDT) Received: by mail-pl1-x633.google.com with SMTP id v14so3003823plg.9; Wed, 21 Jul 2021 21:02:38 -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:in-reply-to:references :mime-version:content-transfer-encoding; bh=xGZxKn6tTfxIz1ElZzbrIszNdNKnNbkGgVXQIKRLvT0=; b=ZhTEaqtfZm3sbccYU5c+CRwB8y2BGZGPt5tfjUDkO8z+/JcaLtgGsstVejflUi26m+ 55uz6B0uKfNETJoU4AzgPq7ETjuN5zrXjgN4Y24SUB2t1QZxvqkX8MrwRULitmX23B5l S7s9/aA2++aGlaY8ukBumWyVe5HvjWBcpTMMQJoSjM20XGfrZ67nKB+91MkO4lXQbM2e 8SOPV7b2T8RUxGjGckO65uj8Zm4WFhKQ2hlX8K6JDIKK95rOo65s1TbCobPZRynE056b sNCN5+a3KBb5oz65paUWrOlxgbJHwaIiRUYfU8N4YuVRXir+StPWLinyPa+53Gt2RnT5 O1qA== 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:in-reply-to :references:mime-version:content-transfer-encoding; bh=xGZxKn6tTfxIz1ElZzbrIszNdNKnNbkGgVXQIKRLvT0=; b=G4ePJjF2VGM0sMiTVtG71ORQfVYa8+UD03if6J5iGxGWJhmNye6f3OP18ZKXwMoDHK Y0gb6I4OmhGJ/C5m4egVLShYuG1pEdU3l7xkJYcMx+sYi/6nTJGQQ+dwqr5HbvE12q0T Gw3ADpzQfEvbljXP02E9uwuPyCob4iwpmm/oC5giDXhFxLRjhVgizAljvQ8m+aa6scHf m/44xkLgYaOQ4/aJ0WM7j7OAnOMfRL+OND6JVo+k8MkojbHF7eSf1MpUTbsh6K3Zc7+3 gwOCfQZN1PMRmOPlNBTZAYCyIfCltLrhEKtG1AZSf8sOOeKtSx6vWi9GTCAU3SVP9jT7 N0lg== X-Gm-Message-State: AOAM533eQBSIjluYJRDLlZgumxDITIvxyIamWpbxhinJm/bWQpwZGwtx 5R8dkpVxJn3Vz4rDyTE4ggc= X-Google-Smtp-Source: ABdhPJz62PnRNpOKLtOez8IcxGXzTFYlQSoGC1XBzWIQYtdS07WAlXw5OEKAAwHE5JDxLMEijMvq4w== X-Received: by 2002:a05:6a00:884:b029:346:8678:ce15 with SMTP id q4-20020a056a000884b02903468678ce15mr20428411pfj.75.1626926557614; Wed, 21 Jul 2021 21:02:37 -0700 (PDT) Received: from jason-z170xgaming7.mshome.net (218-35-143-223.cm.dynamic.apol.com.tw. [218.35.143.223]) by smtp.gmail.com with ESMTPSA id c19sm1663479pfp.184.2021.07.21.21.02.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 21 Jul 2021 21:02:37 -0700 (PDT) From: Jason Lai To: ulf.hansson@linaro.org, adrian.hunter@intel.com Cc: linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, ben.chuang@genesyslogic.com.tw, greg.tu@genesyslogic.com.tw, jason.lai@genesyslogiv.com.tw, AKASHI Takahiro Subject: [RFC PATCH v3.2 24/29] mmc: core: add post-mmc_attach_sd hook Date: Thu, 22 Jul 2021 12:01:19 +0800 Message-Id: <20210722040124.7573-24-jasonlai.genesyslogic@gmail.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210722040124.7573-1-jasonlai.genesyslogic@gmail.com> References: <20210722040124.7573-1-jasonlai.genesyslogic@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org 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(+) -- 2.32.0 diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 0a407ef1cfc0..f984d5a9301a 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -1417,6 +1417,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 89a9e0e12f07..ef613b3c9af2 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -199,6 +199,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 Thu Jul 22 04:01:20 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lai Jason X-Patchwork-Id: 484187 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.5 required=3.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_INVALID, DKIM_SIGNED, FREEMAIL_FORGED_FROMDOMAIN, FREEMAIL_FROM,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D3DE4C63797 for ; Thu, 22 Jul 2021 04:02:53 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id BD62861362 for ; Thu, 22 Jul 2021 04:02:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230308AbhGVDWO (ORCPT ); Wed, 21 Jul 2021 23:22:14 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43858 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230039AbhGVDWE (ORCPT ); Wed, 21 Jul 2021 23:22:04 -0400 Received: from mail-pj1-x1031.google.com (mail-pj1-x1031.google.com [IPv6:2607:f8b0:4864:20::1031]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C39EAC0613D3; Wed, 21 Jul 2021 21:02:39 -0700 (PDT) Received: by mail-pj1-x1031.google.com with SMTP id my10so4367014pjb.1; Wed, 21 Jul 2021 21:02:39 -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:in-reply-to:references :mime-version:content-transfer-encoding; bh=k1VEGFGIDPzjreHKP+UYCuwcYMr/QZ5cwNJBhn6wCoA=; b=T7MI+SJPMEdYZ1Q+3zj70fiQZn6hUyBZY708CioD5GaBeMSn6bGY4Lm1WCTQq0afX2 lXIMOCtzszqqBe8gPRJwlfrzffk/MImeUQLLBj2fNLJ15XHkrO6KL79jc6r0FCSNhANu oDQ0J5+VNG/ZVjPvzStZzLCxvPkbi8ebGH6At6vduEQto9tIy8NRMzTVnkknfSeG+cVh M3dVEjo2dqcSuZoqD08az3wZALhJXSO0nJftL+d5UYlrKEwXKnPmNcQ47hxN6RV5elhQ by7C/VC5glGVRhuixewG65SpobBshBwQq8wF2Br6PI2XVs7osHI+qR7clSsgfOwsqADd +M6g== 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:in-reply-to :references:mime-version:content-transfer-encoding; bh=k1VEGFGIDPzjreHKP+UYCuwcYMr/QZ5cwNJBhn6wCoA=; b=G3OVUoSYPgYsUfbncxeC/g9bcQmb/VMt71184xoZ4oMw9L7gYW1VmfrIWaK6jPt1bO SeWLQvIuiEUfpmzZx5kR1kX+FQ3pUrwlVDONFRGCZRsqnh6KBExz+EIIkViZMNRPDaah 9HiLuS02kLhG5EUNkt2TUlqZqNe6TM9HyDTMe7A5BGi2IYneAXr4m1jwlGEEStvToe/7 rTbb7ma2AkbzoBD0Mjnq0m9deqXsLs7nuqpfZ+mtp+m1ccKjDfQKPQS4/uBzrHDfzYKV snJ6xQr9HybRIk9YAqHxnr+ti7qaPsmT9uesXc/8JvGFuEbLFGyicv38PtL+jyr6vy9P s4+g== X-Gm-Message-State: AOAM531PPRPzSa0CU2ciHvgrB9amDYmWGiQinpjgHfu2hjSZoa8RDtGZ PaNiMSwZSACDcZBq7ymWvUY= X-Google-Smtp-Source: ABdhPJzGs28Jahhiwuk7antILHsHYULeO03MKfwve+syhDbCwPR5AsMigp1XDKCblj6vctG+56Nmdg== X-Received: by 2002:a17:902:76cb:b029:12b:2fb8:7c35 with SMTP id j11-20020a17090276cbb029012b2fb87c35mr30217449plt.16.1626926559417; Wed, 21 Jul 2021 21:02:39 -0700 (PDT) Received: from jason-z170xgaming7.mshome.net (218-35-143-223.cm.dynamic.apol.com.tw. [218.35.143.223]) by smtp.gmail.com with ESMTPSA id c19sm1663479pfp.184.2021.07.21.21.02.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 21 Jul 2021 21:02:39 -0700 (PDT) From: Jason Lai To: ulf.hansson@linaro.org, adrian.hunter@intel.com Cc: linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, ben.chuang@genesyslogic.com.tw, greg.tu@genesyslogic.com.tw, jason.lai@genesyslogiv.com.tw, AKASHI Takahiro Subject: [RFC PATCH v3.2 25/29] mmc: sdhci-uhs2: add post-mmc_attach_sd hook Date: Thu, 22 Jul 2021 12:01:20 +0800 Message-Id: <20210722040124.7573-25-jasonlai.genesyslogic@gmail.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210722040124.7573-1-jasonlai.genesyslogic@gmail.com> References: <20210722040124.7573-1-jasonlai.genesyslogic@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org 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.h | 1 + 1 file changed, 1 insertion(+) -- 2.32.0 diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 4e2cb73a63bd..b85d9d077c61 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -724,6 +724,7 @@ struct sdhci_ops { void (*dump_vendor_regs)(struct sdhci_host *host); void (*dump_uhs2_regs)(struct sdhci_host *host); void (*uhs2_pre_detect_init)(struct sdhci_host *host); + void (*uhs2_post_attach_sd)(struct sdhci_host *host); }; #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS From patchwork Thu Jul 22 04:01:21 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lai Jason X-Patchwork-Id: 484928 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.5 required=3.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_INVALID, DKIM_SIGNED, FREEMAIL_FORGED_FROMDOMAIN, FREEMAIL_FROM,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 68554C6379F for ; Thu, 22 Jul 2021 04:02:53 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 5A5F5608FC for ; Thu, 22 Jul 2021 04:02:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230475AbhGVDWQ (ORCPT ); Wed, 21 Jul 2021 23:22:16 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43860 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230368AbhGVDWG (ORCPT ); Wed, 21 Jul 2021 23:22:06 -0400 Received: from mail-pl1-x631.google.com (mail-pl1-x631.google.com [IPv6:2607:f8b0:4864:20::631]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9E1B0C061796; Wed, 21 Jul 2021 21:02:41 -0700 (PDT) Received: by mail-pl1-x631.google.com with SMTP id c15so2995796pls.13; Wed, 21 Jul 2021 21:02:41 -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:in-reply-to:references :mime-version:content-transfer-encoding; bh=cIp7At3Tr1YQgF3wIFdAFZiItKmHc+GAgVZKUS+gZoU=; b=kWBkFNsy8cspdW9Oc3Lted3toBUQ0n3ZXd4eqIKmICJq3zfuvyWwmCLxl3HgcNyIMa 7vw9Kz7sG1wUTav3u63ftCM8jk6ZIfGSNXzyfRhUtJfPm3mh2JOM8pkVgvNSTSpnYgA5 Qya6jH5vj51xGz5u62STW9QKm11/q2fg0NFcfJTvPHGFZ9DUCNrI2+3uvAx4b8w1dDy3 aRUis4eOoMzhS0ftXn1u+Sy7M9ckS48Bo9SVKdG7CH25VPfD6UIMZAdK2vofa1QO4IAd vuwzfUj+kj75MuusQldLHTKDdK4FB8J5HAwyXi0itb1qaMVz05N04ddgz6kZvhG4rC0K I2ag== 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:in-reply-to :references:mime-version:content-transfer-encoding; bh=cIp7At3Tr1YQgF3wIFdAFZiItKmHc+GAgVZKUS+gZoU=; b=ZTPl/v39d5YhE24XemByvm/DQxt2oNl/+XyvMRADMarSB6JHFuBCIhfR9Rz9v81bIz MBDEmy9BrPY0VWzAmlWsHqU4WzXm1HQ8teQMfU0+2u0vFVx5qjy3oAwwAKSxFWKFyPe+ nP/x9jrCjAFl54e9Laolq+XOzOFcyeH9Uuhbqrzc7oivFdkJokcdVqppZ3I+WYkl9l+Z 4KFOvC5HibvsGZMzjEsiY63M6+3mUM1OHuLU9ZeIO4ZJrPvVAeKAlUQ5oiTbLrhw1CLy nWUJWXFyYqv4S+ck8dTRZ6fF6uwnmr5x79xerF9ttcWIUzLgyQLlqa9lKmyboAsLJgAG GjPw== X-Gm-Message-State: AOAM533XjbCc5VvboMDyzAYm0f4ANqQddEXnrYxFGgrUpQ5Okx0a7kPH p4b8OVXYwTamZIZEm11QBXq+i968Caql8Q== X-Google-Smtp-Source: ABdhPJw8suLMvs6Dzo4erCtOfqXW0iYv7kilTXt9+3NzG8Qnwpx9yaJj8GYoLYYi5eQk3p91YAPHZQ== X-Received: by 2002:a17:902:b941:b029:12b:81c3:6919 with SMTP id h1-20020a170902b941b029012b81c36919mr17965563pls.7.1626926561230; Wed, 21 Jul 2021 21:02:41 -0700 (PDT) Received: from jason-z170xgaming7.mshome.net (218-35-143-223.cm.dynamic.apol.com.tw. [218.35.143.223]) by smtp.gmail.com with ESMTPSA id c19sm1663479pfp.184.2021.07.21.21.02.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 21 Jul 2021 21:02:41 -0700 (PDT) From: Jason Lai To: ulf.hansson@linaro.org, adrian.hunter@intel.com Cc: linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, ben.chuang@genesyslogic.com.tw, greg.tu@genesyslogic.com.tw, jason.lai@genesyslogiv.com.tw, AKASHI Takahiro Subject: [RFC PATCH v3.2 26/29] mmc: sdhci-pci: add UHS-II support framework Date: Thu, 22 Jul 2021 12:01:21 +0800 Message-Id: <20210722040124.7573-26-jasonlai.genesyslogic@gmail.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210722040124.7573-1-jasonlai.genesyslogic@gmail.com> References: <20210722040124.7573-1-jasonlai.genesyslogic@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org This patch prepares for adding UHS-II support at a specific UHS-II capable sdhci-pci controller, GL9755 for now. Signed-off-by: Ben Chuang Signed-off-by: AKASHI Takahiro --- drivers/mmc/host/sdhci-pci-core.c | 16 +++++++++++++++- drivers/mmc/host/sdhci-pci.h | 3 +++ 2 files changed, 18 insertions(+), 1 deletion(-) -- 2.32.0 diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c index be19785227fe..ac2dc51c8628 100644 --- a/drivers/mmc/host/sdhci-pci-core.c +++ b/drivers/mmc/host/sdhci-pci-core.c @@ -39,6 +39,7 @@ #include "sdhci.h" #include "sdhci-pci.h" +#include "sdhci-uhs2.h" static void sdhci_pci_hw_reset(struct sdhci_host *host); @@ -2253,7 +2254,10 @@ static void sdhci_pci_remove_slot(struct sdhci_pci_slot *slot) if (scratch == (u32)-1) dead = 1; - sdhci_remove_host(slot->host, dead); + if (slot->chip->fixes && slot->chip->fixes->remove_host) + slot->chip->fixes->remove_host(slot, dead); + else + sdhci_remove_host(slot->host, dead); if (slot->chip->fixes && slot->chip->fixes->remove_slot) slot->chip->fixes->remove_slot(slot, dead); @@ -2264,6 +2268,16 @@ static void sdhci_pci_remove_slot(struct sdhci_pci_slot *slot) sdhci_free_host(slot->host); } +int sdhci_pci_uhs2_add_host(struct sdhci_pci_slot *slot) +{ + return sdhci_uhs2_add_host(slot->host); +} + +void sdhci_pci_uhs2_remove_host(struct sdhci_pci_slot *slot, int dead) +{ + sdhci_uhs2_remove_host(slot->host, dead); +} + static void sdhci_pci_runtime_pm_allow(struct device *dev) { pm_suspend_ignore_children(dev, 1); diff --git a/drivers/mmc/host/sdhci-pci.h b/drivers/mmc/host/sdhci-pci.h index 8f90c4163bb5..9082a7e9c10f 100644 --- a/drivers/mmc/host/sdhci-pci.h +++ b/drivers/mmc/host/sdhci-pci.h @@ -139,6 +139,7 @@ struct sdhci_pci_fixes { int (*probe_slot) (struct sdhci_pci_slot *); int (*add_host) (struct sdhci_pci_slot *); void (*remove_slot) (struct sdhci_pci_slot *, int); + void (*remove_host) (struct sdhci_pci_slot *, int); #ifdef CONFIG_PM_SLEEP int (*suspend) (struct sdhci_pci_chip *); @@ -188,6 +189,8 @@ static inline void *sdhci_pci_priv(struct sdhci_pci_slot *slot) return (void *)slot->private; } +int sdhci_pci_uhs2_add_host(struct sdhci_pci_slot *slot); +void sdhci_pci_uhs2_remove_host(struct sdhci_pci_slot *slot, int dead); #ifdef CONFIG_PM_SLEEP int sdhci_pci_resume_host(struct sdhci_pci_chip *chip); #endif From patchwork Thu Jul 22 04:01:22 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lai Jason X-Patchwork-Id: 484927 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.5 required=3.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_INVALID, DKIM_SIGNED, FREEMAIL_FORGED_FROMDOMAIN, FREEMAIL_FROM,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1F2ECC07E9D for ; Thu, 22 Jul 2021 04:02:56 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0EF37608FC for ; Thu, 22 Jul 2021 04:02:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230292AbhGVDWQ (ORCPT ); Wed, 21 Jul 2021 23:22:16 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43948 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230495AbhGVDWJ (ORCPT ); Wed, 21 Jul 2021 23:22:09 -0400 Received: from mail-pj1-x102c.google.com (mail-pj1-x102c.google.com [IPv6:2607:f8b0:4864:20::102c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 90052C061798; Wed, 21 Jul 2021 21:02:43 -0700 (PDT) Received: by mail-pj1-x102c.google.com with SMTP id my10so4367224pjb.1; Wed, 21 Jul 2021 21:02: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:in-reply-to:references :mime-version:content-transfer-encoding; bh=jJSbWAzAYGsBzQsFL9bycC7oa9Xnequ8bJ2lfah7lU8=; b=MdqaJuNnZkCYsIOeRhU1SeL/Ug9GZfSuZg2ckOxfLNbIG0jPSZs5WRGUotSS6uLjov zQp6EKQxfcNDV0vOarLEqRTSlnNnI1uNrqdMW7aoXGDuTHfUqC5UJv3607UgnC+9PNf4 XNAHdafmaRmuWZjfGDztCVuo08ecjjuEgR2RFv9klPzyJQ5Vgo6YIorFOFguACA5SH41 XMM0GMbnmqemxpQKhyXc+0JB4XQpxtat1ZfiD0VQ8rlVnHQ+p6GE+2Grf8QmKJozVk3I fHHoC24O4FhBXryaSQZnUXAysef+Qy4G6HXEV0WDQ/qnemlUlQ3BxaHHq6/na1ZeBYGp Jfwg== 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:in-reply-to :references:mime-version:content-transfer-encoding; bh=jJSbWAzAYGsBzQsFL9bycC7oa9Xnequ8bJ2lfah7lU8=; b=IpyitzErMnAoLtEcJd19qIlUw4qxHjG+j+pTfA6kcElkMFruOwBF4OiMdjFLx8LJbF IGKOalTUDC4AM2BapyKhQ0iKRDyDQhhQGEa525bJZf/rvHLQmYfw4LcraqNVyjJmxMkd 2U8IbEOXP7KwFakNkqhORKg4EhQeBRnBbDG3mMw3Mk/E+9dTDyK4MnqDxAFDRbGqGGvg FLfT68iCQWrLp8O7i5RJQs69PthCTn5CI9BcJSJLvmTPYd8GFotLLPmRMpG3w6IsYMCt Kolx1jIZ2Y+8yqWWWSnKMwATpjDrj8H1kRNWz6oXaELLwS8M7mRZ3Bgdf8K5+kpSZ9hg xzvQ== X-Gm-Message-State: AOAM530liOwj2R2/eJeKPSg3fkSPBE33/agDtKbhYRqEt+xH17NGg/Bt WHcmj6LtTs7boYzkITwMgTc= X-Google-Smtp-Source: ABdhPJxwPEpoIDNk6wRkeWfa+D3LdW0ppGHo/PZXCY1TJCkbnPcqpICwheBcsS7bZXCkYUpEbW+BXg== X-Received: by 2002:a63:a18:: with SMTP id 24mr38959837pgk.309.1626926563167; Wed, 21 Jul 2021 21:02:43 -0700 (PDT) Received: from jason-z170xgaming7.mshome.net (218-35-143-223.cm.dynamic.apol.com.tw. [218.35.143.223]) by smtp.gmail.com with ESMTPSA id c19sm1663479pfp.184.2021.07.21.21.02.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 21 Jul 2021 21:02:42 -0700 (PDT) From: Jason Lai To: ulf.hansson@linaro.org, adrian.hunter@intel.com Cc: linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, ben.chuang@genesyslogic.com.tw, greg.tu@genesyslogic.com.tw, jason.lai@genesyslogiv.com.tw, AKASHI Takahiro Subject: [RFC PATCH v3.2 27/29] mmc: sdhci-pci-gli: enable UHS-II mode for GL9755 Date: Thu, 22 Jul 2021 12:01:22 +0800 Message-Id: <20210722040124.7573-27-jasonlai.genesyslogic@gmail.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210722040124.7573-1-jasonlai.genesyslogic@gmail.com> References: <20210722040124.7573-1-jasonlai.genesyslogic@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org 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 Signed-off-by: AKASHI Takahiro --- drivers/mmc/host/Kconfig | 1 + drivers/mmc/host/sdhci-pci-gli.c | 318 ++++++++++++++++++++++++++++++- 2 files changed, 318 insertions(+), 1 deletion(-) -- 2.32.0 diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 684539a65692..5a8a5aa83faa 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 061618aa247f..3d55c049f14c 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" #include "cqhci.h" /* Genesys Logic extra registers */ @@ -76,6 +77,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 @@ -586,9 +623,279 @@ static void gl9755_hw_setting(struct sdhci_pci_slot *slot) GLI_9755_CFG2_L1DLY_VALUE); pci_write_config_dword(pdev, PCI_GLI_9755_CFG2, value); + gl9755_wt_off(pdev); +} + +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) +{ + 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; + } + + pwr |= SDHCI_VDD2_POWER_180; + } + + 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 | 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; @@ -609,6 +916,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; } @@ -893,17 +1201,25 @@ static int gli_probe_slot_gl9763e(struct sdhci_pci_slot *slot) static const struct sdhci_ops sdhci_gl9755_ops = { .set_clock = sdhci_gl9755_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, + .dump_uhs2_regs = sdhci_uhs2_dump_regs, + .set_timeout = sdhci_uhs2_set_timeout, + .irq = sdhci_uhs2_irq, + .uhs2_pre_detect_init = gl9755_pre_detect_init, + .uhs2_post_attach_sd = gl9755_post_attach_sd, }; const struct sdhci_pci_fixes sdhci_gl9755 = { .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, .quirks2 = SDHCI_QUIRK2_BROKEN_DDR50, .probe_slot = gli_probe_slot_gl9755, + .add_host = sdhci_pci_uhs2_add_host, + .remove_host = sdhci_pci_uhs2_remove_host, .ops = &sdhci_gl9755_ops, #ifdef CONFIG_PM_SLEEP .resume = sdhci_pci_gli_resume, From patchwork Thu Jul 22 04:01:23 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lai Jason X-Patchwork-Id: 484186 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.5 required=3.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_INVALID, DKIM_SIGNED, FREEMAIL_FORGED_FROMDOMAIN, FREEMAIL_FROM,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 042A6C64980 for ; Thu, 22 Jul 2021 04:02:57 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E57EF61289 for ; Thu, 22 Jul 2021 04:02:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231193AbhGVDWR (ORCPT ); Wed, 21 Jul 2021 23:22:17 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43802 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230418AbhGVDWK (ORCPT ); Wed, 21 Jul 2021 23:22:10 -0400 Received: from mail-pj1-x102c.google.com (mail-pj1-x102c.google.com [IPv6:2607:f8b0:4864:20::102c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8D8BDC061757; Wed, 21 Jul 2021 21:02:45 -0700 (PDT) Received: by mail-pj1-x102c.google.com with SMTP id p9so4337119pjl.3; Wed, 21 Jul 2021 21:02:45 -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:in-reply-to:references :mime-version:content-transfer-encoding; bh=Jz33oZyW6qGbCKVeZCfohr4PS24TVJXz4sDYeaRdSgU=; b=U9LZQIzUA+Gzl8DyOxl62WTY1OxfSPlVv3a1kssZGocCX55cYGQISq46mGDo+OinOy Z443xMFrZYbAow0zdWiht6FKLLBh1gSgrARCqgxVLtmWuZNcTlxHHDAW5TUfDtrGVr/2 oLHpD1fptykbfBgF2Z3y44vVVofsK94TaS8N46wCKXrG1c+HD4a0FMfJbcFSXFKrdojw ktRb9qv4mMF2i2ti2goqZHbBL2QeWrWqir0TCyMXV6LEeDCM6APeM0co76ES+shiIvJ9 NwElvMzxSJ+ffGSQWMJ5xlIBgA81SiSh7NX8B1ZGXLktZYKyxG429Ed+EGssHQvP1Jr2 082A== 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:in-reply-to :references:mime-version:content-transfer-encoding; bh=Jz33oZyW6qGbCKVeZCfohr4PS24TVJXz4sDYeaRdSgU=; b=UH5u3djp/yMNzloPbwy/mLWMvRmoVuwNj/EDZGpsauMt5HesbjXchQ6DyesXJNeHsz XqsSdFzN9VkbMg0rrV4WRuibyeDN4/TSSfUQdzvMrStwJCQmLK+0WUKBqkCdqGX7qJhE uK+FKg82Q654tsz14Pf1sMiSfclGAQPA0G/KRJTkcK4I6DY6vhMtlOX4ut1VkBoIrAfi e86IiP7E1pMLe5FBWr7NaUo7EHwA6LogdlpCgLvYjDZkA0pB2AIRPAnbkd4u3TN65NhA MJwrb9v9nMEQRS/U02yIiBAAds7nLW24McbGXSqrUm+I4De0AI0pr3VdtSEAN2Zwdqyg cWKA== X-Gm-Message-State: AOAM530u/7piMCQZCCjPOF2XebGvPqEJHwjVVLRQYs7FQj0zLbxQnGPd OHwsH9oMwGKj454FE872O98= X-Google-Smtp-Source: ABdhPJxQJJQ/ghZdsks/I9RZdGFBg7/B62oV9nxVDYxkM95fLPwn7pCFDuGOFTEVTjXt5dp2m8uetQ== X-Received: by 2002:a17:90a:f18f:: with SMTP id bv15mr6880591pjb.63.1626926565079; Wed, 21 Jul 2021 21:02:45 -0700 (PDT) Received: from jason-z170xgaming7.mshome.net (218-35-143-223.cm.dynamic.apol.com.tw. [218.35.143.223]) by smtp.gmail.com with ESMTPSA id c19sm1663479pfp.184.2021.07.21.21.02.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 21 Jul 2021 21:02:44 -0700 (PDT) From: Jason Lai To: ulf.hansson@linaro.org, adrian.hunter@intel.com Cc: linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, ben.chuang@genesyslogic.com.tw, greg.tu@genesyslogic.com.tw, jason.lai@genesyslogiv.com.tw, AKASHI Takahiro , Jason Lai Subject: [RFC PATCH v3.2 28/29] mmc: Remove duplicate code. Date: Thu, 22 Jul 2021 12:01:23 +0800 Message-Id: <20210722040124.7573-28-jasonlai.genesyslogic@gmail.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210722040124.7573-1-jasonlai.genesyslogic@gmail.com> References: <20210722040124.7573-1-jasonlai.genesyslogic@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org 1. core.c : Use tab to replace space. 2. sdhci.c: Remove code which had been moved into sdhci_request_done_dma() Signed-off-by: Jason Lai --- drivers/mmc/core/core.c | 2 +- drivers/mmc/host/sdhci.c | 74 ---------------------------------------- 2 files changed, 1 insertion(+), 75 deletions(-) -- 2.32.0 diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index d53722c21f29..2624d7b30cd2 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -2248,7 +2248,7 @@ void mmc_rescan(struct work_struct *work) if (mmc_card_sd_express(host)) { mmc_release_host(host); goto out; - } + } if (host->caps & MMC_CAP_UHS2) { /* diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 5356cd5f4907..ae8e3b5a38bf 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -3155,83 +3155,9 @@ bool sdhci_request_done(struct sdhci_host *host) sdhci_set_mrq_done(host, mrq); } - if (data && data->host_cookie == COOKIE_MAPPED) { - if (host->bounce_buffer) { - /* - * On reads, copy the bounced data into the - * sglist - */ - if (mmc_get_dma_dir(data) == DMA_FROM_DEVICE) { - unsigned int length = data->bytes_xfered; - - if (length > host->bounce_buffer_size) { - pr_err("%s: bounce buffer is %u bytes but DMA claims to have transferred %u bytes\n", - mmc_hostname(host->mmc), - host->bounce_buffer_size, - data->bytes_xfered); - /* Cap it down and continue */ - length = host->bounce_buffer_size; - } - dma_sync_single_for_cpu( - mmc_dev(host->mmc), - host->bounce_addr, - host->bounce_buffer_size, - DMA_FROM_DEVICE); - sg_copy_from_buffer(data->sg, - data->sg_len, - host->bounce_buffer, - length); - } else { - /* No copying, just switch ownership */ - dma_sync_single_for_cpu( - mmc_dev(host->mmc), - host->bounce_addr, - host->bounce_buffer_size, - mmc_get_dma_dir(data)); - } - } else { - /* Unmap the raw data */ - dma_unmap_sg(mmc_dev(host->mmc), data->sg, - data->sg_len, - mmc_get_dma_dir(data)); - } - data->host_cookie = COOKIE_UNMAPPED; - } - sdhci_request_done_dma(host, mrq); } - /* - * The controller needs a reset of internal state machines - * upon error conditions. - */ - if (sdhci_needs_reset(host, mrq)) { - /* - * Do not finish until command and data lines are available for - * reset. Note there can only be one other mrq, so it cannot - * also be in mrqs_done, otherwise host->cmd and host->data_cmd - * would both be null. - */ - if (host->cmd || host->data_cmd) { - spin_unlock_irqrestore(&host->lock, flags); - return true; - } - - /* Some controllers need this kick or reset won't work here */ - if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET) - /* 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); - - host->pending_reset = false; - } - host->mrqs_done[i] = NULL; spin_unlock_irqrestore(&host->lock, flags); From patchwork Thu Jul 22 04:01:24 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lai Jason X-Patchwork-Id: 484926 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.5 required=3.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_INVALID, DKIM_SIGNED, FREEMAIL_FORGED_FROMDOMAIN, FREEMAIL_FROM,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C60BBC64981 for ; Thu, 22 Jul 2021 04:03:00 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B2E1461222 for ; Thu, 22 Jul 2021 04:02:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230401AbhGVDWV (ORCPT ); Wed, 21 Jul 2021 23:22:21 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43968 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230519AbhGVDWM (ORCPT ); Wed, 21 Jul 2021 23:22:12 -0400 Received: from mail-pj1-x102c.google.com (mail-pj1-x102c.google.com [IPv6:2607:f8b0:4864:20::102c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EA641C061799; Wed, 21 Jul 2021 21:02:47 -0700 (PDT) Received: by mail-pj1-x102c.google.com with SMTP id ds11-20020a17090b08cbb0290172f971883bso2391005pjb.1; Wed, 21 Jul 2021 21:02:47 -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:in-reply-to:references :mime-version:content-transfer-encoding; bh=8WbyGO24ezxGAFQ8Kmtz7FAIEG0xpefmuLWdx5Osp6o=; b=YYLrabcCnVQygJMgP+NolRJk2gKGKPBKwcJuTfcrsLX7G/3v1k+PpKy2tMGY4NuF8F dS4agyXPr5R+WPIjFdjRgNQmXTm41O+q7WDBdbYHPgQjz11JtRv7es5XRXdIujNfiwGp ZPMlYJOedpehw4mriCqwGFMvXeDil9nf50N7j8gHz5lRmhE7VqCaKBrITJQjlOfEiLWX yDquRH9q1J+YAnYchnPj4uOVM0XWJDr8R5psFGP2xi83rXBUsiGJlNj3qIW1+JoTOIR6 fVCP8ac79PcUYXMaEgNZksmBHFR0lX7Tji0Lck4bp0dAbzuRMKoGJa72A2OWXMTkIb0j j8RA== 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:in-reply-to :references:mime-version:content-transfer-encoding; bh=8WbyGO24ezxGAFQ8Kmtz7FAIEG0xpefmuLWdx5Osp6o=; b=ZsZFQc9Ua/FlzlgNH5waTy5CIdfn8KvjnzfVkpjiZ/5mIcXkYgzdBWGGXf1DmBhXi6 kfOtTTYfbnKA0tizt8zxwMRIn/5/+QsHEFwFNhfLuFY3DxXGZKPcrzpD4Ir5F3Pi/QIf 6Jnb/rnHUKlRnWfqBF5mL3puv3eydxSQcHgDsMzt/AMNGhihsZJQU7M7WF/6Ml0q5BwA Mu47LStuzRdnYLIS7SKqR2k4mgDySLTFWf/WSbt7/Fi9Kt7DaZ1YezNY3Hq++EsQ0Fqk 3NzjpTT9mUMrdQe39fKxjrgPmmjmwfFkDWL16cmulyACa3M1y/8+O/N+lb7TMyZAdg3m pPyg== X-Gm-Message-State: AOAM531LJMghjy/Vk2VDuS16S5eiTGhlfgiNhRTKPfszqzgggUtiQioU +WXxUFB8ef5bXQ15/K7xk0k= X-Google-Smtp-Source: ABdhPJw95O01eIxEyxQQjTUu54UgJiWNCkqpCkR5zZr4xAv5Yy/Tmmp0MlmqBuGQLlNcGEUj1WRkRw== X-Received: by 2002:a17:902:ecce:b029:12b:1c81:2741 with SMTP id a14-20020a170902ecceb029012b1c812741mr30380444plh.3.1626926567147; Wed, 21 Jul 2021 21:02:47 -0700 (PDT) Received: from jason-z170xgaming7.mshome.net (218-35-143-223.cm.dynamic.apol.com.tw. [218.35.143.223]) by smtp.gmail.com with ESMTPSA id c19sm1663479pfp.184.2021.07.21.21.02.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 21 Jul 2021 21:02:46 -0700 (PDT) From: Jason Lai To: ulf.hansson@linaro.org, adrian.hunter@intel.com Cc: linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, ben.chuang@genesyslogic.com.tw, greg.tu@genesyslogic.com.tw, jason.lai@genesyslogiv.com.tw, AKASHI Takahiro , Jason Lai Subject: [RFC PATCH v3.2 29/29] mmc: core: Apply Ulf's patch for supporting UHS-II card Date: Thu, 22 Jul 2021 12:01:24 +0800 Message-Id: <20210722040124.7573-29-jasonlai.genesyslogic@gmail.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210722040124.7573-1-jasonlai.genesyslogic@gmail.com> References: <20210722040124.7573-1-jasonlai.genesyslogic@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org 1. mmc: core: core.c: Modify definition name from MMC_TIMING_UHS2 to MMC_TIMING_SD_UHS2. 2. mmc: core: bus.c: Apply Ulf's coding style to function mmc_add_card(). 3. mmc: core: sd_uhs2.c: Move functions from uhs2.c to corespondding functions in sd_uhs2.c and remove uhs2.c from kernel source code. Signed-off-by: Jason Lai --- drivers/mmc/core/Makefile | 2 +- drivers/mmc/core/core.c | 2 +- drivers/mmc/core/sd.c | 2 +- drivers/mmc/core/sd.h | 1 + drivers/mmc/core/sd_uhs2.c | 1157 ++++++++++++++++++++++++++++++++++++ drivers/mmc/core/uhs2.h | 1 + drivers/mmc/host/sdhci-uhs2.c | 5 +++++ include/linux/mmc/uhs2.h | 1 + 8 files changed, 1171 insertions(+), 3 deletions(-) create mode 100644 drivers/mmc/core/sd_uhs2.c diff --git a/drivers/mmc/core/Makefile b/drivers/mmc/core/Makefile index 3d3a55bc7e45..10f1c3ca5e4a 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 uhs2.o + slot-gpio.o regulator.o sd_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/core.c b/drivers/mmc/core/core.c index 9413dea60612..2624d7b30cd2 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1349,7 +1349,7 @@ void mmc_power_up(struct mmc_host *host, u32 ocr) host->ios.chip_select = MMC_CS_HIGH; else host->ios.chip_select = MMC_CS_DONTCARE; - host->ios.timing = MMC_TIMING_SD_UHS2; + host->ios.timing = MMC_TIMING_UHS2; } else { mmc_pwrseq_pre_power_on(host); diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index f984d5a9301a..93e741e3b5a3 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -1014,7 +1014,7 @@ static bool mmc_sd_card_using_v18(struct mmc_card *card) * In the case of a resume, "oldcard" will contain the card * we're trying to reinitialise. */ -static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, +int mmc_sd_init_card(struct mmc_host *host, u32 ocr, struct mmc_card *oldcard) { struct mmc_card *card; diff --git a/drivers/mmc/core/sd.h b/drivers/mmc/core/sd.h index 1af5a038bae9..4fbd990d33e5 100644 --- a/drivers/mmc/core/sd.h +++ b/drivers/mmc/core/sd.h @@ -9,6 +9,7 @@ extern struct device_type sd_type; struct mmc_host; struct mmc_card; +int mmc_sd_init_card(struct mmc_host *host, u32 ocr, struct mmc_card *oldcard); int mmc_sd_get_cid(struct mmc_host *host, u32 ocr, u32 *cid, u32 *rocr); int mmc_sd_get_csd(struct mmc_card *card); void mmc_decode_cid(struct mmc_card *card); diff --git a/drivers/mmc/core/sd_uhs2.c b/drivers/mmc/core/sd_uhs2.c new file mode 100644 index 000000000000..55853202cbea --- /dev/null +++ b/drivers/mmc/core/sd_uhs2.c @@ -0,0 +1,1157 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2021 Linaro Ltd + * + * Author: Ulf Hansson + * + * Support for SD UHS-II cards + */ +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "core.h" +#include "bus.h" +#include "sd_ops.h" +#include "sd.h" +#include "mmc_ops.h" +#include "uhs2.h" + +#define DBG(f, x...) \ + pr_warn("[%s()]: " f, __func__, ## x) + +//static const unsigned int sd_uhs2_freqs[] = { 52000000, 26000000 }; + +/* This function is part of sdhci_uhs2_set_ios() in sdhci-uhs2.c +static int sd_uhs2_set_ios(struct mmc_host *host) +{ + struct mmc_ios *ios = &host->ios; + + return host->ops->uhs2_set_ios(host, ios); +} +*/ + +/* This function is part of mmc_power_up() in core.c +static int sd_uhs2_power_up(struct mmc_host *host) +{ + host->ios.vdd = fls(host->ocr_avail) - 1; + host->ios.clock = host->f_init; + host->ios.timing = MMC_TIMING_SD_UHS2; + host->ios.power_mode = MMC_POWER_UP; + + return sd_uhs2_set_ios(host); +}*/ + +/* This function is part of mmc_power_off() in core.c +static void sd_uhs2_power_off(struct mmc_host *host) +{ + host->ios.vdd = 0; + host->ios.clock = 0; + host->ios.timing = MMC_TIMING_LEGACY; + host->ios.power_mode = MMC_POWER_OFF; + + sd_uhs2_set_ios(host); +} +*/ + +/** + * 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); +} + +/* + * Do the early initialization of the card, by sending the device init broadcast + * command and wait for the process to be completed. + */ +static int sd_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; +} + +/* + * Run the enumeration process by sending the enumerate command to the card. + * Note that, we currently support only the point to point connection, which + * means only one card can be attached per host/slot. + */ +//static int sd_uhs2_enum(struct mmc_host *host, u32 *node_id) // node_id had been saved in host->uhs2_dev_prop.node_id +static int sd_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; +} + +/* + * Read the UHS-II configuration registers (CFG_REG) of the card, by sending it + * commands and by parsing the responses. Store a copy of the relevant data in + * card->uhs2_config. + */ +//static int sd_uhs2_config_read(struct mmc_host *host, struct mmc_card *card) +static int sd_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; +} + +/* + * Based on the card's and host's UHS-II capabilities, let's update the + * configuration of the card and the host. This may also include to move to a + * greater speed range/mode. Depending on the updated configuration, we may need + * to do a soft reset of the card via sending it a GO_DORMANT_STATE command. + * + * In the final step, let's check if the card signals "config completion", which + * indicates that the card has moved from config state into active state. + */ +//static int sd_uhs2_config_write(struct mmc_host *host, struct mmc_card *card) +static int sd_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 gLssDir = 0 + */ + u32 gLssDir = 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 (!gLssDir) { + host->uhs2_dev_prop.n_lss_dir_set = 0; + } else { + host->uhs2_dev_prop.n_lss_dir_set = + max((u8)gLssDir, + 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->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->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->ops->uhs2_set_reg(host, CHECK_DORMANT)) { + pr_err("%s: %s: UHS2 GO_DORMANT_STATE fail!\n", + mmc_hostname(host), __func__); + return -EIO; + } + + if (host->ops->uhs2_disable_clk) + 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->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); + if (host->ops->uhs2_enable_clk) + host->ops->uhs2_enable_clk(host); + + /* Enable Normal INT */ + if (!host->ops->uhs2_set_reg || + 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->ops->uhs2_detect_init(host)) { + pr_err("%s: %s: uhs2_detect_init() fail!\n", + mmc_hostname(host), __func__); + return -EIO; + } + + return 0; +} + +/* + * Initialize the UHS-II card through the SD-TRAN transport layer. This enables + * commands/requests to be backwards compatible through the legacy SD protocol. + * UHS-II cards has a specific power limit specified for VDD1/VDD2, that should + * be set through a legacy CMD6. Note that, the power limit that becomes set, + * survives a soft reset through the GO_DORMANT_STATE command. + */ +static int sd_uhs2_legacy_init(struct mmc_host *host) +{ + int err; + u32 ocr, rocr; + + WARN_ON(!host->claimed); + + // Jason test + mmc_go_idle(host); + mmc_delay(10); + + err = mmc_send_if_cond(host, host->ocr_avail); + if (err) { + pr_err("%s: %s: UHS2 CMD8 fail!\n", mmc_hostname(host), __func__); + //return err; + } + + err = mmc_send_app_op_cond(host, 0, &ocr); + if (err) + return err; + + if (host->ocr_avail_sd) + host->ocr_avail = host->ocr_avail_sd; + + /* + * Some SD cards claims an out of spec VDD voltage range. Let's treat + * these bits as being in-valid and especially also bit7. + */ + ocr &= ~0x7FFF; + + 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 (!rocr) + rocr = host->ocr_avail; + + /* + * Can we support the voltage(s) of the card(s)? + */ + if (!rocr) { + pr_err("%s: UHS2: there is no valid OCR.\n", mmc_hostname(host)); + return -EINVAL; + } + + /* + * Detect and init the card. + */ + err = mmc_sd_init_card(host, rocr, NULL); + if (err) + return err; + + return 0; +} + +/* + * Run the phy initialization sequence, which mainly relies on the UHS-II host + * to check that we reach the expected electrical state, between the host and + * the card. + */ +static int sd_uhs2_phy_init(struct mmc_host *host) +{ + if (!host->ops->uhs2_detect_init || + host->ops->uhs2_detect_init(host)) { + pr_err("%s: fail to detect UHS2!\n", mmc_hostname(host)); + return UHS2_PHY_INIT_ERR; + } + return 0; +} + +static void sd_uhs2_remove(struct mmc_host *host) +{ + mmc_remove_card(host->card); + host->card = NULL; +} + +static int sd_uhs2_alive(struct mmc_host *host) +{ + return mmc_send_status(host->card, NULL); +} + +static void sd_uhs2_detect(struct mmc_host *host) +{ + int err; + + mmc_get_card(host->card, NULL); + err = _mmc_detect_card_removed(host); + mmc_put_card(host->card, NULL); + + if (err) { + sd_uhs2_remove(host); + + mmc_claim_host(host); + mmc_detach_bus(host); + mmc_power_off(host); + mmc_release_host(host); + } +} + +static int sd_uhs2_suspend(struct mmc_host *host) +{ + return 0; +} + +static int sd_uhs2_resume(struct mmc_host *host) +{ + return 0; +} + +static int sd_uhs2_runtime_suspend(struct mmc_host *host) +{ + return 0; +} + +static int sd_uhs2_runtime_resume(struct mmc_host *host) +{ + return 0; +} + +static int sd_uhs2_shutdown(struct mmc_host *host) +{ + return 0; +} + + +/** + * sd_uhs2_hw_reset - invoke SW reset + * @host: MMC host + * + * Invoke SW reset, depending on a bit in @mask and wait for completion. + */ +static int sd_uhs2_hw_reset(struct mmc_host *host) +{ + int err = 0; + + if (!host->ops->uhs2_set_reg || + host->ops->uhs2_set_reg(host, UHS2_SW_RESET)) { + pr_err("%s: %s: UHS2_SW_RESET fail!\n", + mmc_hostname(host), __func__); + return -EIO; + } + + return err; +} + +static int sd_uhs2_attach(struct mmc_host *host) +{ + int err; + + err = sd_uhs2_phy_init(host); + if (err) + return err; + + err = sd_uhs2_init_card(host); + if (err) + return err; + + mmc_release_host(host); + err = mmc_add_card(host->card); + if (err) { + mmc_remove_card(host->card); + host->card = NULL; + mmc_detach_bus(host); + mmc_claim_host(host); + return err;; + } + + mmc_claim_host(host); + + /* TODO: Is this the right place? */ + if (host->ops->uhs2_post_attach_sd) + host->ops->uhs2_post_attach_sd(host); + + return 0; +} + +/** + * 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; + 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; + 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); + +static const struct mmc_bus_ops sd_uhs2_ops = { + .remove = sd_uhs2_remove, + .alive = sd_uhs2_alive, + .detect = sd_uhs2_detect, + .suspend = sd_uhs2_suspend, + .resume = sd_uhs2_resume, + .runtime_suspend = sd_uhs2_runtime_suspend, + .runtime_resume = sd_uhs2_runtime_resume, + .shutdown = sd_uhs2_shutdown, + .hw_reset = sd_uhs2_hw_reset, +}; + +/* + * Allocate the data structure for the mmc_card and run the UHS-II specific + * initialization sequence. + */ +int sd_uhs2_init_card(struct mmc_host *host) +{ +// struct mmc_card *card; +// u32 node_id; + int err = -EIO; + + if (sd_uhs2_dev_init(host)) { + pr_err("%s: UHS2 DEVICE_INIT fail!\n", mmc_hostname(host)); + return err; + } + + if (sd_uhs2_enum(host)) + { + pr_err("%s: UHS2 ENUMERATE fail!\n", mmc_hostname(host)); + return err; + } + + if (sd_uhs2_config_read(host)) { + pr_err("%s: UHS2 INQUIRY_CONFIG fail!\n", mmc_hostname(host)); + return err; + } + + if (sd_uhs2_config_write(host)) { + pr_err("%s: UHS2 SET_COMMON_CONFIG fail!\n", mmc_hostname(host)); + return err; + } + + 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)); + return err; + } + } + + host->flags |= MMC_UHS2_INITIALIZED; + + mmc_attach_bus(host, &sd_uhs2_ops); + + if (sd_uhs2_legacy_init(host)) { + pr_err("%s: sd_uhs2_legacy_init: error %d.\n", mmc_hostname(host), err); + mmc_detach_bus(host); + return err; + } + + 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); + + if (!(host->caps2 & MMC_CAP2_NO_SDIO)) + pr_info("mmc_attach_sdio\n"); + if (!(host->caps2 & MMC_CAP2_NO_SD)) + pr_info("mmc_attach_sd\n"); + + mmc_power_up(host, 0); + + err = sd_uhs2_attach(host); + if (err) { + pr_err("%s: sd_uhs2_attach fail!\n", mmc_hostname(host)); + goto init_fail; + } + else + return 0; + +//-------------------------------------------------------------------------------------- + +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 index 48486ba21062..d05a4c28df3e 100644 --- a/drivers/mmc/core/uhs2.h +++ b/drivers/mmc/core/uhs2.h @@ -16,6 +16,7 @@ #define UHS2_PHY_INIT_ERR 1 int mmc_uhs2_rescan_try_freq(struct mmc_host *host, unsigned int freq); +int sd_uhs2_init_card(struct mmc_host *host); int uhs2_prepare_sd_cmd(struct mmc_host *host, struct mmc_request *mrq); #endif /* MMC_UHS2_H */ diff --git a/drivers/mmc/host/sdhci-uhs2.c b/drivers/mmc/host/sdhci-uhs2.c index 3dd81c89d8f1..a5af2bd950f8 100644-- --- a/drivers/mmc/host/sdhci-uhs2.c2.32.0 +++ b/drivers/mmc/host/sdhci-uhs2.c @@ -545,6 +545,10 @@ static int sdhci_uhs2_set_reg(struct mmc_host *mmc, enum uhs2_act act) case CHECK_DORMANT: err = sdhci_uhs2_check_dormant(host); break; + case UHS2_SW_RESET: + sdhci_uhs2_reset(host, SDHCI_UHS2_SW_RESET_FULL); + /* FIXED IT : Modify return type of sdhci_uhs2_reset()? */ + err = 0; + break; default: pr_err("%s: input action %d is wrong!\n", mmc_hostname(host->mmc), act); diff --git a/include/linux/mmc/uhs2.h b/include/linux/mmc/uhs2.h index 298ac7cd8904..ef249098b46f 100644 --- a/include/linux/mmc/uhs2.h +++ b/include/linux/mmc/uhs2.h @@ -189,6 +189,7 @@ enum uhs2_act { DISABLE_INT, SET_SPEED_B, CHECK_DORMANT, + UHS2_SW_RESET, }; /* UHS-II Device Registers */