xref: /openbmc/linux/drivers/mmc/host/sdhci-st.c (revision b1284d7c)
11802d0beSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2f52d9c4fSPeter Griffin /*
3f52d9c4fSPeter Griffin  * Support for SDHCI on STMicroelectronics SoCs
4f52d9c4fSPeter Griffin  *
5f52d9c4fSPeter Griffin  * Copyright (C) 2014 STMicroelectronics Ltd
6f52d9c4fSPeter Griffin  * Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
7f52d9c4fSPeter Griffin  * Contributors: Peter Griffin <peter.griffin@linaro.org>
8f52d9c4fSPeter Griffin  *
9f52d9c4fSPeter Griffin  * Based on sdhci-cns3xxx.c
10f52d9c4fSPeter Griffin  */
11f52d9c4fSPeter Griffin 
12f52d9c4fSPeter Griffin #include <linux/io.h>
13f52d9c4fSPeter Griffin #include <linux/of.h>
14f52d9c4fSPeter Griffin #include <linux/module.h>
15f52d9c4fSPeter Griffin #include <linux/err.h>
16f52d9c4fSPeter Griffin #include <linux/mmc/host.h>
17406c2431SPeter Griffin #include <linux/reset.h>
18f52d9c4fSPeter Griffin #include "sdhci-pltfm.h"
19f52d9c4fSPeter Griffin 
20406c2431SPeter Griffin struct st_mmc_platform_data {
21406c2431SPeter Griffin 	struct  reset_control *rstc;
223ae50f45SLee Jones 	struct  clk *icnclk;
23406c2431SPeter Griffin 	void __iomem *top_ioaddr;
24406c2431SPeter Griffin };
25406c2431SPeter Griffin 
268bef7178SPeter Griffin /* MMCSS glue logic to setup the HC on some ST SoCs (e.g. STiH407 family) */
278bef7178SPeter Griffin 
288bef7178SPeter Griffin #define ST_MMC_CCONFIG_REG_1		0x400
298bef7178SPeter Griffin #define ST_MMC_CCONFIG_TIMEOUT_CLK_UNIT	BIT(24)
308bef7178SPeter Griffin #define ST_MMC_CCONFIG_TIMEOUT_CLK_FREQ	BIT(12)
318bef7178SPeter Griffin #define ST_MMC_CCONFIG_TUNING_COUNT_DEFAULT	BIT(8)
328bef7178SPeter Griffin #define ST_MMC_CCONFIG_ASYNC_WAKEUP	BIT(0)
338bef7178SPeter Griffin #define ST_MMC_CCONFIG_1_DEFAULT	\
348bef7178SPeter Griffin 				((ST_MMC_CCONFIG_TIMEOUT_CLK_UNIT) | \
358bef7178SPeter Griffin 				 (ST_MMC_CCONFIG_TIMEOUT_CLK_FREQ) | \
368bef7178SPeter Griffin 				 (ST_MMC_CCONFIG_TUNING_COUNT_DEFAULT))
378bef7178SPeter Griffin 
388bef7178SPeter Griffin #define ST_MMC_CCONFIG_REG_2		0x404
398bef7178SPeter Griffin #define ST_MMC_CCONFIG_HIGH_SPEED	BIT(28)
408bef7178SPeter Griffin #define ST_MMC_CCONFIG_ADMA2		BIT(24)
418bef7178SPeter Griffin #define ST_MMC_CCONFIG_8BIT		BIT(20)
428bef7178SPeter Griffin #define ST_MMC_CCONFIG_MAX_BLK_LEN	16
438bef7178SPeter Griffin #define  MAX_BLK_LEN_1024		1
448bef7178SPeter Griffin #define  MAX_BLK_LEN_2048		2
458bef7178SPeter Griffin #define BASE_CLK_FREQ_200		0xc8
468bef7178SPeter Griffin #define BASE_CLK_FREQ_100		0x64
478bef7178SPeter Griffin #define BASE_CLK_FREQ_50		0x32
488bef7178SPeter Griffin #define ST_MMC_CCONFIG_2_DEFAULT \
498bef7178SPeter Griffin 	(ST_MMC_CCONFIG_HIGH_SPEED | ST_MMC_CCONFIG_ADMA2 | \
508bef7178SPeter Griffin 	 ST_MMC_CCONFIG_8BIT | \
518bef7178SPeter Griffin 	 (MAX_BLK_LEN_1024 << ST_MMC_CCONFIG_MAX_BLK_LEN))
528bef7178SPeter Griffin 
538bef7178SPeter Griffin #define ST_MMC_CCONFIG_REG_3			0x408
548bef7178SPeter Griffin #define ST_MMC_CCONFIG_EMMC_SLOT_TYPE		BIT(28)
558bef7178SPeter Griffin #define ST_MMC_CCONFIG_64BIT			BIT(24)
568bef7178SPeter Griffin #define ST_MMC_CCONFIG_ASYNCH_INTR_SUPPORT	BIT(20)
578bef7178SPeter Griffin #define ST_MMC_CCONFIG_1P8_VOLT			BIT(16)
588bef7178SPeter Griffin #define ST_MMC_CCONFIG_3P0_VOLT			BIT(12)
598bef7178SPeter Griffin #define ST_MMC_CCONFIG_3P3_VOLT			BIT(8)
608bef7178SPeter Griffin #define ST_MMC_CCONFIG_SUSP_RES_SUPPORT		BIT(4)
618bef7178SPeter Griffin #define ST_MMC_CCONFIG_SDMA			BIT(0)
628bef7178SPeter Griffin #define ST_MMC_CCONFIG_3_DEFAULT	\
638bef7178SPeter Griffin 			 (ST_MMC_CCONFIG_ASYNCH_INTR_SUPPORT	| \
648bef7178SPeter Griffin 			  ST_MMC_CCONFIG_3P3_VOLT		| \
658bef7178SPeter Griffin 			  ST_MMC_CCONFIG_SUSP_RES_SUPPORT	| \
668bef7178SPeter Griffin 			  ST_MMC_CCONFIG_SDMA)
678bef7178SPeter Griffin 
688bef7178SPeter Griffin #define ST_MMC_CCONFIG_REG_4	0x40c
698bef7178SPeter Griffin #define ST_MMC_CCONFIG_D_DRIVER	BIT(20)
708bef7178SPeter Griffin #define ST_MMC_CCONFIG_C_DRIVER	BIT(16)
718bef7178SPeter Griffin #define ST_MMC_CCONFIG_A_DRIVER	BIT(12)
728bef7178SPeter Griffin #define ST_MMC_CCONFIG_DDR50	BIT(8)
738bef7178SPeter Griffin #define ST_MMC_CCONFIG_SDR104	BIT(4)
748bef7178SPeter Griffin #define ST_MMC_CCONFIG_SDR50	BIT(0)
758bef7178SPeter Griffin #define ST_MMC_CCONFIG_4_DEFAULT	0
768bef7178SPeter Griffin 
778bef7178SPeter Griffin #define ST_MMC_CCONFIG_REG_5		0x410
788bef7178SPeter Griffin #define ST_MMC_CCONFIG_TUNING_FOR_SDR50	BIT(8)
798bef7178SPeter Griffin #define RETUNING_TIMER_CNT_MAX		0xf
808bef7178SPeter Griffin #define ST_MMC_CCONFIG_5_DEFAULT	0
818bef7178SPeter Griffin 
828bef7178SPeter Griffin /* I/O configuration for Arasan IP */
838bef7178SPeter Griffin #define ST_MMC_GP_OUTPUT	0x450
848bef7178SPeter Griffin #define ST_MMC_GP_OUTPUT_CD	BIT(12)
858bef7178SPeter Griffin 
868bef7178SPeter Griffin #define ST_MMC_STATUS_R		0x460
878bef7178SPeter Griffin 
888bef7178SPeter Griffin #define ST_TOP_MMC_DLY_FIX_OFF(x)	(x - 0x8)
898bef7178SPeter Griffin 
908bef7178SPeter Griffin /* TOP config registers to manage static and dynamic delay */
918bef7178SPeter Griffin #define ST_TOP_MMC_TX_CLK_DLY			ST_TOP_MMC_DLY_FIX_OFF(0x8)
928bef7178SPeter Griffin #define ST_TOP_MMC_RX_CLK_DLY			ST_TOP_MMC_DLY_FIX_OFF(0xc)
938bef7178SPeter Griffin /* MMC delay control register */
948bef7178SPeter Griffin #define ST_TOP_MMC_DLY_CTRL			ST_TOP_MMC_DLY_FIX_OFF(0x18)
958bef7178SPeter Griffin #define ST_TOP_MMC_DLY_CTRL_DLL_BYPASS_CMD	BIT(0)
968bef7178SPeter Griffin #define ST_TOP_MMC_DLY_CTRL_DLL_BYPASS_PH_SEL	BIT(1)
978bef7178SPeter Griffin #define ST_TOP_MMC_DLY_CTRL_TX_DLL_ENABLE	BIT(8)
988bef7178SPeter Griffin #define ST_TOP_MMC_DLY_CTRL_RX_DLL_ENABLE	BIT(9)
998bef7178SPeter Griffin #define ST_TOP_MMC_DLY_CTRL_ATUNE_NOT_CFG_DLY	BIT(10)
1008bef7178SPeter Griffin #define ST_TOP_MMC_START_DLL_LOCK		BIT(11)
1018bef7178SPeter Griffin 
1028bef7178SPeter Griffin /* register to provide the phase-shift value for DLL */
1038bef7178SPeter Griffin #define ST_TOP_MMC_TX_DLL_STEP_DLY		ST_TOP_MMC_DLY_FIX_OFF(0x1c)
1048bef7178SPeter Griffin #define ST_TOP_MMC_RX_DLL_STEP_DLY		ST_TOP_MMC_DLY_FIX_OFF(0x20)
1058bef7178SPeter Griffin #define ST_TOP_MMC_RX_CMD_STEP_DLY		ST_TOP_MMC_DLY_FIX_OFF(0x24)
1068bef7178SPeter Griffin 
1078bef7178SPeter Griffin /* phase shift delay on the tx clk 2.188ns */
1088bef7178SPeter Griffin #define ST_TOP_MMC_TX_DLL_STEP_DLY_VALID	0x6
1098bef7178SPeter Griffin 
1108bef7178SPeter Griffin #define ST_TOP_MMC_DLY_MAX			0xf
1118bef7178SPeter Griffin 
1128bef7178SPeter Griffin #define ST_TOP_MMC_DYN_DLY_CONF	\
1138bef7178SPeter Griffin 		(ST_TOP_MMC_DLY_CTRL_TX_DLL_ENABLE | \
1148bef7178SPeter Griffin 		 ST_TOP_MMC_DLY_CTRL_ATUNE_NOT_CFG_DLY | \
1158bef7178SPeter Griffin 		 ST_TOP_MMC_START_DLL_LOCK)
1168bef7178SPeter Griffin 
117bfa44804SPeter Griffin /*
118bfa44804SPeter Griffin  * For clock speeds greater than 90MHz, we need to check that the
119bfa44804SPeter Griffin  * DLL procedure has finished before switching to ultra-speed modes.
120bfa44804SPeter Griffin  */
121bfa44804SPeter Griffin #define	CLK_TO_CHECK_DLL_LOCK	90000000
122bfa44804SPeter Griffin 
st_mmcss_set_static_delay(void __iomem * ioaddr)123bfa44804SPeter Griffin static inline void st_mmcss_set_static_delay(void __iomem *ioaddr)
124bfa44804SPeter Griffin {
125bfa44804SPeter Griffin 	if (!ioaddr)
126bfa44804SPeter Griffin 		return;
127bfa44804SPeter Griffin 
128bfa44804SPeter Griffin 	writel_relaxed(0x0, ioaddr + ST_TOP_MMC_DLY_CTRL);
129bfa44804SPeter Griffin 	writel_relaxed(ST_TOP_MMC_DLY_MAX,
130bfa44804SPeter Griffin 			ioaddr + ST_TOP_MMC_TX_CLK_DLY);
131bfa44804SPeter Griffin }
132bfa44804SPeter Griffin 
1332053812fSPeter Griffin /**
1342053812fSPeter Griffin  * st_mmcss_cconfig: configure the Arasan HC inside the flashSS.
1352053812fSPeter Griffin  * @np: dt device node.
1362053812fSPeter Griffin  * @host: sdhci host
1372053812fSPeter Griffin  * Description: this function is to configure the Arasan host controller.
1382053812fSPeter Griffin  * On some ST SoCs, i.e. STiH407 family, the MMC devices inside a dedicated
1392053812fSPeter Griffin  * flashSS sub-system which needs to be configured to be compliant to eMMC 4.5
1402053812fSPeter Griffin  * or eMMC4.3.  This has to be done before registering the sdhci host.
1412053812fSPeter Griffin  */
st_mmcss_cconfig(struct device_node * np,struct sdhci_host * host)1422053812fSPeter Griffin static void st_mmcss_cconfig(struct device_node *np, struct sdhci_host *host)
1432053812fSPeter Griffin {
1442053812fSPeter Griffin 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
1452053812fSPeter Griffin 	struct mmc_host *mhost = host->mmc;
1462053812fSPeter Griffin 	u32 cconf2, cconf3, cconf4, cconf5;
1472053812fSPeter Griffin 
1482053812fSPeter Griffin 	if (!of_device_is_compatible(np, "st,sdhci-stih407"))
1492053812fSPeter Griffin 		return;
1502053812fSPeter Griffin 
1512053812fSPeter Griffin 	cconf2 = ST_MMC_CCONFIG_2_DEFAULT;
1522053812fSPeter Griffin 	cconf3 = ST_MMC_CCONFIG_3_DEFAULT;
1532053812fSPeter Griffin 	cconf4 = ST_MMC_CCONFIG_4_DEFAULT;
1542053812fSPeter Griffin 	cconf5 = ST_MMC_CCONFIG_5_DEFAULT;
1552053812fSPeter Griffin 
1562053812fSPeter Griffin 	writel_relaxed(ST_MMC_CCONFIG_1_DEFAULT,
1572053812fSPeter Griffin 			host->ioaddr + ST_MMC_CCONFIG_REG_1);
1582053812fSPeter Griffin 
1592053812fSPeter Griffin 	/* Set clock frequency, default to 50MHz if max-frequency is not
1602053812fSPeter Griffin 	 * provided */
1612053812fSPeter Griffin 
1622053812fSPeter Griffin 	switch (mhost->f_max) {
1632053812fSPeter Griffin 	case 200000000:
1642053812fSPeter Griffin 		clk_set_rate(pltfm_host->clk, mhost->f_max);
1652053812fSPeter Griffin 		cconf2 |= BASE_CLK_FREQ_200;
1662053812fSPeter Griffin 		break;
1672053812fSPeter Griffin 	case 100000000:
1682053812fSPeter Griffin 		clk_set_rate(pltfm_host->clk, mhost->f_max);
1692053812fSPeter Griffin 		cconf2 |= BASE_CLK_FREQ_100;
1702053812fSPeter Griffin 		break;
1712053812fSPeter Griffin 	default:
1722053812fSPeter Griffin 		clk_set_rate(pltfm_host->clk, 50000000);
1732053812fSPeter Griffin 		cconf2 |= BASE_CLK_FREQ_50;
1742053812fSPeter Griffin 	}
1752053812fSPeter Griffin 
1762053812fSPeter Griffin 	writel_relaxed(cconf2, host->ioaddr + ST_MMC_CCONFIG_REG_2);
1772053812fSPeter Griffin 
178860951c5SJaehoon Chung 	if (!mmc_card_is_removable(mhost))
1792053812fSPeter Griffin 		cconf3 |= ST_MMC_CCONFIG_EMMC_SLOT_TYPE;
1802053812fSPeter Griffin 	else
1812053812fSPeter Griffin 		/* CARD _D ET_CTRL */
1822053812fSPeter Griffin 		writel_relaxed(ST_MMC_GP_OUTPUT_CD,
1832053812fSPeter Griffin 				host->ioaddr + ST_MMC_GP_OUTPUT);
1842053812fSPeter Griffin 
1852053812fSPeter Griffin 	if (mhost->caps & MMC_CAP_UHS_SDR50) {
1862053812fSPeter Griffin 		/* use 1.8V */
1872053812fSPeter Griffin 		cconf3 |= ST_MMC_CCONFIG_1P8_VOLT;
1882053812fSPeter Griffin 		cconf4 |= ST_MMC_CCONFIG_SDR50;
1892053812fSPeter Griffin 		/* Use tuning */
1902053812fSPeter Griffin 		cconf5 |= ST_MMC_CCONFIG_TUNING_FOR_SDR50;
1912053812fSPeter Griffin 		/* Max timeout for retuning */
1922053812fSPeter Griffin 		cconf5 |= RETUNING_TIMER_CNT_MAX;
1932053812fSPeter Griffin 	}
1942053812fSPeter Griffin 
1952053812fSPeter Griffin 	if (mhost->caps & MMC_CAP_UHS_SDR104) {
1962053812fSPeter Griffin 		/*
1972053812fSPeter Griffin 		 * SDR104 implies the HC can support HS200 mode, so
1982053812fSPeter Griffin 		 * it's mandatory to use 1.8V
1992053812fSPeter Griffin 		 */
2002053812fSPeter Griffin 		cconf3 |= ST_MMC_CCONFIG_1P8_VOLT;
2012053812fSPeter Griffin 		cconf4 |= ST_MMC_CCONFIG_SDR104;
2022053812fSPeter Griffin 		/* Max timeout for retuning */
2032053812fSPeter Griffin 		cconf5 |= RETUNING_TIMER_CNT_MAX;
2042053812fSPeter Griffin 	}
2052053812fSPeter Griffin 
2062053812fSPeter Griffin 	if (mhost->caps & MMC_CAP_UHS_DDR50)
2072053812fSPeter Griffin 		cconf4 |= ST_MMC_CCONFIG_DDR50;
2082053812fSPeter Griffin 
2092053812fSPeter Griffin 	writel_relaxed(cconf3, host->ioaddr + ST_MMC_CCONFIG_REG_3);
2102053812fSPeter Griffin 	writel_relaxed(cconf4, host->ioaddr + ST_MMC_CCONFIG_REG_4);
2112053812fSPeter Griffin 	writel_relaxed(cconf5, host->ioaddr + ST_MMC_CCONFIG_REG_5);
2122053812fSPeter Griffin }
2132053812fSPeter Griffin 
st_mmcss_set_dll(void __iomem * ioaddr)214bfa44804SPeter Griffin static inline void st_mmcss_set_dll(void __iomem *ioaddr)
215bfa44804SPeter Griffin {
216bfa44804SPeter Griffin 	if (!ioaddr)
217bfa44804SPeter Griffin 		return;
218bfa44804SPeter Griffin 
219bfa44804SPeter Griffin 	writel_relaxed(ST_TOP_MMC_DYN_DLY_CONF,	ioaddr + ST_TOP_MMC_DLY_CTRL);
220bfa44804SPeter Griffin 	writel_relaxed(ST_TOP_MMC_TX_DLL_STEP_DLY_VALID,
221bfa44804SPeter Griffin 			ioaddr + ST_TOP_MMC_TX_DLL_STEP_DLY);
222bfa44804SPeter Griffin }
223bfa44804SPeter Griffin 
st_mmcss_lock_dll(void __iomem * ioaddr)224bfa44804SPeter Griffin static int st_mmcss_lock_dll(void __iomem *ioaddr)
225bfa44804SPeter Griffin {
226bfa44804SPeter Griffin 	unsigned long curr, value;
227bfa44804SPeter Griffin 	unsigned long finish = jiffies + HZ;
228bfa44804SPeter Griffin 
229bfa44804SPeter Griffin 	/* Checks if the DLL procedure is finished */
230bfa44804SPeter Griffin 	do {
231bfa44804SPeter Griffin 		curr = jiffies;
232bfa44804SPeter Griffin 		value = readl(ioaddr + ST_MMC_STATUS_R);
233bfa44804SPeter Griffin 		if (value & 0x1)
234bfa44804SPeter Griffin 			return 0;
235bfa44804SPeter Griffin 
236bfa44804SPeter Griffin 		cpu_relax();
237bfa44804SPeter Griffin 	} while (!time_after_eq(curr, finish));
238bfa44804SPeter Griffin 
239bfa44804SPeter Griffin 	return -EBUSY;
240bfa44804SPeter Griffin }
241bfa44804SPeter Griffin 
sdhci_st_set_dll_for_clock(struct sdhci_host * host)242bfa44804SPeter Griffin static int sdhci_st_set_dll_for_clock(struct sdhci_host *host)
243bfa44804SPeter Griffin {
244bfa44804SPeter Griffin 	int ret = 0;
245bfa44804SPeter Griffin 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
24615316752SJisheng Zhang 	struct st_mmc_platform_data *pdata = sdhci_pltfm_priv(pltfm_host);
247bfa44804SPeter Griffin 
248bfa44804SPeter Griffin 	if (host->clock > CLK_TO_CHECK_DLL_LOCK) {
249bfa44804SPeter Griffin 		st_mmcss_set_dll(pdata->top_ioaddr);
250bfa44804SPeter Griffin 		ret = st_mmcss_lock_dll(host->ioaddr);
251bfa44804SPeter Griffin 	}
252bfa44804SPeter Griffin 
253bfa44804SPeter Griffin 	return ret;
254bfa44804SPeter Griffin }
255bfa44804SPeter Griffin 
sdhci_st_set_uhs_signaling(struct sdhci_host * host,unsigned int uhs)256cf48d32eSPeter Griffin static void sdhci_st_set_uhs_signaling(struct sdhci_host *host,
257cf48d32eSPeter Griffin 					unsigned int uhs)
258cf48d32eSPeter Griffin {
259cf48d32eSPeter Griffin 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
26015316752SJisheng Zhang 	struct st_mmc_platform_data *pdata = sdhci_pltfm_priv(pltfm_host);
261cf48d32eSPeter Griffin 	u16 ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
262cf48d32eSPeter Griffin 	int ret = 0;
263cf48d32eSPeter Griffin 
264cf48d32eSPeter Griffin 	/* Select Bus Speed Mode for host */
265cf48d32eSPeter Griffin 	ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
266cf48d32eSPeter Griffin 	switch (uhs) {
267cf48d32eSPeter Griffin 	/*
268cf48d32eSPeter Griffin 	 * Set V18_EN -- UHS modes do not work without this.
269cf48d32eSPeter Griffin 	 * does not change signaling voltage
270cf48d32eSPeter Griffin 	 */
271cf48d32eSPeter Griffin 
272cf48d32eSPeter Griffin 	case MMC_TIMING_UHS_SDR12:
273cf48d32eSPeter Griffin 		st_mmcss_set_static_delay(pdata->top_ioaddr);
274cf48d32eSPeter Griffin 		ctrl_2 |= SDHCI_CTRL_UHS_SDR12 | SDHCI_CTRL_VDD_180;
275cf48d32eSPeter Griffin 		break;
276cf48d32eSPeter Griffin 	case MMC_TIMING_UHS_SDR25:
277cf48d32eSPeter Griffin 		st_mmcss_set_static_delay(pdata->top_ioaddr);
278cf48d32eSPeter Griffin 		ctrl_2 |= SDHCI_CTRL_UHS_SDR25 | SDHCI_CTRL_VDD_180;
279cf48d32eSPeter Griffin 		break;
280cf48d32eSPeter Griffin 	case MMC_TIMING_UHS_SDR50:
281cf48d32eSPeter Griffin 		st_mmcss_set_static_delay(pdata->top_ioaddr);
282cf48d32eSPeter Griffin 		ctrl_2 |= SDHCI_CTRL_UHS_SDR50 | SDHCI_CTRL_VDD_180;
283cf48d32eSPeter Griffin 		ret = sdhci_st_set_dll_for_clock(host);
284cf48d32eSPeter Griffin 		break;
285cf48d32eSPeter Griffin 	case MMC_TIMING_UHS_SDR104:
286cf48d32eSPeter Griffin 	case MMC_TIMING_MMC_HS200:
287cf48d32eSPeter Griffin 		st_mmcss_set_static_delay(pdata->top_ioaddr);
288cf48d32eSPeter Griffin 		ctrl_2 |= SDHCI_CTRL_UHS_SDR104 | SDHCI_CTRL_VDD_180;
289cf48d32eSPeter Griffin 		ret =  sdhci_st_set_dll_for_clock(host);
290cf48d32eSPeter Griffin 		break;
291cf48d32eSPeter Griffin 	case MMC_TIMING_UHS_DDR50:
292cf48d32eSPeter Griffin 	case MMC_TIMING_MMC_DDR52:
293cf48d32eSPeter Griffin 		st_mmcss_set_static_delay(pdata->top_ioaddr);
294cf48d32eSPeter Griffin 		ctrl_2 |= SDHCI_CTRL_UHS_DDR50 | SDHCI_CTRL_VDD_180;
295cf48d32eSPeter Griffin 		break;
296cf48d32eSPeter Griffin 	}
297cf48d32eSPeter Griffin 
298cf48d32eSPeter Griffin 	if (ret)
299cf48d32eSPeter Griffin 		dev_warn(mmc_dev(host->mmc), "Error setting dll for clock "
300cf48d32eSPeter Griffin 						"(uhs %d)\n", uhs);
301cf48d32eSPeter Griffin 
302cf48d32eSPeter Griffin 	dev_dbg(mmc_dev(host->mmc), "uhs %d, ctrl_2 %04X\n", uhs, ctrl_2);
303cf48d32eSPeter Griffin 
304cf48d32eSPeter Griffin 	sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
305cf48d32eSPeter Griffin }
306bfa44804SPeter Griffin 
sdhci_st_readl(struct sdhci_host * host,int reg)307f52d9c4fSPeter Griffin static u32 sdhci_st_readl(struct sdhci_host *host, int reg)
308f52d9c4fSPeter Griffin {
309f52d9c4fSPeter Griffin 	u32 ret;
310f52d9c4fSPeter Griffin 
311f52d9c4fSPeter Griffin 	switch (reg) {
312f52d9c4fSPeter Griffin 	case SDHCI_CAPABILITIES:
313f52d9c4fSPeter Griffin 		ret = readl_relaxed(host->ioaddr + reg);
314f52d9c4fSPeter Griffin 		/* Support 3.3V and 1.8V */
315f52d9c4fSPeter Griffin 		ret &= ~SDHCI_CAN_VDD_300;
316f52d9c4fSPeter Griffin 		break;
317f52d9c4fSPeter Griffin 	default:
318f52d9c4fSPeter Griffin 		ret = readl_relaxed(host->ioaddr + reg);
319f52d9c4fSPeter Griffin 	}
320f52d9c4fSPeter Griffin 	return ret;
321f52d9c4fSPeter Griffin }
322f52d9c4fSPeter Griffin 
323f52d9c4fSPeter Griffin static const struct sdhci_ops sdhci_st_ops = {
324f52d9c4fSPeter Griffin 	.get_max_clock = sdhci_pltfm_clk_get_max_clock,
325f52d9c4fSPeter Griffin 	.set_clock = sdhci_set_clock,
326f52d9c4fSPeter Griffin 	.set_bus_width = sdhci_set_bus_width,
327f52d9c4fSPeter Griffin 	.read_l = sdhci_st_readl,
328f52d9c4fSPeter Griffin 	.reset = sdhci_reset,
329cf48d32eSPeter Griffin 	.set_uhs_signaling = sdhci_st_set_uhs_signaling,
330f52d9c4fSPeter Griffin };
331f52d9c4fSPeter Griffin 
332f52d9c4fSPeter Griffin static const struct sdhci_pltfm_data sdhci_st_pdata = {
333f52d9c4fSPeter Griffin 	.ops = &sdhci_st_ops,
334f52d9c4fSPeter Griffin 	.quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC |
3354e187d31SPeter Griffin 		SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN |
3364e187d31SPeter Griffin 		SDHCI_QUIRK_NO_HISPD_BIT,
3374e187d31SPeter Griffin 	.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
3384e187d31SPeter Griffin 		SDHCI_QUIRK2_STOP_WITH_TC,
339f52d9c4fSPeter Griffin };
340f52d9c4fSPeter Griffin 
341f52d9c4fSPeter Griffin 
sdhci_st_probe(struct platform_device * pdev)342f52d9c4fSPeter Griffin static int sdhci_st_probe(struct platform_device *pdev)
343f52d9c4fSPeter Griffin {
3442053812fSPeter Griffin 	struct device_node *np = pdev->dev.of_node;
345f52d9c4fSPeter Griffin 	struct sdhci_host *host;
346406c2431SPeter Griffin 	struct st_mmc_platform_data *pdata;
347f52d9c4fSPeter Griffin 	struct sdhci_pltfm_host *pltfm_host;
3483ae50f45SLee Jones 	struct clk *clk, *icnclk;
349f52d9c4fSPeter Griffin 	int ret = 0;
350f52d9c4fSPeter Griffin 	u16 host_version;
35115316752SJisheng Zhang 	struct reset_control *rstc;
352f52d9c4fSPeter Griffin 
353f52d9c4fSPeter Griffin 	clk =  devm_clk_get(&pdev->dev, "mmc");
354f52d9c4fSPeter Griffin 	if (IS_ERR(clk)) {
355f52d9c4fSPeter Griffin 		dev_err(&pdev->dev, "Peripheral clk not found\n");
356f52d9c4fSPeter Griffin 		return PTR_ERR(clk);
357f52d9c4fSPeter Griffin 	}
358f52d9c4fSPeter Griffin 
3593ae50f45SLee Jones 	/* ICN clock isn't compulsory, but use it if it's provided. */
3603ae50f45SLee Jones 	icnclk = devm_clk_get(&pdev->dev, "icn");
3613ae50f45SLee Jones 	if (IS_ERR(icnclk))
3623ae50f45SLee Jones 		icnclk = NULL;
3633ae50f45SLee Jones 
36495211a98SPhilipp Zabel 	rstc = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL);
36515316752SJisheng Zhang 	if (IS_ERR(rstc))
36695211a98SPhilipp Zabel 		return PTR_ERR(rstc);
36715316752SJisheng Zhang 	reset_control_deassert(rstc);
368406c2431SPeter Griffin 
36915316752SJisheng Zhang 	host = sdhci_pltfm_init(pdev, &sdhci_st_pdata, sizeof(*pdata));
370f52d9c4fSPeter Griffin 	if (IS_ERR(host)) {
371f52d9c4fSPeter Griffin 		dev_err(&pdev->dev, "Failed sdhci_pltfm_init\n");
372406c2431SPeter Griffin 		ret = PTR_ERR(host);
373406c2431SPeter Griffin 		goto err_pltfm_init;
374f52d9c4fSPeter Griffin 	}
375f52d9c4fSPeter Griffin 
37615316752SJisheng Zhang 	pltfm_host = sdhci_priv(host);
37715316752SJisheng Zhang 	pdata = sdhci_pltfm_priv(pltfm_host);
37815316752SJisheng Zhang 	pdata->rstc = rstc;
37915316752SJisheng Zhang 
380f52d9c4fSPeter Griffin 	ret = mmc_of_parse(host->mmc);
381f52d9c4fSPeter Griffin 	if (ret) {
382f52d9c4fSPeter Griffin 		dev_err(&pdev->dev, "Failed mmc_of_parse\n");
383fc702cb3SUlf Hansson 		goto err_of;
384f52d9c4fSPeter Griffin 	}
385f52d9c4fSPeter Griffin 
3867f55eb10SArvind Yadav 	ret = clk_prepare_enable(clk);
3877f55eb10SArvind Yadav 	if (ret) {
3887f55eb10SArvind Yadav 		dev_err(&pdev->dev, "Failed to prepare clock\n");
3897f55eb10SArvind Yadav 		goto err_of;
3907f55eb10SArvind Yadav 	}
3917f55eb10SArvind Yadav 
3927f55eb10SArvind Yadav 	ret = clk_prepare_enable(icnclk);
3937f55eb10SArvind Yadav 	if (ret) {
3947f55eb10SArvind Yadav 		dev_err(&pdev->dev, "Failed to prepare icn clock\n");
3957f55eb10SArvind Yadav 		goto err_icnclk;
3967f55eb10SArvind Yadav 	}
397f52d9c4fSPeter Griffin 
398406c2431SPeter Griffin 	/* Configure the FlashSS Top registers for setting eMMC TX/RX delay */
399aa857326SLi Zetao 	pdata->top_ioaddr = devm_platform_ioremap_resource_byname(pdev, "top-mmc-delay");
40050eae6baSLaibin Qiu 	if (IS_ERR(pdata->top_ioaddr))
401406c2431SPeter Griffin 		pdata->top_ioaddr = NULL;
402406c2431SPeter Griffin 
403f52d9c4fSPeter Griffin 	pltfm_host->clk = clk;
4043ae50f45SLee Jones 	pdata->icnclk = icnclk;
405f52d9c4fSPeter Griffin 
4062053812fSPeter Griffin 	/* Configure the Arasan HC inside the flashSS */
4072053812fSPeter Griffin 	st_mmcss_cconfig(np, host);
4082053812fSPeter Griffin 
409f52d9c4fSPeter Griffin 	ret = sdhci_add_host(host);
410fb8617e1SJisheng Zhang 	if (ret)
411f52d9c4fSPeter Griffin 		goto err_out;
412f52d9c4fSPeter Griffin 
413f52d9c4fSPeter Griffin 	host_version = readw_relaxed((host->ioaddr + SDHCI_HOST_VERSION));
414f52d9c4fSPeter Griffin 
415f52d9c4fSPeter Griffin 	dev_info(&pdev->dev, "SDHCI ST Initialised: Host Version: 0x%x Vendor Version 0x%x\n",
416f52d9c4fSPeter Griffin 		((host_version & SDHCI_SPEC_VER_MASK) >> SDHCI_SPEC_VER_SHIFT),
417f52d9c4fSPeter Griffin 		((host_version & SDHCI_VENDOR_VER_MASK) >>
418f52d9c4fSPeter Griffin 		SDHCI_VENDOR_VER_SHIFT));
419f52d9c4fSPeter Griffin 
420f52d9c4fSPeter Griffin 	return 0;
421f52d9c4fSPeter Griffin 
422f52d9c4fSPeter Griffin err_out:
4233ae50f45SLee Jones 	clk_disable_unprepare(icnclk);
4247f55eb10SArvind Yadav err_icnclk:
425f52d9c4fSPeter Griffin 	clk_disable_unprepare(clk);
426fc702cb3SUlf Hansson err_of:
427f52d9c4fSPeter Griffin 	sdhci_pltfm_free(pdev);
428406c2431SPeter Griffin err_pltfm_init:
42915316752SJisheng Zhang 	reset_control_assert(rstc);
430406c2431SPeter Griffin 
431406c2431SPeter Griffin 	return ret;
432406c2431SPeter Griffin }
433406c2431SPeter Griffin 
sdhci_st_remove(struct platform_device * pdev)434887c1331SYangtao Li static void sdhci_st_remove(struct platform_device *pdev)
435406c2431SPeter Griffin {
436406c2431SPeter Griffin 	struct sdhci_host *host = platform_get_drvdata(pdev);
437406c2431SPeter Griffin 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
43815316752SJisheng Zhang 	struct st_mmc_platform_data *pdata = sdhci_pltfm_priv(pltfm_host);
43915316752SJisheng Zhang 	struct reset_control *rstc = pdata->rstc;
440*b1284d7cSAdrian Hunter 	struct clk *clk = pltfm_host->clk;
441406c2431SPeter Griffin 
442*b1284d7cSAdrian Hunter 	sdhci_pltfm_remove(pdev);
443406c2431SPeter Griffin 
4443ae50f45SLee Jones 	clk_disable_unprepare(pdata->icnclk);
445*b1284d7cSAdrian Hunter 	clk_disable_unprepare(clk);
4463ae50f45SLee Jones 
44715316752SJisheng Zhang 	reset_control_assert(rstc);
448f52d9c4fSPeter Griffin }
449f52d9c4fSPeter Griffin 
450f52d9c4fSPeter Griffin #ifdef CONFIG_PM_SLEEP
sdhci_st_suspend(struct device * dev)451f52d9c4fSPeter Griffin static int sdhci_st_suspend(struct device *dev)
452f52d9c4fSPeter Griffin {
453f52d9c4fSPeter Griffin 	struct sdhci_host *host = dev_get_drvdata(dev);
454f52d9c4fSPeter Griffin 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
45515316752SJisheng Zhang 	struct st_mmc_platform_data *pdata = sdhci_pltfm_priv(pltfm_host);
456d38dcad4SAdrian Hunter 	int ret;
457f52d9c4fSPeter Griffin 
458d38dcad4SAdrian Hunter 	if (host->tuning_mode != SDHCI_TUNING_MODE_3)
459d38dcad4SAdrian Hunter 		mmc_retune_needed(host->mmc);
460d38dcad4SAdrian Hunter 
461d38dcad4SAdrian Hunter 	ret = sdhci_suspend_host(host);
462f52d9c4fSPeter Griffin 	if (ret)
463f52d9c4fSPeter Griffin 		goto out;
464f52d9c4fSPeter Griffin 
465406c2431SPeter Griffin 	reset_control_assert(pdata->rstc);
466406c2431SPeter Griffin 
4673ae50f45SLee Jones 	clk_disable_unprepare(pdata->icnclk);
468f52d9c4fSPeter Griffin 	clk_disable_unprepare(pltfm_host->clk);
469f52d9c4fSPeter Griffin out:
470f52d9c4fSPeter Griffin 	return ret;
471f52d9c4fSPeter Griffin }
472f52d9c4fSPeter Griffin 
sdhci_st_resume(struct device * dev)473f52d9c4fSPeter Griffin static int sdhci_st_resume(struct device *dev)
474f52d9c4fSPeter Griffin {
475f52d9c4fSPeter Griffin 	struct sdhci_host *host = dev_get_drvdata(dev);
476f52d9c4fSPeter Griffin 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
47715316752SJisheng Zhang 	struct st_mmc_platform_data *pdata = sdhci_pltfm_priv(pltfm_host);
4782053812fSPeter Griffin 	struct device_node *np = dev->of_node;
4797f55eb10SArvind Yadav 	int ret;
480f52d9c4fSPeter Griffin 
4817f55eb10SArvind Yadav 	ret = clk_prepare_enable(pltfm_host->clk);
4827f55eb10SArvind Yadav 	if (ret)
4837f55eb10SArvind Yadav 		return ret;
4847f55eb10SArvind Yadav 
4857f55eb10SArvind Yadav 	ret = clk_prepare_enable(pdata->icnclk);
4867f55eb10SArvind Yadav 	if (ret) {
4877f55eb10SArvind Yadav 		clk_disable_unprepare(pltfm_host->clk);
4887f55eb10SArvind Yadav 		return ret;
4897f55eb10SArvind Yadav 	}
490f52d9c4fSPeter Griffin 
491406c2431SPeter Griffin 	reset_control_deassert(pdata->rstc);
492406c2431SPeter Griffin 
4932053812fSPeter Griffin 	st_mmcss_cconfig(np, host);
4942053812fSPeter Griffin 
495f52d9c4fSPeter Griffin 	return sdhci_resume_host(host);
496f52d9c4fSPeter Griffin }
497f52d9c4fSPeter Griffin #endif
498f52d9c4fSPeter Griffin 
499f52d9c4fSPeter Griffin static SIMPLE_DEV_PM_OPS(sdhci_st_pmops, sdhci_st_suspend, sdhci_st_resume);
500f52d9c4fSPeter Griffin 
501f52d9c4fSPeter Griffin static const struct of_device_id st_sdhci_match[] = {
502f52d9c4fSPeter Griffin 	{ .compatible = "st,sdhci" },
503f52d9c4fSPeter Griffin 	{},
504f52d9c4fSPeter Griffin };
505f52d9c4fSPeter Griffin 
506f52d9c4fSPeter Griffin MODULE_DEVICE_TABLE(of, st_sdhci_match);
507f52d9c4fSPeter Griffin 
508f52d9c4fSPeter Griffin static struct platform_driver sdhci_st_driver = {
509f52d9c4fSPeter Griffin 	.probe = sdhci_st_probe,
510887c1331SYangtao Li 	.remove_new = sdhci_st_remove,
511f52d9c4fSPeter Griffin 	.driver = {
512f52d9c4fSPeter Griffin 		   .name = "sdhci-st",
51321b2cec6SDouglas Anderson 		   .probe_type = PROBE_PREFER_ASYNCHRONOUS,
514f52d9c4fSPeter Griffin 		   .pm = &sdhci_st_pmops,
515bf3023e6SKrzysztof Kozlowski 		   .of_match_table = st_sdhci_match,
516f52d9c4fSPeter Griffin 		  },
517f52d9c4fSPeter Griffin };
518f52d9c4fSPeter Griffin 
519f52d9c4fSPeter Griffin module_platform_driver(sdhci_st_driver);
520f52d9c4fSPeter Griffin 
521f52d9c4fSPeter Griffin MODULE_DESCRIPTION("SDHCI driver for STMicroelectronics SoCs");
522f52d9c4fSPeter Griffin MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>");
523f52d9c4fSPeter Griffin MODULE_LICENSE("GPL v2");
524e6ac184bSZhangfei Gao MODULE_ALIAS("platform:sdhci-st");
525