2 * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
4 * SPDX-License-Identifier: BSD-3-Clause
15 static int dwufs_phy_init(ufs_params_t
*params
)
18 unsigned int fsm0
, fsm1
;
22 assert((params
!= NULL
) && (params
->reg_base
!= 0));
24 base
= params
->reg_base
;
26 /* Unipro VS_MPHY disable */
27 ufshc_dme_set(VS_MPHY_DISABLE_OFFSET
, 0, VS_MPHY_DISABLE_MPHYDIS
);
28 ufshc_dme_set(PA_HS_SERIES_OFFSET
, 0, 2);
30 ufshc_dme_set(0x8114, 0, 1);
32 ufshc_dme_set(0x8121, 0, 0x2d);
34 ufshc_dme_set(0x8122, 0, 0x1);
35 ufshc_dme_set(VS_MPHY_CFG_UPDT_OFFSET
, 0, 1);
37 /* MPHY RXOVRCTRL4 rx0 */
38 ufshc_dme_set(0x800d, 4, 0x58);
39 /* MPHY RXOVRCTRL4 rx1 */
40 ufshc_dme_set(0x800d, 5, 0x58);
41 /* MPHY RXOVRCTRL5 rx0 */
42 ufshc_dme_set(0x800e, 4, 0xb);
43 /* MPHY RXOVRCTRL5 rx1 */
44 ufshc_dme_set(0x800e, 5, 0xb);
45 /* MPHY RXSQCONTROL rx0 */
46 ufshc_dme_set(0x8009, 4, 0x1);
47 /* MPHY RXSQCONTROL rx1 */
48 ufshc_dme_set(0x8009, 5, 0x1);
49 ufshc_dme_set(VS_MPHY_CFG_UPDT_OFFSET
, 0, 1);
51 ufshc_dme_set(0x8113, 0, 0x1);
52 ufshc_dme_set(VS_MPHY_CFG_UPDT_OFFSET
, 0, 1);
54 ufshc_dme_set(RX_HS_G3_SYNC_LENGTH_CAP_OFFSET
, 4, 0x4a);
55 ufshc_dme_set(RX_HS_G3_SYNC_LENGTH_CAP_OFFSET
, 5, 0x4a);
56 ufshc_dme_set(RX_HS_G2_SYNC_LENGTH_CAP_OFFSET
, 4, 0x4a);
57 ufshc_dme_set(RX_HS_G2_SYNC_LENGTH_CAP_OFFSET
, 5, 0x4a);
58 ufshc_dme_set(RX_MIN_ACTIVATETIME_CAP_OFFSET
, 4, 0x7);
59 ufshc_dme_set(RX_MIN_ACTIVATETIME_CAP_OFFSET
, 5, 0x7);
60 ufshc_dme_set(TX_HIBERN8TIME_CAP_OFFSET
, 0, 0x5);
61 ufshc_dme_set(TX_HIBERN8TIME_CAP_OFFSET
, 1, 0x5);
62 ufshc_dme_set(VS_MPHY_CFG_UPDT_OFFSET
, 0, 1);
64 result
= ufshc_dme_get(VS_MPHY_DISABLE_OFFSET
, 0, &data
);
65 assert((result
== 0) && (data
== VS_MPHY_DISABLE_MPHYDIS
));
66 /* enable Unipro VS MPHY */
67 ufshc_dme_set(VS_MPHY_DISABLE_OFFSET
, 0, 0);
70 result
= ufshc_dme_get(TX_FSM_STATE_OFFSET
, 0, &fsm0
);
72 result
= ufshc_dme_get(TX_FSM_STATE_OFFSET
, 1, &fsm1
);
74 if ((fsm0
== TX_FSM_STATE_HIBERN8
) &&
75 (fsm1
== TX_FSM_STATE_HIBERN8
))
79 mmio_write_32(base
+ HCLKDIV
, 0xE4);
80 mmio_clrbits_32(base
+ AHIT
, 0x3FF);
82 ufshc_dme_set(PA_LOCAL_TX_LCC_ENABLE_OFFSET
, 0, 0);
83 ufshc_dme_set(VS_MK2_EXTN_SUPPORT_OFFSET
, 0, 0);
85 result
= ufshc_dme_get(VS_MK2_EXTN_SUPPORT_OFFSET
, 0, &data
);
86 assert((result
== 0) && (data
== 0));
88 ufshc_dme_set(DL_AFC0_CREDIT_THRESHOLD_OFFSET
, 0, 0);
89 ufshc_dme_set(DL_TC0_OUT_ACK_THRESHOLD_OFFSET
, 0, 0);
90 ufshc_dme_set(DL_TC0_TX_FC_THRESHOLD_OFFSET
, 0, 9);
95 static int dwufs_phy_set_pwr_mode(ufs_params_t
*params
)
98 unsigned int data
, tx_lanes
, rx_lanes
;
102 assert((params
!= NULL
) && (params
->reg_base
!= 0));
104 base
= params
->reg_base
;
105 flags
= params
->flags
;
106 if ((flags
& UFS_FLAGS_VENDOR_SKHYNIX
) != 0U) {
107 NOTICE("ufs: H**** device must set VS_DebugSaveConfigTime 0x10\n");
108 /* VS_DebugSaveConfigTime */
109 result
= ufshc_dme_set(0xd0a0, 0x0, 0x10);
112 result
= ufshc_dme_set(0x1556, 0x0, 0x48);
116 result
= ufshc_dme_get(PA_TACTIVATE_OFFSET
, 0, &data
);
119 result
= ufshc_dme_set(PA_TACTIVATE_OFFSET
, 0, 7);
122 result
= ufshc_dme_get(PA_CONNECTED_TX_DATA_LANES_OFFSET
, 0, &tx_lanes
);
124 result
= ufshc_dme_get(PA_CONNECTED_RX_DATA_LANES_OFFSET
, 0, &rx_lanes
);
127 result
= ufshc_dme_set(PA_TX_SKIP_OFFSET
, 0, 0);
129 result
= ufshc_dme_set(PA_TX_GEAR_OFFSET
, 0, 3);
131 result
= ufshc_dme_set(PA_RX_GEAR_OFFSET
, 0, 3);
133 result
= ufshc_dme_set(PA_HS_SERIES_OFFSET
, 0, 2);
135 result
= ufshc_dme_set(PA_TX_TERMINATION_OFFSET
, 0, 1);
137 result
= ufshc_dme_set(PA_RX_TERMINATION_OFFSET
, 0, 1);
139 result
= ufshc_dme_set(PA_SCRAMBLING_OFFSET
, 0, 0);
141 result
= ufshc_dme_set(PA_ACTIVE_TX_DATA_LANES_OFFSET
, 0, tx_lanes
);
143 result
= ufshc_dme_set(PA_ACTIVE_RX_DATA_LANES_OFFSET
, 0, rx_lanes
);
145 result
= ufshc_dme_set(PA_PWR_MODE_USER_DATA0_OFFSET
, 0, 8191);
147 result
= ufshc_dme_set(PA_PWR_MODE_USER_DATA1_OFFSET
, 0, 65535);
149 result
= ufshc_dme_set(PA_PWR_MODE_USER_DATA2_OFFSET
, 0, 32767);
151 result
= ufshc_dme_set(DME_FC0_PROTECTION_TIMEOUT_OFFSET
, 0, 8191);
153 result
= ufshc_dme_set(DME_TC0_REPLAY_TIMEOUT_OFFSET
, 0, 65535);
155 result
= ufshc_dme_set(DME_AFC0_REQ_TIMEOUT_OFFSET
, 0, 32767);
157 result
= ufshc_dme_set(PA_PWR_MODE_USER_DATA3_OFFSET
, 0, 8191);
159 result
= ufshc_dme_set(PA_PWR_MODE_USER_DATA4_OFFSET
, 0, 65535);
161 result
= ufshc_dme_set(PA_PWR_MODE_USER_DATA5_OFFSET
, 0, 32767);
163 result
= ufshc_dme_set(DME_FC1_PROTECTION_TIMEOUT_OFFSET
, 0, 8191);
165 result
= ufshc_dme_set(DME_TC1_REPLAY_TIMEOUT_OFFSET
, 0, 65535);
167 result
= ufshc_dme_set(DME_AFC1_REQ_TIMEOUT_OFFSET
, 0, 32767);
170 result
= ufshc_dme_set(PA_PWR_MODE_OFFSET
, 0, 0x11);
173 data
= mmio_read_32(base
+ IS
);
174 } while ((data
& UFS_INT_UPMS
) == 0);
175 mmio_write_32(base
+ IS
, UFS_INT_UPMS
);
176 data
= mmio_read_32(base
+ HCS
);
177 if ((data
& HCS_UPMCRS_MASK
) == HCS_PWR_LOCAL
)
178 INFO("ufs: change power mode success\n");
180 WARN("ufs: HCS.UPMCRS error, HCS:0x%x\n", data
);
185 const ufs_ops_t dw_ufs_ops
= {
186 .phy_init
= dwufs_phy_init
,
187 .phy_set_pwr_mode
= dwufs_phy_set_pwr_mode
,
190 int dw_ufs_init(dw_ufs_params_t
*params
)
192 ufs_params_t ufs_params
;
194 memset(&ufs_params
, 0, sizeof(ufs_params
));
195 ufs_params
.reg_base
= params
->reg_base
;
196 ufs_params
.desc_base
= params
->desc_base
;
197 ufs_params
.desc_size
= params
->desc_size
;
198 ufs_params
.flags
= params
->flags
;
199 ufs_init(&dw_ufs_ops
, &ufs_params
);