diff mbox series

[v3,2/2] scsi: ufs: Add driver for TI wrapper for Cadence UFS IP

Message ID 20191108164857.11466-3-vigneshr@ti.com (mailing list archive)
State Mainlined
Commit 6979e56cec9782db0d7b5700058c0d60dc31b7cc
Headers show
Series scsi: ufs: Add driver for TI wrapper for Cadence UFS IP | expand

Commit Message

Vignesh Raghavendra Nov. 8, 2019, 4:48 p.m. UTC
TI's J721e SoC has a Cadence UFS IP with a TI specific wrapper. This is
a minimal driver to configure the wrapper. It releases the UFS slave
device out of reset and sets up registers to indicate PHY reference
clock input frequency before probing child Cadence UFS driver.

Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com>
---

v3:
Fix macros to have TI_* prefix


v2: No change

 drivers/scsi/ufs/Kconfig        | 10 ++++
 drivers/scsi/ufs/Makefile       |  1 +
 drivers/scsi/ufs/ti-j721e-ufs.c | 90 +++++++++++++++++++++++++++++++++
 3 files changed, 101 insertions(+)
 create mode 100644 drivers/scsi/ufs/ti-j721e-ufs.c

Comments

Avri Altman Nov. 12, 2019, 7:08 a.m. UTC | #1
> 
> CAUTION: This email originated from outside of Western Digital. Do not click on
> links or open attachments unless you recognize the sender and know that the
> content is safe.
> 
> 
> TI's J721e SoC has a Cadence UFS IP with a TI specific wrapper. This is a minimal
> driver to configure the wrapper. It releases the UFS slave device out of reset and
> sets up registers to indicate PHY reference clock input frequency before probing
> child Cadence UFS driver.
> 
> Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com>
Reviewed-by Avri Altman <avri.altman@wdc.com>
Alim Akhtar Nov. 13, 2019, 1:51 a.m. UTC | #2
Hi Vignesh

