1 // SPDX-License-Identifier: GPL-2.0-only
3 * UNISOC UFS Host Controller driver
5 * Copyright (C) 2022 Unisoc, Inc.
6 * Author: Zhe Wang <zhe.wang1@unisoc.com>
9 #include <linux/arm-smccc.h>
10 #include <linux/mfd/syscon.h>
12 #include <linux/platform_device.h>
13 #include <linux/regmap.h>
14 #include <linux/reset.h>
15 #include <linux/regulator/consumer.h>
17 #include <ufs/ufshcd.h>
18 #include "ufshcd-pltfrm.h"
21 static const struct of_device_id ufs_sprd_of_match
[];
23 static struct ufs_sprd_priv
*ufs_sprd_get_priv_data(struct ufs_hba
*hba
)
25 struct ufs_sprd_host
*host
= ufshcd_get_variant(hba
);
31 static void ufs_sprd_regmap_update(struct ufs_sprd_priv
*priv
, unsigned int index
,
32 unsigned int reg
, unsigned int bits
, unsigned int val
)
34 regmap_update_bits(priv
->sysci
[index
].regmap
, reg
, bits
, val
);
37 static void ufs_sprd_regmap_read(struct ufs_sprd_priv
*priv
, unsigned int index
,
38 unsigned int reg
, unsigned int *val
)
40 regmap_read(priv
->sysci
[index
].regmap
, reg
, val
);
43 static void ufs_sprd_get_unipro_ver(struct ufs_hba
*hba
)
45 struct ufs_sprd_host
*host
= ufshcd_get_variant(hba
);
47 if (ufshcd_dme_get(hba
, UIC_ARG_MIB(PA_LOCALVERINFO
), &host
->unipro_ver
))
51 static void ufs_sprd_ctrl_uic_compl(struct ufs_hba
*hba
, bool enable
)
53 u32 set
= ufshcd_readl(hba
, REG_INTERRUPT_ENABLE
);
56 set
|= UIC_COMMAND_COMPL
;
58 set
&= ~UIC_COMMAND_COMPL
;
59 ufshcd_writel(hba
, set
, REG_INTERRUPT_ENABLE
);
62 static int ufs_sprd_get_reset_ctrl(struct device
*dev
, struct ufs_sprd_rst
*rci
)
64 rci
->rc
= devm_reset_control_get(dev
, rci
->name
);
65 if (IS_ERR(rci
->rc
)) {
66 dev_err(dev
, "failed to get reset ctrl:%s\n", rci
->name
);
67 return PTR_ERR(rci
->rc
);
73 static int ufs_sprd_get_syscon_reg(struct device
*dev
, struct ufs_sprd_syscon
*sysci
)
75 sysci
->regmap
= syscon_regmap_lookup_by_phandle(dev
->of_node
, sysci
->name
);
76 if (IS_ERR(sysci
->regmap
)) {
77 dev_err(dev
, "failed to get ufs syscon:%s\n", sysci
->name
);
78 return PTR_ERR(sysci
->regmap
);
84 static int ufs_sprd_get_vreg(struct device
*dev
, struct ufs_sprd_vreg
*vregi
)
86 vregi
->vreg
= devm_regulator_get(dev
, vregi
->name
);
87 if (IS_ERR(vregi
->vreg
)) {
88 dev_err(dev
, "failed to get vreg:%s\n", vregi
->name
);
89 return PTR_ERR(vregi
->vreg
);
95 static int ufs_sprd_parse_dt(struct device
*dev
, struct ufs_hba
*hba
, struct ufs_sprd_host
*host
)
98 struct ufs_sprd_priv
*priv
= host
->priv
;
101 /* Parse UFS reset ctrl info */
102 for (i
= 0; i
< SPRD_UFS_RST_MAX
; i
++) {
103 if (!priv
->rci
[i
].name
)
105 ret
= ufs_sprd_get_reset_ctrl(dev
, &priv
->rci
[i
]);
110 /* Parse UFS syscon reg info */
111 for (i
= 0; i
< SPRD_UFS_SYSCON_MAX
; i
++) {
112 if (!priv
->sysci
[i
].name
)
114 ret
= ufs_sprd_get_syscon_reg(dev
, &priv
->sysci
[i
]);
119 /* Parse UFS vreg info */
120 for (i
= 0; i
< SPRD_UFS_VREG_MAX
; i
++) {
121 if (!priv
->vregi
[i
].name
)
123 ret
= ufs_sprd_get_vreg(dev
, &priv
->vregi
[i
]);
132 static int ufs_sprd_common_init(struct ufs_hba
*hba
)
134 struct device
*dev
= hba
->dev
;
135 struct ufs_sprd_host
*host
;
136 struct platform_device __maybe_unused
*pdev
= to_platform_device(dev
);
137 const struct of_device_id
*of_id
;
140 host
= devm_kzalloc(dev
, sizeof(*host
), GFP_KERNEL
);
144 of_id
= of_match_node(ufs_sprd_of_match
, pdev
->dev
.of_node
);
145 if (of_id
->data
!= NULL
)
146 host
->priv
= container_of(of_id
->data
, struct ufs_sprd_priv
,
150 ufshcd_set_variant(hba
, host
);
152 hba
->caps
|= UFSHCD_CAP_CLK_GATING
|
155 hba
->quirks
|= UFSHCD_QUIRK_DELAY_BEFORE_DME_CMDS
;
157 ret
= ufs_sprd_parse_dt(dev
, hba
, host
);
162 static int sprd_ufs_pwr_change_notify(struct ufs_hba
*hba
,
163 enum ufs_notify_change_status status
,
164 struct ufs_pa_layer_attr
*dev_max_params
,
165 struct ufs_pa_layer_attr
*dev_req_params
)
167 struct ufs_sprd_host
*host
= ufshcd_get_variant(hba
);
169 if (status
== PRE_CHANGE
) {
170 memcpy(dev_req_params
, dev_max_params
,
171 sizeof(struct ufs_pa_layer_attr
));
172 if (host
->unipro_ver
>= UFS_UNIPRO_VER_1_8
)
173 ufshcd_dme_configure_adapt(hba
, dev_req_params
->gear_tx
,
180 static int ufs_sprd_suspend(struct ufs_hba
*hba
, enum ufs_pm_op pm_op
,
181 enum ufs_notify_change_status status
)
185 if (status
== PRE_CHANGE
) {
186 if (ufshcd_is_auto_hibern8_supported(hba
)) {
187 spin_lock_irqsave(hba
->host
->host_lock
, flags
);
188 ufshcd_writel(hba
, 0, REG_AUTO_HIBERNATE_IDLE_TIMER
);
189 spin_unlock_irqrestore(hba
->host
->host_lock
, flags
);
196 static void ufs_sprd_n6_host_reset(struct ufs_hba
*hba
)
198 struct ufs_sprd_priv
*priv
= ufs_sprd_get_priv_data(hba
);
200 dev_info(hba
->dev
, "ufs host reset!\n");
202 reset_control_assert(priv
->rci
[SPRD_UFSHCI_SOFT_RST
].rc
);
203 usleep_range(1000, 1100);
204 reset_control_deassert(priv
->rci
[SPRD_UFSHCI_SOFT_RST
].rc
);
207 static int ufs_sprd_n6_device_reset(struct ufs_hba
*hba
)
209 struct ufs_sprd_priv
*priv
= ufs_sprd_get_priv_data(hba
);
211 dev_info(hba
->dev
, "ufs device reset!\n");
213 reset_control_assert(priv
->rci
[SPRD_UFS_DEV_RST
].rc
);
214 usleep_range(1000, 1100);
215 reset_control_deassert(priv
->rci
[SPRD_UFS_DEV_RST
].rc
);
220 static void ufs_sprd_n6_key_acc_enable(struct ufs_hba
*hba
)
224 struct arm_smccc_res res
;
227 /* Key access only can be enabled under HCE enable */
228 val
= ufshcd_readl(hba
, REG_CONTROLLER_ENABLE
);
229 if (!(val
& CONTROLLER_ENABLE
)) {
230 ufs_sprd_n6_host_reset(hba
);
231 val
|= CONTROLLER_ENABLE
;
232 ufshcd_writel(hba
, val
, REG_CONTROLLER_ENABLE
);
233 usleep_range(1000, 1100);
241 arm_smccc_smc(SPRD_SIP_SVC_STORAGE_UFS_CRYPTO_ENABLE
,
242 0, 0, 0, 0, 0, 0, 0, &res
);
247 dev_err(hba
->dev
, "key reg access enable fail, disable crypto\n");
248 hba
->caps
&= ~UFSHCD_CAP_CRYPTO
;
251 static int ufs_sprd_n6_init(struct ufs_hba
*hba
)
253 struct ufs_sprd_priv
*priv
;
256 ret
= ufs_sprd_common_init(hba
);
260 priv
= ufs_sprd_get_priv_data(hba
);
262 ret
= regulator_enable(priv
->vregi
[SPRD_UFS_VDD_MPHY
].vreg
);
266 if (hba
->caps
& UFSHCD_CAP_CRYPTO
)
267 ufs_sprd_n6_key_acc_enable(hba
);
272 static int ufs_sprd_n6_phy_init(struct ufs_hba
*hba
)
278 struct ufs_sprd_priv
*priv
= ufs_sprd_get_priv_data(hba
);
280 ufshcd_dme_set(hba
, UIC_ARG_MIB(CBREFCLKCTRL2
), 0x90);
281 ufshcd_dme_set(hba
, UIC_ARG_MIB(CBCRCTRL
), 0x01);
282 ufshcd_dme_set(hba
, UIC_ARG_MIB_SEL(RXSQCONTROL
,
283 UIC_ARG_MPHY_RX_GEN_SEL_INDEX(0)), 0x01);
284 ufshcd_dme_set(hba
, UIC_ARG_MIB_SEL(RXSQCONTROL
,
285 UIC_ARG_MPHY_RX_GEN_SEL_INDEX(1)), 0x01);
286 ufshcd_dme_set(hba
, UIC_ARG_MIB(VS_MPHYCFGUPDT
), 0x01);
287 ufshcd_dme_set(hba
, UIC_ARG_MIB(CBRATESEL
), 0x01);
290 /* phy_sram_init_done */
291 ufs_sprd_regmap_read(priv
, SPRD_UFS_ANLG
, 0xc, &val
);
292 if ((val
& 0x1) == 0x1) {
293 for (offset
= 0x40; offset
< 0x42; offset
++) {
294 /* Lane afe calibration */
295 ufshcd_dme_set(hba
, UIC_ARG_MIB(CBCREGADDRLSB
), 0x1c);
296 ufshcd_dme_set(hba
, UIC_ARG_MIB(CBCREGADDRMSB
), offset
);
297 ufshcd_dme_set(hba
, UIC_ARG_MIB(CBCREGWRLSB
), 0x04);
298 ufshcd_dme_set(hba
, UIC_ARG_MIB(CBCREGWRMSB
), 0x00);
299 ufshcd_dme_set(hba
, UIC_ARG_MIB(CBCREGRDWRSEL
), 0x01);
300 ufshcd_dme_set(hba
, UIC_ARG_MIB(VS_MPHYCFGUPDT
), 0x01);
313 /* phy_sram_ext_ld_done */
314 ufs_sprd_regmap_update(priv
, SPRD_UFS_ANLG
, 0xc, 0x2, 0);
315 ufshcd_dme_set(hba
, UIC_ARG_MIB(VS_MPHYCFGUPDT
), 0x01);
316 ufshcd_dme_set(hba
, UIC_ARG_MIB(VS_MPHYDISABLE
), 0x0);
322 static int sprd_ufs_n6_hce_enable_notify(struct ufs_hba
*hba
,
323 enum ufs_notify_change_status status
)
326 struct ufs_sprd_priv
*priv
= ufs_sprd_get_priv_data(hba
);
328 if (status
== PRE_CHANGE
) {
329 /* phy_sram_ext_ld_done */
330 ufs_sprd_regmap_update(priv
, SPRD_UFS_ANLG
, 0xc, 0x2, 0x2);
331 /* phy_sram_bypass */
332 ufs_sprd_regmap_update(priv
, SPRD_UFS_ANLG
, 0xc, 0x4, 0x4);
334 ufs_sprd_n6_host_reset(hba
);
336 if (hba
->caps
& UFSHCD_CAP_CRYPTO
)
337 ufs_sprd_n6_key_acc_enable(hba
);
340 if (status
== POST_CHANGE
) {
341 err
= ufs_sprd_n6_phy_init(hba
);
343 dev_err(hba
->dev
, "Phy setup failed (%d)\n", err
);
347 ufs_sprd_get_unipro_ver(hba
);
353 static void sprd_ufs_n6_h8_notify(struct ufs_hba
*hba
,
354 enum uic_cmd_dme cmd
,
355 enum ufs_notify_change_status status
)
357 struct ufs_sprd_priv
*priv
= ufs_sprd_get_priv_data(hba
);
359 if (status
== PRE_CHANGE
) {
360 if (cmd
== UIC_CMD_DME_HIBER_ENTER
)
362 * Disable UIC COMPL INTR to prevent access to UFSHCI after
363 * checking HCS.UPMCRS
365 ufs_sprd_ctrl_uic_compl(hba
, false);
367 if (cmd
== UIC_CMD_DME_HIBER_EXIT
) {
368 ufs_sprd_regmap_update(priv
, SPRD_UFS_AON_APB
, APB_UFSDEV_REG
,
369 APB_UFSDEV_REFCLK_EN
, APB_UFSDEV_REFCLK_EN
);
370 ufs_sprd_regmap_update(priv
, SPRD_UFS_AON_APB
, APB_USB31PLL_CTRL
,
371 APB_USB31PLLV_REF2MPHY
, APB_USB31PLLV_REF2MPHY
);
375 if (status
== POST_CHANGE
) {
376 if (cmd
== UIC_CMD_DME_HIBER_EXIT
)
377 ufs_sprd_ctrl_uic_compl(hba
, true);
379 if (cmd
== UIC_CMD_DME_HIBER_ENTER
) {
380 ufs_sprd_regmap_update(priv
, SPRD_UFS_AON_APB
, APB_UFSDEV_REG
,
381 APB_UFSDEV_REFCLK_EN
, 0);
382 ufs_sprd_regmap_update(priv
, SPRD_UFS_AON_APB
, APB_USB31PLL_CTRL
,
383 APB_USB31PLLV_REF2MPHY
, 0);
388 static struct ufs_sprd_priv n6_ufs
= {
389 .rci
[SPRD_UFSHCI_SOFT_RST
] = { .name
= "controller", },
390 .rci
[SPRD_UFS_DEV_RST
] = { .name
= "device", },
392 .sysci
[SPRD_UFS_ANLG
] = { .name
= "sprd,ufs-anlg-syscon", },
393 .sysci
[SPRD_UFS_AON_APB
] = { .name
= "sprd,aon-apb-syscon", },
395 .vregi
[SPRD_UFS_VDD_MPHY
] = { .name
= "vdd-mphy", },
397 .ufs_hba_sprd_vops
= {
398 .name
= "sprd,ums9620-ufs",
399 .init
= ufs_sprd_n6_init
,
400 .hce_enable_notify
= sprd_ufs_n6_hce_enable_notify
,
401 .pwr_change_notify
= sprd_ufs_pwr_change_notify
,
402 .hibern8_notify
= sprd_ufs_n6_h8_notify
,
403 .device_reset
= ufs_sprd_n6_device_reset
,
404 .suspend
= ufs_sprd_suspend
,
408 static const struct of_device_id __maybe_unused ufs_sprd_of_match
[] = {
409 { .compatible
= "sprd,ums9620-ufs", .data
= &n6_ufs
.ufs_hba_sprd_vops
},
412 MODULE_DEVICE_TABLE(of
, ufs_sprd_of_match
);
414 static int ufs_sprd_probe(struct platform_device
*pdev
)
417 struct device
*dev
= &pdev
->dev
;
418 const struct of_device_id
*of_id
;
420 of_id
= of_match_node(ufs_sprd_of_match
, dev
->of_node
);
421 err
= ufshcd_pltfrm_init(pdev
, of_id
->data
);
423 dev_err(dev
, "ufshcd_pltfrm_init() failed %d\n", err
);
428 static void ufs_sprd_remove(struct platform_device
*pdev
)
430 struct ufs_hba
*hba
= platform_get_drvdata(pdev
);
432 pm_runtime_get_sync(&(pdev
)->dev
);
436 static const struct dev_pm_ops ufs_sprd_pm_ops
= {
437 SET_SYSTEM_SLEEP_PM_OPS(ufshcd_system_suspend
, ufshcd_system_resume
)
438 SET_RUNTIME_PM_OPS(ufshcd_runtime_suspend
, ufshcd_runtime_resume
, NULL
)
439 .prepare
= ufshcd_suspend_prepare
,
440 .complete
= ufshcd_resume_complete
,
443 static struct platform_driver ufs_sprd_pltform
= {
444 .probe
= ufs_sprd_probe
,
445 .remove_new
= ufs_sprd_remove
,
447 .name
= "ufshcd-sprd",
448 .pm
= &ufs_sprd_pm_ops
,
449 .of_match_table
= of_match_ptr(ufs_sprd_of_match
),
452 module_platform_driver(ufs_sprd_pltform
);
454 MODULE_AUTHOR("Zhe Wang <zhe.wang1@unisoc.com>");
455 MODULE_DESCRIPTION("Unisoc UFS Host Driver");
456 MODULE_LICENSE("GPL v2");