1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2019 MediaTek Inc.
5 * Stanley Chu <stanley.chu@mediatek.com>
6 * Peter Wang <peter.wang@mediatek.com>
10 #include <linux/of_address.h>
11 #include <linux/phy/phy.h>
12 #include <linux/platform_device.h>
15 #include "ufshcd-pltfrm.h"
17 #include "ufs-mediatek.h"
19 static void ufs_mtk_cfg_unipro_cg(struct ufs_hba
*hba
, bool enable
)
25 UIC_ARG_MIB(VS_SAVEPOWERCONTROL
), &tmp
);
27 (1 << RX_SYMBOL_CLK_GATE_EN
) |
28 (1 << SYS_CLK_GATE_EN
) |
29 (1 << TX_CLK_GATE_EN
);
31 UIC_ARG_MIB(VS_SAVEPOWERCONTROL
), tmp
);
34 UIC_ARG_MIB(VS_DEBUGCLOCKENABLE
), &tmp
);
35 tmp
= tmp
& ~(1 << TX_SYMBOL_CLK_REQ_FORCE
);
37 UIC_ARG_MIB(VS_DEBUGCLOCKENABLE
), tmp
);
40 UIC_ARG_MIB(VS_SAVEPOWERCONTROL
), &tmp
);
41 tmp
= tmp
& ~((1 << RX_SYMBOL_CLK_GATE_EN
) |
42 (1 << SYS_CLK_GATE_EN
) |
43 (1 << TX_CLK_GATE_EN
));
45 UIC_ARG_MIB(VS_SAVEPOWERCONTROL
), tmp
);
48 UIC_ARG_MIB(VS_DEBUGCLOCKENABLE
), &tmp
);
49 tmp
= tmp
| (1 << TX_SYMBOL_CLK_REQ_FORCE
);
51 UIC_ARG_MIB(VS_DEBUGCLOCKENABLE
), tmp
);
55 static int ufs_mtk_bind_mphy(struct ufs_hba
*hba
)
57 struct ufs_mtk_host
*host
= ufshcd_get_variant(hba
);
58 struct device
*dev
= hba
->dev
;
59 struct device_node
*np
= dev
->of_node
;
62 host
->mphy
= devm_of_phy_get_by_index(dev
, np
, 0);
64 if (host
->mphy
== ERR_PTR(-EPROBE_DEFER
)) {
66 * UFS driver might be probed before the phy driver does.
67 * In that case we would like to return EPROBE_DEFER code.
71 "%s: required phy hasn't probed yet. err = %d\n",
73 } else if (IS_ERR(host
->mphy
)) {
74 err
= PTR_ERR(host
->mphy
);
75 dev_info(dev
, "%s: PHY get failed %d\n", __func__
, err
);
85 * ufs_mtk_setup_clocks - enables/disable clocks
86 * @hba: host controller instance
87 * @on: If true, enable clocks else disable them.
88 * @status: PRE_CHANGE or POST_CHANGE notify
90 * Returns 0 on success, non-zero on failure.
92 static int ufs_mtk_setup_clocks(struct ufs_hba
*hba
, bool on
,
93 enum ufs_notify_change_status status
)
95 struct ufs_mtk_host
*host
= ufshcd_get_variant(hba
);
99 * In case ufs_mtk_init() is not yet done, simply ignore.
100 * This ufs_mtk_setup_clocks() shall be called from
101 * ufs_mtk_init() after init is done.
109 ret
= phy_power_off(host
->mphy
);
113 ret
= phy_power_on(host
->mphy
);
121 * ufs_mtk_init - find other essential mmio bases
122 * @hba: host controller instance
124 * Binds PHY with controller and powers up PHY enabling clocks
127 * Returns -EPROBE_DEFER if binding fails, returns negative error
128 * on phy power up failure and returns zero on success.
130 static int ufs_mtk_init(struct ufs_hba
*hba
)
132 struct ufs_mtk_host
*host
;
133 struct device
*dev
= hba
->dev
;
136 host
= devm_kzalloc(dev
, sizeof(*host
), GFP_KERNEL
);
139 dev_info(dev
, "%s: no memory for mtk ufs host\n", __func__
);
144 ufshcd_set_variant(hba
, host
);
146 err
= ufs_mtk_bind_mphy(hba
);
148 goto out_variant_clear
;
151 * ufshcd_vops_init() is invoked after
152 * ufshcd_setup_clock(true) in ufshcd_hba_init() thus
153 * phy clock setup is skipped.
155 * Enable phy clocks specifically here.
157 ufs_mtk_setup_clocks(hba
, true, POST_CHANGE
);
162 ufshcd_set_variant(hba
, NULL
);
167 static int ufs_mtk_pre_pwr_change(struct ufs_hba
*hba
,
168 struct ufs_pa_layer_attr
*dev_max_params
,
169 struct ufs_pa_layer_attr
*dev_req_params
)
171 struct ufs_dev_params host_cap
;
174 host_cap
.tx_lanes
= UFS_MTK_LIMIT_NUM_LANES_TX
;
175 host_cap
.rx_lanes
= UFS_MTK_LIMIT_NUM_LANES_RX
;
176 host_cap
.hs_rx_gear
= UFS_MTK_LIMIT_HSGEAR_RX
;
177 host_cap
.hs_tx_gear
= UFS_MTK_LIMIT_HSGEAR_TX
;
178 host_cap
.pwm_rx_gear
= UFS_MTK_LIMIT_PWMGEAR_RX
;
179 host_cap
.pwm_tx_gear
= UFS_MTK_LIMIT_PWMGEAR_TX
;
180 host_cap
.rx_pwr_pwm
= UFS_MTK_LIMIT_RX_PWR_PWM
;
181 host_cap
.tx_pwr_pwm
= UFS_MTK_LIMIT_TX_PWR_PWM
;
182 host_cap
.rx_pwr_hs
= UFS_MTK_LIMIT_RX_PWR_HS
;
183 host_cap
.tx_pwr_hs
= UFS_MTK_LIMIT_TX_PWR_HS
;
184 host_cap
.hs_rate
= UFS_MTK_LIMIT_HS_RATE
;
185 host_cap
.desired_working_mode
=
186 UFS_MTK_LIMIT_DESIRED_MODE
;
188 ret
= ufshcd_get_pwr_dev_param(&host_cap
,
192 pr_info("%s: failed to determine capabilities\n",
199 static int ufs_mtk_pwr_change_notify(struct ufs_hba
*hba
,
200 enum ufs_notify_change_status stage
,
201 struct ufs_pa_layer_attr
*dev_max_params
,
202 struct ufs_pa_layer_attr
*dev_req_params
)
208 ret
= ufs_mtk_pre_pwr_change(hba
, dev_max_params
,
221 static int ufs_mtk_pre_link(struct ufs_hba
*hba
)
226 /* disable deep stall */
227 ret
= ufshcd_dme_get(hba
, UIC_ARG_MIB(VS_SAVEPOWERCONTROL
), &tmp
);
233 ret
= ufshcd_dme_set(hba
, UIC_ARG_MIB(VS_SAVEPOWERCONTROL
), tmp
);
238 static int ufs_mtk_post_link(struct ufs_hba
*hba
)
240 /* disable device LCC */
241 ufshcd_dme_set(hba
, UIC_ARG_MIB(PA_LOCAL_TX_LCC_ENABLE
), 0);
243 /* enable unipro clock gating feature */
244 ufs_mtk_cfg_unipro_cg(hba
, true);
249 static int ufs_mtk_link_startup_notify(struct ufs_hba
*hba
,
250 enum ufs_notify_change_status stage
)
256 ret
= ufs_mtk_pre_link(hba
);
259 ret
= ufs_mtk_post_link(hba
);
269 static int ufs_mtk_suspend(struct ufs_hba
*hba
, enum ufs_pm_op pm_op
)
271 struct ufs_mtk_host
*host
= ufshcd_get_variant(hba
);
273 if (ufshcd_is_link_hibern8(hba
))
274 phy_power_off(host
->mphy
);
279 static int ufs_mtk_resume(struct ufs_hba
*hba
, enum ufs_pm_op pm_op
)
281 struct ufs_mtk_host
*host
= ufshcd_get_variant(hba
);
283 if (ufshcd_is_link_hibern8(hba
))
284 phy_power_on(host
->mphy
);
290 * struct ufs_hba_mtk_vops - UFS MTK specific variant operations
292 * The variant operations configure the necessary controller and PHY
293 * handshake during initialization.
295 static struct ufs_hba_variant_ops ufs_hba_mtk_vops
= {
296 .name
= "mediatek.ufshci",
297 .init
= ufs_mtk_init
,
298 .setup_clocks
= ufs_mtk_setup_clocks
,
299 .link_startup_notify
= ufs_mtk_link_startup_notify
,
300 .pwr_change_notify
= ufs_mtk_pwr_change_notify
,
301 .suspend
= ufs_mtk_suspend
,
302 .resume
= ufs_mtk_resume
,
306 * ufs_mtk_probe - probe routine of the driver
307 * @pdev: pointer to Platform device handle
309 * Return zero for success and non-zero for failure
311 static int ufs_mtk_probe(struct platform_device
*pdev
)
314 struct device
*dev
= &pdev
->dev
;
316 /* perform generic probe */
317 err
= ufshcd_pltfrm_init(pdev
, &ufs_hba_mtk_vops
);
319 dev_info(dev
, "probe failed %d\n", err
);
325 * ufs_mtk_remove - set driver_data of the device to NULL
326 * @pdev: pointer to platform device handle
330 static int ufs_mtk_remove(struct platform_device
*pdev
)
332 struct ufs_hba
*hba
= platform_get_drvdata(pdev
);
334 pm_runtime_get_sync(&(pdev
)->dev
);
339 static const struct of_device_id ufs_mtk_of_match
[] = {
340 { .compatible
= "mediatek,mt8183-ufshci"},
344 static const struct dev_pm_ops ufs_mtk_pm_ops
= {
345 .suspend
= ufshcd_pltfrm_suspend
,
346 .resume
= ufshcd_pltfrm_resume
,
347 .runtime_suspend
= ufshcd_pltfrm_runtime_suspend
,
348 .runtime_resume
= ufshcd_pltfrm_runtime_resume
,
349 .runtime_idle
= ufshcd_pltfrm_runtime_idle
,
352 static struct platform_driver ufs_mtk_pltform
= {
353 .probe
= ufs_mtk_probe
,
354 .remove
= ufs_mtk_remove
,
355 .shutdown
= ufshcd_pltfrm_shutdown
,
357 .name
= "ufshcd-mtk",
358 .pm
= &ufs_mtk_pm_ops
,
359 .of_match_table
= ufs_mtk_of_match
,
363 MODULE_AUTHOR("Stanley Chu <stanley.chu@mediatek.com>");
364 MODULE_AUTHOR("Peter Wang <peter.wang@mediatek.com>");
365 MODULE_DESCRIPTION("MediaTek UFS Host Driver");
366 MODULE_LICENSE("GPL v2");
368 module_platform_driver(ufs_mtk_pltform
);