xref: /openbmc/linux/drivers/ufs/host/ufs-sprd.c (revision 0818a690)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * UNISOC UFS Host Controller driver
4  *
5  * Copyright (C) 2022 Unisoc, Inc.
6  * Author: Zhe Wang <zhe.wang1@unisoc.com>
7  */
8 
9 #include <linux/arm-smccc.h>
10 #include <linux/mfd/syscon.h>
11 #include <linux/of.h>
12 #include <linux/platform_device.h>
13 #include <linux/regmap.h>
14 #include <linux/reset.h>
15 #include <linux/regulator/consumer.h>
16 
17 #include <ufs/ufshcd.h>
18 #include "ufshcd-pltfrm.h"
19 #include "ufs-sprd.h"
20 
21 static const struct of_device_id ufs_sprd_of_match[];
22 
ufs_sprd_get_priv_data(struct ufs_hba * hba)23 static struct ufs_sprd_priv *ufs_sprd_get_priv_data(struct ufs_hba *hba)
24 {
25 	struct ufs_sprd_host *host = ufshcd_get_variant(hba);
26 
27 	WARN_ON(!host->priv);
28 	return host->priv;
29 }
30 
ufs_sprd_regmap_update(struct ufs_sprd_priv * priv,unsigned int index,unsigned int reg,unsigned int bits,unsigned int val)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)
33 {
34 	regmap_update_bits(priv->sysci[index].regmap, reg, bits, val);
35 }
36 
ufs_sprd_regmap_read(struct ufs_sprd_priv * priv,unsigned int index,unsigned int reg,unsigned int * val)37 static void ufs_sprd_regmap_read(struct ufs_sprd_priv *priv, unsigned int index,
38 				unsigned int reg, unsigned int *val)
39 {
40 	regmap_read(priv->sysci[index].regmap, reg, val);
41 }
42 
ufs_sprd_get_unipro_ver(struct ufs_hba * hba)43 static void ufs_sprd_get_unipro_ver(struct ufs_hba *hba)
44 {
45 	struct ufs_sprd_host *host = ufshcd_get_variant(hba);
46 
47 	if (ufshcd_dme_get(hba, UIC_ARG_MIB(PA_LOCALVERINFO), &host->unipro_ver))
48 		host->unipro_ver = 0;
49 }
50 
ufs_sprd_ctrl_uic_compl(struct ufs_hba * hba,bool enable)51 static void ufs_sprd_ctrl_uic_compl(struct ufs_hba *hba, bool enable)
52 {
53 	u32 set = ufshcd_readl(hba, REG_INTERRUPT_ENABLE);
54 
55 	if (enable == true)
56 		set |= UIC_COMMAND_COMPL;
57 	else
58 		set &= ~UIC_COMMAND_COMPL;
59 	ufshcd_writel(hba, set, REG_INTERRUPT_ENABLE);
60 }
61 
ufs_sprd_get_reset_ctrl(struct device * dev,struct ufs_sprd_rst * rci)62 static int ufs_sprd_get_reset_ctrl(struct device *dev, struct ufs_sprd_rst *rci)
63 {
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);
68 	}
69 
70 	return 0;
71 }
72 
ufs_sprd_get_syscon_reg(struct device * dev,struct ufs_sprd_syscon * sysci)73 static int ufs_sprd_get_syscon_reg(struct device *dev, struct ufs_sprd_syscon *sysci)
74 {
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);
79 	}
80 
81 	return 0;
82 }
83 
ufs_sprd_get_vreg(struct device * dev,struct ufs_sprd_vreg * vregi)84 static int ufs_sprd_get_vreg(struct device *dev, struct ufs_sprd_vreg *vregi)
85 {
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);
90 	}
91 
92 	return 0;
93 }
94 
ufs_sprd_parse_dt(struct device * dev,struct ufs_hba * hba,struct ufs_sprd_host * host)95 static int ufs_sprd_parse_dt(struct device *dev, struct ufs_hba *hba, struct ufs_sprd_host *host)
96 {
97 	u32 i;
98 	struct ufs_sprd_priv *priv = host->priv;
99 	int ret = 0;
100 
101 	/* Parse UFS reset ctrl info */
102 	for (i = 0; i < SPRD_UFS_RST_MAX; i++) {
103 		if (!priv->rci[i].name)
104 			continue;
105 		ret = ufs_sprd_get_reset_ctrl(dev, &priv->rci[i]);
106 		if (ret)
107 			goto out;
108 	}
109 
110 	/* Parse UFS syscon reg info */
111 	for (i = 0; i < SPRD_UFS_SYSCON_MAX; i++) {
112 		if (!priv->sysci[i].name)
113 			continue;
114 		ret = ufs_sprd_get_syscon_reg(dev, &priv->sysci[i]);
115 		if (ret)
116 			goto out;
117 	}
118 
119 	/* Parse UFS vreg info */
120 	for (i = 0; i < SPRD_UFS_VREG_MAX; i++) {
121 		if (!priv->vregi[i].name)
122 			continue;
123 		ret = ufs_sprd_get_vreg(dev, &priv->vregi[i]);
124 		if (ret)
125 			goto out;
126 	}
127 
128 out:
129 	return ret;
130 }
131 
ufs_sprd_common_init(struct ufs_hba * hba)132 static int ufs_sprd_common_init(struct ufs_hba *hba)
133 {
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;
138 	int ret = 0;
139 
140 	host = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL);
141 	if (!host)
142 		return -ENOMEM;
143 
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,
147 					  ufs_hba_sprd_vops);
148 
149 	host->hba = hba;
150 	ufshcd_set_variant(hba, host);
151 
152 	hba->caps |= UFSHCD_CAP_CLK_GATING |
153 		UFSHCD_CAP_CRYPTO |
154 		UFSHCD_CAP_WB_EN;
155 	hba->quirks |= UFSHCD_QUIRK_DELAY_BEFORE_DME_CMDS;
156 
157 	ret = ufs_sprd_parse_dt(dev, hba, host);
158 
159 	return ret;
160 }
161 
sprd_ufs_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)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)
166 {
167 	struct ufs_sprd_host *host = ufshcd_get_variant(hba);
168 
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,
174 						   PA_INITIAL_ADAPT);
175 	}
176 
177 	return 0;
178 }
179 
ufs_sprd_suspend(struct ufs_hba * hba,enum ufs_pm_op pm_op,enum ufs_notify_change_status status)180 static int ufs_sprd_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op,
181 			    enum ufs_notify_change_status status)
182 {
183 	unsigned long flags;
184 
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);
190 		}
191 	}
192 
193 	return 0;
194 }
195 
ufs_sprd_n6_host_reset(struct ufs_hba * hba)196 static void ufs_sprd_n6_host_reset(struct ufs_hba *hba)
197 {
198 	struct ufs_sprd_priv *priv = ufs_sprd_get_priv_data(hba);
199 
200 	dev_info(hba->dev, "ufs host reset!\n");
201 
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);
205 }
206 
ufs_sprd_n6_device_reset(struct ufs_hba * hba)207 static int ufs_sprd_n6_device_reset(struct ufs_hba *hba)
208 {
209 	struct ufs_sprd_priv *priv = ufs_sprd_get_priv_data(hba);
210 
211 	dev_info(hba->dev, "ufs device reset!\n");
212 
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);
216 
217 	return 0;
218 }
219 
ufs_sprd_n6_key_acc_enable(struct ufs_hba * hba)220 static void ufs_sprd_n6_key_acc_enable(struct ufs_hba *hba)
221 {
222 	u32 val;
223 	u32 retry = 10;
224 	struct arm_smccc_res res;
225 
226 check_hce:
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);
234 		if (retry) {
235 			retry--;
236 			goto check_hce;
237 		}
238 		goto disable_crypto;
239 	}
240 
241 	arm_smccc_smc(SPRD_SIP_SVC_STORAGE_UFS_CRYPTO_ENABLE,
242 		      0, 0, 0, 0, 0, 0, 0, &res);
243 	if (!res.a0)
244 		return;
245 
246 disable_crypto:
247 	dev_err(hba->dev, "key reg access enable fail, disable crypto\n");
248 	hba->caps &= ~UFSHCD_CAP_CRYPTO;
249 }
250 
ufs_sprd_n6_init(struct ufs_hba * hba)251 static int ufs_sprd_n6_init(struct ufs_hba *hba)
252 {
253 	struct ufs_sprd_priv *priv;
254 	int ret = 0;
255 
256 	ret = ufs_sprd_common_init(hba);
257 	if (ret != 0)
258 		return ret;
259 
260 	priv = ufs_sprd_get_priv_data(hba);
261 
262 	ret = regulator_enable(priv->vregi[SPRD_UFS_VDD_MPHY].vreg);
263 	if (ret)
264 		return -ENODEV;
265 
266 	if (hba->caps & UFSHCD_CAP_CRYPTO)
267 		ufs_sprd_n6_key_acc_enable(hba);
268 
269 	return 0;
270 }
271 
ufs_sprd_n6_phy_init(struct ufs_hba * hba)272 static int ufs_sprd_n6_phy_init(struct ufs_hba *hba)
273 {
274 	int ret = 0;
275 	uint32_t val = 0;
276 	uint32_t retry = 10;
277 	uint32_t offset;
278 	struct ufs_sprd_priv *priv = ufs_sprd_get_priv_data(hba);
279 
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);
288 
289 	do {
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);
301 			}
302 
303 			goto update_phy;
304 		}
305 		udelay(1000);
306 		retry--;
307 	} while (retry > 0);
308 
309 	ret = -ETIMEDOUT;
310 	goto out;
311 
312 update_phy:
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);
317 out:
318 	return ret;
319 }
320 
321 
sprd_ufs_n6_hce_enable_notify(struct ufs_hba * hba,enum ufs_notify_change_status status)322 static int sprd_ufs_n6_hce_enable_notify(struct ufs_hba *hba,
323 					 enum ufs_notify_change_status status)
324 {
325 	int err = 0;
326 	struct ufs_sprd_priv *priv = ufs_sprd_get_priv_data(hba);
327 
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);
333 
334 		ufs_sprd_n6_host_reset(hba);
335 
336 		if (hba->caps & UFSHCD_CAP_CRYPTO)
337 			ufs_sprd_n6_key_acc_enable(hba);
338 	}
339 
340 	if (status == POST_CHANGE) {
341 		err = ufs_sprd_n6_phy_init(hba);
342 		if (err) {
343 			dev_err(hba->dev, "Phy setup failed (%d)\n", err);
344 			goto out;
345 		}
346 
347 		ufs_sprd_get_unipro_ver(hba);
348 	}
349 out:
350 	return err;
351 }
352 
sprd_ufs_n6_h8_notify(struct ufs_hba * hba,enum uic_cmd_dme cmd,enum ufs_notify_change_status status)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)
356 {
357 	struct ufs_sprd_priv *priv = ufs_sprd_get_priv_data(hba);
358 
359 	if (status == PRE_CHANGE) {
360 		if (cmd == UIC_CMD_DME_HIBER_ENTER)
361 			/*
362 			 * Disable UIC COMPL INTR to prevent access to UFSHCI after
363 			 * checking HCS.UPMCRS
364 			 */
365 			ufs_sprd_ctrl_uic_compl(hba, false);
366 
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);
372 		}
373 	}
374 
375 	if (status == POST_CHANGE) {
376 		if (cmd == UIC_CMD_DME_HIBER_EXIT)
377 			ufs_sprd_ctrl_uic_compl(hba, true);
378 
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);
384 		}
385 	}
386 }
387 
388 static struct ufs_sprd_priv n6_ufs = {
389 	.rci[SPRD_UFSHCI_SOFT_RST] = { .name = "controller", },
390 	.rci[SPRD_UFS_DEV_RST] = { .name = "device", },
391 
392 	.sysci[SPRD_UFS_ANLG] = { .name = "sprd,ufs-anlg-syscon", },
393 	.sysci[SPRD_UFS_AON_APB] = { .name = "sprd,aon-apb-syscon", },
394 
395 	.vregi[SPRD_UFS_VDD_MPHY] = { .name = "vdd-mphy", },
396 
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,
405 	},
406 };
407 
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},
410 	{},
411 };
412 MODULE_DEVICE_TABLE(of, ufs_sprd_of_match);
413 
ufs_sprd_probe(struct platform_device * pdev)414 static int ufs_sprd_probe(struct platform_device *pdev)
415 {
416 	int err;
417 	struct device *dev = &pdev->dev;
418 	const struct of_device_id *of_id;
419 
420 	of_id = of_match_node(ufs_sprd_of_match, dev->of_node);
421 	err = ufshcd_pltfrm_init(pdev, of_id->data);
422 	if (err)
423 		dev_err(dev, "ufshcd_pltfrm_init() failed %d\n", err);
424 
425 	return err;
426 }
427 
ufs_sprd_remove(struct platform_device * pdev)428 static int ufs_sprd_remove(struct platform_device *pdev)
429 {
430 	struct ufs_hba *hba =  platform_get_drvdata(pdev);
431 
432 	pm_runtime_get_sync(&(pdev)->dev);
433 	ufshcd_remove(hba);
434 	return 0;
435 }
436 
437 static const struct dev_pm_ops ufs_sprd_pm_ops = {
438 	SET_SYSTEM_SLEEP_PM_OPS(ufshcd_system_suspend, ufshcd_system_resume)
439 	SET_RUNTIME_PM_OPS(ufshcd_runtime_suspend, ufshcd_runtime_resume, NULL)
440 	.prepare	 = ufshcd_suspend_prepare,
441 	.complete	 = ufshcd_resume_complete,
442 };
443 
444 static struct platform_driver ufs_sprd_pltform = {
445 	.probe = ufs_sprd_probe,
446 	.remove = ufs_sprd_remove,
447 	.driver = {
448 		.name = "ufshcd-sprd",
449 		.pm = &ufs_sprd_pm_ops,
450 		.of_match_table = of_match_ptr(ufs_sprd_of_match),
451 	},
452 };
453 module_platform_driver(ufs_sprd_pltform);
454 
455 MODULE_AUTHOR("Zhe Wang <zhe.wang1@unisoc.com>");
456 MODULE_DESCRIPTION("Unisoc UFS Host Driver");
457 MODULE_LICENSE("GPL v2");
458