linux/drivers/scsi/ufs/ufs-hisi.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * HiSilicon Hixxxx UFS Driver
   4 *
   5 * Copyright (c) 2016-2017 Linaro Ltd.
   6 * Copyright (c) 2016-2017 HiSilicon Technologies Co., Ltd.
   7 */
   8
   9#include <linux/time.h>
  10#include <linux/of.h>
  11#include <linux/of_address.h>
  12#include <linux/dma-mapping.h>
  13#include <linux/platform_device.h>
  14#include <linux/reset.h>
  15
  16#include "ufshcd.h"
  17#include "ufshcd-pltfrm.h"
  18#include "unipro.h"
  19#include "ufs-hisi.h"
  20#include "ufshci.h"
  21#include "ufs_quirks.h"
  22
  23static int ufs_hisi_check_hibern8(struct ufs_hba *hba)
  24{
  25        int err = 0;
  26        u32 tx_fsm_val_0 = 0;
  27        u32 tx_fsm_val_1 = 0;
  28        unsigned long timeout = jiffies + msecs_to_jiffies(HBRN8_POLL_TOUT_MS);
  29
  30        do {
  31                err = ufshcd_dme_get(hba, UIC_ARG_MIB_SEL(MPHY_TX_FSM_STATE, 0),
  32                                      &tx_fsm_val_0);
  33                err |= ufshcd_dme_get(hba,
  34                    UIC_ARG_MIB_SEL(MPHY_TX_FSM_STATE, 1), &tx_fsm_val_1);
  35                if (err || (tx_fsm_val_0 == TX_FSM_HIBERN8 &&
  36                        tx_fsm_val_1 == TX_FSM_HIBERN8))
  37                        break;
  38
  39                /* sleep for max. 200us */
  40                usleep_range(100, 200);
  41        } while (time_before(jiffies, timeout));
  42
  43        /*
  44         * we might have scheduled out for long during polling so
  45         * check the state again.
  46         */
  47        if (time_after(jiffies, timeout)) {
  48                err = ufshcd_dme_get(hba, UIC_ARG_MIB_SEL(MPHY_TX_FSM_STATE, 0),
  49                                     &tx_fsm_val_0);
  50                err |= ufshcd_dme_get(hba,
  51                 UIC_ARG_MIB_SEL(MPHY_TX_FSM_STATE, 1), &tx_fsm_val_1);
  52        }
  53
  54        if (err) {
  55                dev_err(hba->dev, "%s: unable to get TX_FSM_STATE, err %d\n",
  56                        __func__, err);
  57        } else if (tx_fsm_val_0 != TX_FSM_HIBERN8 ||
  58                         tx_fsm_val_1 != TX_FSM_HIBERN8) {
  59                err = -1;
  60                dev_err(hba->dev, "%s: invalid TX_FSM_STATE, lane0 = %d, lane1 = %d\n",
  61                        __func__, tx_fsm_val_0, tx_fsm_val_1);
  62        }
  63
  64        return err;
  65}
  66
  67static void ufs_hisi_clk_init(struct ufs_hba *hba)
  68{
  69        struct ufs_hisi_host *host = ufshcd_get_variant(hba);
  70
  71        ufs_sys_ctrl_clr_bits(host, BIT_SYSCTRL_REF_CLOCK_EN, PHY_CLK_CTRL);
  72        if (ufs_sys_ctrl_readl(host, PHY_CLK_CTRL) & BIT_SYSCTRL_REF_CLOCK_EN)
  73                mdelay(1);
  74        /* use abb clk */
  75        ufs_sys_ctrl_clr_bits(host, BIT_UFS_REFCLK_SRC_SEl, UFS_SYSCTRL);
  76        ufs_sys_ctrl_clr_bits(host, BIT_UFS_REFCLK_ISO_EN, PHY_ISO_EN);
  77        /* open mphy ref clk */
  78        ufs_sys_ctrl_set_bits(host, BIT_SYSCTRL_REF_CLOCK_EN, PHY_CLK_CTRL);
  79}
  80
  81static void ufs_hisi_soc_init(struct ufs_hba *hba)
  82{
  83        struct ufs_hisi_host *host = ufshcd_get_variant(hba);
  84        u32 reg;
  85
  86        if (!IS_ERR(host->rst))
  87                reset_control_assert(host->rst);
  88
  89        /* HC_PSW powerup */
  90        ufs_sys_ctrl_set_bits(host, BIT_UFS_PSW_MTCMOS_EN, PSW_POWER_CTRL);
  91        udelay(10);
  92        /* notify PWR ready */
  93        ufs_sys_ctrl_set_bits(host, BIT_SYSCTRL_PWR_READY, HC_LP_CTRL);
  94        ufs_sys_ctrl_writel(host, MASK_UFS_DEVICE_RESET | 0,
  95                UFS_DEVICE_RESET_CTRL);
  96
  97        reg = ufs_sys_ctrl_readl(host, PHY_CLK_CTRL);
  98        reg = (reg & ~MASK_SYSCTRL_CFG_CLOCK_FREQ) | UFS_FREQ_CFG_CLK;
  99        /* set cfg clk freq */
 100        ufs_sys_ctrl_writel(host, reg, PHY_CLK_CTRL);
 101        /* set ref clk freq */
 102        ufs_sys_ctrl_clr_bits(host, MASK_SYSCTRL_REF_CLOCK_SEL, PHY_CLK_CTRL);
 103        /* bypass ufs clk gate */
 104        ufs_sys_ctrl_set_bits(host, MASK_UFS_CLK_GATE_BYPASS,
 105                                                 CLOCK_GATE_BYPASS);
 106        ufs_sys_ctrl_set_bits(host, MASK_UFS_SYSCRTL_BYPASS, UFS_SYSCTRL);
 107
 108        /* open psw clk */
 109        ufs_sys_ctrl_set_bits(host, BIT_SYSCTRL_PSW_CLK_EN, PSW_CLK_CTRL);
 110        /* disable ufshc iso */
 111        ufs_sys_ctrl_clr_bits(host, BIT_UFS_PSW_ISO_CTRL, PSW_POWER_CTRL);
 112        /* disable phy iso */
 113        ufs_sys_ctrl_clr_bits(host, BIT_UFS_PHY_ISO_CTRL, PHY_ISO_EN);
 114        /* notice iso disable */
 115        ufs_sys_ctrl_clr_bits(host, BIT_SYSCTRL_LP_ISOL_EN, HC_LP_CTRL);
 116
 117        /* disable lp_reset_n */
 118        ufs_sys_ctrl_set_bits(host, BIT_SYSCTRL_LP_RESET_N, RESET_CTRL_EN);
 119        mdelay(1);
 120
 121        ufs_sys_ctrl_writel(host, MASK_UFS_DEVICE_RESET | BIT_UFS_DEVICE_RESET,
 122                UFS_DEVICE_RESET_CTRL);
 123
 124        msleep(20);
 125
 126        /*
 127         * enable the fix of linereset recovery,
 128         * and enable rx_reset/tx_rest beat
 129         * enable ref_clk_en override(bit5) &
 130         * override value = 1(bit4), with mask
 131         */
 132        ufs_sys_ctrl_writel(host, 0x03300330, UFS_DEVICE_RESET_CTRL);
 133
 134        if (!IS_ERR(host->rst))
 135                reset_control_deassert(host->rst);
 136}
 137
 138static int ufs_hisi_link_startup_pre_change(struct ufs_hba *hba)
 139{
 140        struct ufs_hisi_host *host = ufshcd_get_variant(hba);
 141        int err;
 142        uint32_t value;
 143        uint32_t reg;
 144
 145        /* Unipro VS_mphy_disable */
 146        ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0xD0C1, 0x0), 0x1);
 147        /* PA_HSSeries */
 148        ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x156A, 0x0), 0x2);
 149        /* MPHY CBRATESEL */
 150        ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x8114, 0x0), 0x1);
 151        /* MPHY CBOVRCTRL2 */
 152        ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x8121, 0x0), 0x2D);
 153        /* MPHY CBOVRCTRL3 */
 154        ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x8122, 0x0), 0x1);
 155
 156        if (host->caps & UFS_HISI_CAP_PHY10nm) {
 157                /* MPHY CBOVRCTRL4 */
 158                ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x8127, 0x0), 0x98);
 159                /* MPHY CBOVRCTRL5 */
 160                ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x8128, 0x0), 0x1);
 161        }
 162
 163        /* Unipro VS_MphyCfgUpdt */
 164        ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0xD085, 0x0), 0x1);
 165        /* MPHY RXOVRCTRL4 rx0 */
 166        ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x800D, 0x4), 0x58);
 167        /* MPHY RXOVRCTRL4 rx1 */
 168        ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x800D, 0x5), 0x58);
 169        /* MPHY RXOVRCTRL5 rx0 */
 170        ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x800E, 0x4), 0xB);
 171        /* MPHY RXOVRCTRL5 rx1 */
 172        ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x800E, 0x5), 0xB);
 173        /* MPHY RXSQCONTROL rx0 */
 174        ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x8009, 0x4), 0x1);
 175        /* MPHY RXSQCONTROL rx1 */
 176        ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x8009, 0x5), 0x1);
 177        /* Unipro VS_MphyCfgUpdt */
 178        ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0xD085, 0x0), 0x1);
 179
 180        ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x8113, 0x0), 0x1);
 181        ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0xD085, 0x0), 0x1);
 182
 183        if (host->caps & UFS_HISI_CAP_PHY10nm) {
 184                /* RX_Hibern8Time_Capability*/
 185                ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x0092, 0x4), 0xA);
 186                /* RX_Hibern8Time_Capability*/
 187                ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x0092, 0x5), 0xA);
 188                /* RX_Min_ActivateTime */
 189                ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x008f, 0x4), 0xA);
 190                /* RX_Min_ActivateTime*/
 191                ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x008f, 0x5), 0xA);
 192        } else {
 193                /* Tactive RX */
 194                ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x008F, 0x4), 0x7);
 195                /* Tactive RX */
 196                ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x008F, 0x5), 0x7);
 197        }
 198
 199        /* Gear3 Synclength */
 200        ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x0095, 0x4), 0x4F);
 201        /* Gear3 Synclength */
 202        ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x0095, 0x5), 0x4F);
 203        /* Gear2 Synclength */
 204        ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x0094, 0x4), 0x4F);
 205        /* Gear2 Synclength */
 206        ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x0094, 0x5), 0x4F);
 207        /* Gear1 Synclength */
 208        ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x008B, 0x4), 0x4F);
 209        /* Gear1 Synclength */
 210        ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x008B, 0x5), 0x4F);
 211        /* Thibernate Tx */
 212        ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x000F, 0x0), 0x5);
 213        /* Thibernate Tx */
 214        ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x000F, 0x1), 0x5);
 215
 216        ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0xD085, 0x0), 0x1);
 217        /* Unipro VS_mphy_disable */
 218        ufshcd_dme_get(hba, UIC_ARG_MIB_SEL(0xD0C1, 0x0), &value);
 219        if (value != 0x1)
 220                dev_info(hba->dev,
 221                    "Warring!!! Unipro VS_mphy_disable is 0x%x\n", value);
 222
 223        /* Unipro VS_mphy_disable */
 224        ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0xD0C1, 0x0), 0x0);
 225        err = ufs_hisi_check_hibern8(hba);
 226        if (err)
 227                dev_err(hba->dev, "ufs_hisi_check_hibern8 error\n");
 228
 229        if (!(host->caps & UFS_HISI_CAP_PHY10nm))
 230                ufshcd_writel(hba, UFS_HCLKDIV_NORMAL_VALUE, UFS_REG_HCLKDIV);
 231
 232        /* disable auto H8 */
 233        reg = ufshcd_readl(hba, REG_AUTO_HIBERNATE_IDLE_TIMER);
 234        reg = reg & (~UFS_AHIT_AH8ITV_MASK);
 235        ufshcd_writel(hba, reg, REG_AUTO_HIBERNATE_IDLE_TIMER);
 236
 237        /* Unipro PA_Local_TX_LCC_Enable */
 238        ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x155E, 0x0), 0x0);
 239        /* close Unipro VS_Mk2ExtnSupport */
 240        ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0xD0AB, 0x0), 0x0);
 241        ufshcd_dme_get(hba, UIC_ARG_MIB_SEL(0xD0AB, 0x0), &value);
 242        if (value != 0) {
 243                /* Ensure close success */
 244                dev_info(hba->dev, "WARN: close VS_Mk2ExtnSupport failed\n");
 245        }
 246
 247        return err;
 248}
 249
 250static int ufs_hisi_link_startup_post_change(struct ufs_hba *hba)
 251{
 252        struct ufs_hisi_host *host = ufshcd_get_variant(hba);
 253
 254        /* Unipro DL_AFC0CreditThreshold */
 255        ufshcd_dme_set(hba, UIC_ARG_MIB(0x2044), 0x0);
 256        /* Unipro DL_TC0OutAckThreshold */
 257        ufshcd_dme_set(hba, UIC_ARG_MIB(0x2045), 0x0);
 258        /* Unipro DL_TC0TXFCThreshold */
 259        ufshcd_dme_set(hba, UIC_ARG_MIB(0x2040), 0x9);
 260
 261        /* not bypass ufs clk gate */
 262        ufs_sys_ctrl_clr_bits(host, MASK_UFS_CLK_GATE_BYPASS,
 263                                                CLOCK_GATE_BYPASS);
 264        ufs_sys_ctrl_clr_bits(host, MASK_UFS_SYSCRTL_BYPASS,
 265                                                UFS_SYSCTRL);
 266
 267        /* select received symbol cnt */
 268        ufshcd_dme_set(hba, UIC_ARG_MIB(0xd09a), 0x80000000);
 269         /* reset counter0 and enable */
 270        ufshcd_dme_set(hba, UIC_ARG_MIB(0xd09c), 0x00000005);
 271
 272        return 0;
 273}
 274
 275static int ufs_hisi_link_startup_notify(struct ufs_hba *hba,
 276                                          enum ufs_notify_change_status status)
 277{
 278        int err = 0;
 279
 280        switch (status) {
 281        case PRE_CHANGE:
 282                err = ufs_hisi_link_startup_pre_change(hba);
 283                break;
 284        case POST_CHANGE:
 285                err = ufs_hisi_link_startup_post_change(hba);
 286                break;
 287        default:
 288                break;
 289        }
 290
 291        return err;
 292}
 293
 294static void ufs_hisi_set_dev_cap(struct ufs_dev_params *hisi_param)
 295{
 296        hisi_param->rx_lanes = UFS_HISI_LIMIT_NUM_LANES_RX;
 297        hisi_param->tx_lanes = UFS_HISI_LIMIT_NUM_LANES_TX;
 298        hisi_param->hs_rx_gear = UFS_HISI_LIMIT_HSGEAR_RX;
 299        hisi_param->hs_tx_gear = UFS_HISI_LIMIT_HSGEAR_TX;
 300        hisi_param->pwm_rx_gear = UFS_HISI_LIMIT_PWMGEAR_RX;
 301        hisi_param->pwm_tx_gear = UFS_HISI_LIMIT_PWMGEAR_TX;
 302        hisi_param->rx_pwr_pwm = UFS_HISI_LIMIT_RX_PWR_PWM;
 303        hisi_param->tx_pwr_pwm = UFS_HISI_LIMIT_TX_PWR_PWM;
 304        hisi_param->rx_pwr_hs = UFS_HISI_LIMIT_RX_PWR_HS;
 305        hisi_param->tx_pwr_hs = UFS_HISI_LIMIT_TX_PWR_HS;
 306        hisi_param->hs_rate = UFS_HISI_LIMIT_HS_RATE;
 307        hisi_param->desired_working_mode = UFS_HISI_LIMIT_DESIRED_MODE;
 308}
 309
 310static void ufs_hisi_pwr_change_pre_change(struct ufs_hba *hba)
 311{
 312        struct ufs_hisi_host *host = ufshcd_get_variant(hba);
 313
 314        if (host->caps & UFS_HISI_CAP_PHY10nm) {
 315                /*
 316                 * Boston platform need to set SaveConfigTime to 0x13,
 317                 * and change sync length to maximum value
 318                 */
 319                /* VS_DebugSaveConfigTime */
 320                ufshcd_dme_set(hba, UIC_ARG_MIB((u32)0xD0A0), 0x13);
 321                /* g1 sync length */
 322                ufshcd_dme_set(hba, UIC_ARG_MIB((u32)0x1552), 0x4f);
 323                /* g2 sync length */
 324                ufshcd_dme_set(hba, UIC_ARG_MIB((u32)0x1554), 0x4f);
 325                /* g3 sync length */
 326                ufshcd_dme_set(hba, UIC_ARG_MIB((u32)0x1556), 0x4f);
 327                /* PA_Hibern8Time */
 328                ufshcd_dme_set(hba, UIC_ARG_MIB((u32)0x15a7), 0xA);
 329                /* PA_Tactivate */
 330                ufshcd_dme_set(hba, UIC_ARG_MIB((u32)0x15a8), 0xA);
 331                ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0xd085, 0x0), 0x01);
 332        }
 333
 334        if (hba->dev_quirks & UFS_DEVICE_QUIRK_HOST_VS_DEBUGSAVECONFIGTIME) {
 335                pr_info("ufs flash device must set VS_DebugSaveConfigTime 0x10\n");
 336                /* VS_DebugSaveConfigTime */
 337                ufshcd_dme_set(hba, UIC_ARG_MIB(0xD0A0), 0x10);
 338                /* sync length */
 339                ufshcd_dme_set(hba, UIC_ARG_MIB(0x1556), 0x48);
 340        }
 341
 342        /* update */
 343        ufshcd_dme_set(hba, UIC_ARG_MIB(0x15A8), 0x1);
 344        /* PA_TxSkip */
 345        ufshcd_dme_set(hba, UIC_ARG_MIB(0x155c), 0x0);
 346        /*PA_PWRModeUserData0 = 8191, default is 0*/
 347        ufshcd_dme_set(hba, UIC_ARG_MIB(0x15b0), 8191);
 348        /*PA_PWRModeUserData1 = 65535, default is 0*/
 349        ufshcd_dme_set(hba, UIC_ARG_MIB(0x15b1), 65535);
 350        /*PA_PWRModeUserData2 = 32767, default is 0*/
 351        ufshcd_dme_set(hba, UIC_ARG_MIB(0x15b2), 32767);
 352        /*DME_FC0ProtectionTimeOutVal = 8191, default is 0*/
 353        ufshcd_dme_set(hba, UIC_ARG_MIB(0xd041), 8191);
 354        /*DME_TC0ReplayTimeOutVal = 65535, default is 0*/
 355        ufshcd_dme_set(hba, UIC_ARG_MIB(0xd042), 65535);
 356        /*DME_AFC0ReqTimeOutVal = 32767, default is 0*/
 357        ufshcd_dme_set(hba, UIC_ARG_MIB(0xd043), 32767);
 358        /*PA_PWRModeUserData3 = 8191, default is 0*/
 359        ufshcd_dme_set(hba, UIC_ARG_MIB(0x15b3), 8191);
 360        /*PA_PWRModeUserData4 = 65535, default is 0*/
 361        ufshcd_dme_set(hba, UIC_ARG_MIB(0x15b4), 65535);
 362        /*PA_PWRModeUserData5 = 32767, default is 0*/
 363        ufshcd_dme_set(hba, UIC_ARG_MIB(0x15b5), 32767);
 364        /*DME_FC1ProtectionTimeOutVal = 8191, default is 0*/
 365        ufshcd_dme_set(hba, UIC_ARG_MIB(0xd044), 8191);
 366        /*DME_TC1ReplayTimeOutVal = 65535, default is 0*/
 367        ufshcd_dme_set(hba, UIC_ARG_MIB(0xd045), 65535);
 368        /*DME_AFC1ReqTimeOutVal = 32767, default is 0*/
 369        ufshcd_dme_set(hba, UIC_ARG_MIB(0xd046), 32767);
 370}
 371
 372static int ufs_hisi_pwr_change_notify(struct ufs_hba *hba,
 373                                       enum ufs_notify_change_status status,
 374                                       struct ufs_pa_layer_attr *dev_max_params,
 375                                       struct ufs_pa_layer_attr *dev_req_params)
 376{
 377        struct ufs_dev_params ufs_hisi_cap;
 378        int ret = 0;
 379
 380        if (!dev_req_params) {
 381                dev_err(hba->dev,
 382                            "%s: incoming dev_req_params is NULL\n", __func__);
 383                ret = -EINVAL;
 384                goto out;
 385        }
 386
 387        switch (status) {
 388        case PRE_CHANGE:
 389                ufs_hisi_set_dev_cap(&ufs_hisi_cap);
 390                ret = ufshcd_get_pwr_dev_param(&ufs_hisi_cap,
 391                                               dev_max_params, dev_req_params);
 392                if (ret) {
 393                        dev_err(hba->dev,
 394                            "%s: failed to determine capabilities\n", __func__);
 395                        goto out;
 396                }
 397
 398                ufs_hisi_pwr_change_pre_change(hba);
 399                break;
 400        case POST_CHANGE:
 401                break;
 402        default:
 403                ret = -EINVAL;
 404                break;
 405        }
 406out:
 407        return ret;
 408}
 409
 410static int ufs_hisi_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
 411{
 412        struct ufs_hisi_host *host = ufshcd_get_variant(hba);
 413
 414        if (ufshcd_is_runtime_pm(pm_op))
 415                return 0;
 416
 417        if (host->in_suspend) {
 418                WARN_ON(1);
 419                return 0;
 420        }
 421
 422        ufs_sys_ctrl_clr_bits(host, BIT_SYSCTRL_REF_CLOCK_EN, PHY_CLK_CTRL);
 423        udelay(10);
 424        /* set ref_dig_clk override of PHY PCS to 0 */
 425        ufs_sys_ctrl_writel(host, 0x00100000, UFS_DEVICE_RESET_CTRL);
 426
 427        host->in_suspend = true;
 428
 429        return 0;
 430}
 431
 432static int ufs_hisi_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
 433{
 434        struct ufs_hisi_host *host = ufshcd_get_variant(hba);
 435
 436        if (!host->in_suspend)
 437                return 0;
 438
 439        /* set ref_dig_clk override of PHY PCS to 1 */
 440        ufs_sys_ctrl_writel(host, 0x00100010, UFS_DEVICE_RESET_CTRL);
 441        udelay(10);
 442        ufs_sys_ctrl_set_bits(host, BIT_SYSCTRL_REF_CLOCK_EN, PHY_CLK_CTRL);
 443
 444        host->in_suspend = false;
 445        return 0;
 446}
 447
 448static int ufs_hisi_get_resource(struct ufs_hisi_host *host)
 449{
 450        struct resource *mem_res;
 451        struct device *dev = host->hba->dev;
 452        struct platform_device *pdev = to_platform_device(dev);
 453
 454        /* get resource of ufs sys ctrl */
 455        mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
 456        host->ufs_sys_ctrl = devm_ioremap_resource(dev, mem_res);
 457        if (IS_ERR(host->ufs_sys_ctrl))
 458                return PTR_ERR(host->ufs_sys_ctrl);
 459
 460        return 0;
 461}
 462
 463static void ufs_hisi_set_pm_lvl(struct ufs_hba *hba)
 464{
 465        hba->rpm_lvl = UFS_PM_LVL_1;
 466        hba->spm_lvl = UFS_PM_LVL_3;
 467}
 468
 469/**
 470 * ufs_hisi_init_common
 471 * @hba: host controller instance
 472 */
 473static int ufs_hisi_init_common(struct ufs_hba *hba)
 474{
 475        int err = 0;
 476        struct device *dev = hba->dev;
 477        struct ufs_hisi_host *host;
 478
 479        host = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL);
 480        if (!host)
 481                return -ENOMEM;
 482
 483        host->hba = hba;
 484        ufshcd_set_variant(hba, host);
 485
 486        host->rst  = devm_reset_control_get(dev, "rst");
 487        if (IS_ERR(host->rst)) {
 488                dev_err(dev, "%s: failed to get reset control\n", __func__);
 489                return PTR_ERR(host->rst);
 490        }
 491
 492        ufs_hisi_set_pm_lvl(hba);
 493
 494        err = ufs_hisi_get_resource(host);
 495        if (err) {
 496                ufshcd_set_variant(hba, NULL);
 497                return err;
 498        }
 499
 500        return 0;
 501}
 502
 503static int ufs_hi3660_init(struct ufs_hba *hba)
 504{
 505        int ret = 0;
 506        struct device *dev = hba->dev;
 507
 508        ret = ufs_hisi_init_common(hba);
 509        if (ret) {
 510                dev_err(dev, "%s: ufs common init fail\n", __func__);
 511                return ret;
 512        }
 513
 514        ufs_hisi_clk_init(hba);
 515
 516        ufs_hisi_soc_init(hba);
 517
 518        return 0;
 519}
 520
 521static int ufs_hi3670_init(struct ufs_hba *hba)
 522{
 523        int ret = 0;
 524        struct device *dev = hba->dev;
 525        struct ufs_hisi_host *host;
 526
 527        ret = ufs_hisi_init_common(hba);
 528        if (ret) {
 529                dev_err(dev, "%s: ufs common init fail\n", __func__);
 530                return ret;
 531        }
 532
 533        ufs_hisi_clk_init(hba);
 534
 535        ufs_hisi_soc_init(hba);
 536
 537        /* Add cap for 10nm PHY variant on HI3670 SoC */
 538        host = ufshcd_get_variant(hba);
 539        host->caps |= UFS_HISI_CAP_PHY10nm;
 540
 541        return 0;
 542}
 543
 544static const struct ufs_hba_variant_ops ufs_hba_hi3660_vops = {
 545        .name = "hi3660",
 546        .init = ufs_hi3660_init,
 547        .link_startup_notify = ufs_hisi_link_startup_notify,
 548        .pwr_change_notify = ufs_hisi_pwr_change_notify,
 549        .suspend = ufs_hisi_suspend,
 550        .resume = ufs_hisi_resume,
 551};
 552
 553static const struct ufs_hba_variant_ops ufs_hba_hi3670_vops = {
 554        .name = "hi3670",
 555        .init = ufs_hi3670_init,
 556        .link_startup_notify = ufs_hisi_link_startup_notify,
 557        .pwr_change_notify = ufs_hisi_pwr_change_notify,
 558        .suspend = ufs_hisi_suspend,
 559        .resume = ufs_hisi_resume,
 560};
 561
 562static const struct of_device_id ufs_hisi_of_match[] = {
 563        { .compatible = "hisilicon,hi3660-ufs", .data = &ufs_hba_hi3660_vops },
 564        { .compatible = "hisilicon,hi3670-ufs", .data = &ufs_hba_hi3670_vops },
 565        {},
 566};
 567
 568MODULE_DEVICE_TABLE(of, ufs_hisi_of_match);
 569
 570static int ufs_hisi_probe(struct platform_device *pdev)
 571{
 572        const struct of_device_id *of_id;
 573
 574        of_id = of_match_node(ufs_hisi_of_match, pdev->dev.of_node);
 575
 576        return ufshcd_pltfrm_init(pdev, of_id->data);
 577}
 578
 579static int ufs_hisi_remove(struct platform_device *pdev)
 580{
 581        struct ufs_hba *hba =  platform_get_drvdata(pdev);
 582
 583        ufshcd_remove(hba);
 584        return 0;
 585}
 586
 587static const struct dev_pm_ops ufs_hisi_pm_ops = {
 588        .suspend        = ufshcd_pltfrm_suspend,
 589        .resume         = ufshcd_pltfrm_resume,
 590        .runtime_suspend = ufshcd_pltfrm_runtime_suspend,
 591        .runtime_resume  = ufshcd_pltfrm_runtime_resume,
 592        .runtime_idle    = ufshcd_pltfrm_runtime_idle,
 593};
 594
 595static struct platform_driver ufs_hisi_pltform = {
 596        .probe  = ufs_hisi_probe,
 597        .remove = ufs_hisi_remove,
 598        .shutdown = ufshcd_pltfrm_shutdown,
 599        .driver = {
 600                .name   = "ufshcd-hisi",
 601                .pm     = &ufs_hisi_pm_ops,
 602                .of_match_table = of_match_ptr(ufs_hisi_of_match),
 603        },
 604};
 605module_platform_driver(ufs_hisi_pltform);
 606
 607MODULE_LICENSE("GPL");
 608MODULE_ALIAS("platform:ufshcd-hisi");
 609MODULE_DESCRIPTION("HiSilicon Hixxxx UFS Driver");
 610