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