Add support UHS-II for GL9755
Subsystems (9)
v2 cover Add support UHS-II for GL9755
Hi Uffe and Adrian,
These patches support UHS-II and fix GL9755 UHS-II compatibility.
The parts of UHS-II are based on [1][2] and porting to Linux 5.5-rc5. I have seen that Uffe comment that splitting the UHS-II parts into smaller patches. Other than splitting into small patches, could you give me some suggestions for refactoring/splitting files?
Best regards,
Ben
References:
1. [RFC,1/2] mmc: core: support UHS-II in core stack.
(https://patchwork.kernel.org/patch/5544441/)
2. [RFC,2/2] mmc: sdhci: support UHS-II in SDHCI host.
(https://patchwork.kernel.org/patch/5544451/)
v2:
- base on Linux v5.5-rc5
Ben Chuang (6):
mmc: Add UHS-II support in public headers
mmc: core: Add UHS-II support in core layer
mmc: host: Add UHS-II support in host layer
mmc: uhs2: Introduce a uhs2_post_attach_sd function
mmc: sdhci-uhs2: Introduce a uhs2_pre_detect_init function
mmc: sdhci-pci-gli: Fix power/reset/ZC/timeout for GL9755 UHS-II mode
drivers/mmc/core/Makefile | 3 +-
drivers/mmc/core/block.c | 7 +-
drivers/mmc/core/bus.c | 5 +-
drivers/mmc/core/core.c | 65 +-
drivers/mmc/core/core.h | 3 +-
drivers/mmc/core/regulator.c | 14 +
drivers/mmc/core/sd.c | 27 +-
drivers/mmc/core/sd_ops.c | 12 +
drivers/mmc/core/uhs2.c | 995 +++++++++++++++++++++
drivers/mmc/core/uhs2.h | 23 +
drivers/mmc/host/Makefile | 1 +
drivers/mmc/host/{sdhci.c => sdhci-core.c} | 285 +++++-
drivers/mmc/host/sdhci-milbeaut.c | 4 +-
drivers/mmc/host/sdhci-of-arasan.c | 4 +-
drivers/mmc/host/sdhci-of-at91.c | 4 +-
drivers/mmc/host/sdhci-omap.c | 2 +-
drivers/mmc/host/sdhci-pci-core.c | 4 +-
drivers/mmc/host/sdhci-pci-gli.c | 361 +++++++-
drivers/mmc/host/sdhci-pxav3.c | 4 +-
drivers/mmc/host/sdhci-uhs2.c | 754 ++++++++++++++++
drivers/mmc/host/sdhci-uhs2.h | 34 +
drivers/mmc/host/sdhci-xenon.c | 4 +-
drivers/mmc/host/sdhci.h | 286 +++++-
drivers/mmc/host/sdhci_am654.c | 4 +-
include/linux/mmc/card.h | 1 +
include/linux/mmc/core.h | 6 +
include/linux/mmc/host.h | 31 +
include/linux/mmc/uhs2.h | 270 ++++++
28 files changed, 3137 insertions(+), 76 deletions(-)
create mode 100644 drivers/mmc/core/uhs2.c
create mode 100644 drivers/mmc/core/uhs2.h
rename drivers/mmc/host/{sdhci.c => sdhci-core.c} (94%)
create mode 100644 drivers/mmc/host/sdhci-uhs2.c
create mode 100644 drivers/mmc/host/sdhci-uhs2.h
create mode 100644 include/linux/mmc/uhs2.hbase-commit: c79f46a282390e0f5b306007bf7b11a46d529538
Signature · 1 line
2.24.1
RFC PATCH v2 1/6 mmc: Add UHS-II support in public headers
From: Ben Chuang <[email protected]>
Add UHS-II support in public headers
--- include/linux/mmc/card.h | 1 + include/linux/mmc/core.h | 6 ++++++ include/linux/mmc/host.h | 30 ++++++++++++++++++++++++++++++ 3 files changed, 37 insertions(+)
include/linux/mmc/card.h +1 -0
@@ -180,6 +180,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)
include/linux/mmc/core.h +6 -0
@@ -7,6 +7,7 @@#include <linux/completion.h> #include <linux/types.h> +#include <linux/mmc/uhs2.h> struct mmc_data ;struct mmc_request ;
@@ -112,6 +113,11 @@ struct mmc_command {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 {
include/linux/mmc/host.h +30 -0
@@ -15,10 +15,12 @@#include <linux/mmc/card.h> #include <linux/mmc/pm.h> #include <linux/dma-direction.h> +#include <linux/mmc/uhs2.h> struct mmc_ios {unsigned int clock;/* clock rate */ unsigned short vdd; +unsigned short vdd2;/* UHS2 VDD2 power supply */ unsigned int power_delay_ms;/* waiting for stable power */ /* vdd stores the bit number of the selected voltage range from below. */
@@ -60,6 +62,7 @@ struct mmc_ios {#define MMC_TIMING_MMC_DDR52 8#define MMC_TIMING_MMC_HS200 9#define MMC_TIMING_MMC_HS400 10 +#define MMC_TIMING_UHS2 11unsigned char signal_voltage;/* signalling voltage (1.8V or 3.3V) */
@@ -169,6 +172,11 @@ struct mmc_host_ops {*/ int (*multi_io_quirk)(struct mmc_card *card,unsigned int direction,int blk_size); +/* UHS2 interfaces */ +int (*uhs2_detect_init)(struct mmc_host *host); +int (*uhs2_set_reg)(struct mmc_host *host,enum uhs2_act act); +void (*uhs2_disable_clk)(struct mmc_host *host); +void (*uhs2_enable_clk)(struct mmc_host *host); };struct mmc_cqe_ops {
@@ -261,6 +269,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 */ };
@@ -281,12 +290,14 @@ struct mmc_host {u32 ocr_avail_sdio;/* SDIO-specific OCR */ u32 ocr_avail_sd;/* SD-specific OCR */ u32 ocr_avail_mmc;/* MMC-specific OCR */ +u32 ocr_avail_uhs2;/* UHS2-specific OCR */ #ifdef CONFIG_PM_SLEEP struct notifier_block pm_notify;#endif u32 max_current_330;u32 max_current_300;u32 max_current_180; +u32 max_current_180_vdd2;/* UHS2 vdd2 max curt. */ #define MMC_VDD_165_195 0x00000080/* VDD voltage 1.65 - 1.95 */ #define MMC_VDD_20_21 0x00000100/* VDD voltage 2.0 ~ 2.1 */
@@ -305,6 +316,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 */
@@ -336,6 +348,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 */
@@ -374,6 +387,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 */
@@ -566,6 +590,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)
Signature · 1 line
2.24.1
RFC PATCH v2 2/6 mmc: core: Add UHS-II support in core layer
In reply to Ben ChuangFrom: Ben Chuang <[email protected]>
Add UHS-II support in core layer
--- drivers/mmc/core/Makefile | 3 +- drivers/mmc/core/block.c | 7 +- drivers/mmc/core/bus.c | 5 +- drivers/mmc/core/core.c | 65 ++- drivers/mmc/core/core.h | 3 +- drivers/mmc/core/regulator.c | 14 + drivers/mmc/core/sd.c | 27 +- drivers/mmc/core/sd_ops.c | 12 + drivers/mmc/core/uhs2.c | 992 +++++++++++++++++++++++++++++++++++ drivers/mmc/core/uhs2.h | 23 + 10 files changed, 1139 insertions(+), 12 deletions(-) create mode 100644 drivers/mmc/core/uhs2.c create mode 100644 drivers/mmc/core/uhs2.h
drivers/mmc/core/Makefile +2 -1
@@ -8,7 +8,8 @@ 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
drivers/mmc/core/block.c +6 -1
@@ -56,6 +56,7 @@#include "mmc_ops.h" #include "quirks.h" #include "sd_ops.h" +#include "uhs2.h" MODULE_ALIAS ("mmc:block" );#ifdef MODULE_PARAM_PREFIX
@@ -1551,6 +1552,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);
@@ -1561,7 +1565,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. */
@@ -1574,6 +1578,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;
drivers/mmc/core/bus.c +3 -2
@@ -336,8 +336,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 " : "",
drivers/mmc/core/core.c +59 -6
144 lines not on this page · raw message
drivers/mmc/core/core.h +2 -1
@@ -76,7 +76,7 @@ int _mmc_detect_card_removed(struct mmc_host *host);int mmc_detect_card_removed (struct mmc_host *host);int mmc_attach_mmc (struct mmc_host *host); -int mmc_attach_sd (struct mmc_host *host); +int mmc_attach_sd (struct mmc_host *host,bool flag_uhs2);int mmc_attach_sdio (struct mmc_host *host);/* Module parameters */
@@ -124,6 +124,7 @@ int __mmc_claim_host(struct mmc_host *host, struct mmc_ctx *ctx,void mmc_release_host (struct mmc_host *host);void mmc_get_card (struct mmc_card *card,struct mmc_ctx *ctx);void mmc_put_card (struct mmc_card *card,struct mmc_ctx *ctx); +void mmc_set_ios (struct mmc_host *host);/** * mmc_claim_host - exclusively claim a host
drivers/mmc/core/regulator.c +14 -0
@@ -236,6 +236,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 )
@@ -255,6 +256,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);
drivers/mmc/core/sd.c +26 -1
@@ -877,6 +877,19 @@ 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); + } + } }/*
@@ -1019,6 +1032,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)
@@ -1266,7 +1284,7 @@ static const struct mmc_bus_ops mmc_sd_ops = {/* * Starting point for SD card init. */ -int mmc_attach_sd (struct mmc_host *host) +int mmc_attach_sd (struct mmc_host *host,bool flag_uhs2) {int err;u32 ocr, rocr;
@@ -1300,6 +1318,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 (flag_uhs2 && !rocr) + rocr = host->ocr_avail; +/* * Can we support the voltage(s) of the card(s)? */
drivers/mmc/core/sd_ops.c +12 -0
@@ -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) {
@@ -235,6 +244,7 @@ int mmc_app_send_scr(struct mmc_card *card) cmd.opcode =SD_APP_SEND_SCR ; cmd.arg =0 ; cmd.flags =MMC_RSP_SPI_R1 |MMC_RSP_R1 |MMC_CMD_ADTC ; + cmd.uhs2_tmode0_flag =1 ; data.blksz =8 ; data.blocks =1 ;
@@ -282,6 +292,7 @@ int mmc_sd_switch(struct mmc_card *card, int mode, int group, cmd.arg &= ~(0xF << (group *4 )); cmd.arg |= value << (group *4 ); cmd.flags =MMC_RSP_SPI_R1 |MMC_RSP_R1 |MMC_CMD_ADTC ; + cmd.uhs2_tmode0_flag =1 ; data.blksz =64 ; data.blocks =1 ;
@@ -323,6 +334,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 ;
drivers/mmc/core/uhs2.c new file +992 -0
992 lines not on this page · raw message
drivers/mmc/core/uhs2.h new file +23 -0
@@ -0,0 +1,23 @@ +/* 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 <linux/mmc/core.h> +#include <linux/mmc/host.h> + +#define UHS2_PHY_INIT_ERR 1 + +extern int uhs2_prepare_sd_cmd (struct mmc_host *host,struct mmc_request *mrq); +extern void uhs2_power_up (struct mmc_host *host); +extern int mmc_uhs2_try_frequency (struct mmc_host *host,unsigned int freq); +extern int uhs2_abort_trans (struct mmc_host *host); + +#endif /* MMC_UHS2_H */
Signature · 1 line
2.24.1
RFC PATCH v2 3/6 mmc: host: Add UHS-II support in host layer
In reply to Ben ChuangFrom: Ben Chuang <[email protected]>
Add UHS-II support in host layer
---
drivers/mmc/host/Makefile | 1 +
drivers/mmc/host/{sdhci.c => sdhci-core.c} | 276 ++++++--
drivers/mmc/host/sdhci-milbeaut.c | 4 +-
drivers/mmc/host/sdhci-of-arasan.c | 4 +-
drivers/mmc/host/sdhci-of-at91.c | 4 +-
drivers/mmc/host/sdhci-omap.c | 2 +-
drivers/mmc/host/sdhci-pci-core.c | 4 +-
drivers/mmc/host/sdhci-pxav3.c | 4 +-
drivers/mmc/host/sdhci-uhs2.c | 751 +++++++++++++++++++++
drivers/mmc/host/sdhci-uhs2.h | 34 +
drivers/mmc/host/sdhci-xenon.c | 4 +-
drivers/mmc/host/sdhci.h | 284 +++++++-
drivers/mmc/host/sdhci_am654.c | 4 +-
include/linux/mmc/uhs2.h | 270 ++++++++
14 files changed, 1583 insertions(+), 63 deletions(-)
rename drivers/mmc/host/{sdhci.c => sdhci-core.c} (94%)
create mode 100644 drivers/mmc/host/sdhci-uhs2.c
create mode 100644 drivers/mmc/host/sdhci-uhs2.h
create mode 100644 include/linux/mmc/uhs2.hdrivers/mmc/host/Makefile +1 -0
@@ -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 +sdhci-y += sdhci-core.o 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
drivers/mmc/host/sdhci-core.c renamed from drivers/mmc/host/sdhci.c +235 -41
532 lines not on this page · raw message
drivers/mmc/host/sdhci-milbeaut.c +2 -2
@@ -122,14 +122,14 @@ static void sdhci_milbeaut_reset(struct sdhci_host *host, u8 mask) }static void sdhci_milbeaut_set_power (struct sdhci_host *host, -unsigned char mode,unsigned short vdd) +unsigned char mode,unsigned short vdd,unsigned short vdd2) {if (!IS_ERR (host->mmc->supply.vmmc)) {struct mmc_host *mmc = host->mmc;mmc_regulator_set_ocr (mmc, mmc->supply.vmmc, vdd); } -sdhci_set_power_noreg (host, mode, vdd); +sdhci_set_power_noreg (host, mode, vdd,-1 ); }static const struct sdhci_ops sdhci_milbeaut_ops = {
drivers/mmc/host/sdhci-of-arasan.c +2 -2
@@ -326,14 +326,14 @@ static int sdhci_arasan_voltage_switch(struct mmc_host *mmc, }static void sdhci_arasan_set_power (struct sdhci_host *host,unsigned char mode, -unsigned short vdd) +unsigned short vdd,unsigned short vdd2) {if (!IS_ERR (host->mmc->supply.vmmc)) {struct mmc_host *mmc = host->mmc;mmc_regulator_set_ocr (mmc, mmc->supply.vmmc, vdd); } -sdhci_set_power_noreg (host, mode, vdd); +sdhci_set_power_noreg (host, mode, vdd,-1 ); }static const struct sdhci_ops sdhci_arasan_ops = {
drivers/mmc/host/sdhci-of-at91.c +2 -2
@@ -100,14 +100,14 @@ static void sdhci_at91_set_clock(struct sdhci_host *host, unsigned int clock)* an external regulator. */ static void sdhci_at91_set_power (struct sdhci_host *host,unsigned char mode, -unsigned short vdd) +unsigned short vdd,unsigned short vdd2) {if (!IS_ERR (host->mmc->supply.vmmc)) {struct mmc_host *mmc = host->mmc;mmc_regulator_set_ocr (mmc, mmc->supply.vmmc, vdd); } -sdhci_set_power_noreg (host, mode, vdd); +sdhci_set_power_noreg (host, mode, vdd,-1 ); } static void sdhci_at91_set_uhs_signaling(struct sdhci_host *host,
drivers/mmc/host/sdhci-omap.c +1 -1
@@ -671,7 +671,7 @@ static void sdhci_omap_set_clock(struct sdhci_host *host, unsigned int clock) }static void sdhci_omap_set_power (struct sdhci_host *host,unsigned char mode, -unsigned short vdd) +unsigned short vdd,unsigned short vdd2) {struct mmc_host *mmc = host->mmc;
drivers/mmc/host/sdhci-pci-core.c +2 -2
@@ -630,12 +630,12 @@ static int bxt_get_cd(struct mmc_host *mmc)#define SDHCI_INTEL_PWR_TIMEOUT_UDELAY 100static void sdhci_intel_set_power (struct sdhci_host *host,unsigned char mode, -unsigned short vdd) +unsigned short vdd,unsigned short vdd2) {int cntr;u8 reg; -sdhci_set_power (host, mode, vdd); +sdhci_set_power (host, mode, vdd,-1 );if (mode ==MMC_POWER_OFF )return ;
drivers/mmc/host/sdhci-pxav3.c +2 -2
@@ -298,12 +298,12 @@ static void pxav3_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs) }static void pxav3_set_power (struct sdhci_host *host,unsigned char mode, -unsigned short vdd) +unsigned short vdd,unsigned short vdd2) {struct mmc_host *mmc = host->mmc;u8 pwr = host->pwr; -sdhci_set_power_noreg (host, mode, vdd); +sdhci_set_power_noreg (host, mode, vdd,-1 );if (host->pwr == pwr)return ;
drivers/mmc/host/sdhci-uhs2.c new file +751 -0
751 lines not on this page · raw message
drivers/mmc/host/sdhci-uhs2.h new file +34 -0
@@ -0,0 +1,34 @@ +/* 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 <linux/mmc/host.h> +#include <linux/mmc/core.h> +#include <linux/mmc/uhs2.h> + +extern void sdhci_uhs2_reset (struct sdhci_host *host,u16 mask); +extern void sdhci_uhs2_set_transfer_mode (struct sdhci_host *host, +struct mmc_command *cmd); +extern void sdhci_uhs2_send_command (struct sdhci_host *host, +struct mmc_command *cmd); +extern void sdhci_uhs2_finish_command (struct sdhci_host *host); +extern void sdhci_uhs2_do_set_ios (struct sdhci_host *host, +struct mmc_ios *ios); +extern int sdhci_uhs2_do_detect_init (struct sdhci_host *host); +extern int sdhci_uhs2_do_set_reg (struct sdhci_host *host,enum uhs2_act act); +extern void sdhci_uhs2_irq (struct sdhci_host *host); +extern int sdhci_uhs2_add_host (struct sdhci_host *host,u32 caps1); +extern void sdhci_uhs2_remove_host (struct sdhci_host *host,int dead); +extern void sdhci_uhs2_clear_set_irqs (struct sdhci_host *host,u32 clear, +u32 set); +extern void sdhci_uhs2_set_timeout (struct sdhci_host *host); + +#endif /* __SDHCI_UHS2_H */
drivers/mmc/host/sdhci-xenon.c +2 -2
@@ -214,12 +214,12 @@ static void xenon_set_uhs_signaling(struct sdhci_host *host, }static void xenon_set_power (struct sdhci_host *host,unsigned char mode, -unsigned short vdd) +unsigned short vdd,unsigned short vdd2) {struct mmc_host *mmc = host->mmc;u8 pwr = host->pwr; -sdhci_set_power_noreg (host, mode, vdd); +sdhci_set_power_noreg (host, mode, vdd,-1 );if (host->pwr == pwr)return ;
drivers/mmc/host/sdhci.h +277 -7
422 lines not on this page · raw message
drivers/mmc/host/sdhci_am654.c +2 -2
@@ -209,14 +209,14 @@ static void sdhci_j721e_4bit_set_clock(struct sdhci_host *host, }static void sdhci_am654_set_power (struct sdhci_host *host,unsigned char mode, -unsigned short vdd) +unsigned short vdd,unsigned short vdd2) {if (!IS_ERR (host->mmc->supply.vmmc)) {struct mmc_host *mmc = host->mmc;mmc_regulator_set_ocr (mmc, mmc->supply.vmmc, vdd); } -sdhci_set_power_noreg (host, mode, vdd); +sdhci_set_power_noreg (host, mode, vdd,-1 ); }static void sdhci_am654_write_b (struct sdhci_host *host,u8 val,int reg)
include/linux/mmc/uhs2.h new file +270 -0
270 lines not on this page · raw message
Signature · 1 line
2.24.1
Adrian Hunter
maintainerRe: [RFC PATCH v2 3/6] mmc: host: Add UHS-II support in host layer
Quoted 3 lines · Ben Chuang
From: Ben Chuang <[email protected]>
Add UHS-II support in host layer
Split host layer changes from sdhci changes.
Quoted 2 lines
Reported-by kbuild test robot <[email protected]>
Drop "Reported-by: kbuild test robot <[email protected]>"
Quoted 13 lines
Signed-off-by Ben Chuang <[email protected]>--- drivers/mmc/host/Makefile | 1 + drivers/mmc/host/{sdhci.c => sdhci-core.c} | 276 ++++++-- drivers/mmc/host/sdhci-milbeaut.c | 4 +- drivers/mmc/host/sdhci-of-arasan.c | 4 +- drivers/mmc/host/sdhci-of-at91.c | 4 +- drivers/mmc/host/sdhci-omap.c | 2 +- drivers/mmc/host/sdhci-pci-core.c | 4 +- drivers/mmc/host/sdhci-pxav3.c | 4 +- drivers/mmc/host/sdhci-uhs2.c | 751 +++++++++++++++++++++ drivers/mmc/host/sdhci-uhs2.h | 34 + drivers/mmc/host/sdhci-xenon.c | 4 +-
Quoted 8 lines
drivers/mmc/host/sdhci.h | 284 +++++++-
drivers/mmc/host/sdhci_am654.c | 4 +-
include/linux/mmc/uhs2.h | 270 ++++++++
14 files changed, 1583 insertions(+), 63 deletions(-)
rename drivers/mmc/host/{sdhci.c => sdhci-core.c} (94%)
create mode 100644 drivers/mmc/host/sdhci-uhs2.c
create mode 100644 drivers/mmc/host/sdhci-uhs2.h
create mode 100644 include/linux/mmc/uhs2.hPlease make sdhci-uhs2 a module and do not rename sdhci.c.
References in sdhci.c to sdhci-uhs2.c will need to be enclosed by #if IS_REACHABLE(CONFIG_SDHCI_UHS2)
Move all UHS-II definitions into sdhci-uhs2.h. Things that are for V4 but not necessarily UHS-II can be in sdhci.h
Make the set_power parameter change into a separate patch
Fix all spelling mistakes
Make comment style correct.
Review all checkpatch warnings and checks (i.e. --strict option)
If possible provide a link to a tree that contains the patches.
Re-base on Ulf's next branch
The patch set could use an overview of how UHS-II is different from regular SD.
In other patches there are a bunch of memory allocations on the I/O path. That is a problem. Memory needed should be allocated in advance.
Re: [RFC PATCH v2 3/6] mmc: host: Add UHS-II support in host layer
Quoted 51 lines · Adrian Hunter
Quoted 3 lines · Ben Chuang
From: Ben Chuang <[email protected]>
Add UHS-II support in host layer
Split host layer changes from sdhci changes.
Quoted 2 lines
Reported-by kbuild test robot <[email protected]>Drop "Reported-by: kbuild test robot <[email protected]>"
Quoted 13 lines
Signed-off-by Ben Chuang <[email protected]>--- drivers/mmc/host/Makefile | 1 + drivers/mmc/host/{sdhci.c => sdhci-core.c} | 276 ++++++-- drivers/mmc/host/sdhci-milbeaut.c | 4 +- drivers/mmc/host/sdhci-of-arasan.c | 4 +- drivers/mmc/host/sdhci-of-at91.c | 4 +- drivers/mmc/host/sdhci-omap.c | 2 +- drivers/mmc/host/sdhci-pci-core.c | 4 +- drivers/mmc/host/sdhci-pxav3.c | 4 +- drivers/mmc/host/sdhci-uhs2.c | 751 +++++++++++++++++++++ drivers/mmc/host/sdhci-uhs2.h | 34 + drivers/mmc/host/sdhci-xenon.c | 4 +-Quoted 8 lines
drivers/mmc/host/sdhci.h | 284 +++++++- drivers/mmc/host/sdhci_am654.c | 4 +- include/linux/mmc/uhs2.h | 270 ++++++++ 14 files changed, 1583 insertions(+), 63 deletions(-) rename drivers/mmc/host/{sdhci.c => sdhci-core.c} (94%) create mode 100644 drivers/mmc/host/sdhci-uhs2.c create mode 100644 drivers/mmc/host/sdhci-uhs2.h create mode 100644 include/linux/mmc/uhs2.hPlease make sdhci-uhs2 a module and do not rename
sdhci.c.References in
sdhci.ctosdhci-uhs2.cwill need to be enclosed by #ifIS_REACHABLE(CONFIG_SDHCI_UHS2)Move all UHS-II definitions into
sdhci-uhs2.h. Things that are for V4 but not necessarily UHS-II can be insdhci.hMake the
set_powerparameter change into a separate patchFix all spelling mistakes
Make comment style correct.
Review all checkpatch warnings and checks (i.e. --strict option)
Quoted 8 lines
If possible provide a link to a tree that contains the patches.
Re-base on Ulf's next branch
The patch set could use an overview of how UHS-II is different from regular SD.
In other patches there are a bunch of memory allocations on the I/O path. That is a problem. Memory needed should be allocated in advance.
Thanks for your comments and guidance.
There seems to be a lot of work to do. I will do my best to meet these.
RFC PATCH v2 4/6 mmc: uhs2: Introduce a uhs2_post_attach_sd function
In reply to Ben ChuangFrom: Ben Chuang <[email protected]>
Introduce a uhs2_post_attach_sd function after attach_sd on UHS-II mode.
--- drivers/mmc/core/uhs2.c | 5 ++++- drivers/mmc/host/sdhci-core.c | 9 +++++++++ drivers/mmc/host/sdhci.h | 1 + include/linux/mmc/host.h | 1 + 4 files changed, 15 insertions(+), 1 deletion(-)
drivers/mmc/core/uhs2.c +4 -1
@@ -935,8 +935,11 @@ int mmc_uhs2_try_frequency(struct mmc_host *host, unsigned int freq)*/ err =mmc_attach_sd (host, true); -if (!err) +if (!err) { +if (host->ops->uhs2_post_attach_sd) + host->ops->uhs2_post_attach_sd (host);return 0 ; + } init_fail:mmc_power_off (host);
drivers/mmc/host/sdhci-core.c +9 -0
@@ -2778,6 +2778,14 @@ void sdhci_uhs2_enable_clk(struct mmc_host *mmc) }EXPORT_SYMBOL_GPL (sdhci_uhs2_enable_clk); +static void sdhci_uhs2_post_attach_sd (struct mmc_host *mmc) +{ +struct sdhci_host *host =mmc_priv (mmc); + +if (host->ops && host->ops->uhs2_post_attach_sd) + host->ops->uhs2_post_attach_sd (host); +} +static const struct mmc_host_ops sdhci_ops = { .request = sdhci_request, .post_req = sdhci_post_req,
@@ -2797,6 +2805,7 @@ static const struct mmc_host_ops sdhci_ops = { .uhs2_set_reg = sdhci_uhs2_set_reg, .uhs2_disable_clk = sdhci_uhs2_disable_clk, .uhs2_enable_clk = sdhci_uhs2_enable_clk, + .uhs2_post_attach_sd = sdhci_uhs2_post_attach_sd, };/*****************************************************************************\
drivers/mmc/host/sdhci.h +1 -0
@@ -906,6 +906,7 @@ struct sdhci_ops {void (*voltage_switch)(struct sdhci_host *host);void (*adma_write_desc)(struct sdhci_host *host,void **desc,dma_addr_t addr,int len,unsigned int cmd); +void (*uhs2_post_attach_sd)(struct sdhci_host *host); };#ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS
include/linux/mmc/host.h +1 -0
@@ -177,6 +177,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 {
Signature · 1 line
2.24.1
RFC PATCH v2 5/6 mmc: sdhci-uhs2: Introduce a uhs2_pre_detect_init function
In reply to Ben ChuangFrom: Ben Chuang <[email protected]>
Introduce a uhs2_pre_detect_init function before detect uhs2 interface.
--- drivers/mmc/host/sdhci-uhs2.c | 3 +++ drivers/mmc/host/sdhci.h | 1 + 2 files changed, 4 insertions(+)
drivers/mmc/host/sdhci-uhs2.c +3 -0
@@ -506,6 +506,9 @@ int sdhci_uhs2_do_detect_init(struct sdhci_host *host)DBG ("%s: begin UHS2 init.\n" , __func__);spin_lock_irqsave (&host->lock, flags); +if (host->ops && host->ops->uhs2_pre_detect_init) + host->ops->uhs2_pre_detect_init (host); +if (sdhci_uhs2_interface_detect (host)) {pr_warn ("%s: cannot detect UHS2 interface.\n" ,mmc_hostname (host->mmc));
drivers/mmc/host/sdhci.h +1 -0
@@ -906,6 +906,7 @@ struct sdhci_ops {void (*voltage_switch)(struct sdhci_host *host);void (*adma_write_desc)(struct sdhci_host *host,void **desc,dma_addr_t addr,int len,unsigned int cmd); +void (*uhs2_pre_detect_init)(struct sdhci_host *host);void (*uhs2_post_attach_sd)(struct sdhci_host *host); };
Signature · 1 line
2.24.1
RFC PATCH v2 6/6 mmc: sdhci-pci-gli: Fix power/reset/ZC/timeout for GL9755 UHS-II mode
In reply to Ben ChuangFrom: Ben Chuang <[email protected]>
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.
--- drivers/mmc/host/sdhci-pci-gli.c | 361 ++++++++++++++++++++++++++++++- 1 file changed, 360 insertions(+), 1 deletion(-)
drivers/mmc/host/sdhci-pci-gli.c +360 -1
@@ -14,6 +14,7 @@#include <linux/delay.h> #include "sdhci.h" #include "sdhci-pci.h" +#include "sdhci-uhs2.h" /* Genesys Logic extra registers */ #define SDHCI_GLI_9750_WT 0x800
@@ -60,6 +61,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 GLI_MAX_TUNING_LOOP 40/* Genesys Logic chipset */
@@ -262,6 +299,324 @@ static int gl9750_execute_tuning(struct sdhci_host *host, u32 opcode)return 0 ; } +static inline void gl9755_wt_on (struct pci_dev *pdev) +{ +u32 wt_value; +u32 wt_enable; + +pci_read_config_dword (pdev,PCI_GLI_9755_WT , &wt_value); + wt_enable =FIELD_GET (PCI_GLI_9755_WT_EN , wt_value); + +if (wt_enable ==GLI_9755_WT_EN_ON ) +return ; + + wt_value &= ~PCI_GLI_9755_WT_EN ; + wt_value |=FIELD_PREP (PCI_GLI_9755_WT_EN ,GLI_9755_WT_EN_ON ); + +pci_write_config_dword (pdev,PCI_GLI_9755_WT , wt_value); +} + +static inline void gl9755_wt_off (struct pci_dev *pdev) +{ +u32 wt_value; +u32 wt_enable; + +pci_read_config_dword (pdev,PCI_GLI_9755_WT , &wt_value); + wt_enable =FIELD_GET (PCI_GLI_9755_WT_EN , wt_value); + +if (wt_enable ==GLI_9755_WT_EN_OFF ) +return ; + + wt_value &= ~PCI_GLI_9755_WT_EN ; + wt_value |=FIELD_PREP (PCI_GLI_9755_WT_EN ,GLI_9755_WT_EN_OFF ); + +pci_write_config_dword (pdev,PCI_GLI_9755_WT , wt_value); +} + +static void gl9755_vendor_init (struct sdhci_host *host) +{ +struct sdhci_pci_slot *slot =sdhci_priv (host); +struct pci_dev *pdev = slot->chip->pdev; +u32 serdes; +u32 pllssc; +u32 uhs2_pll; + +gl9755_wt_on (pdev); + +pci_read_config_dword (pdev,PCI_GLI_9755_UHS2_SERDES , &serdes); + serdes &= ~PCI_GLI_9755_UHS2_SERDES_TRAN ; + serdes |=FIELD_PREP (PCI_GLI_9755_UHS2_SERDES_TRAN , +GLI_9755_UHS2_SERDES_TRAN_VALUE ); + serdes &= ~PCI_GLI_9755_UHS2_SERDES_RECV ; + serdes |=FIELD_PREP (PCI_GLI_9755_UHS2_SERDES_RECV , +GLI_9755_UHS2_SERDES_RECV_VALUE ); + serdes &= ~PCI_GLI_9755_UHS2_SERDES_INTR ; + serdes |=FIELD_PREP (PCI_GLI_9755_UHS2_SERDES_INTR , +GLI_9755_UHS2_SERDES_INTR_VALUE ); + serdes &= ~PCI_GLI_9755_UHS2_SERDES_ZC1 ; + serdes |=FIELD_PREP (PCI_GLI_9755_UHS2_SERDES_ZC1 , +GLI_9755_UHS2_SERDES_ZC1_VALUE ); + serdes &= ~PCI_GLI_9755_UHS2_SERDES_ZC2 ; + serdes |=FIELD_PREP (PCI_GLI_9755_UHS2_SERDES_ZC2 , +GLI_9755_UHS2_SERDES_ZC2_DEFAULT ); +pci_write_config_dword (pdev,PCI_GLI_9755_UHS2_SERDES , serdes); + +pci_read_config_dword (pdev,PCI_GLI_9755_UHS2_PLL , &uhs2_pll); + uhs2_pll &= ~PCI_GLI_9755_UHS2_PLL_SSC ; + uhs2_pll |=FIELD_PREP (PCI_GLI_9755_UHS2_PLL_SSC , +GLI_9755_UHS2_PLL_SSC_VALUE ); + uhs2_pll &= ~PCI_GLI_9755_UHS2_PLL_DELAY ; + uhs2_pll |=FIELD_PREP (PCI_GLI_9755_UHS2_PLL_DELAY , +GLI_9755_UHS2_PLL_DELAY_VALUE ); + uhs2_pll &= ~PCI_GLI_9755_UHS2_PLL_PDRST ; + uhs2_pll |=FIELD_PREP (PCI_GLI_9755_UHS2_PLL_PDRST , +GLI_9755_UHS2_PLL_PDRST_VALUE ); +pci_write_config_dword (pdev,PCI_GLI_9755_UHS2_PLL , uhs2_pll); + +pci_read_config_dword (pdev,PCI_GLI_9755_PLLSSC , &pllssc); + pllssc &= ~PCI_GLI_9755_PLLSSC_RTL ; + pllssc |=FIELD_PREP (PCI_GLI_9755_PLLSSC_RTL , +GLI_9755_PLLSSC_RTL_VALUE ); + pllssc &= ~PCI_GLI_9755_PLLSSC_TRANS_PASS ; + pllssc |=FIELD_PREP (PCI_GLI_9755_PLLSSC_TRANS_PASS , +GLI_9755_PLLSSC_TRANS_PASS_VALUE ); + pllssc &= ~PCI_GLI_9755_PLLSSC_RECV ; + pllssc |=FIELD_PREP (PCI_GLI_9755_PLLSSC_RECV , +GLI_9755_PLLSSC_RECV_VALUE ); + pllssc &= ~PCI_GLI_9755_PLLSSC_TRAN ; + pllssc |=FIELD_PREP (PCI_GLI_9755_PLLSSC_TRAN , +GLI_9755_PLLSSC_TRAN_VALUE ); +pci_write_config_dword (pdev,PCI_GLI_9755_PLLSSC , pllssc); + +gl9755_wt_off (pdev); +} + +static void gl9755_pre_detect_init (struct sdhci_host *host) +{ +/* GL9755 need more time on UHS2 detect flow */ +sdhci_writeb (host,0xA7 ,SDHCI_UHS2_TIMER_CTRL ); +} + +static void gl9755_post_attach_sd (struct sdhci_host *host) +{ +struct pci_dev *pdev; +struct sdhci_pci_chip *chip; +struct sdhci_pci_slot *slot; +u32 serdes; + + slot =sdhci_priv (host); + chip = slot->chip; + pdev = chip->pdev; + +gl9755_wt_on (pdev); + +pci_read_config_dword (pdev,PCI_GLI_9755_UHS2_SERDES , &serdes); + serdes &= ~PCI_GLI_9755_UHS2_SERDES_ZC1 ; + serdes &= ~PCI_GLI_9755_UHS2_SERDES_ZC2 ; + serdes |=FIELD_PREP (PCI_GLI_9755_UHS2_SERDES_ZC1 , +GLI_9755_UHS2_SERDES_ZC1_VALUE ); + +/* the manfid of sandisk card is 0x3 */ +if (host->mmc->card->cid.manfid ==0x3 ) + serdes |=FIELD_PREP (PCI_GLI_9755_UHS2_SERDES_ZC2 , +GLI_9755_UHS2_SERDES_ZC2_SANDISK ); +else + serdes |=FIELD_PREP (PCI_GLI_9755_UHS2_SERDES_ZC2 , +GLI_9755_UHS2_SERDES_ZC2_DEFAULT ); + +pci_write_config_dword (pdev,PCI_GLI_9755_UHS2_SERDES , serdes); + +gl9755_wt_off (pdev); +} + +static void gl9755_overcurrent_event_enable (struct sdhci_host *host, +bool enable) +{ +u32 mask; + + mask =sdhci_readl (host,SDHCI_SIGNAL_ENABLE ); +if (enable) + mask |=SDHCI_INT_BUS_POWER ; +else + mask &= ~SDHCI_INT_BUS_POWER ; + +sdhci_writel (host, mask,SDHCI_SIGNAL_ENABLE ); + + mask =sdhci_readl (host,SDHCI_INT_ENABLE ); +if (enable) + mask |=SDHCI_INT_BUS_POWER ; +else + mask &= ~SDHCI_INT_BUS_POWER ; + +sdhci_writel (host, mask,SDHCI_INT_ENABLE ); +} + +static void gl9755_set_power (struct sdhci_host *host,unsigned char mode, +unsigned short vdd,unsigned short vdd2) +{ +u8 pwr =0 ; + +if (mode !=MMC_POWER_OFF ) { +switch (1 << vdd) { +case MMC_VDD_165_195 : +/* +* Without a regulator, SDHCI does not support 2.0v +* so we only get here if the driver deliberately +* added the 2.0v range to ocr_avail. Map it to 1.8v +* for the purpose of turning on the power. +*/ +case MMC_VDD_20_21 : + pwr =SDHCI_POWER_180 ; +break ; +case MMC_VDD_29_30 : +case MMC_VDD_30_31 : + pwr =SDHCI_POWER_300 ; +break ; +case MMC_VDD_32_33 : +case MMC_VDD_33_34 : + pwr =SDHCI_POWER_330 ; +break ; +default : +WARN (1 ,"%s: Invalid vdd %#x\n" , +mmc_hostname (host->mmc), vdd); +break ; + } + } + +if (mode !=MMC_POWER_OFF ) { +if (vdd2 != (unsigned short )-1 ) { +switch (1 << vdd2) { +case MMC_VDD2_165_195 : + pwr |=SDHCI_VDD2_POWER_180 ; +break ; +default : +WARN (1 ,"%s: Invalid vdd2 %#x\n" , +mmc_hostname (host->mmc), vdd2); +break ; + } + } + } + +if (host->pwr == pwr) +return ; + + host->pwr = pwr; + +if (pwr ==0 ) { +gl9755_overcurrent_event_enable (host, false); +sdhci_writeb (host,0 ,SDHCI_POWER_CONTROL ); + }else { +gl9755_overcurrent_event_enable (host, false); +sdhci_writeb (host,0 ,SDHCI_POWER_CONTROL ); + + pwr |=SDHCI_POWER_ON ; +if (vdd2 != (unsigned short )-1 ) + pwr |=SDHCI_VDD2_POWER_ON ; + +sdhci_writeb (host, pwr&0xf ,SDHCI_POWER_CONTROL ); +/* wait stable */ +mdelay (5 ); +sdhci_writeb (host, pwr,SDHCI_POWER_CONTROL ); +/* wait stable */ +mdelay (5 ); +gl9755_overcurrent_event_enable (host, true); + } +} + +static bool sdhci_wait_clock_stable (struct sdhci_host *host) +{ +u16 clk =0 ; +ktime_t timeout; + +/* Wait max 20 ms */ + timeout =ktime_add_ms (ktime_get (),20 ); +while (1 ) { +bool timedout =ktime_after (ktime_get (), timeout); + + clk =sdhci_readw (host,SDHCI_CLOCK_CONTROL ); +if (clk &SDHCI_CLOCK_INT_STABLE ) +break ; +if (timedout) { +pr_err ("%s: Internal clock never stabilised.\n" , +mmc_hostname (host->mmc)); +sdhci_dumpregs (host); +return false; + } +udelay (10 ); + } +return true; +} + +static void gl9755_uhs2_reset_sd_tran (struct sdhci_host *host) +{ +/* do this on UHS2 mode */ +if (host->mmc->flags &MMC_UHS2_INITIALIZED ) { +sdhci_uhs2_reset (host,SDHCI_UHS2_SW_RESET_SD ); +sdhci_writel (host, host->ier,SDHCI_INT_ENABLE ); +sdhci_writel (host, host->ier,SDHCI_SIGNAL_ENABLE ); +sdhci_uhs2_clear_set_irqs (host, +SDHCI_INT_ALL_MASK , +SDHCI_UHS2_ERR_INT_STATUS_MASK ); + } +} + +static void sdhci_gl9755_reset (struct sdhci_host *host,u8 mask) +{ +ktime_t timeout; +u16 ctrl2; +u16 clk_ctrl; + +/* need internal clock */ +if (mask &SDHCI_RESET_ALL ) { + ctrl2 =sdhci_readw (host,SDHCI_HOST_CONTROL2 ); + clk_ctrl =sdhci_readw (host,SDHCI_CLOCK_CONTROL ); + +if ((ctrl2 &SDHCI_CTRL_V4_MODE ) && + (ctrl2 &SDHCI_CTRL_UHS2_INTERFACE_EN )) { +sdhci_writew (host, +SDHCI_CLOCK_INT_EN , +SDHCI_CLOCK_CONTROL ); + }else { +sdhci_writew (host, +SDHCI_CLOCK_INT_EN , +SDHCI_CLOCK_CONTROL ); +sdhci_wait_clock_stable (host); +sdhci_writew (host, +SDHCI_CTRL_V4_MODE , +SDHCI_HOST_CONTROL2 ); + } + } + +sdhci_writeb (host, mask,SDHCI_SOFTWARE_RESET ); + +/* reset sd-tran on UHS2 mode if need to reset cmd/data */ +if ((mask &SDHCI_RESET_CMD ) | (mask &SDHCI_RESET_DATA )) +gl9755_uhs2_reset_sd_tran (host); + +if (mask &SDHCI_RESET_ALL ) + host->clock =0 ; + +/* Wait max 100 ms */ + timeout =ktime_add_ms (ktime_get (),100 ); + +/* hw clears the bit when it's done */ +while (1 ) { +bool timedout =ktime_after (ktime_get (), timeout); + +if (!(sdhci_readb (host,SDHCI_SOFTWARE_RESET ) & mask)) +break ; +if (timedout) { +pr_err ("%s: Reset 0x%x never completed.\n" , +mmc_hostname (host->mmc), (int )mask); +sdhci_dumpregs (host); +/* manual clear */ +sdhci_writeb (host,0 ,SDHCI_SOFTWARE_RESET ); +return ; + } +udelay (10 ); + } +} +static int gli_probe_slot_gl9750 (struct sdhci_pci_slot *slot) {struct sdhci_host *host = slot->host;
@@ -278,6 +633,7 @@ static int gli_probe_slot_gl9755(struct sdhci_pci_slot *slot) slot->host->mmc->caps2 |=MMC_CAP2_NO_SDIO ;sdhci_enable_v4_mode (host); +gl9755_vendor_init (host);return 0 ; }
@@ -319,11 +675,14 @@ static u32 sdhci_gl9750_readl(struct sdhci_host *host, int reg)static const struct sdhci_ops sdhci_gl9755_ops = { .set_clock = sdhci_set_clock, + .set_power = gl9755_set_power, .enable_dma = sdhci_pci_enable_dma, .set_bus_width = sdhci_set_bus_width, - .reset = sdhci_reset, + .reset = sdhci_gl9755_reset, .set_uhs_signaling = sdhci_set_uhs_signaling, .voltage_switch = sdhci_gli_voltage_switch, + .uhs2_pre_detect_init = gl9755_pre_detect_init, + .uhs2_post_attach_sd = gl9755_post_attach_sd, };const struct sdhci_pci_fixes sdhci_gl9755 = {
Signature · 1 line
2.24.1
Hi Uffe and Adrian,
Quoted 5 lines · Ben Chuang
Hi Uffe and Adrian,
These patches support UHS-II and fix GL9755 UHS-II compatibility.
Quoted 7 lines
The parts of UHS-II are based on [1][2] and porting to Linux 5.5-rc5. I have seen that Uffe comment that splitting the UHS-II parts into smaller patches. Other than splitting into small patches, could you give me some suggestions for refactoring/splitting files?
Best regards,
Ben
Gentle Ping, Any comments?
Best regards,
Ben
Quoted 59 lines
References:
1. [RFC,1/2] mmc: core: support UHS-II in core stack.
(https://patchwork.kernel.org/patch/5544441/)
2. [RFC,2/2] mmc: sdhci: support UHS-II in SDHCI host.
(https://patchwork.kernel.org/patch/5544451/)v2:
- base on Linux v5.5-rc5Ben Chuang (6):
mmc: Add UHS-II support in public headers
mmc: core: Add UHS-II support in core layer
mmc: host: Add UHS-II support in host layer
mmc: uhs2: Introduce auhs2_post_attach_sdfunction
mmc: sdhci-uhs2: Introduce auhs2_pre_detect_initfunction
mmc: sdhci-pci-gli: Fix power/reset/ZC/timeout for GL9755 UHS-II modedrivers/mmc/core/Makefile | 3 +- drivers/mmc/core/block.c | 7 +- drivers/mmc/core/bus.c | 5 +- drivers/mmc/core/core.c | 65 +- drivers/mmc/core/core.h | 3 +- drivers/mmc/core/regulator.c | 14 + drivers/mmc/core/sd.c | 27 +- drivers/mmc/core/sd_ops.c | 12 + drivers/mmc/core/uhs2.c | 995 +++++++++++++++++++++ drivers/mmc/core/uhs2.h | 23 + drivers/mmc/host/Makefile | 1 + drivers/mmc/host/{sdhci.c => sdhci-core.c} | 285 +++++- drivers/mmc/host/sdhci-milbeaut.c | 4 +- drivers/mmc/host/sdhci-of-arasan.c | 4 +- drivers/mmc/host/sdhci-of-at91.c | 4 +- drivers/mmc/host/sdhci-omap.c | 2 +- drivers/mmc/host/sdhci-pci-core.c | 4 +- drivers/mmc/host/sdhci-pci-gli.c | 361 +++++++- drivers/mmc/host/sdhci-pxav3.c | 4 +- drivers/mmc/host/sdhci-uhs2.c | 754 ++++++++++++++++ drivers/mmc/host/sdhci-uhs2.h | 34 + drivers/mmc/host/sdhci-xenon.c | 4 +- drivers/mmc/host/sdhci.h | 286 +++++- drivers/mmc/host/sdhci_am654.c | 4 +- include/linux/mmc/card.h | 1 + include/linux/mmc/core.h | 6 + include/linux/mmc/host.h | 31 + include/linux/mmc/uhs2.h | 270 ++++++ 28 files changed, 3137 insertions(+), 76 deletions(-) create mode 100644 drivers/mmc/core/uhs2.c create mode 100644 drivers/mmc/core/uhs2.h rename drivers/mmc/host/{sdhci.c => sdhci-core.c} (94%) create mode 100644 drivers/mmc/host/sdhci-uhs2.c create mode 100644 drivers/mmc/host/sdhci-uhs2.h create mode 100644 include/linux/mmc/uhs2.hbase-commit:
c79f46a282390e0f5b306007bf7b11a46d529538--
2.24.1
Quoted 14 lines · Ben Chuang
Hi Uffe and Adrian,
Quoted 10 lines · Ben Chuang
Hi Uffe and Adrian,
These patches support UHS-II and fix GL9755 UHS-II compatibility.
The parts of UHS-II are based on [1][2] and porting to Linux 5.5-rc5. I have seen that Uffe comment that splitting the UHS-II parts into smaller patches. Other than splitting into small patches, could you give me some suggestions for refactoring/splitting files?
Quoted 4 lines
Quoted 2 lines
Best regards,
BenGentle Ping, Any comments?
I coming to this, but I need some additional time. In any case, thanks for posting this and for pinging!
[...]
Kind regards
Uffe
Quoted 16 lines · Ulf Hansson
Quoted 14 lines · Ben Chuang
Hi Uffe and Adrian,
Quoted 10 lines · Ben Chuang
Hi Uffe and Adrian,
These patches support UHS-II and fix GL9755 UHS-II compatibility.
The parts of UHS-II are based on [1][2] and porting to Linux 5.5-rc5. I have seen that Uffe comment that splitting the UHS-II parts into smaller patches. Other than splitting into small patches, could you give me some suggestions for refactoring/splitting files?
Quoted 8 lines
Quoted 4 lines
Quoted 2 lines
Best regards,
BenGentle Ping, Any comments?
I coming to this, but I need some additional time. In any case, thanks for posting this and for pinging!
Thank you for taking the time and pinging back quickly. :-) I will wait patiently for the next reply.
Quoted 4 lines
[...]
Kind regards
Uffe
Best regards,
Ben