xref: /openbmc/linux/drivers/ufs/host/ti-j721e-ufs.c (revision a9814b6c)
1dd11376bSBart Van Assche // SPDX-License-Identifier: GPL-2.0
2dd11376bSBart Van Assche //
3dd11376bSBart Van Assche // Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
4dd11376bSBart Van Assche //
5dd11376bSBart Van Assche 
6dd11376bSBart Van Assche #include <linux/clk.h>
7dd11376bSBart Van Assche #include <linux/io.h>
8dd11376bSBart Van Assche #include <linux/kernel.h>
9dd11376bSBart Van Assche #include <linux/module.h>
10dd11376bSBart Van Assche #include <linux/of_platform.h>
11dd11376bSBart Van Assche #include <linux/platform_device.h>
12dd11376bSBart Van Assche #include <linux/pm_runtime.h>
13dd11376bSBart Van Assche 
14dd11376bSBart Van Assche #define TI_UFS_SS_CTRL		0x4
15dd11376bSBart Van Assche #define TI_UFS_SS_RST_N_PCS	BIT(0)
16dd11376bSBart Van Assche #define TI_UFS_SS_CLK_26MHZ	BIT(4)
17dd11376bSBart Van Assche 
ti_j721e_ufs_probe(struct platform_device * pdev)18dd11376bSBart Van Assche static int ti_j721e_ufs_probe(struct platform_device *pdev)
19dd11376bSBart Van Assche {
20dd11376bSBart Van Assche 	struct device *dev = &pdev->dev;
21dd11376bSBart Van Assche 	unsigned long clk_rate;
22dd11376bSBart Van Assche 	void __iomem *regbase;
23dd11376bSBart Van Assche 	struct clk *clk;
24dd11376bSBart Van Assche 	u32 reg = 0;
25dd11376bSBart Van Assche 	int ret;
26dd11376bSBart Van Assche 
27dd11376bSBart Van Assche 	regbase = devm_platform_ioremap_resource(pdev, 0);
28dd11376bSBart Van Assche 	if (IS_ERR(regbase))
29dd11376bSBart Van Assche 		return PTR_ERR(regbase);
30dd11376bSBart Van Assche 
31dd11376bSBart Van Assche 	pm_runtime_enable(dev);
32dd11376bSBart Van Assche 	ret = pm_runtime_resume_and_get(dev);
33dd11376bSBart Van Assche 	if (ret < 0)
34dd11376bSBart Van Assche 		goto disable_pm;
35dd11376bSBart Van Assche 
36dd11376bSBart Van Assche 	/* Select MPHY refclk frequency */
37dd11376bSBart Van Assche 	clk = devm_clk_get(dev, NULL);
38dd11376bSBart Van Assche 	if (IS_ERR(clk)) {
39dd11376bSBart Van Assche 		ret = PTR_ERR(clk);
40dd11376bSBart Van Assche 		dev_err(dev, "Cannot claim MPHY clock.\n");
41dd11376bSBart Van Assche 		goto clk_err;
42dd11376bSBart Van Assche 	}
43dd11376bSBart Van Assche 	clk_rate = clk_get_rate(clk);
44dd11376bSBart Van Assche 	if (clk_rate == 26000000)
45dd11376bSBart Van Assche 		reg |= TI_UFS_SS_CLK_26MHZ;
46dd11376bSBart Van Assche 	devm_clk_put(dev, clk);
47dd11376bSBart Van Assche 
48dd11376bSBart Van Assche 	/*  Take UFS slave device out of reset */
49dd11376bSBart Van Assche 	reg |= TI_UFS_SS_RST_N_PCS;
50dd11376bSBart Van Assche 	writel(reg, regbase + TI_UFS_SS_CTRL);
51dd11376bSBart Van Assche 
52dd11376bSBart Van Assche 	ret = of_platform_populate(pdev->dev.of_node, NULL, NULL,
53dd11376bSBart Van Assche 				   dev);
54dd11376bSBart Van Assche 	if (ret) {
55dd11376bSBart Van Assche 		dev_err(dev, "failed to populate child nodes %d\n", ret);
56dd11376bSBart Van Assche 		goto clk_err;
57dd11376bSBart Van Assche 	}
58dd11376bSBart Van Assche 
59dd11376bSBart Van Assche 	return ret;
60dd11376bSBart Van Assche 
61dd11376bSBart Van Assche clk_err:
62dd11376bSBart Van Assche 	pm_runtime_put_sync(dev);
63dd11376bSBart Van Assche disable_pm:
64dd11376bSBart Van Assche 	pm_runtime_disable(dev);
65dd11376bSBart Van Assche 	return ret;
66dd11376bSBart Van Assche }
67dd11376bSBart Van Assche 
ti_j721e_ufs_remove(struct platform_device * pdev)68dd11376bSBart Van Assche static int ti_j721e_ufs_remove(struct platform_device *pdev)
69dd11376bSBart Van Assche {
70dd11376bSBart Van Assche 	of_platform_depopulate(&pdev->dev);
71dd11376bSBart Van Assche 	pm_runtime_put_sync(&pdev->dev);
72dd11376bSBart Van Assche 	pm_runtime_disable(&pdev->dev);
73dd11376bSBart Van Assche 
74dd11376bSBart Van Assche 	return 0;
75dd11376bSBart Van Assche }
76dd11376bSBart Van Assche 
77dd11376bSBart Van Assche static const struct of_device_id ti_j721e_ufs_of_match[] = {
78dd11376bSBart Van Assche 	{
79dd11376bSBart Van Assche 		.compatible = "ti,j721e-ufs",
80dd11376bSBart Van Assche 	},
81dd11376bSBart Van Assche 	{ },
82dd11376bSBart Van Assche };
83dd11376bSBart Van Assche 
84*a9814b6cSUdit Kumar MODULE_DEVICE_TABLE(of, ti_j721e_ufs_of_match);
85*a9814b6cSUdit Kumar 
86dd11376bSBart Van Assche static struct platform_driver ti_j721e_ufs_driver = {
87dd11376bSBart Van Assche 	.probe	= ti_j721e_ufs_probe,
88dd11376bSBart Van Assche 	.remove	= ti_j721e_ufs_remove,
89dd11376bSBart Van Assche 	.driver	= {
90dd11376bSBart Van Assche 		.name   = "ti-j721e-ufs",
91dd11376bSBart Van Assche 		.of_match_table = ti_j721e_ufs_of_match,
92dd11376bSBart Van Assche 	},
93dd11376bSBart Van Assche };
94dd11376bSBart Van Assche module_platform_driver(ti_j721e_ufs_driver);
95dd11376bSBart Van Assche 
96dd11376bSBart Van Assche MODULE_AUTHOR("Vignesh Raghavendra <vigneshr@ti.com>");
97dd11376bSBart Van Assche MODULE_DESCRIPTION("TI UFS host controller glue driver");
98dd11376bSBart Van Assche MODULE_LICENSE("GPL v2");
99