A very gentle ping. Could you please take a look at the proposed patch? Thanks, Jan > On 20 Sep 2018, at 15:08, Janek Kotas <jank@xxxxxxxxxxx> wrote: > > This patch adds a device tree platform driver for > Cadence UFS Host Controller. > It can be enabled with SCSI_UFS_CDNS_PLATFORM Kconfig option. > > Signed-off-by: Jan Kotas <jank@xxxxxxxxxxx> > --- > drivers/scsi/ufs/Kconfig | 8 +++ > drivers/scsi/ufs/Makefile | 1 + > drivers/scsi/ufs/cdns-pltfrm.c | 149 +++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 158 insertions(+) > create mode 100644 drivers/scsi/ufs/cdns-pltfrm.c > > diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig > index e09fe6a..8f884c3 100644 > --- a/drivers/scsi/ufs/Kconfig > +++ b/drivers/scsi/ufs/Kconfig > @@ -80,6 +80,14 @@ config SCSI_UFSHCD_PLATFORM > > If unsure, say N. > > +config SCSI_UFS_CDNS_PLATFORM > + tristate "Cadence UFS Controller platform driver" > + depends on SCSI_UFSHCD_PLATFORM > + help > + This selects the Cadence specific additions to UFSHCD platform driver. > + > + If unsure, say N. > + > config SCSI_UFS_DWC_TC_PLATFORM > tristate "DesignWare platform support using a G210 Test Chip" > depends on SCSI_UFSHCD_PLATFORM > diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile > index 2c50f03..e17d14a 100644 > --- a/drivers/scsi/ufs/Makefile > +++ b/drivers/scsi/ufs/Makefile > @@ -2,6 +2,7 @@ > # UFSHCD makefile > obj-$(CONFIG_SCSI_UFS_DWC_TC_PCI) += tc-dwc-g210-pci.o ufshcd-dwc.o tc-dwc-g210.o > obj-$(CONFIG_SCSI_UFS_DWC_TC_PLATFORM) += tc-dwc-g210-pltfrm.o ufshcd-dwc.o tc-dwc-g210.o > +obj-$(CONFIG_SCSI_UFS_CDNS_PLATFORM) += cdns-pltfrm.o > obj-$(CONFIG_SCSI_UFS_QCOM) += ufs-qcom.o > obj-$(CONFIG_SCSI_UFSHCD) += ufshcd-core.o > ufshcd-core-objs := ufshcd.o ufs-sysfs.o > diff --git a/drivers/scsi/ufs/cdns-pltfrm.c b/drivers/scsi/ufs/cdns-pltfrm.c > new file mode 100644 > index 0000000..8bcf863 > --- /dev/null > +++ b/drivers/scsi/ufs/cdns-pltfrm.c > @@ -0,0 +1,149 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Platform UFS Host driver for Cadence controller > + * > + * Copyright (C) 2018 Cadence Design Systems, Inc. > + * > + * Authors: > + * Jan Kotas <jank@xxxxxxxxxxx> > + * > + */ > + > +#include <linux/kernel.h> > +#include <linux/module.h> > +#include <linux/platform_device.h> > +#include <linux/of.h> > +#include <linux/time.h> > + > +#include "ufshcd-pltfrm.h" > + > +#define CDNS_UFS_REG_HCLKDIV 0xFC > + > +/** > + * Sets HCLKDIV register value based on the core_clk > + * @hba: host controller instance > + * > + * Return zero for success and non-zero for failure > + */ > +static int cdns_ufs_set_hclkdiv(struct ufs_hba *hba) > +{ > + struct ufs_clk_info *clki; > + struct list_head *head = &hba->clk_list_head; > + unsigned long core_clk_rate = 0; > + u32 core_clk_div = 0; > + > + if (list_empty(head)) > + return 0; > + > + list_for_each_entry(clki, head, list) { > + if (IS_ERR_OR_NULL(clki->clk)) > + continue; > + if (!strcmp(clki->name, "core_clk")) > + core_clk_rate = clk_get_rate(clki->clk); > + } > + > + if (!core_clk_rate) { > + dev_err(hba->dev, "%s: unable to find core_clk rate\n", > + __func__); > + return -EINVAL; > + } > + > + core_clk_div = core_clk_rate / USEC_PER_SEC; > + > + ufshcd_writel(hba, core_clk_div, CDNS_UFS_REG_HCLKDIV); > + /** > + * Make sure the register was updated, > + * UniPro layer will not work with an incorrect value. > + */ > + mb(); > + > + return 0; > +} > + > +/** > + * Sets clocks used by the controller > + * @hba: host controller instance > + * @on: if true, enable clocks, otherwise disable > + * @status: notify stage (pre, post change) > + * > + * Return zero for success and non-zero for failure > + */ > +static int cdns_ufs_setup_clocks(struct ufs_hba *hba, bool on, > + enum ufs_notify_change_status status) > +{ > + if ((!on) || (status == PRE_CHANGE)) > + return 0; > + > + return cdns_ufs_set_hclkdiv(hba); > +} > + > +static struct ufs_hba_variant_ops cdns_pltfm_hba_vops = { > + .name = "cdns-ufs-pltfm", > + .setup_clocks = cdns_ufs_setup_clocks, > +}; > + > +/** > + * cdns_ufs_pltfrm_probe - probe routine of the driver > + * @pdev: pointer to platform device handle > + * > + * Return zero for success and non-zero for failure > + */ > +static int cdns_ufs_pltfrm_probe(struct platform_device *pdev) > +{ > + int err; > + struct device *dev = &pdev->dev; > + > + /* Perform generic probe */ > + err = ufshcd_pltfrm_init(pdev, &cdns_pltfm_hba_vops); > + if (err) > + dev_err(dev, "ufshcd_pltfrm_init() failed %d\n", err); > + > + return err; > +} > + > +/** > + * cdns_ufs_pltfrm_remove - removes the ufs driver > + * @pdev: pointer to platform device handle > + * > + * Always returns 0 > + */ > +static int cdns_ufs_pltfrm_remove(struct platform_device *pdev) > +{ > + struct ufs_hba *hba = platform_get_drvdata(pdev); > + > + ufshcd_remove(hba); > + return 0; > +} > + > +static const struct of_device_id cdns_ufs_of_match[] = { > + { .compatible = "cdns,ufshc" }, > + {}, > +}; > + > +MODULE_DEVICE_TABLE(of, cdns_ufs_of_match); > + > +static const struct dev_pm_ops cdns_ufs_dev_pm_ops = { > + .suspend = ufshcd_pltfrm_suspend, > + .resume = ufshcd_pltfrm_resume, > + .runtime_suspend = ufshcd_pltfrm_runtime_suspend, > + .runtime_resume = ufshcd_pltfrm_runtime_resume, > + .runtime_idle = ufshcd_pltfrm_runtime_idle, > +}; > + > +static struct platform_driver cdns_ufs_pltfrm_driver = { > + .probe = cdns_ufs_pltfrm_probe, > + .remove = cdns_ufs_pltfrm_remove, > + .driver = { > + .name = "cdns-ufshcd", > + .owner = THIS_MODULE, > + .pm = &cdns_ufs_dev_pm_ops, > + .of_match_table = cdns_ufs_of_match, > + }, > +}; > + > +module_platform_driver(cdns_ufs_pltfrm_driver); > + > +MODULE_AUTHOR("Jan Kotas <jank@xxxxxxxxxxx>"); > +MODULE_DESCRIPTION("Cadence UFS host controller platform driver"); > +MODULE_LICENSE("GPL v2"); > +MODULE_VERSION(UFSHCD_DRIVER_VERSION); > -- > 1.9.0 > >