brintos

brintos / linux-shallow public Read only

0
0
Text · 18.7 KiB · 9dc5185 Raw
750 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (C) STMicroelectronics 2018 - All Rights Reserved4 * Author: Ludovic.barre@st.com for STMicroelectronics.5 */6#include <linux/bitfield.h>7#include <linux/delay.h>8#include <linux/dma-mapping.h>9#include <linux/iopoll.h>10#include <linux/mmc/host.h>11#include <linux/mmc/card.h>12#include <linux/of_address.h>13#include <linux/reset.h>14#include <linux/scatterlist.h>15#include "mmci.h"16 17#define SDMMC_LLI_BUF_LEN	PAGE_SIZE18 19#define DLYB_CR			0x020#define DLYB_CR_DEN		BIT(0)21#define DLYB_CR_SEN		BIT(1)22 23#define DLYB_CFGR		0x424#define DLYB_CFGR_SEL_MASK	GENMASK(3, 0)25#define DLYB_CFGR_UNIT_MASK	GENMASK(14, 8)26#define DLYB_CFGR_LNG_MASK	GENMASK(27, 16)27#define DLYB_CFGR_LNGF		BIT(31)28 29#define DLYB_NB_DELAY		1130#define DLYB_CFGR_SEL_MAX	(DLYB_NB_DELAY + 1)31#define DLYB_CFGR_UNIT_MAX	12732 33#define DLYB_LNG_TIMEOUT_US	100034#define SDMMC_VSWEND_TIMEOUT_US 1000035 36#define SYSCFG_DLYBSD_CR	0x037#define DLYBSD_CR_EN		BIT(0)38#define DLYBSD_CR_RXTAPSEL_MASK	GENMASK(6, 1)39#define DLYBSD_TAPSEL_NB	3240#define DLYBSD_BYP_EN		BIT(16)41#define DLYBSD_BYP_CMD		GENMASK(21, 17)42#define DLYBSD_ANTIGLITCH_EN	BIT(22)43 44#define SYSCFG_DLYBSD_SR	0x445#define DLYBSD_SR_LOCK		BIT(0)46#define DLYBSD_SR_RXTAPSEL_ACK	BIT(1)47 48#define DLYBSD_TIMEOUT_1S_IN_US	100000049 50struct sdmmc_lli_desc {51	u32 idmalar;52	u32 idmabase;53	u32 idmasize;54};55 56struct sdmmc_idma {57	dma_addr_t sg_dma;58	void *sg_cpu;59	dma_addr_t bounce_dma_addr;60	void *bounce_buf;61	bool use_bounce_buffer;62};63 64struct sdmmc_dlyb;65 66struct sdmmc_tuning_ops {67	int (*dlyb_enable)(struct sdmmc_dlyb *dlyb);68	void (*set_input_ck)(struct sdmmc_dlyb *dlyb);69	int (*tuning_prepare)(struct mmci_host *host);70	int (*set_cfg)(struct sdmmc_dlyb *dlyb, int unit __maybe_unused,71		       int phase, bool sampler __maybe_unused);72};73 74struct sdmmc_dlyb {75	void __iomem *base;76	u32 unit;77	u32 max;78	struct sdmmc_tuning_ops *ops;79};80 81static int sdmmc_idma_validate_data(struct mmci_host *host,82				    struct mmc_data *data)83{84	struct sdmmc_idma *idma = host->dma_priv;85	struct device *dev = mmc_dev(host->mmc);86	struct scatterlist *sg;87	int i;88 89	/*90	 * idma has constraints on idmabase & idmasize for each element91	 * excepted the last element which has no constraint on idmasize92	 */93	idma->use_bounce_buffer = false;94	for_each_sg(data->sg, sg, data->sg_len - 1, i) {95		if (!IS_ALIGNED(sg->offset, sizeof(u32)) ||96		    !IS_ALIGNED(sg->length,97				host->variant->stm32_idmabsize_align)) {98			dev_dbg(mmc_dev(host->mmc),99				"unaligned scatterlist: ofst:%x length:%d\n",100				data->sg->offset, data->sg->length);101			goto use_bounce_buffer;102		}103	}104 105	if (!IS_ALIGNED(sg->offset, sizeof(u32))) {106		dev_dbg(mmc_dev(host->mmc),107			"unaligned last scatterlist: ofst:%x length:%d\n",108			data->sg->offset, data->sg->length);109		goto use_bounce_buffer;110	}111 112	return 0;113 114use_bounce_buffer:115	if (!idma->bounce_buf) {116		idma->bounce_buf = dmam_alloc_coherent(dev,117						       host->mmc->max_req_size,118						       &idma->bounce_dma_addr,119						       GFP_KERNEL);120		if (!idma->bounce_buf) {121			dev_err(dev, "Unable to map allocate DMA bounce buffer.\n");122			return -ENOMEM;123		}124	}125 126	idma->use_bounce_buffer = true;127 128	return 0;129}130 131static int _sdmmc_idma_prep_data(struct mmci_host *host,132				 struct mmc_data *data)133{134	struct sdmmc_idma *idma = host->dma_priv;135 136	if (idma->use_bounce_buffer) {137		if (data->flags & MMC_DATA_WRITE) {138			unsigned int xfer_bytes = data->blksz * data->blocks;139 140			sg_copy_to_buffer(data->sg, data->sg_len,141					  idma->bounce_buf, xfer_bytes);142			dma_wmb();143		}144	} else {145		int n_elem;146 147		n_elem = dma_map_sg(mmc_dev(host->mmc),148				    data->sg,149				    data->sg_len,150				    mmc_get_dma_dir(data));151 152		if (!n_elem) {153			dev_err(mmc_dev(host->mmc), "dma_map_sg failed\n");154			return -EINVAL;155		}156	}157	return 0;158}159 160static int sdmmc_idma_prep_data(struct mmci_host *host,161				struct mmc_data *data, bool next)162{163	/* Check if job is already prepared. */164	if (!next && data->host_cookie == host->next_cookie)165		return 0;166 167	return _sdmmc_idma_prep_data(host, data);168}169 170static void sdmmc_idma_unprep_data(struct mmci_host *host,171				   struct mmc_data *data, int err)172{173	struct sdmmc_idma *idma = host->dma_priv;174 175	if (idma->use_bounce_buffer) {176		if (data->flags & MMC_DATA_READ) {177			unsigned int xfer_bytes = data->blksz * data->blocks;178 179			sg_copy_from_buffer(data->sg, data->sg_len,180					    idma->bounce_buf, xfer_bytes);181		}182	} else {183		dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len,184			     mmc_get_dma_dir(data));185	}186}187 188static int sdmmc_idma_setup(struct mmci_host *host)189{190	struct sdmmc_idma *idma;191	struct device *dev = mmc_dev(host->mmc);192 193	idma = devm_kzalloc(dev, sizeof(*idma), GFP_KERNEL);194	if (!idma)195		return -ENOMEM;196 197	host->dma_priv = idma;198 199	if (host->variant->dma_lli) {200		idma->sg_cpu = dmam_alloc_coherent(dev, SDMMC_LLI_BUF_LEN,201						   &idma->sg_dma, GFP_KERNEL);202		if (!idma->sg_cpu) {203			dev_err(dev, "Failed to alloc IDMA descriptor\n");204			return -ENOMEM;205		}206		host->mmc->max_segs = SDMMC_LLI_BUF_LEN /207			sizeof(struct sdmmc_lli_desc);208		host->mmc->max_seg_size = host->variant->stm32_idmabsize_mask;209 210		host->mmc->max_req_size = SZ_1M;211	} else {212		host->mmc->max_segs = 1;213		host->mmc->max_seg_size = host->mmc->max_req_size;214	}215 216	dma_set_max_seg_size(dev, host->mmc->max_seg_size);217	return 0;218}219 220static int sdmmc_idma_start(struct mmci_host *host, unsigned int *datactrl)221 222{223	struct sdmmc_idma *idma = host->dma_priv;224	struct sdmmc_lli_desc *desc = (struct sdmmc_lli_desc *)idma->sg_cpu;225	struct mmc_data *data = host->data;226	struct scatterlist *sg;227	int i;228 229	host->dma_in_progress = true;230 231	if (!host->variant->dma_lli || data->sg_len == 1 ||232	    idma->use_bounce_buffer) {233		u32 dma_addr;234 235		if (idma->use_bounce_buffer)236			dma_addr = idma->bounce_dma_addr;237		else238			dma_addr = sg_dma_address(data->sg);239 240		writel_relaxed(dma_addr,241			       host->base + MMCI_STM32_IDMABASE0R);242		writel_relaxed(MMCI_STM32_IDMAEN,243			       host->base + MMCI_STM32_IDMACTRLR);244		return 0;245	}246 247	for_each_sg(data->sg, sg, data->sg_len, i) {248		desc[i].idmalar = (i + 1) * sizeof(struct sdmmc_lli_desc);249		desc[i].idmalar |= MMCI_STM32_ULA | MMCI_STM32_ULS250			| MMCI_STM32_ABR;251		desc[i].idmabase = sg_dma_address(sg);252		desc[i].idmasize = sg_dma_len(sg);253	}254 255	/* notice the end of link list */256	desc[data->sg_len - 1].idmalar &= ~MMCI_STM32_ULA;257 258	dma_wmb();259	writel_relaxed(idma->sg_dma, host->base + MMCI_STM32_IDMABAR);260	writel_relaxed(desc[0].idmalar, host->base + MMCI_STM32_IDMALAR);261	writel_relaxed(desc[0].idmabase, host->base + MMCI_STM32_IDMABASE0R);262	writel_relaxed(desc[0].idmasize, host->base + MMCI_STM32_IDMABSIZER);263	writel_relaxed(MMCI_STM32_IDMAEN | MMCI_STM32_IDMALLIEN,264		       host->base + MMCI_STM32_IDMACTRLR);265 266	return 0;267}268 269static void sdmmc_idma_error(struct mmci_host *host)270{271	struct mmc_data *data = host->data;272	struct sdmmc_idma *idma = host->dma_priv;273 274	if (!dma_inprogress(host))275		return;276 277	writel_relaxed(0, host->base + MMCI_STM32_IDMACTRLR);278	host->dma_in_progress = false;279	data->host_cookie = 0;280 281	if (!idma->use_bounce_buffer)282		dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len,283			     mmc_get_dma_dir(data));284}285 286static void sdmmc_idma_finalize(struct mmci_host *host, struct mmc_data *data)287{288	if (!dma_inprogress(host))289		return;290 291	writel_relaxed(0, host->base + MMCI_STM32_IDMACTRLR);292	host->dma_in_progress = false;293 294	if (!data->host_cookie)295		sdmmc_idma_unprep_data(host, data, 0);296}297 298static void mmci_sdmmc_set_clkreg(struct mmci_host *host, unsigned int desired)299{300	unsigned int clk = 0, ddr = 0;301 302	if (host->mmc->ios.timing == MMC_TIMING_MMC_DDR52 ||303	    host->mmc->ios.timing == MMC_TIMING_UHS_DDR50)304		ddr = MCI_STM32_CLK_DDR;305 306	/*307	 * cclk = mclk / (2 * clkdiv)308	 * clkdiv 0 => bypass309	 * in ddr mode bypass is not possible310	 */311	if (desired) {312		if (desired >= host->mclk && !ddr) {313			host->cclk = host->mclk;314		} else {315			clk = DIV_ROUND_UP(host->mclk, 2 * desired);316			if (clk > MCI_STM32_CLK_CLKDIV_MSK)317				clk = MCI_STM32_CLK_CLKDIV_MSK;318			host->cclk = host->mclk / (2 * clk);319		}320	} else {321		/*322		 * while power-on phase the clock can't be define to 0,323		 * Only power-off and power-cyc deactivate the clock.324		 * if desired clock is 0, set max divider325		 */326		clk = MCI_STM32_CLK_CLKDIV_MSK;327		host->cclk = host->mclk / (2 * clk);328	}329 330	/* Set actual clock for debug */331	if (host->mmc->ios.power_mode == MMC_POWER_ON)332		host->mmc->actual_clock = host->cclk;333	else334		host->mmc->actual_clock = 0;335 336	if (host->mmc->ios.bus_width == MMC_BUS_WIDTH_4)337		clk |= MCI_STM32_CLK_WIDEBUS_4;338	if (host->mmc->ios.bus_width == MMC_BUS_WIDTH_8)339		clk |= MCI_STM32_CLK_WIDEBUS_8;340 341	clk |= MCI_STM32_CLK_HWFCEN;342	clk |= host->clk_reg_add;343	clk |= ddr;344 345	if (host->mmc->ios.timing >= MMC_TIMING_UHS_SDR50)346		clk |= MCI_STM32_CLK_BUSSPEED;347 348	mmci_write_clkreg(host, clk);349}350 351static void sdmmc_dlyb_mp15_input_ck(struct sdmmc_dlyb *dlyb)352{353	if (!dlyb || !dlyb->base)354		return;355 356	/* Output clock = Input clock */357	writel_relaxed(0, dlyb->base + DLYB_CR);358}359 360static void mmci_sdmmc_set_pwrreg(struct mmci_host *host, unsigned int pwr)361{362	struct mmc_ios ios = host->mmc->ios;363	struct sdmmc_dlyb *dlyb = host->variant_priv;364 365	/* adds OF options */366	pwr = host->pwr_reg_add;367 368	if (dlyb && dlyb->ops->set_input_ck)369		dlyb->ops->set_input_ck(dlyb);370 371	if (ios.power_mode == MMC_POWER_OFF) {372		/* Only a reset could power-off sdmmc */373		reset_control_assert(host->rst);374		udelay(2);375		reset_control_deassert(host->rst);376 377		/*378		 * Set the SDMMC in Power-cycle state.379		 * This will make that the SDMMC_D[7:0], SDMMC_CMD and SDMMC_CK380		 * are driven low, to prevent the Card from being supplied381		 * through the signal lines.382		 */383		mmci_write_pwrreg(host, MCI_STM32_PWR_CYC | pwr);384	} else if (ios.power_mode == MMC_POWER_ON) {385		/*386		 * After power-off (reset): the irq mask defined in probe387		 * functionis lost388		 * ault irq mask (probe) must be activated389		 */390		writel(MCI_IRQENABLE | host->variant->start_err,391		       host->base + MMCIMASK0);392 393		/* preserves voltage switch bits */394		pwr |= host->pwr_reg & (MCI_STM32_VSWITCHEN |395					MCI_STM32_VSWITCH);396 397		/*398		 * After a power-cycle state, we must set the SDMMC in399		 * Power-off. The SDMMC_D[7:0], SDMMC_CMD and SDMMC_CK are400		 * driven high. Then we can set the SDMMC to Power-on state401		 */402		mmci_write_pwrreg(host, MCI_PWR_OFF | pwr);403		mdelay(1);404		mmci_write_pwrreg(host, MCI_PWR_ON | pwr);405	}406}407 408static u32 sdmmc_get_dctrl_cfg(struct mmci_host *host)409{410	u32 datactrl;411 412	datactrl = mmci_dctrl_blksz(host);413 414	if (host->hw_revision >= 3) {415		u32 thr = 0;416 417		if (host->mmc->ios.timing == MMC_TIMING_UHS_SDR104 ||418		    host->mmc->ios.timing == MMC_TIMING_MMC_HS200) {419			thr = ffs(min_t(unsigned int, host->data->blksz,420					host->variant->fifosize));421			thr = min_t(u32, thr, MMCI_STM32_THR_MASK);422		}423 424		writel_relaxed(thr, host->base + MMCI_STM32_FIFOTHRR);425	}426 427	if (host->mmc->card && mmc_card_sdio(host->mmc->card) &&428	    host->data->blocks == 1)429		datactrl |= MCI_DPSM_STM32_MODE_SDIO;430	else if (host->data->stop && !host->mrq->sbc)431		datactrl |= MCI_DPSM_STM32_MODE_BLOCK_STOP;432	else433		datactrl |= MCI_DPSM_STM32_MODE_BLOCK;434 435	return datactrl;436}437 438static bool sdmmc_busy_complete(struct mmci_host *host, struct mmc_command *cmd,439				u32 status, u32 err_msk)440{441	void __iomem *base = host->base;442	u32 busy_d0, busy_d0end, mask, sdmmc_status;443 444	mask = readl_relaxed(base + MMCIMASK0);445	sdmmc_status = readl_relaxed(base + MMCISTATUS);446	busy_d0end = sdmmc_status & MCI_STM32_BUSYD0END;447	busy_d0 = sdmmc_status & MCI_STM32_BUSYD0;448 449	/* complete if there is an error or busy_d0end */450	if ((status & err_msk) || busy_d0end)451		goto complete;452 453	/*454	 * On response the busy signaling is reflected in the BUSYD0 flag.455	 * if busy_d0 is in-progress we must activate busyd0end interrupt456	 * to wait this completion. Else this request has no busy step.457	 */458	if (busy_d0) {459		if (!host->busy_status) {460			writel_relaxed(mask | host->variant->busy_detect_mask,461				       base + MMCIMASK0);462			host->busy_status = status &463				(MCI_CMDSENT | MCI_CMDRESPEND);464		}465		return false;466	}467 468complete:469	if (host->busy_status) {470		writel_relaxed(mask & ~host->variant->busy_detect_mask,471			       base + MMCIMASK0);472		host->busy_status = 0;473	}474 475	writel_relaxed(host->variant->busy_detect_mask, base + MMCICLEAR);476 477	return true;478}479 480static int sdmmc_dlyb_mp15_enable(struct sdmmc_dlyb *dlyb)481{482	writel_relaxed(DLYB_CR_DEN, dlyb->base + DLYB_CR);483 484	return 0;485}486 487static int sdmmc_dlyb_mp15_set_cfg(struct sdmmc_dlyb *dlyb,488				   int unit, int phase, bool sampler)489{490	u32 cfgr;491 492	writel_relaxed(DLYB_CR_SEN | DLYB_CR_DEN, dlyb->base + DLYB_CR);493 494	cfgr = FIELD_PREP(DLYB_CFGR_UNIT_MASK, unit) |495	       FIELD_PREP(DLYB_CFGR_SEL_MASK, phase);496	writel_relaxed(cfgr, dlyb->base + DLYB_CFGR);497 498	if (!sampler)499		writel_relaxed(DLYB_CR_DEN, dlyb->base + DLYB_CR);500 501	return 0;502}503 504static int sdmmc_dlyb_mp15_prepare(struct mmci_host *host)505{506	struct sdmmc_dlyb *dlyb = host->variant_priv;507	u32 cfgr;508	int i, lng, ret;509 510	for (i = 0; i <= DLYB_CFGR_UNIT_MAX; i++) {511		dlyb->ops->set_cfg(dlyb, i, DLYB_CFGR_SEL_MAX, true);512 513		ret = readl_relaxed_poll_timeout(dlyb->base + DLYB_CFGR, cfgr,514						 (cfgr & DLYB_CFGR_LNGF),515						 1, DLYB_LNG_TIMEOUT_US);516		if (ret) {517			dev_warn(mmc_dev(host->mmc),518				 "delay line cfg timeout unit:%d cfgr:%d\n",519				 i, cfgr);520			continue;521		}522 523		lng = FIELD_GET(DLYB_CFGR_LNG_MASK, cfgr);524		if (lng < BIT(DLYB_NB_DELAY) && lng > 0)525			break;526	}527 528	if (i > DLYB_CFGR_UNIT_MAX)529		return -EINVAL;530 531	dlyb->unit = i;532	dlyb->max = __fls(lng);533 534	return 0;535}536 537static int sdmmc_dlyb_mp25_enable(struct sdmmc_dlyb *dlyb)538{539	u32 cr, sr;540 541	cr = readl_relaxed(dlyb->base + SYSCFG_DLYBSD_CR);542	cr |= DLYBSD_CR_EN;543 544	writel_relaxed(cr, dlyb->base + SYSCFG_DLYBSD_CR);545 546	return readl_relaxed_poll_timeout(dlyb->base + SYSCFG_DLYBSD_SR,547					   sr, sr & DLYBSD_SR_LOCK, 1,548					   DLYBSD_TIMEOUT_1S_IN_US);549}550 551static int sdmmc_dlyb_mp25_set_cfg(struct sdmmc_dlyb *dlyb,552				   int unit __maybe_unused, int phase,553				   bool sampler __maybe_unused)554{555	u32 cr, sr;556 557	cr = readl_relaxed(dlyb->base + SYSCFG_DLYBSD_CR);558	cr &= ~DLYBSD_CR_RXTAPSEL_MASK;559	cr |= FIELD_PREP(DLYBSD_CR_RXTAPSEL_MASK, phase);560 561	writel_relaxed(cr, dlyb->base + SYSCFG_DLYBSD_CR);562 563	return readl_relaxed_poll_timeout(dlyb->base + SYSCFG_DLYBSD_SR,564					  sr, sr & DLYBSD_SR_RXTAPSEL_ACK, 1,565					  DLYBSD_TIMEOUT_1S_IN_US);566}567 568static int sdmmc_dlyb_mp25_prepare(struct mmci_host *host)569{570	struct sdmmc_dlyb *dlyb = host->variant_priv;571 572	dlyb->max = DLYBSD_TAPSEL_NB;573 574	return 0;575}576 577static int sdmmc_dlyb_phase_tuning(struct mmci_host *host, u32 opcode)578{579	struct sdmmc_dlyb *dlyb = host->variant_priv;580	int cur_len = 0, max_len = 0, end_of_len = 0;581	int phase, ret;582 583	for (phase = 0; phase <= dlyb->max; phase++) {584		ret = dlyb->ops->set_cfg(dlyb, dlyb->unit, phase, false);585		if (ret) {586			dev_err(mmc_dev(host->mmc), "tuning config failed\n");587			return ret;588		}589 590		if (mmc_send_tuning(host->mmc, opcode, NULL)) {591			cur_len = 0;592		} else {593			cur_len++;594			if (cur_len > max_len) {595				max_len = cur_len;596				end_of_len = phase;597			}598		}599	}600 601	if (!max_len) {602		dev_err(mmc_dev(host->mmc), "no tuning point found\n");603		return -EINVAL;604	}605 606	if (dlyb->ops->set_input_ck)607		dlyb->ops->set_input_ck(dlyb);608 609	phase = end_of_len - max_len / 2;610	ret = dlyb->ops->set_cfg(dlyb, dlyb->unit, phase, false);611	if (ret) {612		dev_err(mmc_dev(host->mmc), "tuning reconfig failed\n");613		return ret;614	}615 616	dev_dbg(mmc_dev(host->mmc), "unit:%d max_dly:%d phase:%d\n",617		dlyb->unit, dlyb->max, phase);618 619	return 0;620}621 622static int sdmmc_execute_tuning(struct mmc_host *mmc, u32 opcode)623{624	struct mmci_host *host = mmc_priv(mmc);625	struct sdmmc_dlyb *dlyb = host->variant_priv;626	u32 clk;627	int ret;628 629	if ((host->mmc->ios.timing != MMC_TIMING_UHS_SDR104 &&630	     host->mmc->ios.timing != MMC_TIMING_MMC_HS200) ||631	    host->mmc->actual_clock <= 50000000)632		return 0;633 634	if (!dlyb || !dlyb->base)635		return -EINVAL;636 637	ret = dlyb->ops->dlyb_enable(dlyb);638	if (ret)639		return ret;640 641	/*642	 * SDMMC_FBCK is selected when an external Delay Block is needed643	 * with SDR104 or HS200.644	 */645	clk = host->clk_reg;646	clk &= ~MCI_STM32_CLK_SEL_MSK;647	clk |= MCI_STM32_CLK_SELFBCK;648	mmci_write_clkreg(host, clk);649 650	ret = dlyb->ops->tuning_prepare(host);651	if (ret)652		return ret;653 654	return sdmmc_dlyb_phase_tuning(host, opcode);655}656 657static void sdmmc_pre_sig_volt_vswitch(struct mmci_host *host)658{659	/* clear the voltage switch completion flag */660	writel_relaxed(MCI_STM32_VSWENDC, host->base + MMCICLEAR);661	/* enable Voltage switch procedure */662	mmci_write_pwrreg(host, host->pwr_reg | MCI_STM32_VSWITCHEN);663}664 665static int sdmmc_post_sig_volt_switch(struct mmci_host *host,666				      struct mmc_ios *ios)667{668	unsigned long flags;669	u32 status;670	int ret = 0;671 672	spin_lock_irqsave(&host->lock, flags);673	if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180 &&674	    host->pwr_reg & MCI_STM32_VSWITCHEN) {675		mmci_write_pwrreg(host, host->pwr_reg | MCI_STM32_VSWITCH);676		spin_unlock_irqrestore(&host->lock, flags);677 678		/* wait voltage switch completion while 10ms */679		ret = readl_relaxed_poll_timeout(host->base + MMCISTATUS,680						 status,681						 (status & MCI_STM32_VSWEND),682						 10, SDMMC_VSWEND_TIMEOUT_US);683 684		writel_relaxed(MCI_STM32_VSWENDC | MCI_STM32_CKSTOPC,685			       host->base + MMCICLEAR);686		spin_lock_irqsave(&host->lock, flags);687		mmci_write_pwrreg(host, host->pwr_reg &688				  ~(MCI_STM32_VSWITCHEN | MCI_STM32_VSWITCH));689	}690	spin_unlock_irqrestore(&host->lock, flags);691 692	return ret;693}694 695static struct mmci_host_ops sdmmc_variant_ops = {696	.validate_data = sdmmc_idma_validate_data,697	.prep_data = sdmmc_idma_prep_data,698	.unprep_data = sdmmc_idma_unprep_data,699	.get_datactrl_cfg = sdmmc_get_dctrl_cfg,700	.dma_setup = sdmmc_idma_setup,701	.dma_start = sdmmc_idma_start,702	.dma_finalize = sdmmc_idma_finalize,703	.dma_error = sdmmc_idma_error,704	.set_clkreg = mmci_sdmmc_set_clkreg,705	.set_pwrreg = mmci_sdmmc_set_pwrreg,706	.busy_complete = sdmmc_busy_complete,707	.pre_sig_volt_switch = sdmmc_pre_sig_volt_vswitch,708	.post_sig_volt_switch = sdmmc_post_sig_volt_switch,709};710 711static struct sdmmc_tuning_ops dlyb_tuning_mp15_ops = {712	.dlyb_enable = sdmmc_dlyb_mp15_enable,713	.set_input_ck = sdmmc_dlyb_mp15_input_ck,714	.tuning_prepare = sdmmc_dlyb_mp15_prepare,715	.set_cfg = sdmmc_dlyb_mp15_set_cfg,716};717 718static struct sdmmc_tuning_ops dlyb_tuning_mp25_ops = {719	.dlyb_enable = sdmmc_dlyb_mp25_enable,720	.tuning_prepare = sdmmc_dlyb_mp25_prepare,721	.set_cfg = sdmmc_dlyb_mp25_set_cfg,722};723 724void sdmmc_variant_init(struct mmci_host *host)725{726	struct device_node *np = host->mmc->parent->of_node;727	void __iomem *base_dlyb;728	struct sdmmc_dlyb *dlyb;729 730	host->ops = &sdmmc_variant_ops;731	host->pwr_reg = readl_relaxed(host->base + MMCIPOWER);732 733	base_dlyb = devm_of_iomap(mmc_dev(host->mmc), np, 1, NULL);734	if (IS_ERR(base_dlyb))735		return;736 737	dlyb = devm_kzalloc(mmc_dev(host->mmc), sizeof(*dlyb), GFP_KERNEL);738	if (!dlyb)739		return;740 741	dlyb->base = base_dlyb;742	if (of_device_is_compatible(np, "st,stm32mp25-sdmmc2"))743		dlyb->ops = &dlyb_tuning_mp25_ops;744	else745		dlyb->ops = &dlyb_tuning_mp15_ops;746 747	host->variant_priv = dlyb;748	host->mmc_ops->execute_tuning = sdmmc_execute_tuning;749}750