1*df7320baSZhe Wang // SPDX-License-Identifier: GPL-2.0-only 2*df7320baSZhe Wang /* 3*df7320baSZhe Wang * UNISOC UFS Host Controller driver 4*df7320baSZhe Wang * 5*df7320baSZhe Wang * Copyright (C) 2022 Unisoc, Inc. 6*df7320baSZhe Wang * Author: Zhe Wang <zhe.wang1@unisoc.com> 7*df7320baSZhe Wang */ 8*df7320baSZhe Wang 9*df7320baSZhe Wang #include <linux/arm-smccc.h> 10*df7320baSZhe Wang #include <linux/mfd/syscon.h> 11*df7320baSZhe Wang #include <linux/of.h> 12*df7320baSZhe Wang #include <linux/platform_device.h> 13*df7320baSZhe Wang #include <linux/regmap.h> 14*df7320baSZhe Wang #include <linux/reset.h> 15*df7320baSZhe Wang #include <linux/regulator/consumer.h> 16*df7320baSZhe Wang 17*df7320baSZhe Wang #include <ufs/ufshcd.h> 18*df7320baSZhe Wang #include "ufshcd-pltfrm.h" 19*df7320baSZhe Wang #include "ufs-sprd.h" 20*df7320baSZhe Wang 21*df7320baSZhe Wang static const struct of_device_id ufs_sprd_of_match[]; 22*df7320baSZhe Wang 23*df7320baSZhe Wang static struct ufs_sprd_priv *ufs_sprd_get_priv_data(struct ufs_hba *hba) 24*df7320baSZhe Wang { 25*df7320baSZhe Wang struct ufs_sprd_host *host = ufshcd_get_variant(hba); 26*df7320baSZhe Wang 27*df7320baSZhe Wang WARN_ON(!host->priv); 28*df7320baSZhe Wang return host->priv; 29*df7320baSZhe Wang } 30*df7320baSZhe Wang 31*df7320baSZhe Wang static void ufs_sprd_regmap_update(struct ufs_sprd_priv *priv, unsigned int index, 32*df7320baSZhe Wang unsigned int reg, unsigned int bits, unsigned int val) 33*df7320baSZhe Wang { 34*df7320baSZhe Wang regmap_update_bits(priv->sysci[index].regmap, reg, bits, val); 35*df7320baSZhe Wang } 36*df7320baSZhe Wang 37*df7320baSZhe Wang static void ufs_sprd_regmap_read(struct ufs_sprd_priv *priv, unsigned int index, 38*df7320baSZhe Wang unsigned int reg, unsigned int *val) 39*df7320baSZhe Wang { 40*df7320baSZhe Wang regmap_read(priv->sysci[index].regmap, reg, val); 41*df7320baSZhe Wang } 42*df7320baSZhe Wang 43*df7320baSZhe Wang static void ufs_sprd_get_unipro_ver(struct ufs_hba *hba) 44*df7320baSZhe Wang { 45*df7320baSZhe Wang struct ufs_sprd_host *host = ufshcd_get_variant(hba); 46*df7320baSZhe Wang 47*df7320baSZhe Wang if (ufshcd_dme_get(hba, UIC_ARG_MIB(PA_LOCALVERINFO), &host->unipro_ver)) 48*df7320baSZhe Wang host->unipro_ver = 0; 49*df7320baSZhe Wang } 50*df7320baSZhe Wang 51*df7320baSZhe Wang static void ufs_sprd_ctrl_uic_compl(struct ufs_hba *hba, bool enable) 52*df7320baSZhe Wang { 53*df7320baSZhe Wang u32 set = ufshcd_readl(hba, REG_INTERRUPT_ENABLE); 54*df7320baSZhe Wang 55*df7320baSZhe Wang if (enable == true) 56*df7320baSZhe Wang set |= UIC_COMMAND_COMPL; 57*df7320baSZhe Wang else 58*df7320baSZhe Wang set &= ~UIC_COMMAND_COMPL; 59*df7320baSZhe Wang ufshcd_writel(hba, set, REG_INTERRUPT_ENABLE); 60*df7320baSZhe Wang } 61*df7320baSZhe Wang 62*df7320baSZhe Wang static int ufs_sprd_get_reset_ctrl(struct device *dev, struct ufs_sprd_rst *rci) 63*df7320baSZhe Wang { 64*df7320baSZhe Wang rci->rc = devm_reset_control_get(dev, rci->name); 65*df7320baSZhe Wang if (IS_ERR(rci->rc)) { 66*df7320baSZhe Wang dev_err(dev, "failed to get reset ctrl:%s\n", rci->name); 67*df7320baSZhe Wang return PTR_ERR(rci->rc); 68*df7320baSZhe Wang } 69*df7320baSZhe Wang 70*df7320baSZhe Wang return 0; 71*df7320baSZhe Wang } 72*df7320baSZhe Wang 73*df7320baSZhe Wang static int ufs_sprd_get_syscon_reg(struct device *dev, struct ufs_sprd_syscon *sysci) 74*df7320baSZhe Wang { 75*df7320baSZhe Wang sysci->regmap = syscon_regmap_lookup_by_phandle(dev->of_node, sysci->name); 76*df7320baSZhe Wang if (IS_ERR(sysci->regmap)) { 77*df7320baSZhe Wang dev_err(dev, "failed to get ufs syscon:%s\n", sysci->name); 78*df7320baSZhe Wang return PTR_ERR(sysci->regmap); 79*df7320baSZhe Wang } 80*df7320baSZhe Wang 81*df7320baSZhe Wang return 0; 82*df7320baSZhe Wang } 83*df7320baSZhe Wang 84*df7320baSZhe Wang static int ufs_sprd_get_vreg(struct device *dev, struct ufs_sprd_vreg *vregi) 85*df7320baSZhe Wang { 86*df7320baSZhe Wang vregi->vreg = devm_regulator_get(dev, vregi->name); 87*df7320baSZhe Wang if (IS_ERR(vregi->vreg)) { 88*df7320baSZhe Wang dev_err(dev, "failed to get vreg:%s\n", vregi->name); 89*df7320baSZhe Wang return PTR_ERR(vregi->vreg); 90*df7320baSZhe Wang } 91*df7320baSZhe Wang 92*df7320baSZhe Wang return 0; 93*df7320baSZhe Wang } 94*df7320baSZhe Wang 95*df7320baSZhe Wang static int ufs_sprd_parse_dt(struct device *dev, struct ufs_hba *hba, struct ufs_sprd_host *host) 96*df7320baSZhe Wang { 97*df7320baSZhe Wang u32 i; 98*df7320baSZhe Wang struct ufs_sprd_priv *priv = host->priv; 99*df7320baSZhe Wang int ret = 0; 100*df7320baSZhe Wang 101*df7320baSZhe Wang /* Parse UFS reset ctrl info */ 102*df7320baSZhe Wang for (i = 0; i < SPRD_UFS_RST_MAX; i++) { 103*df7320baSZhe Wang if (!priv->rci[i].name) 104*df7320baSZhe Wang continue; 105*df7320baSZhe Wang ret = ufs_sprd_get_reset_ctrl(dev, &priv->rci[i]); 106*df7320baSZhe Wang if (ret) 107*df7320baSZhe Wang goto out; 108*df7320baSZhe Wang } 109*df7320baSZhe Wang 110*df7320baSZhe Wang /* Parse UFS syscon reg info */ 111*df7320baSZhe Wang for (i = 0; i < SPRD_UFS_SYSCON_MAX; i++) { 112*df7320baSZhe Wang if (!priv->sysci[i].name) 113*df7320baSZhe Wang continue; 114*df7320baSZhe Wang ret = ufs_sprd_get_syscon_reg(dev, &priv->sysci[i]); 115*df7320baSZhe Wang if (ret) 116*df7320baSZhe Wang goto out; 117*df7320baSZhe Wang } 118*df7320baSZhe Wang 119*df7320baSZhe Wang /* Parse UFS vreg info */ 120*df7320baSZhe Wang for (i = 0; i < SPRD_UFS_VREG_MAX; i++) { 121*df7320baSZhe Wang if (!priv->vregi[i].name) 122*df7320baSZhe Wang continue; 123*df7320baSZhe Wang ret = ufs_sprd_get_vreg(dev, &priv->vregi[i]); 124*df7320baSZhe Wang if (ret) 125*df7320baSZhe Wang goto out; 126*df7320baSZhe Wang } 127*df7320baSZhe Wang 128*df7320baSZhe Wang out: 129*df7320baSZhe Wang return ret; 130*df7320baSZhe Wang } 131*df7320baSZhe Wang 132*df7320baSZhe Wang static int ufs_sprd_common_init(struct ufs_hba *hba) 133*df7320baSZhe Wang { 134*df7320baSZhe Wang struct device *dev = hba->dev; 135*df7320baSZhe Wang struct ufs_sprd_host *host; 136*df7320baSZhe Wang struct platform_device __maybe_unused *pdev = to_platform_device(dev); 137*df7320baSZhe Wang const struct of_device_id *of_id; 138*df7320baSZhe Wang int ret = 0; 139*df7320baSZhe Wang 140*df7320baSZhe Wang host = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL); 141*df7320baSZhe Wang if (!host) 142*df7320baSZhe Wang return -ENOMEM; 143*df7320baSZhe Wang 144*df7320baSZhe Wang of_id = of_match_node(ufs_sprd_of_match, pdev->dev.of_node); 145*df7320baSZhe Wang if (of_id->data != NULL) 146*df7320baSZhe Wang host->priv = container_of(of_id->data, struct ufs_sprd_priv, 147*df7320baSZhe Wang ufs_hba_sprd_vops); 148*df7320baSZhe Wang 149*df7320baSZhe Wang host->hba = hba; 150*df7320baSZhe Wang ufshcd_set_variant(hba, host); 151*df7320baSZhe Wang 152*df7320baSZhe Wang hba->caps |= UFSHCD_CAP_CLK_GATING | 153*df7320baSZhe Wang UFSHCD_CAP_CRYPTO | 154*df7320baSZhe Wang UFSHCD_CAP_WB_EN; 155*df7320baSZhe Wang hba->quirks |= UFSHCD_QUIRK_DELAY_BEFORE_DME_CMDS; 156*df7320baSZhe Wang 157*df7320baSZhe Wang ret = ufs_sprd_parse_dt(dev, hba, host); 158*df7320baSZhe Wang 159*df7320baSZhe Wang return ret; 160*df7320baSZhe Wang } 161*df7320baSZhe Wang 162*df7320baSZhe Wang static int sprd_ufs_pwr_change_notify(struct ufs_hba *hba, 163*df7320baSZhe Wang enum ufs_notify_change_status status, 164*df7320baSZhe Wang struct ufs_pa_layer_attr *dev_max_params, 165*df7320baSZhe Wang struct ufs_pa_layer_attr *dev_req_params) 166*df7320baSZhe Wang { 167*df7320baSZhe Wang struct ufs_sprd_host *host = ufshcd_get_variant(hba); 168*df7320baSZhe Wang 169*df7320baSZhe Wang if (status == PRE_CHANGE) { 170*df7320baSZhe Wang memcpy(dev_req_params, dev_max_params, 171*df7320baSZhe Wang sizeof(struct ufs_pa_layer_attr)); 172*df7320baSZhe Wang if (host->unipro_ver >= UFS_UNIPRO_VER_1_8) 173*df7320baSZhe Wang ufshcd_dme_configure_adapt(hba, dev_req_params->gear_tx, 174*df7320baSZhe Wang PA_INITIAL_ADAPT); 175*df7320baSZhe Wang } 176*df7320baSZhe Wang 177*df7320baSZhe Wang return 0; 178*df7320baSZhe Wang } 179*df7320baSZhe Wang 180*df7320baSZhe Wang static int ufs_sprd_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op, 181*df7320baSZhe Wang enum ufs_notify_change_status status) 182*df7320baSZhe Wang { 183*df7320baSZhe Wang unsigned long flags; 184*df7320baSZhe Wang 185*df7320baSZhe Wang if (status == PRE_CHANGE) { 186*df7320baSZhe Wang if (ufshcd_is_auto_hibern8_supported(hba)) { 187*df7320baSZhe Wang spin_lock_irqsave(hba->host->host_lock, flags); 188*df7320baSZhe Wang ufshcd_writel(hba, 0, REG_AUTO_HIBERNATE_IDLE_TIMER); 189*df7320baSZhe Wang spin_unlock_irqrestore(hba->host->host_lock, flags); 190*df7320baSZhe Wang } 191*df7320baSZhe Wang } 192*df7320baSZhe Wang 193*df7320baSZhe Wang return 0; 194*df7320baSZhe Wang } 195*df7320baSZhe Wang 196*df7320baSZhe Wang static void ufs_sprd_n6_host_reset(struct ufs_hba *hba) 197*df7320baSZhe Wang { 198*df7320baSZhe Wang struct ufs_sprd_priv *priv = ufs_sprd_get_priv_data(hba); 199*df7320baSZhe Wang 200*df7320baSZhe Wang dev_info(hba->dev, "ufs host reset!\n"); 201*df7320baSZhe Wang 202*df7320baSZhe Wang reset_control_assert(priv->rci[SPRD_UFSHCI_SOFT_RST].rc); 203*df7320baSZhe Wang usleep_range(1000, 1100); 204*df7320baSZhe Wang reset_control_deassert(priv->rci[SPRD_UFSHCI_SOFT_RST].rc); 205*df7320baSZhe Wang } 206*df7320baSZhe Wang 207*df7320baSZhe Wang static int ufs_sprd_n6_device_reset(struct ufs_hba *hba) 208*df7320baSZhe Wang { 209*df7320baSZhe Wang struct ufs_sprd_priv *priv = ufs_sprd_get_priv_data(hba); 210*df7320baSZhe Wang 211*df7320baSZhe Wang dev_info(hba->dev, "ufs device reset!\n"); 212*df7320baSZhe Wang 213*df7320baSZhe Wang reset_control_assert(priv->rci[SPRD_UFS_DEV_RST].rc); 214*df7320baSZhe Wang usleep_range(1000, 1100); 215*df7320baSZhe Wang reset_control_deassert(priv->rci[SPRD_UFS_DEV_RST].rc); 216*df7320baSZhe Wang 217*df7320baSZhe Wang return 0; 218*df7320baSZhe Wang } 219*df7320baSZhe Wang 220*df7320baSZhe Wang static void ufs_sprd_n6_key_acc_enable(struct ufs_hba *hba) 221*df7320baSZhe Wang { 222*df7320baSZhe Wang u32 val; 223*df7320baSZhe Wang u32 retry = 10; 224*df7320baSZhe Wang struct arm_smccc_res res; 225*df7320baSZhe Wang 226*df7320baSZhe Wang check_hce: 227*df7320baSZhe Wang /* Key access only can be enabled under HCE enable */ 228*df7320baSZhe Wang val = ufshcd_readl(hba, REG_CONTROLLER_ENABLE); 229*df7320baSZhe Wang if (!(val & CONTROLLER_ENABLE)) { 230*df7320baSZhe Wang ufs_sprd_n6_host_reset(hba); 231*df7320baSZhe Wang val |= CONTROLLER_ENABLE; 232*df7320baSZhe Wang ufshcd_writel(hba, val, REG_CONTROLLER_ENABLE); 233*df7320baSZhe Wang usleep_range(1000, 1100); 234*df7320baSZhe Wang if (retry) { 235*df7320baSZhe Wang retry--; 236*df7320baSZhe Wang goto check_hce; 237*df7320baSZhe Wang } 238*df7320baSZhe Wang goto disable_crypto; 239*df7320baSZhe Wang } 240*df7320baSZhe Wang 241*df7320baSZhe Wang arm_smccc_smc(SPRD_SIP_SVC_STORAGE_UFS_CRYPTO_ENABLE, 242*df7320baSZhe Wang 0, 0, 0, 0, 0, 0, 0, &res); 243*df7320baSZhe Wang if (!res.a0) 244*df7320baSZhe Wang return; 245*df7320baSZhe Wang 246*df7320baSZhe Wang disable_crypto: 247*df7320baSZhe Wang dev_err(hba->dev, "key reg access enable fail, disable crypto\n"); 248*df7320baSZhe Wang hba->caps &= ~UFSHCD_CAP_CRYPTO; 249*df7320baSZhe Wang } 250*df7320baSZhe Wang 251*df7320baSZhe Wang static int ufs_sprd_n6_init(struct ufs_hba *hba) 252*df7320baSZhe Wang { 253*df7320baSZhe Wang struct ufs_sprd_priv *priv; 254*df7320baSZhe Wang int ret = 0; 255*df7320baSZhe Wang 256*df7320baSZhe Wang ret = ufs_sprd_common_init(hba); 257*df7320baSZhe Wang if (ret != 0) 258*df7320baSZhe Wang return ret; 259*df7320baSZhe Wang 260*df7320baSZhe Wang priv = ufs_sprd_get_priv_data(hba); 261*df7320baSZhe Wang 262*df7320baSZhe Wang ret = regulator_enable(priv->vregi[SPRD_UFS_VDD_MPHY].vreg); 263*df7320baSZhe Wang if (ret) 264*df7320baSZhe Wang return -ENODEV; 265*df7320baSZhe Wang 266*df7320baSZhe Wang if (hba->caps & UFSHCD_CAP_CRYPTO) 267*df7320baSZhe Wang ufs_sprd_n6_key_acc_enable(hba); 268*df7320baSZhe Wang 269*df7320baSZhe Wang return 0; 270*df7320baSZhe Wang } 271*df7320baSZhe Wang 272*df7320baSZhe Wang static int ufs_sprd_n6_phy_init(struct ufs_hba *hba) 273*df7320baSZhe Wang { 274*df7320baSZhe Wang int ret = 0; 275*df7320baSZhe Wang uint32_t val = 0; 276*df7320baSZhe Wang uint32_t retry = 10; 277*df7320baSZhe Wang uint32_t offset; 278*df7320baSZhe Wang struct ufs_sprd_priv *priv = ufs_sprd_get_priv_data(hba); 279*df7320baSZhe Wang 280*df7320baSZhe Wang ufshcd_dme_set(hba, UIC_ARG_MIB(CBREFCLKCTRL2), 0x90); 281*df7320baSZhe Wang ufshcd_dme_set(hba, UIC_ARG_MIB(CBCRCTRL), 0x01); 282*df7320baSZhe Wang ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(RXSQCONTROL, 283*df7320baSZhe Wang UIC_ARG_MPHY_RX_GEN_SEL_INDEX(0)), 0x01); 284*df7320baSZhe Wang ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(RXSQCONTROL, 285*df7320baSZhe Wang UIC_ARG_MPHY_RX_GEN_SEL_INDEX(1)), 0x01); 286*df7320baSZhe Wang ufshcd_dme_set(hba, UIC_ARG_MIB(VS_MPHYCFGUPDT), 0x01); 287*df7320baSZhe Wang ufshcd_dme_set(hba, UIC_ARG_MIB(CBRATESEL), 0x01); 288*df7320baSZhe Wang 289*df7320baSZhe Wang do { 290*df7320baSZhe Wang /* phy_sram_init_done */ 291*df7320baSZhe Wang ufs_sprd_regmap_read(priv, SPRD_UFS_ANLG, 0xc, &val); 292*df7320baSZhe Wang if ((val & 0x1) == 0x1) { 293*df7320baSZhe Wang for (offset = 0x40; offset < 0x42; offset++) { 294*df7320baSZhe Wang /* Lane afe calibration */ 295*df7320baSZhe Wang ufshcd_dme_set(hba, UIC_ARG_MIB(CBCREGADDRLSB), 0x1c); 296*df7320baSZhe Wang ufshcd_dme_set(hba, UIC_ARG_MIB(CBCREGADDRMSB), offset); 297*df7320baSZhe Wang ufshcd_dme_set(hba, UIC_ARG_MIB(CBCREGWRLSB), 0x04); 298*df7320baSZhe Wang ufshcd_dme_set(hba, UIC_ARG_MIB(CBCREGWRMSB), 0x00); 299*df7320baSZhe Wang ufshcd_dme_set(hba, UIC_ARG_MIB(CBCREGRDWRSEL), 0x01); 300*df7320baSZhe Wang ufshcd_dme_set(hba, UIC_ARG_MIB(VS_MPHYCFGUPDT), 0x01); 301*df7320baSZhe Wang } 302*df7320baSZhe Wang 303*df7320baSZhe Wang goto update_phy; 304*df7320baSZhe Wang } 305*df7320baSZhe Wang udelay(1000); 306*df7320baSZhe Wang retry--; 307*df7320baSZhe Wang } while (retry > 0); 308*df7320baSZhe Wang 309*df7320baSZhe Wang ret = -ETIMEDOUT; 310*df7320baSZhe Wang goto out; 311*df7320baSZhe Wang 312*df7320baSZhe Wang update_phy: 313*df7320baSZhe Wang /* phy_sram_ext_ld_done */ 314*df7320baSZhe Wang ufs_sprd_regmap_update(priv, SPRD_UFS_ANLG, 0xc, 0x2, 0); 315*df7320baSZhe Wang ufshcd_dme_set(hba, UIC_ARG_MIB(VS_MPHYCFGUPDT), 0x01); 316*df7320baSZhe Wang ufshcd_dme_set(hba, UIC_ARG_MIB(VS_MPHYDISABLE), 0x0); 317*df7320baSZhe Wang out: 318*df7320baSZhe Wang return ret; 319*df7320baSZhe Wang } 320*df7320baSZhe Wang 321*df7320baSZhe Wang 322*df7320baSZhe Wang static int sprd_ufs_n6_hce_enable_notify(struct ufs_hba *hba, 323*df7320baSZhe Wang enum ufs_notify_change_status status) 324*df7320baSZhe Wang { 325*df7320baSZhe Wang int err = 0; 326*df7320baSZhe Wang struct ufs_sprd_priv *priv = ufs_sprd_get_priv_data(hba); 327*df7320baSZhe Wang 328*df7320baSZhe Wang if (status == PRE_CHANGE) { 329*df7320baSZhe Wang /* phy_sram_ext_ld_done */ 330*df7320baSZhe Wang ufs_sprd_regmap_update(priv, SPRD_UFS_ANLG, 0xc, 0x2, 0x2); 331*df7320baSZhe Wang /* phy_sram_bypass */ 332*df7320baSZhe Wang ufs_sprd_regmap_update(priv, SPRD_UFS_ANLG, 0xc, 0x4, 0x4); 333*df7320baSZhe Wang 334*df7320baSZhe Wang ufs_sprd_n6_host_reset(hba); 335*df7320baSZhe Wang 336*df7320baSZhe Wang if (hba->caps & UFSHCD_CAP_CRYPTO) 337*df7320baSZhe Wang ufs_sprd_n6_key_acc_enable(hba); 338*df7320baSZhe Wang } 339*df7320baSZhe Wang 340*df7320baSZhe Wang if (status == POST_CHANGE) { 341*df7320baSZhe Wang err = ufs_sprd_n6_phy_init(hba); 342*df7320baSZhe Wang if (err) { 343*df7320baSZhe Wang dev_err(hba->dev, "Phy setup failed (%d)\n", err); 344*df7320baSZhe Wang goto out; 345*df7320baSZhe Wang } 346*df7320baSZhe Wang 347*df7320baSZhe Wang ufs_sprd_get_unipro_ver(hba); 348*df7320baSZhe Wang } 349*df7320baSZhe Wang out: 350*df7320baSZhe Wang return err; 351*df7320baSZhe Wang } 352*df7320baSZhe Wang 353*df7320baSZhe Wang static void sprd_ufs_n6_h8_notify(struct ufs_hba *hba, 354*df7320baSZhe Wang enum uic_cmd_dme cmd, 355*df7320baSZhe Wang enum ufs_notify_change_status status) 356*df7320baSZhe Wang { 357*df7320baSZhe Wang struct ufs_sprd_priv *priv = ufs_sprd_get_priv_data(hba); 358*df7320baSZhe Wang 359*df7320baSZhe Wang if (status == PRE_CHANGE) { 360*df7320baSZhe Wang if (cmd == UIC_CMD_DME_HIBER_ENTER) 361*df7320baSZhe Wang /* 362*df7320baSZhe Wang * Disable UIC COMPL INTR to prevent access to UFSHCI after 363*df7320baSZhe Wang * checking HCS.UPMCRS 364*df7320baSZhe Wang */ 365*df7320baSZhe Wang ufs_sprd_ctrl_uic_compl(hba, false); 366*df7320baSZhe Wang 367*df7320baSZhe Wang if (cmd == UIC_CMD_DME_HIBER_EXIT) { 368*df7320baSZhe Wang ufs_sprd_regmap_update(priv, SPRD_UFS_AON_APB, APB_UFSDEV_REG, 369*df7320baSZhe Wang APB_UFSDEV_REFCLK_EN, APB_UFSDEV_REFCLK_EN); 370*df7320baSZhe Wang ufs_sprd_regmap_update(priv, SPRD_UFS_AON_APB, APB_USB31PLL_CTRL, 371*df7320baSZhe Wang APB_USB31PLLV_REF2MPHY, APB_USB31PLLV_REF2MPHY); 372*df7320baSZhe Wang } 373*df7320baSZhe Wang } 374*df7320baSZhe Wang 375*df7320baSZhe Wang if (status == POST_CHANGE) { 376*df7320baSZhe Wang if (cmd == UIC_CMD_DME_HIBER_EXIT) 377*df7320baSZhe Wang ufs_sprd_ctrl_uic_compl(hba, true); 378*df7320baSZhe Wang 379*df7320baSZhe Wang if (cmd == UIC_CMD_DME_HIBER_ENTER) { 380*df7320baSZhe Wang ufs_sprd_regmap_update(priv, SPRD_UFS_AON_APB, APB_UFSDEV_REG, 381*df7320baSZhe Wang APB_UFSDEV_REFCLK_EN, 0); 382*df7320baSZhe Wang ufs_sprd_regmap_update(priv, SPRD_UFS_AON_APB, APB_USB31PLL_CTRL, 383*df7320baSZhe Wang APB_USB31PLLV_REF2MPHY, 0); 384*df7320baSZhe Wang } 385*df7320baSZhe Wang } 386*df7320baSZhe Wang } 387*df7320baSZhe Wang 388*df7320baSZhe Wang static struct ufs_sprd_priv n6_ufs = { 389*df7320baSZhe Wang .rci[SPRD_UFSHCI_SOFT_RST] = { .name = "controller", }, 390*df7320baSZhe Wang .rci[SPRD_UFS_DEV_RST] = { .name = "device", }, 391*df7320baSZhe Wang 392*df7320baSZhe Wang .sysci[SPRD_UFS_ANLG] = { .name = "sprd,ufs-anlg-syscon", }, 393*df7320baSZhe Wang .sysci[SPRD_UFS_AON_APB] = { .name = "sprd,aon-apb-syscon", }, 394*df7320baSZhe Wang 395*df7320baSZhe Wang .vregi[SPRD_UFS_VDD_MPHY] = { .name = "vdd-mphy", }, 396*df7320baSZhe Wang 397*df7320baSZhe Wang .ufs_hba_sprd_vops = { 398*df7320baSZhe Wang .name = "sprd,ums9620-ufs", 399*df7320baSZhe Wang .init = ufs_sprd_n6_init, 400*df7320baSZhe Wang .hce_enable_notify = sprd_ufs_n6_hce_enable_notify, 401*df7320baSZhe Wang .pwr_change_notify = sprd_ufs_pwr_change_notify, 402*df7320baSZhe Wang .hibern8_notify = sprd_ufs_n6_h8_notify, 403*df7320baSZhe Wang .device_reset = ufs_sprd_n6_device_reset, 404*df7320baSZhe Wang .suspend = ufs_sprd_suspend, 405*df7320baSZhe Wang }, 406*df7320baSZhe Wang }; 407*df7320baSZhe Wang 408*df7320baSZhe Wang static const struct of_device_id __maybe_unused ufs_sprd_of_match[] = { 409*df7320baSZhe Wang { .compatible = "sprd,ums9620-ufs", .data = &n6_ufs.ufs_hba_sprd_vops}, 410*df7320baSZhe Wang {}, 411*df7320baSZhe Wang }; 412*df7320baSZhe Wang MODULE_DEVICE_TABLE(of, ufs_sprd_of_match); 413*df7320baSZhe Wang 414*df7320baSZhe Wang static int ufs_sprd_probe(struct platform_device *pdev) 415*df7320baSZhe Wang { 416*df7320baSZhe Wang int err; 417*df7320baSZhe Wang struct device *dev = &pdev->dev; 418*df7320baSZhe Wang const struct of_device_id *of_id; 419*df7320baSZhe Wang 420*df7320baSZhe Wang of_id = of_match_node(ufs_sprd_of_match, dev->of_node); 421*df7320baSZhe Wang err = ufshcd_pltfrm_init(pdev, of_id->data); 422*df7320baSZhe Wang if (err) 423*df7320baSZhe Wang dev_err(dev, "ufshcd_pltfrm_init() failed %d\n", err); 424*df7320baSZhe Wang 425*df7320baSZhe Wang return err; 426*df7320baSZhe Wang } 427*df7320baSZhe Wang 428*df7320baSZhe Wang static int ufs_sprd_remove(struct platform_device *pdev) 429*df7320baSZhe Wang { 430*df7320baSZhe Wang struct ufs_hba *hba = platform_get_drvdata(pdev); 431*df7320baSZhe Wang 432*df7320baSZhe Wang pm_runtime_get_sync(&(pdev)->dev); 433*df7320baSZhe Wang ufshcd_remove(hba); 434*df7320baSZhe Wang return 0; 435*df7320baSZhe Wang } 436*df7320baSZhe Wang 437*df7320baSZhe Wang static const struct dev_pm_ops ufs_sprd_pm_ops = { 438*df7320baSZhe Wang SET_SYSTEM_SLEEP_PM_OPS(ufshcd_system_suspend, ufshcd_system_resume) 439*df7320baSZhe Wang SET_RUNTIME_PM_OPS(ufshcd_runtime_suspend, ufshcd_runtime_resume, NULL) 440*df7320baSZhe Wang .prepare = ufshcd_suspend_prepare, 441*df7320baSZhe Wang .complete = ufshcd_resume_complete, 442*df7320baSZhe Wang }; 443*df7320baSZhe Wang 444*df7320baSZhe Wang static struct platform_driver ufs_sprd_pltform = { 445*df7320baSZhe Wang .probe = ufs_sprd_probe, 446*df7320baSZhe Wang .remove = ufs_sprd_remove, 447*df7320baSZhe Wang .shutdown = ufshcd_pltfrm_shutdown, 448*df7320baSZhe Wang .driver = { 449*df7320baSZhe Wang .name = "ufshcd-sprd", 450*df7320baSZhe Wang .pm = &ufs_sprd_pm_ops, 451*df7320baSZhe Wang .of_match_table = of_match_ptr(ufs_sprd_of_match), 452*df7320baSZhe Wang }, 453*df7320baSZhe Wang }; 454*df7320baSZhe Wang module_platform_driver(ufs_sprd_pltform); 455*df7320baSZhe Wang 456*df7320baSZhe Wang MODULE_AUTHOR("Zhe Wang <zhe.wang1@unisoc.com>"); 457*df7320baSZhe Wang MODULE_DESCRIPTION("Unisoc UFS Host Driver"); 458*df7320baSZhe Wang MODULE_LICENSE("GPL v2"); 459