0001
0002
0003
0004
0005
0006 #include <linux/clk.h>
0007 #include <linux/io.h>
0008 #include <linux/kernel.h>
0009 #include <linux/module.h>
0010 #include <linux/of_platform.h>
0011 #include <linux/platform_device.h>
0012 #include <linux/pm_runtime.h>
0013
0014 #define TI_UFS_SS_CTRL 0x4
0015 #define TI_UFS_SS_RST_N_PCS BIT(0)
0016 #define TI_UFS_SS_CLK_26MHZ BIT(4)
0017
0018 static int ti_j721e_ufs_probe(struct platform_device *pdev)
0019 {
0020 struct device *dev = &pdev->dev;
0021 unsigned long clk_rate;
0022 void __iomem *regbase;
0023 struct clk *clk;
0024 u32 reg = 0;
0025 int ret;
0026
0027 regbase = devm_platform_ioremap_resource(pdev, 0);
0028 if (IS_ERR(regbase))
0029 return PTR_ERR(regbase);
0030
0031 pm_runtime_enable(dev);
0032 ret = pm_runtime_resume_and_get(dev);
0033 if (ret < 0)
0034 goto disable_pm;
0035
0036
0037 clk = devm_clk_get(dev, NULL);
0038 if (IS_ERR(clk)) {
0039 ret = PTR_ERR(clk);
0040 dev_err(dev, "Cannot claim MPHY clock.\n");
0041 goto clk_err;
0042 }
0043 clk_rate = clk_get_rate(clk);
0044 if (clk_rate == 26000000)
0045 reg |= TI_UFS_SS_CLK_26MHZ;
0046 devm_clk_put(dev, clk);
0047
0048
0049 reg |= TI_UFS_SS_RST_N_PCS;
0050 writel(reg, regbase + TI_UFS_SS_CTRL);
0051
0052 ret = of_platform_populate(pdev->dev.of_node, NULL, NULL,
0053 dev);
0054 if (ret) {
0055 dev_err(dev, "failed to populate child nodes %d\n", ret);
0056 goto clk_err;
0057 }
0058
0059 return ret;
0060
0061 clk_err:
0062 pm_runtime_put_sync(dev);
0063 disable_pm:
0064 pm_runtime_disable(dev);
0065 return ret;
0066 }
0067
0068 static int ti_j721e_ufs_remove(struct platform_device *pdev)
0069 {
0070 of_platform_depopulate(&pdev->dev);
0071 pm_runtime_put_sync(&pdev->dev);
0072 pm_runtime_disable(&pdev->dev);
0073
0074 return 0;
0075 }
0076
0077 static const struct of_device_id ti_j721e_ufs_of_match[] = {
0078 {
0079 .compatible = "ti,j721e-ufs",
0080 },
0081 { },
0082 };
0083
0084 static struct platform_driver ti_j721e_ufs_driver = {
0085 .probe = ti_j721e_ufs_probe,
0086 .remove = ti_j721e_ufs_remove,
0087 .driver = {
0088 .name = "ti-j721e-ufs",
0089 .of_match_table = ti_j721e_ufs_of_match,
0090 },
0091 };
0092 module_platform_driver(ti_j721e_ufs_driver);
0093
0094 MODULE_AUTHOR("Vignesh Raghavendra <vigneshr@ti.com>");
0095 MODULE_DESCRIPTION("TI UFS host controller glue driver");
0096 MODULE_LICENSE("GPL v2");