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_disable_host_tx_lcc(hba);
 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        ufshcd_init_pwr_dev_param(hisi_param);
 297}
 298
 299static void ufs_hisi_pwr_change_pre_change(struct ufs_hba *hba)
 300{
 301        struct ufs_hisi_host *host = ufshcd_get_variant(hba);
 302
 303        if (host->caps & UFS_HISI_CAP_PHY10nm) {
 304                /*
 305                 * Boston platform need to set SaveConfigTime to 0x13,
 306                 * and change sync length to maximum value
 307                 */
 308                /* VS_DebugSaveConfigTime */
 309                ufshcd_dme_set(hba, UIC_ARG_MIB((u32)0xD0A0), 0x13);
 310                /* g1 sync length */
 311                ufshcd_dme_set(hba, UIC_ARG_MIB((u32)0x1552), 0x4f);
 312                /* g2 sync length */
 313                ufshcd_dme_set(hba, UIC_ARG_MIB((u32)0x1554), 0x4f);
 314                /* g3 sync length */
 315                ufshcd_dme_set(hba, UIC_ARG_MIB((u32)0x1556), 0x4f);
 316                /* PA_Hibern8Time */
 317                ufshcd_dme_set(hba, UIC_ARG_MIB((u32)0x15a7), 0xA);
 318                /* PA_Tactivate */
 319                ufshcd_dme_set(hba, UIC_ARG_MIB((u32)0x15a8), 0xA);
 320                ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0xd085, 0x0), 0x01);
 321        }
 322
 323        if (hba->dev_quirks & UFS_DEVICE_QUIRK_HOST_VS_DEBUGSAVECONFIGTIME) {
 324                pr_info("ufs flash device must set VS_DebugSaveConfigTime 0x10\n");
 325                /* VS_DebugSaveConfigTime */
 326                ufshcd_dme_set(hba, UIC_ARG_MIB(0xD0A0), 0x10);
 327                /* sync length */
 328                ufshcd_dme_set(hba, UIC_ARG_MIB(0x1556), 0x48);
 329        }
 330
 331        /* update */
 332        ufshcd_dme_set(hba, UIC_ARG_MIB(0x15A8), 0x1);
 333        /* PA_TxSkip */
 334        ufshcd_dme_set(hba, UIC_ARG_MIB(0x155c), 0x0);
 335        /*PA_PWRModeUserData0 = 8191, default is 0*/
 336        ufshcd_dme_set(hba, UIC_ARG_MIB(0x15b0), 8191);
 337        /*PA_PWRModeUserData1 = 65535, default is 0*/
 338        ufshcd_dme_set(hba, UIC_ARG_MIB(0x15b1), 65535);
 339        /*PA_PWRModeUserData2 = 32767, default is 0*/
 340        ufshcd_dme_set(hba, UIC_ARG_MIB(0x15b2), 32767);
 341        /*DME_FC0ProtectionTimeOutVal = 8191, default is 0*/
 342        ufshcd_dme_set(hba, UIC_ARG_MIB(0xd041), 8191);
 343        /*DME_TC0ReplayTimeOutVal = 65535, default is 0*/
 344        ufshcd_dme_set(hba, UIC_ARG_MIB(0xd042), 65535);
 345        /*DME_AFC0ReqTimeOutVal = 32767, default is 0*/
 346        ufshcd_dme_set(hba, UIC_ARG_MIB(0xd043), 32767);
 347        /*PA_PWRModeUserData3 = 8191, default is 0*/
 348        ufshcd_dme_set(hba, UIC_ARG_MIB(0x15b3), 8191);
 349        /*PA_PWRModeUserData4 = 65535, default is 0*/
 350        ufshcd_dme_set(hba, UIC_ARG_MIB(0x15b4), 65535);
 351        /*PA_PWRModeUserData5 = 32767, default is 0*/
 352        ufshcd_dme_set(hba, UIC_ARG_MIB(0x15b5), 32767);
 353        /*DME_FC1ProtectionTimeOutVal = 8191, default is 0*/
 354        ufshcd_dme_set(hba, UIC_ARG_MIB(0xd044), 8191);
 355        /*DME_TC1ReplayTimeOutVal = 65535, default is 0*/
 356        ufshcd_dme_set(hba, UIC_ARG_MIB(0xd045), 65535);
 357        /*DME_AFC1ReqTimeOutVal = 32767, default is 0*/
 358        ufshcd_dme_set(hba, UIC_ARG_MIB(0xd046), 32767);
 359}
 360
 361static int ufs_hisi_pwr_change_notify(struct ufs_hba *hba,
 362                                       enum ufs_notify_change_status status,
 363                                       struct ufs_pa_layer_attr *dev_max_params,
 364                                       struct ufs_pa_layer_attr *dev_req_params)
 365{
 366        struct ufs_dev_params ufs_hisi_cap;
 367        int ret = 0;
 368
 369        if (!dev_req_params) {
 370                dev_err(hba->dev,
 371                            "%s: incoming dev_req_params is NULL\n", __func__);
 372                ret = -EINVAL;
 373                goto out;
 374        }
 375
 376        switch (status) {
 377        case PRE_CHANGE:
 378                ufs_hisi_set_dev_cap(&ufs_hisi_cap);
 379                ret = ufshcd_get_pwr_dev_param(&ufs_hisi_cap,
 380                                               dev_max_params, dev_req_params);
 381                if (ret) {
 382                        dev_err(hba->dev,
 383                            "%s: failed to determine capabilities\n", __func__);
 384                        goto out;
 385                }
 386
 387                ufs_hisi_pwr_change_pre_change(hba);
 388                break;
 389        case POST_CHANGE:
 390                break;
 391        default:
 392                ret = -EINVAL;
 393                break;
 394        }
 395out:
 396        return ret;
 397}
 398
 399static int ufs_hisi_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
 400{
 401        struct ufs_hisi_host *host = ufshcd_get_variant(hba);
 402
 403        if (ufshcd_is_runtime_pm(pm_op))
 404                return 0;
 405
 406        if (host->in_suspend) {
 407                WARN_ON(1);
 408                return 0;
 409        }
 410
 411        ufs_sys_ctrl_clr_bits(host, BIT_SYSCTRL_REF_CLOCK_EN, PHY_CLK_CTRL);
 412        udelay(10);
 413        /* set ref_dig_clk override of PHY PCS to 0 */
 414        ufs_sys_ctrl_writel(host, 0x00100000, UFS_DEVICE_RESET_CTRL);
 415
 416        host->in_suspend = true;
 417
 418        return 0;
 419}
 420
 421static int ufs_hisi_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
 422{
 423        struct ufs_hisi_host *host = ufshcd_get_variant(hba);
 424
 425        if (!host->in_suspend)
 426                return 0;
 427
 428        /* set ref_dig_clk override of PHY PCS to 1 */
 429        ufs_sys_ctrl_writel(host, 0x00100010, UFS_DEVICE_RESET_CTRL);
 430        udelay(10);
 431        ufs_sys_ctrl_set_bits(host, BIT_SYSCTRL_REF_CLOCK_EN, PHY_CLK_CTRL);
 432
 433        host->in_suspend = false;
 434        return 0;
 435}
 436
 437static int ufs_hisi_get_resource(struct ufs_hisi_host *host)
 438{
 439        struct device *dev = host->hba->dev;
 440        struct platform_device *pdev = to_platform_device(dev);
 441
 442        /* get resource of ufs sys ctrl */
 443        host->ufs_sys_ctrl = devm_platform_ioremap_resource(pdev, 1);
 444        return PTR_ERR_OR_ZERO(host->ufs_sys_ctrl);
 445}
 446
 447static void ufs_hisi_set_pm_lvl(struct ufs_hba *hba)
 448{
 449        hba->rpm_lvl = UFS_PM_LVL_1;
 450        hba->spm_lvl = UFS_PM_LVL_3;
 451}
 452
 453/**
 454 * ufs_hisi_init_common
 455 * @hba: host controller instance
 456 */
 457static int ufs_hisi_init_common(struct ufs_hba *hba)
 458{
 459        int err = 0;
 460        struct device *dev = hba->dev;
 461        struct ufs_hisi_host *host;
 462
 463        host = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL);
 464        if (!host)
 465                return -ENOMEM;
 466
 467        host->hba = hba;
 468        ufshcd_set_variant(hba, host);
 469
 470        host->rst  = devm_reset_control_get(dev, "rst");
 471        if (IS_ERR(host->rst)) {
 472                dev_err(dev, "%s: failed to get reset control\n", __func__);
 473                return PTR_ERR(host->rst);
 474        }
 475
 476        ufs_hisi_set_pm_lvl(hba);
 477
 478        err = ufs_hisi_get_resource(host);
 479        if (err) {
 480                ufshcd_set_variant(hba, NULL);
 481                return err;
 482        }
 483
 484        return 0;
 485}
 486
 487static int ufs_hi3660_init(struct ufs_hba *hba)
 488{
 489        int ret = 0;
 490        struct device *dev = hba->dev;
 491
 492        ret = ufs_hisi_init_common(hba);
 493        if (ret) {
 494                dev_err(dev, "%s: ufs common init fail\n", __func__);
 495                return ret;
 496        }
 497
 498        ufs_hisi_clk_init(hba);
 499
 500        ufs_hisi_soc_init(hba);
 501
 502        return 0;
 503}
 504
 505static int ufs_hi3670_init(struct ufs_hba *hba)
 506{
 507        int ret = 0;
 508        struct device *dev = hba->dev;
 509        struct ufs_hisi_host *host;
 510
 511        ret = ufs_hisi_init_common(hba);
 512        if (ret) {
 513                dev_err(dev, "%s: ufs common init fail\n", __func__);
 514                return ret;
 515        }
 516
 517        ufs_hisi_clk_init(hba);
 518
 519        ufs_hisi_soc_init(hba);
 520
 521        /* Add cap for 10nm PHY variant on HI3670 SoC */
 522        host = ufshcd_get_variant(hba);
 523        host->caps |= UFS_HISI_CAP_PHY10nm;
 524
 525        return 0;
 526}
 527
 528static const struct ufs_hba_variant_ops ufs_hba_hi3660_vops = {
 529        .name = "hi3660",
 530        .init = ufs_hi3660_init,
 531        .link_startup_notify = ufs_hisi_link_startup_notify,
 532        .pwr_change_notify = ufs_hisi_pwr_change_notify,
 533        .suspend = ufs_hisi_suspend,
 534        .resume = ufs_hisi_resume,
 535};
 536
 537static const struct ufs_hba_variant_ops ufs_hba_hi3670_vops = {
 538        .name = "hi3670",
 539        .init = ufs_hi3670_init,
 540        .link_startup_notify = ufs_hisi_link_startup_notify,
 541        .pwr_change_notify = ufs_hisi_pwr_change_notify,
 542        .suspend = ufs_hisi_suspend,
 543        .resume = ufs_hisi_resume,
 544};
 545
 546static const struct of_device_id ufs_hisi_of_match[] = {
 547        { .compatible = "hisilicon,hi3660-ufs", .data = &ufs_hba_hi3660_vops },
 548        { .compatible = "hisilicon,hi3670-ufs", .data = &ufs_hba_hi3670_vops },
 549        {},
 550};
 551
 552MODULE_DEVICE_TABLE(of, ufs_hisi_of_match);
 553
 554static int ufs_hisi_probe(struct platform_device *pdev)
 555{
 556        const struct of_device_id *of_id;
 557
 558        of_id = of_match_node(ufs_hisi_of_match, pdev->dev.of_node);
 559
 560        return ufshcd_pltfrm_init(pdev, of_id->data);
 561}
 562
 563static int ufs_hisi_remove(struct platform_device *pdev)
 564{
 565        struct ufs_hba *hba =  platform_get_drvdata(pdev);
 566
 567        ufshcd_remove(hba);
 568        return 0;
 569}
 570
 571static const struct dev_pm_ops ufs_hisi_pm_ops = {
 572        .suspend        = ufshcd_pltfrm_suspend,
 573        .resume         = ufshcd_pltfrm_resume,
 574        .runtime_suspend = ufshcd_pltfrm_runtime_suspend,
 575        .runtime_resume  = ufshcd_pltfrm_runtime_resume,
 576        .runtime_idle    = ufshcd_pltfrm_runtime_idle,
 577};
 578
 579static struct platform_driver ufs_hisi_pltform = {
 580        .probe  = ufs_hisi_probe,
 581        .remove = ufs_hisi_remove,
 582        .shutdown = ufshcd_pltfrm_shutdown,
 583        .driver = {
 584                .name   = "ufshcd-hisi",
 585                .pm     = &ufs_hisi_pm_ops,
 586                .of_match_table = of_match_ptr(ufs_hisi_of_match),
 587        },
 588};
 589module_platform_driver(ufs_hisi_pltform);
 590
 591MODULE_LICENSE("GPL");
 592MODULE_ALIAS("platform:ufshcd-hisi");
 593MODULE_DESCRIPTION("HiSilicon Hixxxx UFS Driver");
 594