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