Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 //
0003 // Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
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     /* Select MPHY refclk frequency */
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     /*  Take UFS slave device out of reset */
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");