12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2e3ec3a3dSSoren Brinkmann /*
3e3ec3a3dSSoren Brinkmann  * Arasan Secure Digital Host Controller Interface.
4e3ec3a3dSSoren Brinkmann  * Copyright (C) 2011 - 2012 Michal Simek <monstr@monstr.eu>
5e3ec3a3dSSoren Brinkmann  * Copyright (c) 2012 Wind River Systems, Inc.
6e3ec3a3dSSoren Brinkmann  * Copyright (C) 2013 Pengutronix e.K.
7e3ec3a3dSSoren Brinkmann  * Copyright (C) 2013 Xilinx Inc.
8e3ec3a3dSSoren Brinkmann  *
9e3ec3a3dSSoren Brinkmann  * Based on sdhci-of-esdhc.c
10e3ec3a3dSSoren Brinkmann  *
11e3ec3a3dSSoren Brinkmann  * Copyright (c) 2007 Freescale Semiconductor, Inc.
12e3ec3a3dSSoren Brinkmann  * Copyright (c) 2009 MontaVista Software, Inc.
13e3ec3a3dSSoren Brinkmann  *
14e3ec3a3dSSoren Brinkmann  * Authors: Xiaobo Xie <X.Xie@freescale.com>
15e3ec3a3dSSoren Brinkmann  *	    Anton Vorontsov <avorontsov@ru.mvista.com>
16e3ec3a3dSSoren Brinkmann  */
17e3ec3a3dSSoren Brinkmann 
18c390f211SDouglas Anderson #include <linux/clk-provider.h>
193ea4666eSDouglas Anderson #include <linux/mfd/syscon.h>
20e3ec3a3dSSoren Brinkmann #include <linux/module.h>
21308f3f8dSSuman Tripathi #include <linux/of_device.h>
2291aa3661SShawn Lin #include <linux/phy/phy.h>
233ea4666eSDouglas Anderson #include <linux/regmap.h>
243794c542SZach Brown #include <linux/of.h>
25a5c8b2aeSManish Narani #include <linux/firmware/xlnx-zynqmp.h>
26e3ec3a3dSSoren Brinkmann 
2784362d79SShawn Lin #include "cqhci.h"
2884362d79SShawn Lin #include "sdhci-pltfm.h"
29e3ec3a3dSSoren Brinkmann 
3084362d79SShawn Lin #define SDHCI_ARASAN_VENDOR_REGISTER	0x78
311a470721SManish Narani 
321a470721SManish Narani #define SDHCI_ARASAN_ITAPDLY_REGISTER	0xF0F8
331a470721SManish Narani #define SDHCI_ARASAN_OTAPDLY_REGISTER	0xF0FC
341a470721SManish Narani 
3584362d79SShawn Lin #define SDHCI_ARASAN_CQE_BASE_ADDR	0x200
36a05c8465SShawn Lin #define VENDOR_ENHANCED_STROBE		BIT(0)
37e3ec3a3dSSoren Brinkmann 
38b2db9c67SDouglas Anderson #define PHY_CLK_TOO_SLOW_HZ		400000
39b2db9c67SDouglas Anderson 
401a470721SManish Narani #define SDHCI_ITAPDLY_CHGWIN		0x200
411a470721SManish Narani #define SDHCI_ITAPDLY_ENABLE		0x100
421a470721SManish Narani #define SDHCI_OTAPDLY_ENABLE		0x40
431a470721SManish Narani 
44a5c8b2aeSManish Narani /* Default settings for ZynqMP Clock Phases */
45a5c8b2aeSManish Narani #define ZYNQMP_ICLK_PHASE {0, 63, 63, 0, 63,  0,   0, 183, 54,  0, 0}
46a5c8b2aeSManish Narani #define ZYNQMP_OCLK_PHASE {0, 72, 60, 0, 60, 72, 135, 48, 72, 135, 0}
47a5c8b2aeSManish Narani 
481a470721SManish Narani #define VERSAL_ICLK_PHASE {0, 132, 132, 0, 132, 0, 0, 162, 90, 0, 0}
491a470721SManish Narani #define VERSAL_OCLK_PHASE {0,  60, 48, 0, 48, 72, 90, 36, 60, 90, 0}
501a470721SManish Narani 
513ea4666eSDouglas Anderson /*
523ea4666eSDouglas Anderson  * On some SoCs the syscon area has a feature where the upper 16-bits of
533ea4666eSDouglas Anderson  * each 32-bit register act as a write mask for the lower 16-bits.  This allows
543ea4666eSDouglas Anderson  * atomic updates of the register without locking.  This macro is used on SoCs
553ea4666eSDouglas Anderson  * that have that feature.
563ea4666eSDouglas Anderson  */
573ea4666eSDouglas Anderson #define HIWORD_UPDATE(val, mask, shift) \
583ea4666eSDouglas Anderson 		((val) << (shift) | (mask) << ((shift) + 16))
593ea4666eSDouglas Anderson 
603ea4666eSDouglas Anderson /**
613ea4666eSDouglas Anderson  * struct sdhci_arasan_soc_ctl_field - Field used in sdhci_arasan_soc_ctl_map
623ea4666eSDouglas Anderson  *
633ea4666eSDouglas Anderson  * @reg:	Offset within the syscon of the register containing this field
643ea4666eSDouglas Anderson  * @width:	Number of bits for this field
653ea4666eSDouglas Anderson  * @shift:	Bit offset within @reg of this field (or -1 if not avail)
663ea4666eSDouglas Anderson  */
673ea4666eSDouglas Anderson struct sdhci_arasan_soc_ctl_field {
683ea4666eSDouglas Anderson 	u32 reg;
693ea4666eSDouglas Anderson 	u16 width;
703ea4666eSDouglas Anderson 	s16 shift;
713ea4666eSDouglas Anderson };
723ea4666eSDouglas Anderson 
733ea4666eSDouglas Anderson /**
743ea4666eSDouglas Anderson  * struct sdhci_arasan_soc_ctl_map - Map in syscon to corecfg registers
753ea4666eSDouglas Anderson  *
763ea4666eSDouglas Anderson  * @baseclkfreq:	Where to find corecfg_baseclkfreq
77b2ca77c9SShawn Lin  * @clockmultiplier:	Where to find corecfg_clockmultiplier
783ea4666eSDouglas Anderson  * @hiword_update:	If true, use HIWORD_UPDATE to access the syscon
794908460eSManish Narani  *
804908460eSManish Narani  * It's up to the licensee of the Arsan IP block to make these available
814908460eSManish Narani  * somewhere if needed.  Presumably these will be scattered somewhere that's
824908460eSManish Narani  * accessible via the syscon API.
833ea4666eSDouglas Anderson  */
843ea4666eSDouglas Anderson struct sdhci_arasan_soc_ctl_map {
853ea4666eSDouglas Anderson 	struct sdhci_arasan_soc_ctl_field	baseclkfreq;
86b2ca77c9SShawn Lin 	struct sdhci_arasan_soc_ctl_field	clockmultiplier;
873ea4666eSDouglas Anderson 	bool					hiword_update;
883ea4666eSDouglas Anderson };
893ea4666eSDouglas Anderson 
90e3ec3a3dSSoren Brinkmann /**
9116ada730SManish Narani  * struct sdhci_arasan_clk_ops - Clock Operations for Arasan SD controller
9216ada730SManish Narani  *
9316ada730SManish Narani  * @sdcardclk_ops:	The output clock related operations
9416ada730SManish Narani  * @sampleclk_ops:	The sample clock related operations
9516ada730SManish Narani  */
9616ada730SManish Narani struct sdhci_arasan_clk_ops {
9716ada730SManish Narani 	const struct clk_ops *sdcardclk_ops;
9816ada730SManish Narani 	const struct clk_ops *sampleclk_ops;
9916ada730SManish Narani };
10016ada730SManish Narani 
10116ada730SManish Narani /**
1024908460eSManish Narani  * struct sdhci_arasan_clk_data - Arasan Controller Clock Data.
1034908460eSManish Narani  *
104e1463618SManish Narani  * @sdcardclk_hw:	Struct for the clock we might provide to a PHY.
105e1463618SManish Narani  * @sdcardclk:		Pointer to normal 'struct clock' for sdcardclk_hw.
10607a14d1dSManish Narani  * @sampleclk_hw:	Struct for the clock we might provide to a PHY.
10707a14d1dSManish Narani  * @sampleclk:		Pointer to normal 'struct clock' for sampleclk_hw.
108f3dafc37SManish Narani  * @clk_phase_in:	Array of Input Clock Phase Delays for all speed modes
109f3dafc37SManish Narani  * @clk_phase_out:	Array of Output Clock Phase Delays for all speed modes
110f3dafc37SManish Narani  * @set_clk_delays:	Function pointer for setting Clock Delays
111a5c8b2aeSManish Narani  * @clk_of_data:	Platform specific runtime clock data storage pointer
112e1463618SManish Narani  */
113e1463618SManish Narani struct sdhci_arasan_clk_data {
114e1463618SManish Narani 	struct clk_hw	sdcardclk_hw;
115e1463618SManish Narani 	struct clk      *sdcardclk;
11607a14d1dSManish Narani 	struct clk_hw	sampleclk_hw;
11707a14d1dSManish Narani 	struct clk      *sampleclk;
118f3dafc37SManish Narani 	int		clk_phase_in[MMC_TIMING_MMC_HS400 + 1];
119f3dafc37SManish Narani 	int		clk_phase_out[MMC_TIMING_MMC_HS400 + 1];
120f3dafc37SManish Narani 	void		(*set_clk_delays)(struct sdhci_host *host);
121a5c8b2aeSManish Narani 	void		*clk_of_data;
122a5c8b2aeSManish Narani };
123a5c8b2aeSManish Narani 
124a5c8b2aeSManish Narani struct sdhci_arasan_zynqmp_clk_data {
125a5c8b2aeSManish Narani 	const struct zynqmp_eemi_ops *eemi_ops;
126e1463618SManish Narani };
127e1463618SManish Narani 
128e1463618SManish Narani /**
1294908460eSManish Narani  * struct sdhci_arasan_data - Arasan Controller Data
1304908460eSManish Narani  *
131c390f211SDouglas Anderson  * @host:		Pointer to the main SDHCI host structure.
132e3ec3a3dSSoren Brinkmann  * @clk_ahb:		Pointer to the AHB clock
13391aa3661SShawn Lin  * @phy:		Pointer to the generic phy
134b2db9c67SDouglas Anderson  * @is_phy_on:		True if the PHY is on; false if not.
1354908460eSManish Narani  * @has_cqe:		True if controller has command queuing engine.
136e1463618SManish Narani  * @clk_data:		Struct for the Arasan Controller Clock Data.
13716ada730SManish Narani  * @clk_ops:		Struct for the Arasan Controller Clock Operations.
1383ea4666eSDouglas Anderson  * @soc_ctl_base:	Pointer to regmap for syscon for soc_ctl registers.
1393ea4666eSDouglas Anderson  * @soc_ctl_map:	Map to get offsets into soc_ctl registers.
1404908460eSManish Narani  * @quirks:		Arasan deviations from spec.
141e3ec3a3dSSoren Brinkmann  */
142e3ec3a3dSSoren Brinkmann struct sdhci_arasan_data {
143c390f211SDouglas Anderson 	struct sdhci_host *host;
144e3ec3a3dSSoren Brinkmann 	struct clk	*clk_ahb;
14591aa3661SShawn Lin 	struct phy	*phy;
146b2db9c67SDouglas Anderson 	bool		is_phy_on;
1473ea4666eSDouglas Anderson 
14884362d79SShawn Lin 	bool		has_cqe;
149e1463618SManish Narani 	struct sdhci_arasan_clk_data clk_data;
15016ada730SManish Narani 	const struct sdhci_arasan_clk_ops *clk_ops;
151c390f211SDouglas Anderson 
1523ea4666eSDouglas Anderson 	struct regmap	*soc_ctl_base;
1533ea4666eSDouglas Anderson 	const struct sdhci_arasan_soc_ctl_map *soc_ctl_map;
1544908460eSManish Narani 	unsigned int	quirks;
1553794c542SZach Brown 
1563794c542SZach Brown /* Controller does not have CD wired and will not function normally without */
1573794c542SZach Brown #define SDHCI_ARASAN_QUIRK_FORCE_CDTEST	BIT(0)
1583f2c7d5dSHelmut Grohne /* Controller immediately reports SDHCI_CLOCK_INT_STABLE after enabling the
1593f2c7d5dSHelmut Grohne  * internal clock even when the clock isn't stable */
1603f2c7d5dSHelmut Grohne #define SDHCI_ARASAN_QUIRK_CLOCK_UNSTABLE BIT(1)
161e3ec3a3dSSoren Brinkmann };
162e3ec3a3dSSoren Brinkmann 
16306b23ca0SFaiz Abbas struct sdhci_arasan_of_data {
16406b23ca0SFaiz Abbas 	const struct sdhci_arasan_soc_ctl_map *soc_ctl_map;
16506b23ca0SFaiz Abbas 	const struct sdhci_pltfm_data *pdata;
16616ada730SManish Narani 	const struct sdhci_arasan_clk_ops *clk_ops;
16706b23ca0SFaiz Abbas };
16806b23ca0SFaiz Abbas 
1693ea4666eSDouglas Anderson static const struct sdhci_arasan_soc_ctl_map rk3399_soc_ctl_map = {
1703ea4666eSDouglas Anderson 	.baseclkfreq = { .reg = 0xf000, .width = 8, .shift = 8 },
171b2ca77c9SShawn Lin 	.clockmultiplier = { .reg = 0xf02c, .width = 8, .shift = 0},
1723ea4666eSDouglas Anderson 	.hiword_update = true,
1733ea4666eSDouglas Anderson };
1743ea4666eSDouglas Anderson 
1755c1a4f40SRamuthevar Vadivel Muruganx static const struct sdhci_arasan_soc_ctl_map intel_lgm_emmc_soc_ctl_map = {
1765c1a4f40SRamuthevar Vadivel Muruganx 	.baseclkfreq = { .reg = 0xa0, .width = 8, .shift = 2 },
1775c1a4f40SRamuthevar Vadivel Muruganx 	.clockmultiplier = { .reg = 0, .width = -1, .shift = -1 },
1785c1a4f40SRamuthevar Vadivel Muruganx 	.hiword_update = false,
1795c1a4f40SRamuthevar Vadivel Muruganx };
1805c1a4f40SRamuthevar Vadivel Muruganx 
181d1807ad6SRamuthevar Vadivel Murugan static const struct sdhci_arasan_soc_ctl_map intel_lgm_sdxc_soc_ctl_map = {
182d1807ad6SRamuthevar Vadivel Murugan 	.baseclkfreq = { .reg = 0x80, .width = 8, .shift = 2 },
183d1807ad6SRamuthevar Vadivel Murugan 	.clockmultiplier = { .reg = 0, .width = -1, .shift = -1 },
184d1807ad6SRamuthevar Vadivel Murugan 	.hiword_update = false,
185d1807ad6SRamuthevar Vadivel Murugan };
186d1807ad6SRamuthevar Vadivel Murugan 
1873ea4666eSDouglas Anderson /**
1883ea4666eSDouglas Anderson  * sdhci_arasan_syscon_write - Write to a field in soc_ctl registers
1893ea4666eSDouglas Anderson  *
1904908460eSManish Narani  * @host:	The sdhci_host
1914908460eSManish Narani  * @fld:	The field to write to
1924908460eSManish Narani  * @val:	The value to write
1934908460eSManish Narani  *
1943ea4666eSDouglas Anderson  * This function allows writing to fields in sdhci_arasan_soc_ctl_map.
1953ea4666eSDouglas Anderson  * Note that if a field is specified as not available (shift < 0) then
1963ea4666eSDouglas Anderson  * this function will silently return an error code.  It will be noisy
1973ea4666eSDouglas Anderson  * and print errors for any other (unexpected) errors.
1983ea4666eSDouglas Anderson  *
1994908460eSManish Narani  * Return: 0 on success and error value on error
2003ea4666eSDouglas Anderson  */
2013ea4666eSDouglas Anderson static int sdhci_arasan_syscon_write(struct sdhci_host *host,
2023ea4666eSDouglas Anderson 				   const struct sdhci_arasan_soc_ctl_field *fld,
2033ea4666eSDouglas Anderson 				   u32 val)
2043ea4666eSDouglas Anderson {
2053ea4666eSDouglas Anderson 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
2063ea4666eSDouglas Anderson 	struct sdhci_arasan_data *sdhci_arasan = sdhci_pltfm_priv(pltfm_host);
2073ea4666eSDouglas Anderson 	struct regmap *soc_ctl_base = sdhci_arasan->soc_ctl_base;
2083ea4666eSDouglas Anderson 	u32 reg = fld->reg;
2093ea4666eSDouglas Anderson 	u16 width = fld->width;
2103ea4666eSDouglas Anderson 	s16 shift = fld->shift;
2113ea4666eSDouglas Anderson 	int ret;
2123ea4666eSDouglas Anderson 
2133ea4666eSDouglas Anderson 	/*
2143ea4666eSDouglas Anderson 	 * Silently return errors for shift < 0 so caller doesn't have
2153ea4666eSDouglas Anderson 	 * to check for fields which are optional.  For fields that
2163ea4666eSDouglas Anderson 	 * are required then caller needs to do something special
2173ea4666eSDouglas Anderson 	 * anyway.
2183ea4666eSDouglas Anderson 	 */
2193ea4666eSDouglas Anderson 	if (shift < 0)
2203ea4666eSDouglas Anderson 		return -EINVAL;
2213ea4666eSDouglas Anderson 
2223ea4666eSDouglas Anderson 	if (sdhci_arasan->soc_ctl_map->hiword_update)
2233ea4666eSDouglas Anderson 		ret = regmap_write(soc_ctl_base, reg,
2243ea4666eSDouglas Anderson 				   HIWORD_UPDATE(val, GENMASK(width, 0),
2253ea4666eSDouglas Anderson 						 shift));
2263ea4666eSDouglas Anderson 	else
2273ea4666eSDouglas Anderson 		ret = regmap_update_bits(soc_ctl_base, reg,
2283ea4666eSDouglas Anderson 					 GENMASK(shift + width, shift),
2293ea4666eSDouglas Anderson 					 val << shift);
2303ea4666eSDouglas Anderson 
2313ea4666eSDouglas Anderson 	/* Yell about (unexpected) regmap errors */
2323ea4666eSDouglas Anderson 	if (ret)
2333ea4666eSDouglas Anderson 		pr_warn("%s: Regmap write fail: %d\n",
2343ea4666eSDouglas Anderson 			 mmc_hostname(host->mmc), ret);
2353ea4666eSDouglas Anderson 
2363ea4666eSDouglas Anderson 	return ret;
2373ea4666eSDouglas Anderson }
2383ea4666eSDouglas Anderson 
239802ac39aSShawn Lin static void sdhci_arasan_set_clock(struct sdhci_host *host, unsigned int clock)
240802ac39aSShawn Lin {
241802ac39aSShawn Lin 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
242802ac39aSShawn Lin 	struct sdhci_arasan_data *sdhci_arasan = sdhci_pltfm_priv(pltfm_host);
243f3dafc37SManish Narani 	struct sdhci_arasan_clk_data *clk_data = &sdhci_arasan->clk_data;
2446fc09244SDouglas Anderson 	bool ctrl_phy = false;
245802ac39aSShawn Lin 
246b2db9c67SDouglas Anderson 	if (!IS_ERR(sdhci_arasan->phy)) {
247b2db9c67SDouglas Anderson 		if (!sdhci_arasan->is_phy_on && clock <= PHY_CLK_TOO_SLOW_HZ) {
248b2db9c67SDouglas Anderson 			/*
249b2db9c67SDouglas Anderson 			 * If PHY off, set clock to max speed and power PHY on.
250b2db9c67SDouglas Anderson 			 *
251b2db9c67SDouglas Anderson 			 * Although PHY docs apparently suggest power cycling
252b2db9c67SDouglas Anderson 			 * when changing the clock the PHY doesn't like to be
253b2db9c67SDouglas Anderson 			 * powered on while at low speeds like those used in ID
254b2db9c67SDouglas Anderson 			 * mode.  Even worse is powering the PHY on while the
255b2db9c67SDouglas Anderson 			 * clock is off.
256b2db9c67SDouglas Anderson 			 *
257b2db9c67SDouglas Anderson 			 * To workaround the PHY limitations, the best we can
258b2db9c67SDouglas Anderson 			 * do is to power it on at a faster speed and then slam
259b2db9c67SDouglas Anderson 			 * through low speeds without power cycling.
260b2db9c67SDouglas Anderson 			 */
261b2db9c67SDouglas Anderson 			sdhci_set_clock(host, host->max_clk);
262b2db9c67SDouglas Anderson 			phy_power_on(sdhci_arasan->phy);
263b2db9c67SDouglas Anderson 			sdhci_arasan->is_phy_on = true;
264802ac39aSShawn Lin 
265b2db9c67SDouglas Anderson 			/*
266b2db9c67SDouglas Anderson 			 * We'll now fall through to the below case with
267b2db9c67SDouglas Anderson 			 * ctrl_phy = false (so we won't turn off/on).  The
268b2db9c67SDouglas Anderson 			 * sdhci_set_clock() will set the real clock.
269b2db9c67SDouglas Anderson 			 */
270b2db9c67SDouglas Anderson 		} else if (clock > PHY_CLK_TOO_SLOW_HZ) {
271b2db9c67SDouglas Anderson 			/*
272b2db9c67SDouglas Anderson 			 * At higher clock speeds the PHY is fine being power
273b2db9c67SDouglas Anderson 			 * cycled and docs say you _should_ power cycle when
274b2db9c67SDouglas Anderson 			 * changing clock speeds.
275b2db9c67SDouglas Anderson 			 */
276b2db9c67SDouglas Anderson 			ctrl_phy = true;
277b2db9c67SDouglas Anderson 		}
278b2db9c67SDouglas Anderson 	}
279b2db9c67SDouglas Anderson 
280b2db9c67SDouglas Anderson 	if (ctrl_phy && sdhci_arasan->is_phy_on) {
281802ac39aSShawn Lin 		phy_power_off(sdhci_arasan->phy);
282b2db9c67SDouglas Anderson 		sdhci_arasan->is_phy_on = false;
283802ac39aSShawn Lin 	}
284802ac39aSShawn Lin 
285f3dafc37SManish Narani 	/* Set the Input and Output Clock Phase Delays */
286f3dafc37SManish Narani 	if (clk_data->set_clk_delays)
287f3dafc37SManish Narani 		clk_data->set_clk_delays(host);
288f3dafc37SManish Narani 
289802ac39aSShawn Lin 	sdhci_set_clock(host, clock);
290802ac39aSShawn Lin 
2913f2c7d5dSHelmut Grohne 	if (sdhci_arasan->quirks & SDHCI_ARASAN_QUIRK_CLOCK_UNSTABLE)
2923f2c7d5dSHelmut Grohne 		/*
2933f2c7d5dSHelmut Grohne 		 * Some controllers immediately report SDHCI_CLOCK_INT_STABLE
2943f2c7d5dSHelmut Grohne 		 * after enabling the clock even though the clock is not
2953f2c7d5dSHelmut Grohne 		 * stable. Trying to use a clock without waiting here results
2963f2c7d5dSHelmut Grohne 		 * in EILSEQ while detecting some older/slower cards. The
2973f2c7d5dSHelmut Grohne 		 * chosen delay is the maximum delay from sdhci_set_clock.
2983f2c7d5dSHelmut Grohne 		 */
2993f2c7d5dSHelmut Grohne 		msleep(20);
3003f2c7d5dSHelmut Grohne 
3016fc09244SDouglas Anderson 	if (ctrl_phy) {
302802ac39aSShawn Lin 		phy_power_on(sdhci_arasan->phy);
303b2db9c67SDouglas Anderson 		sdhci_arasan->is_phy_on = true;
304802ac39aSShawn Lin 	}
305802ac39aSShawn Lin }
306802ac39aSShawn Lin 
307a05c8465SShawn Lin static void sdhci_arasan_hs400_enhanced_strobe(struct mmc_host *mmc,
308a05c8465SShawn Lin 					struct mmc_ios *ios)
309a05c8465SShawn Lin {
310a05c8465SShawn Lin 	u32 vendor;
311a05c8465SShawn Lin 	struct sdhci_host *host = mmc_priv(mmc);
312a05c8465SShawn Lin 
3130daf72feSJean-Francois Dagenais 	vendor = sdhci_readl(host, SDHCI_ARASAN_VENDOR_REGISTER);
314a05c8465SShawn Lin 	if (ios->enhanced_strobe)
315a05c8465SShawn Lin 		vendor |= VENDOR_ENHANCED_STROBE;
316a05c8465SShawn Lin 	else
317a05c8465SShawn Lin 		vendor &= ~VENDOR_ENHANCED_STROBE;
318a05c8465SShawn Lin 
3190daf72feSJean-Francois Dagenais 	sdhci_writel(host, vendor, SDHCI_ARASAN_VENDOR_REGISTER);
320a05c8465SShawn Lin }
321a05c8465SShawn Lin 
32213d62fd2SWei Yongjun static void sdhci_arasan_reset(struct sdhci_host *host, u8 mask)
3233794c542SZach Brown {
3243794c542SZach Brown 	u8 ctrl;
3253794c542SZach Brown 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
3263794c542SZach Brown 	struct sdhci_arasan_data *sdhci_arasan = sdhci_pltfm_priv(pltfm_host);
3273794c542SZach Brown 
3283794c542SZach Brown 	sdhci_reset(host, mask);
3293794c542SZach Brown 
3303794c542SZach Brown 	if (sdhci_arasan->quirks & SDHCI_ARASAN_QUIRK_FORCE_CDTEST) {
3313794c542SZach Brown 		ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
3323794c542SZach Brown 		ctrl |= SDHCI_CTRL_CDTEST_INS | SDHCI_CTRL_CDTEST_EN;
3333794c542SZach Brown 		sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
3343794c542SZach Brown 	}
3353794c542SZach Brown }
3363794c542SZach Brown 
3378a3bee9bSShawn Lin static int sdhci_arasan_voltage_switch(struct mmc_host *mmc,
3388a3bee9bSShawn Lin 				       struct mmc_ios *ios)
3398a3bee9bSShawn Lin {
3408a3bee9bSShawn Lin 	switch (ios->signal_voltage) {
3418a3bee9bSShawn Lin 	case MMC_SIGNAL_VOLTAGE_180:
3428a3bee9bSShawn Lin 		/*
3438a3bee9bSShawn Lin 		 * Plese don't switch to 1V8 as arasan,5.1 doesn't
3448a3bee9bSShawn Lin 		 * actually refer to this setting to indicate the
3458a3bee9bSShawn Lin 		 * signal voltage and the state machine will be broken
3468a3bee9bSShawn Lin 		 * actually if we force to enable 1V8. That's something
3478a3bee9bSShawn Lin 		 * like broken quirk but we could work around here.
3488a3bee9bSShawn Lin 		 */
3498a3bee9bSShawn Lin 		return 0;
3508a3bee9bSShawn Lin 	case MMC_SIGNAL_VOLTAGE_330:
3518a3bee9bSShawn Lin 	case MMC_SIGNAL_VOLTAGE_120:
3528a3bee9bSShawn Lin 		/* We don't support 3V3 and 1V2 */
3538a3bee9bSShawn Lin 		break;
3548a3bee9bSShawn Lin 	}
3558a3bee9bSShawn Lin 
3568a3bee9bSShawn Lin 	return -EINVAL;
3578a3bee9bSShawn Lin }
3588a3bee9bSShawn Lin 
359a81dae3aSJulia Lawall static const struct sdhci_ops sdhci_arasan_ops = {
360802ac39aSShawn Lin 	.set_clock = sdhci_arasan_set_clock,
361e3ec3a3dSSoren Brinkmann 	.get_max_clock = sdhci_pltfm_clk_get_max_clock,
3628cc35289SShawn Lin 	.get_timeout_clock = sdhci_pltfm_clk_get_max_clock,
3632317f56cSRussell King 	.set_bus_width = sdhci_set_bus_width,
3643794c542SZach Brown 	.reset = sdhci_arasan_reset,
36596d7b78cSRussell King 	.set_uhs_signaling = sdhci_set_uhs_signaling,
366c2c5252cSNicolas Saenz Julienne 	.set_power = sdhci_set_power_and_bus_voltage,
367e3ec3a3dSSoren Brinkmann };
368e3ec3a3dSSoren Brinkmann 
36984362d79SShawn Lin static u32 sdhci_arasan_cqhci_irq(struct sdhci_host *host, u32 intmask)
37084362d79SShawn Lin {
37184362d79SShawn Lin 	int cmd_error = 0;
37284362d79SShawn Lin 	int data_error = 0;
37384362d79SShawn Lin 
37484362d79SShawn Lin 	if (!sdhci_cqe_irq(host, intmask, &cmd_error, &data_error))
37584362d79SShawn Lin 		return intmask;
37684362d79SShawn Lin 
37784362d79SShawn Lin 	cqhci_irq(host->mmc, intmask, cmd_error, data_error);
37884362d79SShawn Lin 
37984362d79SShawn Lin 	return 0;
38084362d79SShawn Lin }
38184362d79SShawn Lin 
38284362d79SShawn Lin static void sdhci_arasan_dumpregs(struct mmc_host *mmc)
38384362d79SShawn Lin {
38484362d79SShawn Lin 	sdhci_dumpregs(mmc_priv(mmc));
38584362d79SShawn Lin }
38684362d79SShawn Lin 
38784362d79SShawn Lin static void sdhci_arasan_cqe_enable(struct mmc_host *mmc)
38884362d79SShawn Lin {
38984362d79SShawn Lin 	struct sdhci_host *host = mmc_priv(mmc);
39084362d79SShawn Lin 	u32 reg;
39184362d79SShawn Lin 
39284362d79SShawn Lin 	reg = sdhci_readl(host, SDHCI_PRESENT_STATE);
39384362d79SShawn Lin 	while (reg & SDHCI_DATA_AVAILABLE) {
39484362d79SShawn Lin 		sdhci_readl(host, SDHCI_BUFFER);
39584362d79SShawn Lin 		reg = sdhci_readl(host, SDHCI_PRESENT_STATE);
39684362d79SShawn Lin 	}
39784362d79SShawn Lin 
39884362d79SShawn Lin 	sdhci_cqe_enable(mmc);
39984362d79SShawn Lin }
40084362d79SShawn Lin 
40184362d79SShawn Lin static const struct cqhci_host_ops sdhci_arasan_cqhci_ops = {
40284362d79SShawn Lin 	.enable         = sdhci_arasan_cqe_enable,
40384362d79SShawn Lin 	.disable        = sdhci_cqe_disable,
40484362d79SShawn Lin 	.dumpregs       = sdhci_arasan_dumpregs,
40584362d79SShawn Lin };
40684362d79SShawn Lin 
40784362d79SShawn Lin static const struct sdhci_ops sdhci_arasan_cqe_ops = {
40884362d79SShawn Lin 	.set_clock = sdhci_arasan_set_clock,
40984362d79SShawn Lin 	.get_max_clock = sdhci_pltfm_clk_get_max_clock,
41084362d79SShawn Lin 	.get_timeout_clock = sdhci_pltfm_clk_get_max_clock,
41184362d79SShawn Lin 	.set_bus_width = sdhci_set_bus_width,
41284362d79SShawn Lin 	.reset = sdhci_arasan_reset,
41384362d79SShawn Lin 	.set_uhs_signaling = sdhci_set_uhs_signaling,
414c2c5252cSNicolas Saenz Julienne 	.set_power = sdhci_set_power_and_bus_voltage,
41584362d79SShawn Lin 	.irq = sdhci_arasan_cqhci_irq,
41684362d79SShawn Lin };
41784362d79SShawn Lin 
41884362d79SShawn Lin static const struct sdhci_pltfm_data sdhci_arasan_cqe_pdata = {
41984362d79SShawn Lin 	.ops = &sdhci_arasan_cqe_ops,
42084362d79SShawn Lin 	.quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
42184362d79SShawn Lin 	.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
42284362d79SShawn Lin 			SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN,
42384362d79SShawn Lin };
42484362d79SShawn Lin 
425e3ec3a3dSSoren Brinkmann #ifdef CONFIG_PM_SLEEP
426e3ec3a3dSSoren Brinkmann /**
427e3ec3a3dSSoren Brinkmann  * sdhci_arasan_suspend - Suspend method for the driver
428e3ec3a3dSSoren Brinkmann  * @dev:	Address of the device structure
429e3ec3a3dSSoren Brinkmann  *
430e3ec3a3dSSoren Brinkmann  * Put the device in a low power state.
4314908460eSManish Narani  *
4324908460eSManish Narani  * Return: 0 on success and error value on error
433e3ec3a3dSSoren Brinkmann  */
434e3ec3a3dSSoren Brinkmann static int sdhci_arasan_suspend(struct device *dev)
435e3ec3a3dSSoren Brinkmann {
436970f2d90SWolfram Sang 	struct sdhci_host *host = dev_get_drvdata(dev);
437e3ec3a3dSSoren Brinkmann 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
43889211418SJisheng Zhang 	struct sdhci_arasan_data *sdhci_arasan = sdhci_pltfm_priv(pltfm_host);
439e3ec3a3dSSoren Brinkmann 	int ret;
440e3ec3a3dSSoren Brinkmann 
441d38dcad4SAdrian Hunter 	if (host->tuning_mode != SDHCI_TUNING_MODE_3)
442d38dcad4SAdrian Hunter 		mmc_retune_needed(host->mmc);
443d38dcad4SAdrian Hunter 
44484362d79SShawn Lin 	if (sdhci_arasan->has_cqe) {
44584362d79SShawn Lin 		ret = cqhci_suspend(host->mmc);
44684362d79SShawn Lin 		if (ret)
44784362d79SShawn Lin 			return ret;
44884362d79SShawn Lin 	}
44984362d79SShawn Lin 
450e3ec3a3dSSoren Brinkmann 	ret = sdhci_suspend_host(host);
451e3ec3a3dSSoren Brinkmann 	if (ret)
452e3ec3a3dSSoren Brinkmann 		return ret;
453e3ec3a3dSSoren Brinkmann 
454b2db9c67SDouglas Anderson 	if (!IS_ERR(sdhci_arasan->phy) && sdhci_arasan->is_phy_on) {
45591aa3661SShawn Lin 		ret = phy_power_off(sdhci_arasan->phy);
45691aa3661SShawn Lin 		if (ret) {
45791aa3661SShawn Lin 			dev_err(dev, "Cannot power off phy.\n");
45891aa3661SShawn Lin 			sdhci_resume_host(host);
45991aa3661SShawn Lin 			return ret;
46091aa3661SShawn Lin 		}
461b2db9c67SDouglas Anderson 		sdhci_arasan->is_phy_on = false;
46291aa3661SShawn Lin 	}
46391aa3661SShawn Lin 
464e3ec3a3dSSoren Brinkmann 	clk_disable(pltfm_host->clk);
465e3ec3a3dSSoren Brinkmann 	clk_disable(sdhci_arasan->clk_ahb);
466e3ec3a3dSSoren Brinkmann 
467e3ec3a3dSSoren Brinkmann 	return 0;
468e3ec3a3dSSoren Brinkmann }
469e3ec3a3dSSoren Brinkmann 
470e3ec3a3dSSoren Brinkmann /**
471e3ec3a3dSSoren Brinkmann  * sdhci_arasan_resume - Resume method for the driver
472e3ec3a3dSSoren Brinkmann  * @dev:	Address of the device structure
473e3ec3a3dSSoren Brinkmann  *
474e3ec3a3dSSoren Brinkmann  * Resume operation after suspend
4754908460eSManish Narani  *
4764908460eSManish Narani  * Return: 0 on success and error value on error
477e3ec3a3dSSoren Brinkmann  */
478e3ec3a3dSSoren Brinkmann static int sdhci_arasan_resume(struct device *dev)
479e3ec3a3dSSoren Brinkmann {
480970f2d90SWolfram Sang 	struct sdhci_host *host = dev_get_drvdata(dev);
481e3ec3a3dSSoren Brinkmann 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
48289211418SJisheng Zhang 	struct sdhci_arasan_data *sdhci_arasan = sdhci_pltfm_priv(pltfm_host);
483e3ec3a3dSSoren Brinkmann 	int ret;
484e3ec3a3dSSoren Brinkmann 
485e3ec3a3dSSoren Brinkmann 	ret = clk_enable(sdhci_arasan->clk_ahb);
486e3ec3a3dSSoren Brinkmann 	if (ret) {
487e3ec3a3dSSoren Brinkmann 		dev_err(dev, "Cannot enable AHB clock.\n");
488e3ec3a3dSSoren Brinkmann 		return ret;
489e3ec3a3dSSoren Brinkmann 	}
490e3ec3a3dSSoren Brinkmann 
491e3ec3a3dSSoren Brinkmann 	ret = clk_enable(pltfm_host->clk);
492e3ec3a3dSSoren Brinkmann 	if (ret) {
493e3ec3a3dSSoren Brinkmann 		dev_err(dev, "Cannot enable SD clock.\n");
494e3ec3a3dSSoren Brinkmann 		return ret;
495e3ec3a3dSSoren Brinkmann 	}
496e3ec3a3dSSoren Brinkmann 
497b2db9c67SDouglas Anderson 	if (!IS_ERR(sdhci_arasan->phy) && host->mmc->actual_clock) {
49891aa3661SShawn Lin 		ret = phy_power_on(sdhci_arasan->phy);
49991aa3661SShawn Lin 		if (ret) {
50091aa3661SShawn Lin 			dev_err(dev, "Cannot power on phy.\n");
50191aa3661SShawn Lin 			return ret;
50291aa3661SShawn Lin 		}
503b2db9c67SDouglas Anderson 		sdhci_arasan->is_phy_on = true;
50491aa3661SShawn Lin 	}
50591aa3661SShawn Lin 
50684362d79SShawn Lin 	ret = sdhci_resume_host(host);
50784362d79SShawn Lin 	if (ret) {
50884362d79SShawn Lin 		dev_err(dev, "Cannot resume host.\n");
50984362d79SShawn Lin 		return ret;
51084362d79SShawn Lin 	}
51184362d79SShawn Lin 
51284362d79SShawn Lin 	if (sdhci_arasan->has_cqe)
51384362d79SShawn Lin 		return cqhci_resume(host->mmc);
51484362d79SShawn Lin 
51584362d79SShawn Lin 	return 0;
516e3ec3a3dSSoren Brinkmann }
517e3ec3a3dSSoren Brinkmann #endif /* ! CONFIG_PM_SLEEP */
518e3ec3a3dSSoren Brinkmann 
519e3ec3a3dSSoren Brinkmann static SIMPLE_DEV_PM_OPS(sdhci_arasan_dev_pm_ops, sdhci_arasan_suspend,
520e3ec3a3dSSoren Brinkmann 			 sdhci_arasan_resume);
521e3ec3a3dSSoren Brinkmann 
5223ea4666eSDouglas Anderson /**
523c390f211SDouglas Anderson  * sdhci_arasan_sdcardclk_recalc_rate - Return the card clock rate
524c390f211SDouglas Anderson  *
5254908460eSManish Narani  * @hw:			Pointer to the hardware clock structure.
5264908460eSManish Narani  * @parent_rate:		The parent rate (should be rate of clk_xin).
5274908460eSManish Narani  *
528c390f211SDouglas Anderson  * Return the current actual rate of the SD card clock.  This can be used
529c390f211SDouglas Anderson  * to communicate with out PHY.
530c390f211SDouglas Anderson  *
5314908460eSManish Narani  * Return: The card clock rate.
532c390f211SDouglas Anderson  */
533c390f211SDouglas Anderson static unsigned long sdhci_arasan_sdcardclk_recalc_rate(struct clk_hw *hw,
534c390f211SDouglas Anderson 						      unsigned long parent_rate)
535c390f211SDouglas Anderson {
536e1463618SManish Narani 	struct sdhci_arasan_clk_data *clk_data =
537e1463618SManish Narani 		container_of(hw, struct sdhci_arasan_clk_data, sdcardclk_hw);
538c390f211SDouglas Anderson 	struct sdhci_arasan_data *sdhci_arasan =
539e1463618SManish Narani 		container_of(clk_data, struct sdhci_arasan_data, clk_data);
540c390f211SDouglas Anderson 	struct sdhci_host *host = sdhci_arasan->host;
541c390f211SDouglas Anderson 
542c390f211SDouglas Anderson 	return host->mmc->actual_clock;
543c390f211SDouglas Anderson }
544c390f211SDouglas Anderson 
545c390f211SDouglas Anderson static const struct clk_ops arasan_sdcardclk_ops = {
546c390f211SDouglas Anderson 	.recalc_rate = sdhci_arasan_sdcardclk_recalc_rate,
547c390f211SDouglas Anderson };
548c390f211SDouglas Anderson 
549c390f211SDouglas Anderson /**
55007a14d1dSManish Narani  * sdhci_arasan_sampleclk_recalc_rate - Return the sampling clock rate
55107a14d1dSManish Narani  *
5524908460eSManish Narani  * @hw:			Pointer to the hardware clock structure.
5534908460eSManish Narani  * @parent_rate:		The parent rate (should be rate of clk_xin).
5544908460eSManish Narani  *
55507a14d1dSManish Narani  * Return the current actual rate of the sampling clock.  This can be used
55607a14d1dSManish Narani  * to communicate with out PHY.
55707a14d1dSManish Narani  *
5584908460eSManish Narani  * Return: The sample clock rate.
55907a14d1dSManish Narani  */
56007a14d1dSManish Narani static unsigned long sdhci_arasan_sampleclk_recalc_rate(struct clk_hw *hw,
56107a14d1dSManish Narani 						      unsigned long parent_rate)
56207a14d1dSManish Narani {
56307a14d1dSManish Narani 	struct sdhci_arasan_clk_data *clk_data =
56407a14d1dSManish Narani 		container_of(hw, struct sdhci_arasan_clk_data, sampleclk_hw);
56507a14d1dSManish Narani 	struct sdhci_arasan_data *sdhci_arasan =
56607a14d1dSManish Narani 		container_of(clk_data, struct sdhci_arasan_data, clk_data);
56707a14d1dSManish Narani 	struct sdhci_host *host = sdhci_arasan->host;
56807a14d1dSManish Narani 
56907a14d1dSManish Narani 	return host->mmc->actual_clock;
57007a14d1dSManish Narani }
57107a14d1dSManish Narani 
57207a14d1dSManish Narani static const struct clk_ops arasan_sampleclk_ops = {
57307a14d1dSManish Narani 	.recalc_rate = sdhci_arasan_sampleclk_recalc_rate,
57407a14d1dSManish Narani };
57507a14d1dSManish Narani 
57607a14d1dSManish Narani /**
577a5c8b2aeSManish Narani  * sdhci_zynqmp_sdcardclk_set_phase - Set the SD Output Clock Tap Delays
578a5c8b2aeSManish Narani  *
5794908460eSManish Narani  * @hw:			Pointer to the hardware clock structure.
5804908460eSManish Narani  * @degrees:		The clock phase shift between 0 - 359.
5814908460eSManish Narani  *
582a5c8b2aeSManish Narani  * Set the SD Output Clock Tap Delays for Output path
583a5c8b2aeSManish Narani  *
584a5c8b2aeSManish Narani  * Return: 0 on success and error value on error
585a5c8b2aeSManish Narani  */
586a5c8b2aeSManish Narani static int sdhci_zynqmp_sdcardclk_set_phase(struct clk_hw *hw, int degrees)
587a5c8b2aeSManish Narani {
588a5c8b2aeSManish Narani 	struct sdhci_arasan_clk_data *clk_data =
589a5c8b2aeSManish Narani 		container_of(hw, struct sdhci_arasan_clk_data, sdcardclk_hw);
590a5c8b2aeSManish Narani 	struct sdhci_arasan_data *sdhci_arasan =
591a5c8b2aeSManish Narani 		container_of(clk_data, struct sdhci_arasan_data, clk_data);
592a5c8b2aeSManish Narani 	struct sdhci_host *host = sdhci_arasan->host;
593a5c8b2aeSManish Narani 	struct sdhci_arasan_zynqmp_clk_data *zynqmp_clk_data =
594a5c8b2aeSManish Narani 		clk_data->clk_of_data;
595a5c8b2aeSManish Narani 	const struct zynqmp_eemi_ops *eemi_ops = zynqmp_clk_data->eemi_ops;
596a5c8b2aeSManish Narani 	const char *clk_name = clk_hw_get_name(hw);
597a5c8b2aeSManish Narani 	u32 node_id = !strcmp(clk_name, "clk_out_sd0") ? NODE_SD_0 : NODE_SD_1;
598a5c8b2aeSManish Narani 	u8 tap_delay, tap_max = 0;
599a5c8b2aeSManish Narani 	int ret;
600a5c8b2aeSManish Narani 
601a5c8b2aeSManish Narani 	/*
602a5c8b2aeSManish Narani 	 * This is applicable for SDHCI_SPEC_300 and above
603a5c8b2aeSManish Narani 	 * ZynqMP does not set phase for <=25MHz clock.
604a5c8b2aeSManish Narani 	 * If degrees is zero, no need to do anything.
605a5c8b2aeSManish Narani 	 */
606a5c8b2aeSManish Narani 	if (host->version < SDHCI_SPEC_300 ||
607a5c8b2aeSManish Narani 	    host->timing == MMC_TIMING_LEGACY ||
608a5c8b2aeSManish Narani 	    host->timing == MMC_TIMING_UHS_SDR12 || !degrees)
609a5c8b2aeSManish Narani 		return 0;
610a5c8b2aeSManish Narani 
611a5c8b2aeSManish Narani 	switch (host->timing) {
612a5c8b2aeSManish Narani 	case MMC_TIMING_MMC_HS:
613a5c8b2aeSManish Narani 	case MMC_TIMING_SD_HS:
614a5c8b2aeSManish Narani 	case MMC_TIMING_UHS_SDR25:
615a5c8b2aeSManish Narani 	case MMC_TIMING_UHS_DDR50:
616a5c8b2aeSManish Narani 	case MMC_TIMING_MMC_DDR52:
617a5c8b2aeSManish Narani 		/* For 50MHz clock, 30 Taps are available */
618a5c8b2aeSManish Narani 		tap_max = 30;
619a5c8b2aeSManish Narani 		break;
620a5c8b2aeSManish Narani 	case MMC_TIMING_UHS_SDR50:
621a5c8b2aeSManish Narani 		/* For 100MHz clock, 15 Taps are available */
622a5c8b2aeSManish Narani 		tap_max = 15;
623a5c8b2aeSManish Narani 		break;
624a5c8b2aeSManish Narani 	case MMC_TIMING_UHS_SDR104:
625a5c8b2aeSManish Narani 	case MMC_TIMING_MMC_HS200:
626a5c8b2aeSManish Narani 		/* For 200MHz clock, 8 Taps are available */
627a5c8b2aeSManish Narani 		tap_max = 8;
628a5c8b2aeSManish Narani 	default:
629a5c8b2aeSManish Narani 		break;
630a5c8b2aeSManish Narani 	}
631a5c8b2aeSManish Narani 
632a5c8b2aeSManish Narani 	tap_delay = (degrees * tap_max) / 360;
633a5c8b2aeSManish Narani 
634a5c8b2aeSManish Narani 	/* Set the Clock Phase */
635a5c8b2aeSManish Narani 	ret = eemi_ops->ioctl(node_id, IOCTL_SET_SD_TAPDELAY,
636a5c8b2aeSManish Narani 			      PM_TAPDELAY_OUTPUT, tap_delay, NULL);
637a5c8b2aeSManish Narani 	if (ret)
638a5c8b2aeSManish Narani 		pr_err("Error setting Output Tap Delay\n");
639a5c8b2aeSManish Narani 
640a5c8b2aeSManish Narani 	return ret;
641a5c8b2aeSManish Narani }
642a5c8b2aeSManish Narani 
643a5c8b2aeSManish Narani static const struct clk_ops zynqmp_sdcardclk_ops = {
644a5c8b2aeSManish Narani 	.recalc_rate = sdhci_arasan_sdcardclk_recalc_rate,
645a5c8b2aeSManish Narani 	.set_phase = sdhci_zynqmp_sdcardclk_set_phase,
646a5c8b2aeSManish Narani };
647a5c8b2aeSManish Narani 
648a5c8b2aeSManish Narani /**
649a5c8b2aeSManish Narani  * sdhci_zynqmp_sampleclk_set_phase - Set the SD Input Clock Tap Delays
650a5c8b2aeSManish Narani  *
6514908460eSManish Narani  * @hw:			Pointer to the hardware clock structure.
6524908460eSManish Narani  * @degrees:		The clock phase shift between 0 - 359.
6534908460eSManish Narani  *
654a5c8b2aeSManish Narani  * Set the SD Input Clock Tap Delays for Input path
655a5c8b2aeSManish Narani  *
656a5c8b2aeSManish Narani  * Return: 0 on success and error value on error
657a5c8b2aeSManish Narani  */
658a5c8b2aeSManish Narani static int sdhci_zynqmp_sampleclk_set_phase(struct clk_hw *hw, int degrees)
659a5c8b2aeSManish Narani {
660a5c8b2aeSManish Narani 	struct sdhci_arasan_clk_data *clk_data =
661a5c8b2aeSManish Narani 		container_of(hw, struct sdhci_arasan_clk_data, sampleclk_hw);
662a5c8b2aeSManish Narani 	struct sdhci_arasan_data *sdhci_arasan =
663a5c8b2aeSManish Narani 		container_of(clk_data, struct sdhci_arasan_data, clk_data);
664a5c8b2aeSManish Narani 	struct sdhci_host *host = sdhci_arasan->host;
665a5c8b2aeSManish Narani 	struct sdhci_arasan_zynqmp_clk_data *zynqmp_clk_data =
666a5c8b2aeSManish Narani 		clk_data->clk_of_data;
667a5c8b2aeSManish Narani 	const struct zynqmp_eemi_ops *eemi_ops = zynqmp_clk_data->eemi_ops;
668a5c8b2aeSManish Narani 	const char *clk_name = clk_hw_get_name(hw);
669a5c8b2aeSManish Narani 	u32 node_id = !strcmp(clk_name, "clk_in_sd0") ? NODE_SD_0 : NODE_SD_1;
670a5c8b2aeSManish Narani 	u8 tap_delay, tap_max = 0;
671a5c8b2aeSManish Narani 	int ret;
672a5c8b2aeSManish Narani 
673a5c8b2aeSManish Narani 	/*
674a5c8b2aeSManish Narani 	 * This is applicable for SDHCI_SPEC_300 and above
675a5c8b2aeSManish Narani 	 * ZynqMP does not set phase for <=25MHz clock.
676a5c8b2aeSManish Narani 	 * If degrees is zero, no need to do anything.
677a5c8b2aeSManish Narani 	 */
678a5c8b2aeSManish Narani 	if (host->version < SDHCI_SPEC_300 ||
679a5c8b2aeSManish Narani 	    host->timing == MMC_TIMING_LEGACY ||
680a5c8b2aeSManish Narani 	    host->timing == MMC_TIMING_UHS_SDR12 || !degrees)
681a5c8b2aeSManish Narani 		return 0;
682a5c8b2aeSManish Narani 
683a5c8b2aeSManish Narani 	switch (host->timing) {
684a5c8b2aeSManish Narani 	case MMC_TIMING_MMC_HS:
685a5c8b2aeSManish Narani 	case MMC_TIMING_SD_HS:
686a5c8b2aeSManish Narani 	case MMC_TIMING_UHS_SDR25:
687a5c8b2aeSManish Narani 	case MMC_TIMING_UHS_DDR50:
688a5c8b2aeSManish Narani 	case MMC_TIMING_MMC_DDR52:
689a5c8b2aeSManish Narani 		/* For 50MHz clock, 120 Taps are available */
690a5c8b2aeSManish Narani 		tap_max = 120;
691a5c8b2aeSManish Narani 		break;
692a5c8b2aeSManish Narani 	case MMC_TIMING_UHS_SDR50:
693a5c8b2aeSManish Narani 		/* For 100MHz clock, 60 Taps are available */
694a5c8b2aeSManish Narani 		tap_max = 60;
695a5c8b2aeSManish Narani 		break;
696a5c8b2aeSManish Narani 	case MMC_TIMING_UHS_SDR104:
697a5c8b2aeSManish Narani 	case MMC_TIMING_MMC_HS200:
698a5c8b2aeSManish Narani 		/* For 200MHz clock, 30 Taps are available */
699a5c8b2aeSManish Narani 		tap_max = 30;
700a5c8b2aeSManish Narani 	default:
701a5c8b2aeSManish Narani 		break;
702a5c8b2aeSManish Narani 	}
703a5c8b2aeSManish Narani 
704a5c8b2aeSManish Narani 	tap_delay = (degrees * tap_max) / 360;
705a5c8b2aeSManish Narani 
706a5c8b2aeSManish Narani 	/* Set the Clock Phase */
707a5c8b2aeSManish Narani 	ret = eemi_ops->ioctl(node_id, IOCTL_SET_SD_TAPDELAY,
708a5c8b2aeSManish Narani 			      PM_TAPDELAY_INPUT, tap_delay, NULL);
709a5c8b2aeSManish Narani 	if (ret)
710a5c8b2aeSManish Narani 		pr_err("Error setting Input Tap Delay\n");
711a5c8b2aeSManish Narani 
712a5c8b2aeSManish Narani 	return ret;
713a5c8b2aeSManish Narani }
714a5c8b2aeSManish Narani 
715a5c8b2aeSManish Narani static const struct clk_ops zynqmp_sampleclk_ops = {
716a5c8b2aeSManish Narani 	.recalc_rate = sdhci_arasan_sampleclk_recalc_rate,
717a5c8b2aeSManish Narani 	.set_phase = sdhci_zynqmp_sampleclk_set_phase,
718a5c8b2aeSManish Narani };
719a5c8b2aeSManish Narani 
7201a470721SManish Narani /**
7211a470721SManish Narani  * sdhci_versal_sdcardclk_set_phase - Set the SD Output Clock Tap Delays
7221a470721SManish Narani  *
7234908460eSManish Narani  * @hw:			Pointer to the hardware clock structure.
7244908460eSManish Narani  * @degrees:		The clock phase shift between 0 - 359.
7254908460eSManish Narani  *
7261a470721SManish Narani  * Set the SD Output Clock Tap Delays for Output path
7271a470721SManish Narani  *
7281a470721SManish Narani  * Return: 0 on success and error value on error
7291a470721SManish Narani  */
7301a470721SManish Narani static int sdhci_versal_sdcardclk_set_phase(struct clk_hw *hw, int degrees)
7311a470721SManish Narani {
7321a470721SManish Narani 	struct sdhci_arasan_clk_data *clk_data =
7331a470721SManish Narani 		container_of(hw, struct sdhci_arasan_clk_data, sdcardclk_hw);
7341a470721SManish Narani 	struct sdhci_arasan_data *sdhci_arasan =
7351a470721SManish Narani 		container_of(clk_data, struct sdhci_arasan_data, clk_data);
7361a470721SManish Narani 	struct sdhci_host *host = sdhci_arasan->host;
7371a470721SManish Narani 	u8 tap_delay, tap_max = 0;
7381a470721SManish Narani 
7391a470721SManish Narani 	/*
7401a470721SManish Narani 	 * This is applicable for SDHCI_SPEC_300 and above
7411a470721SManish Narani 	 * Versal does not set phase for <=25MHz clock.
7421a470721SManish Narani 	 * If degrees is zero, no need to do anything.
7431a470721SManish Narani 	 */
7441a470721SManish Narani 	if (host->version < SDHCI_SPEC_300 ||
7451a470721SManish Narani 	    host->timing == MMC_TIMING_LEGACY ||
7461a470721SManish Narani 	    host->timing == MMC_TIMING_UHS_SDR12 || !degrees)
7471a470721SManish Narani 		return 0;
7481a470721SManish Narani 
7491a470721SManish Narani 	switch (host->timing) {
7501a470721SManish Narani 	case MMC_TIMING_MMC_HS:
7511a470721SManish Narani 	case MMC_TIMING_SD_HS:
7521a470721SManish Narani 	case MMC_TIMING_UHS_SDR25:
7531a470721SManish Narani 	case MMC_TIMING_UHS_DDR50:
7541a470721SManish Narani 	case MMC_TIMING_MMC_DDR52:
7551a470721SManish Narani 		/* For 50MHz clock, 30 Taps are available */
7561a470721SManish Narani 		tap_max = 30;
7571a470721SManish Narani 		break;
7581a470721SManish Narani 	case MMC_TIMING_UHS_SDR50:
7591a470721SManish Narani 		/* For 100MHz clock, 15 Taps are available */
7601a470721SManish Narani 		tap_max = 15;
7611a470721SManish Narani 		break;
7621a470721SManish Narani 	case MMC_TIMING_UHS_SDR104:
7631a470721SManish Narani 	case MMC_TIMING_MMC_HS200:
7641a470721SManish Narani 		/* For 200MHz clock, 8 Taps are available */
7651a470721SManish Narani 		tap_max = 8;
7661a470721SManish Narani 	default:
7671a470721SManish Narani 		break;
7681a470721SManish Narani 	}
7691a470721SManish Narani 
7701a470721SManish Narani 	tap_delay = (degrees * tap_max) / 360;
7711a470721SManish Narani 
7721a470721SManish Narani 	/* Set the Clock Phase */
7731a470721SManish Narani 	if (tap_delay) {
7741a470721SManish Narani 		u32 regval;
7751a470721SManish Narani 
7761a470721SManish Narani 		regval = sdhci_readl(host, SDHCI_ARASAN_OTAPDLY_REGISTER);
7771a470721SManish Narani 		regval |= SDHCI_OTAPDLY_ENABLE;
7781a470721SManish Narani 		sdhci_writel(host, regval, SDHCI_ARASAN_OTAPDLY_REGISTER);
7791a470721SManish Narani 		regval |= tap_delay;
7801a470721SManish Narani 		sdhci_writel(host, regval, SDHCI_ARASAN_OTAPDLY_REGISTER);
7811a470721SManish Narani 	}
7821a470721SManish Narani 
783098c408bSNathan Chancellor 	return 0;
7841a470721SManish Narani }
7851a470721SManish Narani 
7861a470721SManish Narani static const struct clk_ops versal_sdcardclk_ops = {
7871a470721SManish Narani 	.recalc_rate = sdhci_arasan_sdcardclk_recalc_rate,
7881a470721SManish Narani 	.set_phase = sdhci_versal_sdcardclk_set_phase,
7891a470721SManish Narani };
7901a470721SManish Narani 
7911a470721SManish Narani /**
7921a470721SManish Narani  * sdhci_versal_sampleclk_set_phase - Set the SD Input Clock Tap Delays
7931a470721SManish Narani  *
7944908460eSManish Narani  * @hw:			Pointer to the hardware clock structure.
7954908460eSManish Narani  * @degrees:		The clock phase shift between 0 - 359.
7964908460eSManish Narani  *
7971a470721SManish Narani  * Set the SD Input Clock Tap Delays for Input path
7981a470721SManish Narani  *
7991a470721SManish Narani  * Return: 0 on success and error value on error
8001a470721SManish Narani  */
8011a470721SManish Narani static int sdhci_versal_sampleclk_set_phase(struct clk_hw *hw, int degrees)
8021a470721SManish Narani {
8031a470721SManish Narani 	struct sdhci_arasan_clk_data *clk_data =
8041a470721SManish Narani 		container_of(hw, struct sdhci_arasan_clk_data, sampleclk_hw);
8051a470721SManish Narani 	struct sdhci_arasan_data *sdhci_arasan =
8061a470721SManish Narani 		container_of(clk_data, struct sdhci_arasan_data, clk_data);
8071a470721SManish Narani 	struct sdhci_host *host = sdhci_arasan->host;
8081a470721SManish Narani 	u8 tap_delay, tap_max = 0;
8091a470721SManish Narani 
8101a470721SManish Narani 	/*
8111a470721SManish Narani 	 * This is applicable for SDHCI_SPEC_300 and above
8121a470721SManish Narani 	 * Versal does not set phase for <=25MHz clock.
8131a470721SManish Narani 	 * If degrees is zero, no need to do anything.
8141a470721SManish Narani 	 */
8151a470721SManish Narani 	if (host->version < SDHCI_SPEC_300 ||
8161a470721SManish Narani 	    host->timing == MMC_TIMING_LEGACY ||
8171a470721SManish Narani 	    host->timing == MMC_TIMING_UHS_SDR12 || !degrees)
8181a470721SManish Narani 		return 0;
8191a470721SManish Narani 
8201a470721SManish Narani 	switch (host->timing) {
8211a470721SManish Narani 	case MMC_TIMING_MMC_HS:
8221a470721SManish Narani 	case MMC_TIMING_SD_HS:
8231a470721SManish Narani 	case MMC_TIMING_UHS_SDR25:
8241a470721SManish Narani 	case MMC_TIMING_UHS_DDR50:
8251a470721SManish Narani 	case MMC_TIMING_MMC_DDR52:
8261a470721SManish Narani 		/* For 50MHz clock, 120 Taps are available */
8271a470721SManish Narani 		tap_max = 120;
8281a470721SManish Narani 		break;
8291a470721SManish Narani 	case MMC_TIMING_UHS_SDR50:
8301a470721SManish Narani 		/* For 100MHz clock, 60 Taps are available */
8311a470721SManish Narani 		tap_max = 60;
8321a470721SManish Narani 		break;
8331a470721SManish Narani 	case MMC_TIMING_UHS_SDR104:
8341a470721SManish Narani 	case MMC_TIMING_MMC_HS200:
8351a470721SManish Narani 		/* For 200MHz clock, 30 Taps are available */
8361a470721SManish Narani 		tap_max = 30;
8371a470721SManish Narani 	default:
8381a470721SManish Narani 		break;
8391a470721SManish Narani 	}
8401a470721SManish Narani 
8411a470721SManish Narani 	tap_delay = (degrees * tap_max) / 360;
8421a470721SManish Narani 
8431a470721SManish Narani 	/* Set the Clock Phase */
8441a470721SManish Narani 	if (tap_delay) {
8451a470721SManish Narani 		u32 regval;
8461a470721SManish Narani 
8471a470721SManish Narani 		regval = sdhci_readl(host, SDHCI_ARASAN_ITAPDLY_REGISTER);
8481a470721SManish Narani 		regval |= SDHCI_ITAPDLY_CHGWIN;
8491a470721SManish Narani 		sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER);
8501a470721SManish Narani 		regval |= SDHCI_ITAPDLY_ENABLE;
8511a470721SManish Narani 		sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER);
8521a470721SManish Narani 		regval |= tap_delay;
8531a470721SManish Narani 		sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER);
8541a470721SManish Narani 		regval &= ~SDHCI_ITAPDLY_CHGWIN;
8551a470721SManish Narani 		sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER);
8561a470721SManish Narani 	}
8571a470721SManish Narani 
858098c408bSNathan Chancellor 	return 0;
8591a470721SManish Narani }
8601a470721SManish Narani 
8611a470721SManish Narani static const struct clk_ops versal_sampleclk_ops = {
8621a470721SManish Narani 	.recalc_rate = sdhci_arasan_sampleclk_recalc_rate,
8631a470721SManish Narani 	.set_phase = sdhci_versal_sampleclk_set_phase,
8641a470721SManish Narani };
8651a470721SManish Narani 
8668d2e3343SManish Narani static void arasan_zynqmp_dll_reset(struct sdhci_host *host, u32 deviceid)
8678d2e3343SManish Narani {
8688d2e3343SManish Narani 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
8698d2e3343SManish Narani 	struct sdhci_arasan_data *sdhci_arasan = sdhci_pltfm_priv(pltfm_host);
8708d2e3343SManish Narani 	struct sdhci_arasan_zynqmp_clk_data *zynqmp_clk_data =
8718d2e3343SManish Narani 		sdhci_arasan->clk_data.clk_of_data;
8728d2e3343SManish Narani 	const struct zynqmp_eemi_ops *eemi_ops = zynqmp_clk_data->eemi_ops;
8738d2e3343SManish Narani 	u16 clk;
8748d2e3343SManish Narani 
8758d2e3343SManish Narani 	clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
8768d2e3343SManish Narani 	clk &= ~(SDHCI_CLOCK_CARD_EN | SDHCI_CLOCK_INT_EN);
8778d2e3343SManish Narani 	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
8788d2e3343SManish Narani 
8798d2e3343SManish Narani 	/* Issue DLL Reset */
8808d2e3343SManish Narani 	eemi_ops->ioctl(deviceid, IOCTL_SD_DLL_RESET,
8818d2e3343SManish Narani 			PM_DLL_RESET_PULSE, 0, NULL);
8828d2e3343SManish Narani 
8838d2e3343SManish Narani 	clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
8848d2e3343SManish Narani 
8858d2e3343SManish Narani 	sdhci_enable_clk(host, clk);
8868d2e3343SManish Narani }
8878d2e3343SManish Narani 
8888d2e3343SManish Narani static int arasan_zynqmp_execute_tuning(struct mmc_host *mmc, u32 opcode)
8898d2e3343SManish Narani {
8908d2e3343SManish Narani 	struct sdhci_host *host = mmc_priv(mmc);
8918d2e3343SManish Narani 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
8928d2e3343SManish Narani 	struct sdhci_arasan_data *sdhci_arasan = sdhci_pltfm_priv(pltfm_host);
8938d2e3343SManish Narani 	struct clk_hw *hw = &sdhci_arasan->clk_data.sdcardclk_hw;
8948d2e3343SManish Narani 	const char *clk_name = clk_hw_get_name(hw);
8958d2e3343SManish Narani 	u32 device_id = !strcmp(clk_name, "clk_out_sd0") ? NODE_SD_0 :
8968d2e3343SManish Narani 							   NODE_SD_1;
8978d2e3343SManish Narani 	int err;
8988d2e3343SManish Narani 
8998d2e3343SManish Narani 	arasan_zynqmp_dll_reset(host, device_id);
9008d2e3343SManish Narani 
9018d2e3343SManish Narani 	err = sdhci_execute_tuning(mmc, opcode);
9028d2e3343SManish Narani 	if (err)
9038d2e3343SManish Narani 		return err;
9048d2e3343SManish Narani 
9058d2e3343SManish Narani 	arasan_zynqmp_dll_reset(host, device_id);
9068d2e3343SManish Narani 
9078d2e3343SManish Narani 	return 0;
9088d2e3343SManish Narani }
9098d2e3343SManish Narani 
910a5c8b2aeSManish Narani /**
911b2ca77c9SShawn Lin  * sdhci_arasan_update_clockmultiplier - Set corecfg_clockmultiplier
912b2ca77c9SShawn Lin  *
9134908460eSManish Narani  * @host:		The sdhci_host
9144908460eSManish Narani  * @value:		The value to write
9154908460eSManish Narani  *
916b2ca77c9SShawn Lin  * The corecfg_clockmultiplier is supposed to contain clock multiplier
917b2ca77c9SShawn Lin  * value of programmable clock generator.
918b2ca77c9SShawn Lin  *
919b2ca77c9SShawn Lin  * NOTES:
920b2ca77c9SShawn Lin  * - Many existing devices don't seem to do this and work fine.  To keep
921b2ca77c9SShawn Lin  *   compatibility for old hardware where the device tree doesn't provide a
922b2ca77c9SShawn Lin  *   register map, this function is a noop if a soc_ctl_map hasn't been provided
923b2ca77c9SShawn Lin  *   for this platform.
924b2ca77c9SShawn Lin  * - The value of corecfg_clockmultiplier should sync with that of corresponding
925b2ca77c9SShawn Lin  *   value reading from sdhci_capability_register. So this function is called
926b2ca77c9SShawn Lin  *   once at probe time and never called again.
927b2ca77c9SShawn Lin  */
928b2ca77c9SShawn Lin static void sdhci_arasan_update_clockmultiplier(struct sdhci_host *host,
929b2ca77c9SShawn Lin 						u32 value)
930b2ca77c9SShawn Lin {
931b2ca77c9SShawn Lin 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
932b2ca77c9SShawn Lin 	struct sdhci_arasan_data *sdhci_arasan = sdhci_pltfm_priv(pltfm_host);
933b2ca77c9SShawn Lin 	const struct sdhci_arasan_soc_ctl_map *soc_ctl_map =
934b2ca77c9SShawn Lin 		sdhci_arasan->soc_ctl_map;
935b2ca77c9SShawn Lin 
936b2ca77c9SShawn Lin 	/* Having a map is optional */
937b2ca77c9SShawn Lin 	if (!soc_ctl_map)
938b2ca77c9SShawn Lin 		return;
939b2ca77c9SShawn Lin 
940b2ca77c9SShawn Lin 	/* If we have a map, we expect to have a syscon */
941b2ca77c9SShawn Lin 	if (!sdhci_arasan->soc_ctl_base) {
942b2ca77c9SShawn Lin 		pr_warn("%s: Have regmap, but no soc-ctl-syscon\n",
943b2ca77c9SShawn Lin 			mmc_hostname(host->mmc));
944b2ca77c9SShawn Lin 		return;
945b2ca77c9SShawn Lin 	}
946b2ca77c9SShawn Lin 
947b2ca77c9SShawn Lin 	sdhci_arasan_syscon_write(host, &soc_ctl_map->clockmultiplier, value);
948b2ca77c9SShawn Lin }
949b2ca77c9SShawn Lin 
950b2ca77c9SShawn Lin /**
9513ea4666eSDouglas Anderson  * sdhci_arasan_update_baseclkfreq - Set corecfg_baseclkfreq
9523ea4666eSDouglas Anderson  *
9534908460eSManish Narani  * @host:		The sdhci_host
9544908460eSManish Narani  *
9553ea4666eSDouglas Anderson  * The corecfg_baseclkfreq is supposed to contain the MHz of clk_xin.  This
9563ea4666eSDouglas Anderson  * function can be used to make that happen.
9573ea4666eSDouglas Anderson  *
9583ea4666eSDouglas Anderson  * NOTES:
9593ea4666eSDouglas Anderson  * - Many existing devices don't seem to do this and work fine.  To keep
9603ea4666eSDouglas Anderson  *   compatibility for old hardware where the device tree doesn't provide a
9613ea4666eSDouglas Anderson  *   register map, this function is a noop if a soc_ctl_map hasn't been provided
9623ea4666eSDouglas Anderson  *   for this platform.
9633ea4666eSDouglas Anderson  * - It's assumed that clk_xin is not dynamic and that we use the SDHCI divider
9643ea4666eSDouglas Anderson  *   to achieve lower clock rates.  That means that this function is called once
9653ea4666eSDouglas Anderson  *   at probe time and never called again.
9663ea4666eSDouglas Anderson  */
9673ea4666eSDouglas Anderson static void sdhci_arasan_update_baseclkfreq(struct sdhci_host *host)
9683ea4666eSDouglas Anderson {
9693ea4666eSDouglas Anderson 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
9703ea4666eSDouglas Anderson 	struct sdhci_arasan_data *sdhci_arasan = sdhci_pltfm_priv(pltfm_host);
9713ea4666eSDouglas Anderson 	const struct sdhci_arasan_soc_ctl_map *soc_ctl_map =
9723ea4666eSDouglas Anderson 		sdhci_arasan->soc_ctl_map;
9733ea4666eSDouglas Anderson 	u32 mhz = DIV_ROUND_CLOSEST(clk_get_rate(pltfm_host->clk), 1000000);
9743ea4666eSDouglas Anderson 
9753ea4666eSDouglas Anderson 	/* Having a map is optional */
9763ea4666eSDouglas Anderson 	if (!soc_ctl_map)
9773ea4666eSDouglas Anderson 		return;
9783ea4666eSDouglas Anderson 
9793ea4666eSDouglas Anderson 	/* If we have a map, we expect to have a syscon */
9803ea4666eSDouglas Anderson 	if (!sdhci_arasan->soc_ctl_base) {
9813ea4666eSDouglas Anderson 		pr_warn("%s: Have regmap, but no soc-ctl-syscon\n",
9823ea4666eSDouglas Anderson 			mmc_hostname(host->mmc));
9833ea4666eSDouglas Anderson 		return;
9843ea4666eSDouglas Anderson 	}
9853ea4666eSDouglas Anderson 
9863ea4666eSDouglas Anderson 	sdhci_arasan_syscon_write(host, &soc_ctl_map->baseclkfreq, mhz);
9873ea4666eSDouglas Anderson }
9883ea4666eSDouglas Anderson 
989f3dafc37SManish Narani static void sdhci_arasan_set_clk_delays(struct sdhci_host *host)
990f3dafc37SManish Narani {
991f3dafc37SManish Narani 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
992f3dafc37SManish Narani 	struct sdhci_arasan_data *sdhci_arasan = sdhci_pltfm_priv(pltfm_host);
993f3dafc37SManish Narani 	struct sdhci_arasan_clk_data *clk_data = &sdhci_arasan->clk_data;
994f3dafc37SManish Narani 
995f3dafc37SManish Narani 	clk_set_phase(clk_data->sampleclk,
996f3dafc37SManish Narani 		      clk_data->clk_phase_in[host->timing]);
997f3dafc37SManish Narani 	clk_set_phase(clk_data->sdcardclk,
998f3dafc37SManish Narani 		      clk_data->clk_phase_out[host->timing]);
999f3dafc37SManish Narani }
1000f3dafc37SManish Narani 
1001f3dafc37SManish Narani static void arasan_dt_read_clk_phase(struct device *dev,
1002f3dafc37SManish Narani 				     struct sdhci_arasan_clk_data *clk_data,
1003f3dafc37SManish Narani 				     unsigned int timing, const char *prop)
1004f3dafc37SManish Narani {
1005f3dafc37SManish Narani 	struct device_node *np = dev->of_node;
1006f3dafc37SManish Narani 
1007f3dafc37SManish Narani 	int clk_phase[2] = {0};
1008f3dafc37SManish Narani 
1009f3dafc37SManish Narani 	/*
1010f3dafc37SManish Narani 	 * Read Tap Delay values from DT, if the DT does not contain the
1011f3dafc37SManish Narani 	 * Tap Values then use the pre-defined values.
1012f3dafc37SManish Narani 	 */
1013f3dafc37SManish Narani 	if (of_property_read_variable_u32_array(np, prop, &clk_phase[0],
1014f3dafc37SManish Narani 						2, 0)) {
1015f3dafc37SManish Narani 		dev_dbg(dev, "Using predefined clock phase for %s = %d %d\n",
1016f3dafc37SManish Narani 			prop, clk_data->clk_phase_in[timing],
1017f3dafc37SManish Narani 			clk_data->clk_phase_out[timing]);
1018f3dafc37SManish Narani 		return;
1019f3dafc37SManish Narani 	}
1020f3dafc37SManish Narani 
1021f3dafc37SManish Narani 	/* The values read are Input and Output Clock Delays in order */
1022f3dafc37SManish Narani 	clk_data->clk_phase_in[timing] = clk_phase[0];
1023f3dafc37SManish Narani 	clk_data->clk_phase_out[timing] = clk_phase[1];
1024f3dafc37SManish Narani }
1025f3dafc37SManish Narani 
1026f3dafc37SManish Narani /**
1027f3dafc37SManish Narani  * arasan_dt_parse_clk_phases - Read Clock Delay values from DT
1028f3dafc37SManish Narani  *
1029f3dafc37SManish Narani  * @dev:		Pointer to our struct device.
1030f3dafc37SManish Narani  * @clk_data:		Pointer to the Clock Data structure
10314908460eSManish Narani  *
10324908460eSManish Narani  * Called at initialization to parse the values of Clock Delays.
1033f3dafc37SManish Narani  */
1034f3dafc37SManish Narani static void arasan_dt_parse_clk_phases(struct device *dev,
1035f3dafc37SManish Narani 				       struct sdhci_arasan_clk_data *clk_data)
1036f3dafc37SManish Narani {
1037a5c8b2aeSManish Narani 	int *iclk_phase, *oclk_phase;
1038a5c8b2aeSManish Narani 	u32 mio_bank = 0;
1039a5c8b2aeSManish Narani 	int i;
1040a5c8b2aeSManish Narani 
1041f3dafc37SManish Narani 	/*
1042f3dafc37SManish Narani 	 * This has been kept as a pointer and is assigned a function here.
1043f3dafc37SManish Narani 	 * So that different controller variants can assign their own handling
1044f3dafc37SManish Narani 	 * function.
1045f3dafc37SManish Narani 	 */
1046f3dafc37SManish Narani 	clk_data->set_clk_delays = sdhci_arasan_set_clk_delays;
1047f3dafc37SManish Narani 
1048a5c8b2aeSManish Narani 	if (of_device_is_compatible(dev->of_node, "xlnx,zynqmp-8.9a")) {
1049a5c8b2aeSManish Narani 		iclk_phase = (int [MMC_TIMING_MMC_HS400 + 1]) ZYNQMP_ICLK_PHASE;
1050a5c8b2aeSManish Narani 		oclk_phase = (int [MMC_TIMING_MMC_HS400 + 1]) ZYNQMP_OCLK_PHASE;
1051a5c8b2aeSManish Narani 
1052a5c8b2aeSManish Narani 		of_property_read_u32(dev->of_node, "xlnx,mio-bank", &mio_bank);
1053a5c8b2aeSManish Narani 		if (mio_bank == 2) {
1054a5c8b2aeSManish Narani 			oclk_phase[MMC_TIMING_UHS_SDR104] = 90;
1055a5c8b2aeSManish Narani 			oclk_phase[MMC_TIMING_MMC_HS200] = 90;
1056a5c8b2aeSManish Narani 		}
1057a5c8b2aeSManish Narani 
1058a5c8b2aeSManish Narani 		for (i = 0; i <= MMC_TIMING_MMC_HS400; i++) {
1059a5c8b2aeSManish Narani 			clk_data->clk_phase_in[i] = iclk_phase[i];
1060a5c8b2aeSManish Narani 			clk_data->clk_phase_out[i] = oclk_phase[i];
1061a5c8b2aeSManish Narani 		}
1062a5c8b2aeSManish Narani 	}
1063a5c8b2aeSManish Narani 
10641a470721SManish Narani 	if (of_device_is_compatible(dev->of_node, "xlnx,versal-8.9a")) {
10651a470721SManish Narani 		iclk_phase = (int [MMC_TIMING_MMC_HS400 + 1]) VERSAL_ICLK_PHASE;
10661a470721SManish Narani 		oclk_phase = (int [MMC_TIMING_MMC_HS400 + 1]) VERSAL_OCLK_PHASE;
10671a470721SManish Narani 
10681a470721SManish Narani 		for (i = 0; i <= MMC_TIMING_MMC_HS400; i++) {
10691a470721SManish Narani 			clk_data->clk_phase_in[i] = iclk_phase[i];
10701a470721SManish Narani 			clk_data->clk_phase_out[i] = oclk_phase[i];
10711a470721SManish Narani 		}
10721a470721SManish Narani 	}
10731a470721SManish Narani 
1074f3dafc37SManish Narani 	arasan_dt_read_clk_phase(dev, clk_data, MMC_TIMING_LEGACY,
1075f3dafc37SManish Narani 				 "clk-phase-legacy");
1076f3dafc37SManish Narani 	arasan_dt_read_clk_phase(dev, clk_data, MMC_TIMING_MMC_HS,
1077f3dafc37SManish Narani 				 "clk-phase-mmc-hs");
1078f3dafc37SManish Narani 	arasan_dt_read_clk_phase(dev, clk_data, MMC_TIMING_SD_HS,
1079f3dafc37SManish Narani 				 "clk-phase-sd-hs");
1080f3dafc37SManish Narani 	arasan_dt_read_clk_phase(dev, clk_data, MMC_TIMING_UHS_SDR12,
1081f3dafc37SManish Narani 				 "clk-phase-uhs-sdr12");
1082f3dafc37SManish Narani 	arasan_dt_read_clk_phase(dev, clk_data, MMC_TIMING_UHS_SDR25,
1083f3dafc37SManish Narani 				 "clk-phase-uhs-sdr25");
1084f3dafc37SManish Narani 	arasan_dt_read_clk_phase(dev, clk_data, MMC_TIMING_UHS_SDR50,
1085f3dafc37SManish Narani 				 "clk-phase-uhs-sdr50");
1086f3dafc37SManish Narani 	arasan_dt_read_clk_phase(dev, clk_data, MMC_TIMING_UHS_SDR104,
1087f3dafc37SManish Narani 				 "clk-phase-uhs-sdr104");
1088f3dafc37SManish Narani 	arasan_dt_read_clk_phase(dev, clk_data, MMC_TIMING_UHS_DDR50,
1089f3dafc37SManish Narani 				 "clk-phase-uhs-ddr50");
1090f3dafc37SManish Narani 	arasan_dt_read_clk_phase(dev, clk_data, MMC_TIMING_MMC_DDR52,
1091f3dafc37SManish Narani 				 "clk-phase-mmc-ddr52");
1092f3dafc37SManish Narani 	arasan_dt_read_clk_phase(dev, clk_data, MMC_TIMING_MMC_HS200,
1093f3dafc37SManish Narani 				 "clk-phase-mmc-hs200");
1094f3dafc37SManish Narani 	arasan_dt_read_clk_phase(dev, clk_data, MMC_TIMING_MMC_HS400,
1095f3dafc37SManish Narani 				 "clk-phase-mmc-hs400");
1096f3dafc37SManish Narani }
1097f3dafc37SManish Narani 
109837d3ee7cSManish Narani static const struct sdhci_pltfm_data sdhci_arasan_pdata = {
109937d3ee7cSManish Narani 	.ops = &sdhci_arasan_ops,
110037d3ee7cSManish Narani 	.quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
110137d3ee7cSManish Narani 	.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
110237d3ee7cSManish Narani 			SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN |
110337d3ee7cSManish Narani 			SDHCI_QUIRK2_STOP_WITH_TC,
110437d3ee7cSManish Narani };
110537d3ee7cSManish Narani 
110616ada730SManish Narani static const struct sdhci_arasan_clk_ops arasan_clk_ops = {
110716ada730SManish Narani 	.sdcardclk_ops = &arasan_sdcardclk_ops,
110816ada730SManish Narani 	.sampleclk_ops = &arasan_sampleclk_ops,
110916ada730SManish Narani };
111016ada730SManish Narani 
111137d3ee7cSManish Narani static struct sdhci_arasan_of_data sdhci_arasan_generic_data = {
111237d3ee7cSManish Narani 	.pdata = &sdhci_arasan_pdata,
111316ada730SManish Narani 	.clk_ops = &arasan_clk_ops,
111437d3ee7cSManish Narani };
111537d3ee7cSManish Narani 
111637d3ee7cSManish Narani static struct sdhci_arasan_of_data sdhci_arasan_rk3399_data = {
111737d3ee7cSManish Narani 	.soc_ctl_map = &rk3399_soc_ctl_map,
111837d3ee7cSManish Narani 	.pdata = &sdhci_arasan_cqe_pdata,
111916ada730SManish Narani 	.clk_ops = &arasan_clk_ops,
112037d3ee7cSManish Narani };
112137d3ee7cSManish Narani 
112237d3ee7cSManish Narani static struct sdhci_arasan_of_data intel_lgm_emmc_data = {
112337d3ee7cSManish Narani 	.soc_ctl_map = &intel_lgm_emmc_soc_ctl_map,
112437d3ee7cSManish Narani 	.pdata = &sdhci_arasan_cqe_pdata,
112516ada730SManish Narani 	.clk_ops = &arasan_clk_ops,
112637d3ee7cSManish Narani };
112737d3ee7cSManish Narani 
112837d3ee7cSManish Narani static struct sdhci_arasan_of_data intel_lgm_sdxc_data = {
112937d3ee7cSManish Narani 	.soc_ctl_map = &intel_lgm_sdxc_soc_ctl_map,
113037d3ee7cSManish Narani 	.pdata = &sdhci_arasan_cqe_pdata,
113116ada730SManish Narani 	.clk_ops = &arasan_clk_ops,
113237d3ee7cSManish Narani };
113337d3ee7cSManish Narani 
113437d3ee7cSManish Narani static const struct sdhci_pltfm_data sdhci_arasan_zynqmp_pdata = {
113537d3ee7cSManish Narani 	.ops = &sdhci_arasan_ops,
113637d3ee7cSManish Narani 	.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
113737d3ee7cSManish Narani 			SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN |
113837d3ee7cSManish Narani 			SDHCI_QUIRK2_STOP_WITH_TC,
113937d3ee7cSManish Narani };
114037d3ee7cSManish Narani 
114116ada730SManish Narani static const struct sdhci_arasan_clk_ops zynqmp_clk_ops = {
114216ada730SManish Narani 	.sdcardclk_ops = &zynqmp_sdcardclk_ops,
114316ada730SManish Narani 	.sampleclk_ops = &zynqmp_sampleclk_ops,
114416ada730SManish Narani };
114516ada730SManish Narani 
114637d3ee7cSManish Narani static struct sdhci_arasan_of_data sdhci_arasan_zynqmp_data = {
114737d3ee7cSManish Narani 	.pdata = &sdhci_arasan_zynqmp_pdata,
114816ada730SManish Narani 	.clk_ops = &zynqmp_clk_ops,
114916ada730SManish Narani };
115016ada730SManish Narani 
115116ada730SManish Narani static const struct sdhci_arasan_clk_ops versal_clk_ops = {
115216ada730SManish Narani 	.sdcardclk_ops = &versal_sdcardclk_ops,
115316ada730SManish Narani 	.sampleclk_ops = &versal_sampleclk_ops,
115437d3ee7cSManish Narani };
115537d3ee7cSManish Narani 
115637d3ee7cSManish Narani static struct sdhci_arasan_of_data sdhci_arasan_versal_data = {
115737d3ee7cSManish Narani 	.pdata = &sdhci_arasan_zynqmp_pdata,
115816ada730SManish Narani 	.clk_ops = &versal_clk_ops,
115937d3ee7cSManish Narani };
116037d3ee7cSManish Narani 
116137d3ee7cSManish Narani static const struct of_device_id sdhci_arasan_of_match[] = {
116237d3ee7cSManish Narani 	/* SoC-specific compatible strings w/ soc_ctl_map */
116337d3ee7cSManish Narani 	{
116437d3ee7cSManish Narani 		.compatible = "rockchip,rk3399-sdhci-5.1",
116537d3ee7cSManish Narani 		.data = &sdhci_arasan_rk3399_data,
116637d3ee7cSManish Narani 	},
116737d3ee7cSManish Narani 	{
116837d3ee7cSManish Narani 		.compatible = "intel,lgm-sdhci-5.1-emmc",
116937d3ee7cSManish Narani 		.data = &intel_lgm_emmc_data,
117037d3ee7cSManish Narani 	},
117137d3ee7cSManish Narani 	{
117237d3ee7cSManish Narani 		.compatible = "intel,lgm-sdhci-5.1-sdxc",
117337d3ee7cSManish Narani 		.data = &intel_lgm_sdxc_data,
117437d3ee7cSManish Narani 	},
117537d3ee7cSManish Narani 	/* Generic compatible below here */
117637d3ee7cSManish Narani 	{
117737d3ee7cSManish Narani 		.compatible = "arasan,sdhci-8.9a",
117837d3ee7cSManish Narani 		.data = &sdhci_arasan_generic_data,
117937d3ee7cSManish Narani 	},
118037d3ee7cSManish Narani 	{
118137d3ee7cSManish Narani 		.compatible = "arasan,sdhci-5.1",
118237d3ee7cSManish Narani 		.data = &sdhci_arasan_generic_data,
118337d3ee7cSManish Narani 	},
118437d3ee7cSManish Narani 	{
118537d3ee7cSManish Narani 		.compatible = "arasan,sdhci-4.9a",
118637d3ee7cSManish Narani 		.data = &sdhci_arasan_generic_data,
118737d3ee7cSManish Narani 	},
118837d3ee7cSManish Narani 	{
118937d3ee7cSManish Narani 		.compatible = "xlnx,zynqmp-8.9a",
119037d3ee7cSManish Narani 		.data = &sdhci_arasan_zynqmp_data,
119137d3ee7cSManish Narani 	},
119237d3ee7cSManish Narani 	{
119337d3ee7cSManish Narani 		.compatible = "xlnx,versal-8.9a",
119437d3ee7cSManish Narani 		.data = &sdhci_arasan_versal_data,
119537d3ee7cSManish Narani 	},
119637d3ee7cSManish Narani 	{ /* sentinel */ }
119737d3ee7cSManish Narani };
119837d3ee7cSManish Narani MODULE_DEVICE_TABLE(of, sdhci_arasan_of_match);
119937d3ee7cSManish Narani 
1200c390f211SDouglas Anderson /**
120107a14d1dSManish Narani  * sdhci_arasan_register_sdcardclk - Register the sdcardclk for a PHY to use
1202c390f211SDouglas Anderson  *
12034908460eSManish Narani  * @sdhci_arasan:	Our private data structure.
12044908460eSManish Narani  * @clk_xin:		Pointer to the functional clock
12054908460eSManish Narani  * @dev:		Pointer to our struct device.
12064908460eSManish Narani  *
1207c390f211SDouglas Anderson  * Some PHY devices need to know what the actual card clock is.  In order for
1208c390f211SDouglas Anderson  * them to find out, we'll provide a clock through the common clock framework
1209c390f211SDouglas Anderson  * for them to query.
1210c390f211SDouglas Anderson  *
12114908460eSManish Narani  * Return: 0 on success and error value on error
1212c390f211SDouglas Anderson  */
121307a14d1dSManish Narani static int
121407a14d1dSManish Narani sdhci_arasan_register_sdcardclk(struct sdhci_arasan_data *sdhci_arasan,
1215c390f211SDouglas Anderson 				struct clk *clk_xin,
1216c390f211SDouglas Anderson 				struct device *dev)
1217c390f211SDouglas Anderson {
1218e1463618SManish Narani 	struct sdhci_arasan_clk_data *clk_data = &sdhci_arasan->clk_data;
1219c390f211SDouglas Anderson 	struct device_node *np = dev->of_node;
1220c390f211SDouglas Anderson 	struct clk_init_data sdcardclk_init;
1221c390f211SDouglas Anderson 	const char *parent_clk_name;
1222c390f211SDouglas Anderson 	int ret;
1223c390f211SDouglas Anderson 
1224c390f211SDouglas Anderson 	ret = of_property_read_string_index(np, "clock-output-names", 0,
1225c390f211SDouglas Anderson 					    &sdcardclk_init.name);
1226c390f211SDouglas Anderson 	if (ret) {
1227c390f211SDouglas Anderson 		dev_err(dev, "DT has #clock-cells but no clock-output-names\n");
1228c390f211SDouglas Anderson 		return ret;
1229c390f211SDouglas Anderson 	}
1230c390f211SDouglas Anderson 
1231c390f211SDouglas Anderson 	parent_clk_name = __clk_get_name(clk_xin);
1232c390f211SDouglas Anderson 	sdcardclk_init.parent_names = &parent_clk_name;
1233c390f211SDouglas Anderson 	sdcardclk_init.num_parents = 1;
1234c390f211SDouglas Anderson 	sdcardclk_init.flags = CLK_GET_RATE_NOCACHE;
123516ada730SManish Narani 	sdcardclk_init.ops = sdhci_arasan->clk_ops->sdcardclk_ops;
1236c390f211SDouglas Anderson 
1237e1463618SManish Narani 	clk_data->sdcardclk_hw.init = &sdcardclk_init;
1238e1463618SManish Narani 	clk_data->sdcardclk =
1239e1463618SManish Narani 		devm_clk_register(dev, &clk_data->sdcardclk_hw);
1240e1463618SManish Narani 	clk_data->sdcardclk_hw.init = NULL;
1241c390f211SDouglas Anderson 
1242c390f211SDouglas Anderson 	ret = of_clk_add_provider(np, of_clk_src_simple_get,
1243e1463618SManish Narani 				  clk_data->sdcardclk);
1244c390f211SDouglas Anderson 	if (ret)
124507a14d1dSManish Narani 		dev_err(dev, "Failed to add sdcard clock provider\n");
124607a14d1dSManish Narani 
124707a14d1dSManish Narani 	return ret;
124807a14d1dSManish Narani }
124907a14d1dSManish Narani 
125007a14d1dSManish Narani /**
125107a14d1dSManish Narani  * sdhci_arasan_register_sampleclk - Register the sampleclk for a PHY to use
125207a14d1dSManish Narani  *
12534908460eSManish Narani  * @sdhci_arasan:	Our private data structure.
12544908460eSManish Narani  * @clk_xin:		Pointer to the functional clock
12554908460eSManish Narani  * @dev:		Pointer to our struct device.
12564908460eSManish Narani  *
125707a14d1dSManish Narani  * Some PHY devices need to know what the actual card clock is.  In order for
125807a14d1dSManish Narani  * them to find out, we'll provide a clock through the common clock framework
125907a14d1dSManish Narani  * for them to query.
126007a14d1dSManish Narani  *
12614908460eSManish Narani  * Return: 0 on success and error value on error
126207a14d1dSManish Narani  */
126307a14d1dSManish Narani static int
126407a14d1dSManish Narani sdhci_arasan_register_sampleclk(struct sdhci_arasan_data *sdhci_arasan,
126507a14d1dSManish Narani 				struct clk *clk_xin,
126607a14d1dSManish Narani 				struct device *dev)
126707a14d1dSManish Narani {
126807a14d1dSManish Narani 	struct sdhci_arasan_clk_data *clk_data = &sdhci_arasan->clk_data;
126907a14d1dSManish Narani 	struct device_node *np = dev->of_node;
127007a14d1dSManish Narani 	struct clk_init_data sampleclk_init;
127107a14d1dSManish Narani 	const char *parent_clk_name;
127207a14d1dSManish Narani 	int ret;
127307a14d1dSManish Narani 
127407a14d1dSManish Narani 	ret = of_property_read_string_index(np, "clock-output-names", 1,
127507a14d1dSManish Narani 					    &sampleclk_init.name);
127607a14d1dSManish Narani 	if (ret) {
127707a14d1dSManish Narani 		dev_err(dev, "DT has #clock-cells but no clock-output-names\n");
127807a14d1dSManish Narani 		return ret;
127907a14d1dSManish Narani 	}
128007a14d1dSManish Narani 
128107a14d1dSManish Narani 	parent_clk_name = __clk_get_name(clk_xin);
128207a14d1dSManish Narani 	sampleclk_init.parent_names = &parent_clk_name;
128307a14d1dSManish Narani 	sampleclk_init.num_parents = 1;
128407a14d1dSManish Narani 	sampleclk_init.flags = CLK_GET_RATE_NOCACHE;
128516ada730SManish Narani 	sampleclk_init.ops = sdhci_arasan->clk_ops->sampleclk_ops;
128607a14d1dSManish Narani 
128707a14d1dSManish Narani 	clk_data->sampleclk_hw.init = &sampleclk_init;
128807a14d1dSManish Narani 	clk_data->sampleclk =
128907a14d1dSManish Narani 		devm_clk_register(dev, &clk_data->sampleclk_hw);
129007a14d1dSManish Narani 	clk_data->sampleclk_hw.init = NULL;
129107a14d1dSManish Narani 
129207a14d1dSManish Narani 	ret = of_clk_add_provider(np, of_clk_src_simple_get,
129307a14d1dSManish Narani 				  clk_data->sampleclk);
129407a14d1dSManish Narani 	if (ret)
129507a14d1dSManish Narani 		dev_err(dev, "Failed to add sample clock provider\n");
1296c390f211SDouglas Anderson 
1297c390f211SDouglas Anderson 	return ret;
1298c390f211SDouglas Anderson }
1299c390f211SDouglas Anderson 
1300c390f211SDouglas Anderson /**
1301c390f211SDouglas Anderson  * sdhci_arasan_unregister_sdclk - Undoes sdhci_arasan_register_sdclk()
1302c390f211SDouglas Anderson  *
13034908460eSManish Narani  * @dev:		Pointer to our struct device.
13044908460eSManish Narani  *
1305c390f211SDouglas Anderson  * Should be called any time we're exiting and sdhci_arasan_register_sdclk()
1306c390f211SDouglas Anderson  * returned success.
1307c390f211SDouglas Anderson  */
1308c390f211SDouglas Anderson static void sdhci_arasan_unregister_sdclk(struct device *dev)
1309c390f211SDouglas Anderson {
1310c390f211SDouglas Anderson 	struct device_node *np = dev->of_node;
1311c390f211SDouglas Anderson 
1312c390f211SDouglas Anderson 	if (!of_find_property(np, "#clock-cells", NULL))
1313c390f211SDouglas Anderson 		return;
1314c390f211SDouglas Anderson 
1315c390f211SDouglas Anderson 	of_clk_del_provider(dev->of_node);
1316c390f211SDouglas Anderson }
1317c390f211SDouglas Anderson 
131807a14d1dSManish Narani /**
131907a14d1dSManish Narani  * sdhci_arasan_register_sdclk - Register the sdcardclk for a PHY to use
132007a14d1dSManish Narani  *
13214908460eSManish Narani  * @sdhci_arasan:	Our private data structure.
13224908460eSManish Narani  * @clk_xin:		Pointer to the functional clock
13234908460eSManish Narani  * @dev:		Pointer to our struct device.
13244908460eSManish Narani  *
132507a14d1dSManish Narani  * Some PHY devices need to know what the actual card clock is.  In order for
132607a14d1dSManish Narani  * them to find out, we'll provide a clock through the common clock framework
132707a14d1dSManish Narani  * for them to query.
132807a14d1dSManish Narani  *
132907a14d1dSManish Narani  * Note: without seriously re-architecting SDHCI's clock code and testing on
133007a14d1dSManish Narani  * all platforms, there's no way to create a totally beautiful clock here
133107a14d1dSManish Narani  * with all clock ops implemented.  Instead, we'll just create a clock that can
133207a14d1dSManish Narani  * be queried and set the CLK_GET_RATE_NOCACHE attribute to tell common clock
133307a14d1dSManish Narani  * framework that we're doing things behind its back.  This should be sufficient
133407a14d1dSManish Narani  * to create nice clean device tree bindings and later (if needed) we can try
133507a14d1dSManish Narani  * re-architecting SDHCI if we see some benefit to it.
133607a14d1dSManish Narani  *
13374908460eSManish Narani  * Return: 0 on success and error value on error
133807a14d1dSManish Narani  */
133907a14d1dSManish Narani static int sdhci_arasan_register_sdclk(struct sdhci_arasan_data *sdhci_arasan,
134007a14d1dSManish Narani 				       struct clk *clk_xin,
134107a14d1dSManish Narani 				       struct device *dev)
134207a14d1dSManish Narani {
134307a14d1dSManish Narani 	struct device_node *np = dev->of_node;
134407a14d1dSManish Narani 	u32 num_clks = 0;
134507a14d1dSManish Narani 	int ret;
134607a14d1dSManish Narani 
134707a14d1dSManish Narani 	/* Providing a clock to the PHY is optional; no error if missing */
134807a14d1dSManish Narani 	if (of_property_read_u32(np, "#clock-cells", &num_clks) < 0)
134907a14d1dSManish Narani 		return 0;
135007a14d1dSManish Narani 
135107a14d1dSManish Narani 	ret = sdhci_arasan_register_sdcardclk(sdhci_arasan, clk_xin, dev);
135207a14d1dSManish Narani 	if (ret)
135307a14d1dSManish Narani 		return ret;
135407a14d1dSManish Narani 
135507a14d1dSManish Narani 	if (num_clks) {
135607a14d1dSManish Narani 		ret = sdhci_arasan_register_sampleclk(sdhci_arasan, clk_xin,
135707a14d1dSManish Narani 						      dev);
135807a14d1dSManish Narani 		if (ret) {
135907a14d1dSManish Narani 			sdhci_arasan_unregister_sdclk(dev);
136007a14d1dSManish Narani 			return ret;
136107a14d1dSManish Narani 		}
136207a14d1dSManish Narani 	}
136307a14d1dSManish Narani 
136407a14d1dSManish Narani 	return 0;
136507a14d1dSManish Narani }
136607a14d1dSManish Narani 
136784362d79SShawn Lin static int sdhci_arasan_add_host(struct sdhci_arasan_data *sdhci_arasan)
136884362d79SShawn Lin {
136984362d79SShawn Lin 	struct sdhci_host *host = sdhci_arasan->host;
137084362d79SShawn Lin 	struct cqhci_host *cq_host;
137184362d79SShawn Lin 	bool dma64;
137284362d79SShawn Lin 	int ret;
137384362d79SShawn Lin 
137484362d79SShawn Lin 	if (!sdhci_arasan->has_cqe)
137584362d79SShawn Lin 		return sdhci_add_host(host);
137684362d79SShawn Lin 
137784362d79SShawn Lin 	ret = sdhci_setup_host(host);
137884362d79SShawn Lin 	if (ret)
137984362d79SShawn Lin 		return ret;
138084362d79SShawn Lin 
138184362d79SShawn Lin 	cq_host = devm_kzalloc(host->mmc->parent,
138284362d79SShawn Lin 			       sizeof(*cq_host), GFP_KERNEL);
138384362d79SShawn Lin 	if (!cq_host) {
138484362d79SShawn Lin 		ret = -ENOMEM;
138584362d79SShawn Lin 		goto cleanup;
138684362d79SShawn Lin 	}
138784362d79SShawn Lin 
138884362d79SShawn Lin 	cq_host->mmio = host->ioaddr + SDHCI_ARASAN_CQE_BASE_ADDR;
138984362d79SShawn Lin 	cq_host->ops = &sdhci_arasan_cqhci_ops;
139084362d79SShawn Lin 
139184362d79SShawn Lin 	dma64 = host->flags & SDHCI_USE_64_BIT_DMA;
139284362d79SShawn Lin 	if (dma64)
139384362d79SShawn Lin 		cq_host->caps |= CQHCI_TASK_DESC_SZ_128;
139484362d79SShawn Lin 
139584362d79SShawn Lin 	ret = cqhci_init(cq_host, host->mmc, dma64);
139684362d79SShawn Lin 	if (ret)
139784362d79SShawn Lin 		goto cleanup;
139884362d79SShawn Lin 
139984362d79SShawn Lin 	ret = __sdhci_add_host(host);
140084362d79SShawn Lin 	if (ret)
140184362d79SShawn Lin 		goto cleanup;
140284362d79SShawn Lin 
140384362d79SShawn Lin 	return 0;
140484362d79SShawn Lin 
140584362d79SShawn Lin cleanup:
140684362d79SShawn Lin 	sdhci_cleanup_host(host);
140784362d79SShawn Lin 	return ret;
140884362d79SShawn Lin }
140984362d79SShawn Lin 
1410e3ec3a3dSSoren Brinkmann static int sdhci_arasan_probe(struct platform_device *pdev)
1411e3ec3a3dSSoren Brinkmann {
1412e3ec3a3dSSoren Brinkmann 	int ret;
14133ea4666eSDouglas Anderson 	const struct of_device_id *match;
14143ea4666eSDouglas Anderson 	struct device_node *node;
1415e3ec3a3dSSoren Brinkmann 	struct clk *clk_xin;
1416e3ec3a3dSSoren Brinkmann 	struct sdhci_host *host;
1417e3ec3a3dSSoren Brinkmann 	struct sdhci_pltfm_host *pltfm_host;
1418e3ec3a3dSSoren Brinkmann 	struct sdhci_arasan_data *sdhci_arasan;
14193794c542SZach Brown 	struct device_node *np = pdev->dev.of_node;
142006b23ca0SFaiz Abbas 	const struct sdhci_arasan_of_data *data;
1421e3ec3a3dSSoren Brinkmann 
142206b23ca0SFaiz Abbas 	match = of_match_node(sdhci_arasan_of_match, pdev->dev.of_node);
142306b23ca0SFaiz Abbas 	data = match->data;
142406b23ca0SFaiz Abbas 	host = sdhci_pltfm_init(pdev, data->pdata, sizeof(*sdhci_arasan));
142584362d79SShawn Lin 
142689211418SJisheng Zhang 	if (IS_ERR(host))
142789211418SJisheng Zhang 		return PTR_ERR(host);
142889211418SJisheng Zhang 
142989211418SJisheng Zhang 	pltfm_host = sdhci_priv(host);
143089211418SJisheng Zhang 	sdhci_arasan = sdhci_pltfm_priv(pltfm_host);
1431c390f211SDouglas Anderson 	sdhci_arasan->host = host;
1432e3ec3a3dSSoren Brinkmann 
143306b23ca0SFaiz Abbas 	sdhci_arasan->soc_ctl_map = data->soc_ctl_map;
143416ada730SManish Narani 	sdhci_arasan->clk_ops = data->clk_ops;
14353ea4666eSDouglas Anderson 
14363ea4666eSDouglas Anderson 	node = of_parse_phandle(pdev->dev.of_node, "arasan,soc-ctl-syscon", 0);
14373ea4666eSDouglas Anderson 	if (node) {
14383ea4666eSDouglas Anderson 		sdhci_arasan->soc_ctl_base = syscon_node_to_regmap(node);
14393ea4666eSDouglas Anderson 		of_node_put(node);
14403ea4666eSDouglas Anderson 
14413ea4666eSDouglas Anderson 		if (IS_ERR(sdhci_arasan->soc_ctl_base)) {
14423ea4666eSDouglas Anderson 			ret = PTR_ERR(sdhci_arasan->soc_ctl_base);
14433ea4666eSDouglas Anderson 			if (ret != -EPROBE_DEFER)
14443ea4666eSDouglas Anderson 				dev_err(&pdev->dev, "Can't get syscon: %d\n",
14453ea4666eSDouglas Anderson 					ret);
14463ea4666eSDouglas Anderson 			goto err_pltfm_free;
14473ea4666eSDouglas Anderson 		}
14483ea4666eSDouglas Anderson 	}
14493ea4666eSDouglas Anderson 
1450e3ec3a3dSSoren Brinkmann 	sdhci_arasan->clk_ahb = devm_clk_get(&pdev->dev, "clk_ahb");
1451e3ec3a3dSSoren Brinkmann 	if (IS_ERR(sdhci_arasan->clk_ahb)) {
1452e3ec3a3dSSoren Brinkmann 		dev_err(&pdev->dev, "clk_ahb clock not found.\n");
1453278d0962SShawn Lin 		ret = PTR_ERR(sdhci_arasan->clk_ahb);
1454278d0962SShawn Lin 		goto err_pltfm_free;
1455e3ec3a3dSSoren Brinkmann 	}
1456e3ec3a3dSSoren Brinkmann 
1457e3ec3a3dSSoren Brinkmann 	clk_xin = devm_clk_get(&pdev->dev, "clk_xin");
1458e3ec3a3dSSoren Brinkmann 	if (IS_ERR(clk_xin)) {
1459e3ec3a3dSSoren Brinkmann 		dev_err(&pdev->dev, "clk_xin clock not found.\n");
1460278d0962SShawn Lin 		ret = PTR_ERR(clk_xin);
1461278d0962SShawn Lin 		goto err_pltfm_free;
1462e3ec3a3dSSoren Brinkmann 	}
1463e3ec3a3dSSoren Brinkmann 
1464e3ec3a3dSSoren Brinkmann 	ret = clk_prepare_enable(sdhci_arasan->clk_ahb);
1465e3ec3a3dSSoren Brinkmann 	if (ret) {
1466e3ec3a3dSSoren Brinkmann 		dev_err(&pdev->dev, "Unable to enable AHB clock.\n");
1467278d0962SShawn Lin 		goto err_pltfm_free;
1468e3ec3a3dSSoren Brinkmann 	}
1469e3ec3a3dSSoren Brinkmann 
1470e3ec3a3dSSoren Brinkmann 	ret = clk_prepare_enable(clk_xin);
1471e3ec3a3dSSoren Brinkmann 	if (ret) {
1472e3ec3a3dSSoren Brinkmann 		dev_err(&pdev->dev, "Unable to enable SD clock.\n");
1473e3ec3a3dSSoren Brinkmann 		goto clk_dis_ahb;
1474e3ec3a3dSSoren Brinkmann 	}
1475e3ec3a3dSSoren Brinkmann 
1476e3ec3a3dSSoren Brinkmann 	sdhci_get_of_property(pdev);
14773794c542SZach Brown 
14783794c542SZach Brown 	if (of_property_read_bool(np, "xlnx,fails-without-test-cd"))
14793794c542SZach Brown 		sdhci_arasan->quirks |= SDHCI_ARASAN_QUIRK_FORCE_CDTEST;
14803794c542SZach Brown 
14813f2c7d5dSHelmut Grohne 	if (of_property_read_bool(np, "xlnx,int-clock-stable-broken"))
14823f2c7d5dSHelmut Grohne 		sdhci_arasan->quirks |= SDHCI_ARASAN_QUIRK_CLOCK_UNSTABLE;
14833f2c7d5dSHelmut Grohne 
1484e3ec3a3dSSoren Brinkmann 	pltfm_host->clk = clk_xin;
1485e3ec3a3dSSoren Brinkmann 
1486b2ca77c9SShawn Lin 	if (of_device_is_compatible(pdev->dev.of_node,
1487b2ca77c9SShawn Lin 				    "rockchip,rk3399-sdhci-5.1"))
1488b2ca77c9SShawn Lin 		sdhci_arasan_update_clockmultiplier(host, 0x0);
1489b2ca77c9SShawn Lin 
14903ea4666eSDouglas Anderson 	sdhci_arasan_update_baseclkfreq(host);
14913ea4666eSDouglas Anderson 
1492c390f211SDouglas Anderson 	ret = sdhci_arasan_register_sdclk(sdhci_arasan, clk_xin, &pdev->dev);
1493c390f211SDouglas Anderson 	if (ret)
1494c390f211SDouglas Anderson 		goto clk_disable_all;
1495c390f211SDouglas Anderson 
1496a5c8b2aeSManish Narani 	if (of_device_is_compatible(np, "xlnx,zynqmp-8.9a")) {
1497a5c8b2aeSManish Narani 		struct sdhci_arasan_zynqmp_clk_data *zynqmp_clk_data;
1498a5c8b2aeSManish Narani 		const struct zynqmp_eemi_ops *eemi_ops;
1499a5c8b2aeSManish Narani 
1500a5c8b2aeSManish Narani 		zynqmp_clk_data = devm_kzalloc(&pdev->dev,
1501a5c8b2aeSManish Narani 					       sizeof(*zynqmp_clk_data),
1502a5c8b2aeSManish Narani 					       GFP_KERNEL);
1503a5c8b2aeSManish Narani 		eemi_ops = zynqmp_pm_get_eemi_ops();
1504a5c8b2aeSManish Narani 		if (IS_ERR(eemi_ops)) {
1505a5c8b2aeSManish Narani 			ret = PTR_ERR(eemi_ops);
1506a5c8b2aeSManish Narani 			goto unreg_clk;
1507a5c8b2aeSManish Narani 		}
1508a5c8b2aeSManish Narani 
1509a5c8b2aeSManish Narani 		zynqmp_clk_data->eemi_ops = eemi_ops;
1510a5c8b2aeSManish Narani 		sdhci_arasan->clk_data.clk_of_data = zynqmp_clk_data;
15118d2e3343SManish Narani 		host->mmc_host_ops.execute_tuning =
15128d2e3343SManish Narani 			arasan_zynqmp_execute_tuning;
1513a5c8b2aeSManish Narani 	}
1514a5c8b2aeSManish Narani 
1515f3dafc37SManish Narani 	arasan_dt_parse_clk_phases(&pdev->dev, &sdhci_arasan->clk_data);
1516f3dafc37SManish Narani 
151716b23787SMichal Simek 	ret = mmc_of_parse(host->mmc);
151816b23787SMichal Simek 	if (ret) {
151960208a26SMichal Simek 		if (ret != -EPROBE_DEFER)
1520940e698cSShubhrajyoti Datta 			dev_err(&pdev->dev, "parsing dt failed (%d)\n", ret);
1521c390f211SDouglas Anderson 		goto unreg_clk;
152216b23787SMichal Simek 	}
152316b23787SMichal Simek 
152491aa3661SShawn Lin 	sdhci_arasan->phy = ERR_PTR(-ENODEV);
152591aa3661SShawn Lin 	if (of_device_is_compatible(pdev->dev.of_node,
152691aa3661SShawn Lin 				    "arasan,sdhci-5.1")) {
152791aa3661SShawn Lin 		sdhci_arasan->phy = devm_phy_get(&pdev->dev,
152891aa3661SShawn Lin 						 "phy_arasan");
152991aa3661SShawn Lin 		if (IS_ERR(sdhci_arasan->phy)) {
153091aa3661SShawn Lin 			ret = PTR_ERR(sdhci_arasan->phy);
153191aa3661SShawn Lin 			dev_err(&pdev->dev, "No phy for arasan,sdhci-5.1.\n");
1532c390f211SDouglas Anderson 			goto unreg_clk;
153391aa3661SShawn Lin 		}
153491aa3661SShawn Lin 
153591aa3661SShawn Lin 		ret = phy_init(sdhci_arasan->phy);
153691aa3661SShawn Lin 		if (ret < 0) {
153791aa3661SShawn Lin 			dev_err(&pdev->dev, "phy_init err.\n");
1538c390f211SDouglas Anderson 			goto unreg_clk;
153991aa3661SShawn Lin 		}
154091aa3661SShawn Lin 
1541a05c8465SShawn Lin 		host->mmc_host_ops.hs400_enhanced_strobe =
1542a05c8465SShawn Lin 					sdhci_arasan_hs400_enhanced_strobe;
15438a3bee9bSShawn Lin 		host->mmc_host_ops.start_signal_voltage_switch =
15448a3bee9bSShawn Lin 					sdhci_arasan_voltage_switch;
154584362d79SShawn Lin 		sdhci_arasan->has_cqe = true;
15467bda9482SChristoph Muellner 		host->mmc->caps2 |= MMC_CAP2_CQE;
15477bda9482SChristoph Muellner 
15487bda9482SChristoph Muellner 		if (!of_property_read_bool(np, "disable-cqe-dcmd"))
15497bda9482SChristoph Muellner 			host->mmc->caps2 |= MMC_CAP2_CQE_DCMD;
155091aa3661SShawn Lin 	}
155191aa3661SShawn Lin 
155284362d79SShawn Lin 	ret = sdhci_arasan_add_host(sdhci_arasan);
1553b1df9de7SMike Looijmans 	if (ret)
155491aa3661SShawn Lin 		goto err_add_host;
1555e3ec3a3dSSoren Brinkmann 
1556e3ec3a3dSSoren Brinkmann 	return 0;
1557e3ec3a3dSSoren Brinkmann 
155891aa3661SShawn Lin err_add_host:
155991aa3661SShawn Lin 	if (!IS_ERR(sdhci_arasan->phy))
156091aa3661SShawn Lin 		phy_exit(sdhci_arasan->phy);
1561c390f211SDouglas Anderson unreg_clk:
1562c390f211SDouglas Anderson 	sdhci_arasan_unregister_sdclk(&pdev->dev);
1563e3ec3a3dSSoren Brinkmann clk_disable_all:
1564e3ec3a3dSSoren Brinkmann 	clk_disable_unprepare(clk_xin);
1565e3ec3a3dSSoren Brinkmann clk_dis_ahb:
1566e3ec3a3dSSoren Brinkmann 	clk_disable_unprepare(sdhci_arasan->clk_ahb);
1567278d0962SShawn Lin err_pltfm_free:
1568278d0962SShawn Lin 	sdhci_pltfm_free(pdev);
1569e3ec3a3dSSoren Brinkmann 	return ret;
1570e3ec3a3dSSoren Brinkmann }
1571e3ec3a3dSSoren Brinkmann 
1572e3ec3a3dSSoren Brinkmann static int sdhci_arasan_remove(struct platform_device *pdev)
1573e3ec3a3dSSoren Brinkmann {
15740c7fe32eSJisheng Zhang 	int ret;
1575e3ec3a3dSSoren Brinkmann 	struct sdhci_host *host = platform_get_drvdata(pdev);
1576e3ec3a3dSSoren Brinkmann 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
157789211418SJisheng Zhang 	struct sdhci_arasan_data *sdhci_arasan = sdhci_pltfm_priv(pltfm_host);
157889211418SJisheng Zhang 	struct clk *clk_ahb = sdhci_arasan->clk_ahb;
1579e3ec3a3dSSoren Brinkmann 
158091aa3661SShawn Lin 	if (!IS_ERR(sdhci_arasan->phy)) {
1581b2db9c67SDouglas Anderson 		if (sdhci_arasan->is_phy_on)
158291aa3661SShawn Lin 			phy_power_off(sdhci_arasan->phy);
158391aa3661SShawn Lin 		phy_exit(sdhci_arasan->phy);
158491aa3661SShawn Lin 	}
158591aa3661SShawn Lin 
1586c390f211SDouglas Anderson 	sdhci_arasan_unregister_sdclk(&pdev->dev);
1587c390f211SDouglas Anderson 
15880c7fe32eSJisheng Zhang 	ret = sdhci_pltfm_unregister(pdev);
15890c7fe32eSJisheng Zhang 
159089211418SJisheng Zhang 	clk_disable_unprepare(clk_ahb);
1591e3ec3a3dSSoren Brinkmann 
15920c7fe32eSJisheng Zhang 	return ret;
1593e3ec3a3dSSoren Brinkmann }
1594e3ec3a3dSSoren Brinkmann 
1595e3ec3a3dSSoren Brinkmann static struct platform_driver sdhci_arasan_driver = {
1596e3ec3a3dSSoren Brinkmann 	.driver = {
1597e3ec3a3dSSoren Brinkmann 		.name = "sdhci-arasan",
1598e3ec3a3dSSoren Brinkmann 		.of_match_table = sdhci_arasan_of_match,
1599e3ec3a3dSSoren Brinkmann 		.pm = &sdhci_arasan_dev_pm_ops,
1600e3ec3a3dSSoren Brinkmann 	},
1601e3ec3a3dSSoren Brinkmann 	.probe = sdhci_arasan_probe,
1602e3ec3a3dSSoren Brinkmann 	.remove = sdhci_arasan_remove,
1603e3ec3a3dSSoren Brinkmann };
1604e3ec3a3dSSoren Brinkmann 
1605e3ec3a3dSSoren Brinkmann module_platform_driver(sdhci_arasan_driver);
1606e3ec3a3dSSoren Brinkmann 
1607e3ec3a3dSSoren Brinkmann MODULE_DESCRIPTION("Driver for the Arasan SDHCI Controller");
1608e3ec3a3dSSoren Brinkmann MODULE_AUTHOR("Soeren Brinkmann <soren.brinkmann@xilinx.com>");
1609e3ec3a3dSSoren Brinkmann MODULE_LICENSE("GPL");
1610