On Fri, Nov 8, 2019 at 10:20 PM Vignesh Raghavendra <vigneshr@ti.com> wrote:
>
> TI's J721e SoC has a Cadence UFS IP with a TI specific wrapper. This is
> a minimal driver to configure the wrapper. It releases the UFS slave
> device out of reset and sets up registers to indicate PHY reference
> clock input frequency before probing child Cadence UFS driver.
>
> Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com>
> ---
Reviewed-by: Alim Akhtar <alim.akhtar@samsung.com>
>
> v3:
> Fix macros to have TI_* prefix
>
>
> v2: No change
>
>  drivers/scsi/ufs/Kconfig        | 10 ++++
>  drivers/scsi/ufs/Makefile       |  1 +
>  drivers/scsi/ufs/ti-j721e-ufs.c | 90 +++++++++++++++++++++++++++++++++
>  3 files changed, 101 insertions(+)
>  create mode 100644 drivers/scsi/ufs/ti-j721e-ufs.c
>
> diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig
> index 0b845ab7c3bf..d14c2243e02a 100644
> --- a/drivers/scsi/ufs/Kconfig
> +++ b/drivers/scsi/ufs/Kconfig
> @@ -132,6 +132,16 @@ config SCSI_UFS_HISI
>           Select this if you have UFS controller on Hisilicon chipset.
>           If unsure, say N.
>
> +config SCSI_UFS_TI_J721E
> +       tristate "TI glue layer for Cadence UFS Controller"
> +       depends on OF && HAS_IOMEM && (ARCH_K3 || COMPILE_TEST)
> +       help
> +         This selects driver for TI glue layer for Cadence UFS Host
> +         Controller IP.
> +
> +         Selects this if you have TI platform with UFS controller.
> +         If unsure, say N.
> +
>  config SCSI_UFS_BSG
>         bool "Universal Flash Storage BSG device node"
>         depends on SCSI_UFSHCD
> diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile
> index 2a9097939bcb..94c6c5d7334b 100644
> --- a/drivers/scsi/ufs/Makefile
> +++ b/drivers/scsi/ufs/Makefile
> @@ -11,3 +11,4 @@ obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o
>  obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o
>  obj-$(CONFIG_SCSI_UFS_HISI) += ufs-hisi.o
>  obj-$(CONFIG_SCSI_UFS_MEDIATEK) += ufs-mediatek.o
> +obj-$(CONFIG_SCSI_UFS_TI_J721E) += ti-j721e-ufs.o
> diff --git a/drivers/scsi/ufs/ti-j721e-ufs.c b/drivers/scsi/ufs/ti-j721e-ufs.c
> new file mode 100644
> index 000000000000..5216d228cdd9
> --- /dev/null
> +++ b/drivers/scsi/ufs/ti-j721e-ufs.c
> @@ -0,0 +1,90 @@
> +// SPDX-License-Identifier: GPL-2.0
> +//
> +// Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
> +//
> +
> +#include <linux/clk.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/of_platform.h>
> +#include <linux/platform_device.h>
> +#include <linux/pm_runtime.h>
> +
> +#define TI_UFS_SS_CTRL         0x4
> +#define TI_UFS_SS_RST_N_PCS    BIT(0)
> +#define TI_UFS_SS_CLK_26MHZ    BIT(4)
> +
> +static int ti_j721e_ufs_probe(struct platform_device *pdev)
> +{
> +       struct device *dev = &pdev->dev;
> +       unsigned long clk_rate;
> +       void __iomem *regbase;
> +       struct clk *clk;
> +       u32 reg = 0;
> +       int ret;
> +
> +       regbase = devm_platform_ioremap_resource(pdev, 0);
> +       if (IS_ERR(regbase))
> +               return PTR_ERR(regbase);
> +
> +       pm_runtime_enable(dev);
> +       ret = pm_runtime_get_sync(dev);
> +       if (ret < 0) {
> +               pm_runtime_put_noidle(dev);
> +               return ret;
> +       }
> +
> +       /* Select MPHY refclk frequency */
> +       clk = devm_clk_get(dev, NULL);
> +       if (IS_ERR(clk)) {
> +               dev_err(dev, "Cannot claim MPHY clock.\n");
> +               return PTR_ERR(clk);
> +       }
> +       clk_rate = clk_get_rate(clk);
> +       if (clk_rate == 26000000)
> +               reg |= TI_UFS_SS_CLK_26MHZ;
> +       devm_clk_put(dev, clk);
> +
> +       /*  Take UFS slave device out of reset */
> +       reg |= TI_UFS_SS_RST_N_PCS;
> +       writel(reg, regbase + TI_UFS_SS_CTRL);
> +
> +       ret = of_platform_populate(pdev->dev.of_node, NULL, NULL,
> +                                  dev);
> +       if (ret) {
> +               dev_err(dev, "failed to populate child nodes %d\n", ret);
> +               pm_runtime_put_sync(dev);
> +       }
> +
> +       return ret;
> +}
> +
> +static int ti_j721e_ufs_remove(struct platform_device *pdev)
> +{
> +       of_platform_depopulate(&pdev->dev);
> +       pm_runtime_put_sync(&pdev->dev);
> +
> +       return 0;
> +}
> +
> +static const struct of_device_id ti_j721e_ufs_of_match[] = {
> +       {
> +               .compatible = "ti,j721e-ufs",
> +       },
> +       { },
> +};
> +
> +static struct platform_driver ti_j721e_ufs_driver = {
> +       .probe  = ti_j721e_ufs_probe,
> +       .remove = ti_j721e_ufs_remove,
> +       .driver = {
> +               .name   = "ti-j721e-ufs",
> +               .of_match_table = ti_j721e_ufs_of_match,
> +       },
> +};
> +module_platform_driver(ti_j721e_ufs_driver);
> +
> +MODULE_AUTHOR("Vignesh Raghavendra <vigneshr@ti.com>");
> +MODULE_DESCRIPTION("TI UFS host controller glue driver");
> +MODULE_LICENSE("GPL v2");
> --
> 2.24.0
>
diff mbox series

Patch

diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig
index 0b845ab7c3bf..d14c2243e02a 100644
--- a/drivers/scsi/ufs/Kconfig
+++ b/drivers/scsi/ufs/Kconfig
@@ -132,6 +132,16 @@  config SCSI_UFS_HISI
 	  Select this if you have UFS controller on Hisilicon chipset.
 	  If unsure, say N.
 
+config SCSI_UFS_TI_J721E
+	tristate "TI glue layer for Cadence UFS Controller"
+	depends on OF && HAS_IOMEM && (ARCH_K3 || COMPILE_TEST)
+	help
+	  This selects driver for TI glue layer for Cadence UFS Host
+	  Controller IP.
+
+	  Selects this if you have TI platform with UFS controller.
+	  If unsure, say N.
+
 config SCSI_UFS_BSG
 	bool "Universal Flash Storage BSG device node"
 	depends on SCSI_UFSHCD
diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile
index 2a9097939bcb..94c6c5d7334b 100644
--- a/drivers/scsi/ufs/Makefile
+++ b/drivers/scsi/ufs/Makefile
@@ -11,3 +11,4 @@  obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o
 obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o
 obj-$(CONFIG_SCSI_UFS_HISI) += ufs-hisi.o
 obj-$(CONFIG_SCSI_UFS_MEDIATEK) += ufs-mediatek.o
+obj-$(CONFIG_SCSI_UFS_TI_J721E) += ti-j721e-ufs.o
diff --git a/drivers/scsi/ufs/ti-j721e-ufs.c b/drivers/scsi/ufs/ti-j721e-ufs.c
new file mode 100644
index 000000000000..5216d228cdd9
--- /dev/null
+++ b/drivers/scsi/ufs/ti-j721e-ufs.c
@@ -0,0 +1,90 @@ 
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
+//
+
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+
+#define TI_UFS_SS_CTRL		0x4
+#define TI_UFS_SS_RST_N_PCS	BIT(0)
+#define TI_UFS_SS_CLK_26MHZ	BIT(4)
+
+static int ti_j721e_ufs_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	unsigned long clk_rate;
+	void __iomem *regbase;
+	struct clk *clk;
+	u32 reg = 0;
+	int ret;
+
+	regbase = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(regbase))
+		return PTR_ERR(regbase);
+
+	pm_runtime_enable(dev);
+	ret = pm_runtime_get_sync(dev);
+	if (ret < 0) {
+		pm_runtime_put_noidle(dev);
+		return ret;
+	}
+
+	/* Select MPHY refclk frequency */
+	clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(clk)) {
+		dev_err(dev, "Cannot claim MPHY clock.\n");
+		return PTR_ERR(clk);
+	}
+	clk_rate = clk_get_rate(clk);
+	if (clk_rate == 26000000)
+		reg |= TI_UFS_SS_CLK_26MHZ;
+	devm_clk_put(dev, clk);
+
+	/*  Take UFS slave device out of reset */
+	reg |= TI_UFS_SS_RST_N_PCS;
+	writel(reg, regbase + TI_UFS_SS_CTRL);
+
+	ret = of_platform_populate(pdev->dev.of_node, NULL, NULL,
+				   dev);
+	if (ret) {
+		dev_err(dev, "failed to populate child nodes %d\n", ret);
+		pm_runtime_put_sync(dev);
+	}
+
+	return ret;
+}
+
+static int ti_j721e_ufs_remove(struct platform_device *pdev)
+{
+	of_platform_depopulate(&pdev->dev);
+	pm_runtime_put_sync(&pdev->dev);
+
+	return 0;
+}
+
+static const struct of_device_id ti_j721e_ufs_of_match[] = {
+	{
+		.compatible = "ti,j721e-ufs",
+	},
+	{ },
+};
+
+static struct platform_driver ti_j721e_ufs_driver = {
+	.probe	= ti_j721e_ufs_probe,
+	.remove	= ti_j721e_ufs_remove,
+	.driver	= {
+		.name   = "ti-j721e-ufs",
+		.of_match_table = ti_j721e_ufs_of_match,
+	},
+};
+module_platform_driver(ti_j721e_ufs_driver);
+
+MODULE_AUTHOR("Vignesh Raghavendra <vigneshr@ti.com>");
+MODULE_DESCRIPTION("TI UFS host controller glue driver");
+MODULE_LICENSE("GPL v2");