All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/2] Add support for Unisoc UFS host controller
@ 2022-11-16 13:31 Zhe Wang
  2022-11-16 13:31 ` [PATCH v2 1/2] dt-bindings: ufs: Add document " Zhe Wang
  2022-11-16 13:31 ` [PATCH v2 2/2] scsi: ufs-unisoc: Add support " Zhe Wang
  0 siblings, 2 replies; 8+ messages in thread
From: Zhe Wang @ 2022-11-16 13:31 UTC (permalink / raw)
  To: martin.petersen, jejb, krzysztof.kozlowski+dt, robh+dt,
	alim.akhtar, avri.altman
  Cc: linux-scsi, devicetree, orsonzhai, yuelin.tang, zhenxiong.lai,
	zhang.lyra

Add this patchset to support the Unisoc UFS host controller.

V1 -> V2:
 - Fix dt-binding doc in v2 patch
 - Do some minor format changes
 - Remove of_match_ptr
 - Remove functions from headers

Zhe Wang (2):
  dt-bindings: ufs: Add document for Unisoc UFS host controller
  scsi: ufs-unisoc: Add support for Unisoc UFS host controller

 .../bindings/ufs/sprd,ums9620-ufs.yaml        |  78 +++
 drivers/ufs/host/Kconfig                      |  12 +
 drivers/ufs/host/Makefile                     |   1 +
 drivers/ufs/host/ufs-sprd.c                   | 484 ++++++++++++++++++
 drivers/ufs/host/ufs-sprd.h                   |  86 ++++
 5 files changed, 661 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/ufs/sprd,ums9620-ufs.yaml
 create mode 100644 drivers/ufs/host/ufs-sprd.c
 create mode 100644 drivers/ufs/host/ufs-sprd.h

-- 
2.17.1


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v2 1/2] dt-bindings: ufs: Add document for Unisoc UFS host controller
  2022-11-16 13:31 [PATCH v2 0/2] Add support for Unisoc UFS host controller Zhe Wang
@ 2022-11-16 13:31 ` Zhe Wang
  2022-11-16 17:03   ` Krzysztof Kozlowski
  2022-11-20 16:49   ` Rob Herring
  2022-11-16 13:31 ` [PATCH v2 2/2] scsi: ufs-unisoc: Add support " Zhe Wang
  1 sibling, 2 replies; 8+ messages in thread
From: Zhe Wang @ 2022-11-16 13:31 UTC (permalink / raw)
  To: martin.petersen, jejb, krzysztof.kozlowski+dt, robh+dt,
	alim.akhtar, avri.altman
  Cc: linux-scsi, devicetree, orsonzhai, yuelin.tang, zhenxiong.lai,
	zhang.lyra

Add Unisoc ums9620 ufs host controller devicetree document.

Signed-off-by: Zhe Wang <zhe.wang1@unisoc.com>
---
 .../bindings/ufs/sprd,ums9620-ufs.yaml        | 78 +++++++++++++++++++
 1 file changed, 78 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/ufs/sprd,ums9620-ufs.yaml

diff --git a/Documentation/devicetree/bindings/ufs/sprd,ums9620-ufs.yaml b/Documentation/devicetree/bindings/ufs/sprd,ums9620-ufs.yaml
new file mode 100644
index 000000000000..ce9d05be1a6b
--- /dev/null
+++ b/Documentation/devicetree/bindings/ufs/sprd,ums9620-ufs.yaml
@@ -0,0 +1,78 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/ufs/sprd,ums9620-ufs.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Unisoc Universal Flash Storage (UFS) Controller
+
+maintainers:
+  - Zhe Wang <zhe.wang1@unisoc.com>
+
+allOf:
+  - $ref: ufs-common.yaml
+
+properties:
+  compatible:
+    const: sprd,ums9620-ufs
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    maxItems: 4
+
+  clock-names:
+    items:
+      - const: ufs_eb
+      - const: ufs_cfg_eb
+      - const: ufsh
+      - const: ufsh_source
+
+  resets:
+    maxItems: 2
+
+  reset-names:
+    items:
+      - const: ufs
+      - const: ufsdev
+
+  vdd-mphy-supply:
+    description:
+      Phandle to vdd-mphy supply regulator node.
+
+  sprd,ufs-anlg-syscon:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description: phandle of syscon used to control ufs analog regs.
+
+  sprd,aon-apb-syscon:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description: phandle of syscon used to control always-on regs.
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - clock-names
+  - resets
+  - reset-names
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+    ufs: ufs@22000000 {
+        compatible = "sprd,ums9620-ufs";
+        reg = <0x22000000 0x3000>;
+        interrupts = <GIC_SPI 159 IRQ_TYPE_LEVEL_HIGH>;
+        vcc-supply = <&vddemmccore>;
+        vdd-mphy-supply = <&vddufs1v2>;
+        clock-names = "ufs_eb", "ufs_cfg_eb", "ufsh", "ufsh_source";
+        clocks = <&apahb_gate 5>, <&apahb_gate 22>, <&aonapb_clk 52>, <&g5l_pll 12>;
+        reset-names = "ufs", "ufsdev";
+        resets = <&apahb_gate 4>, <&aonapb_gate 69>;
+        sprd,ufs-anlg-syscon = <&anlg_phy_g12_regs>;
+        sprd,aon-apb-syscon = <&aon_apb_regs>;
+    };
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v2 2/2] scsi: ufs-unisoc: Add support for Unisoc UFS host controller
  2022-11-16 13:31 [PATCH v2 0/2] Add support for Unisoc UFS host controller Zhe Wang
  2022-11-16 13:31 ` [PATCH v2 1/2] dt-bindings: ufs: Add document " Zhe Wang
@ 2022-11-16 13:31 ` Zhe Wang
  1 sibling, 0 replies; 8+ messages in thread
From: Zhe Wang @ 2022-11-16 13:31 UTC (permalink / raw)
  To: martin.petersen, jejb, krzysztof.kozlowski+dt, robh+dt,
	alim.akhtar, avri.altman
  Cc: linux-scsi, devicetree, orsonzhai, yuelin.tang, zhenxiong.lai,
	zhang.lyra

Add driver code for Unisoc ufs host controller, along with ufs
initialization.

Signed-off-by: Zhe Wang <zhe.wang1@unisoc.com>
---
 drivers/ufs/host/Kconfig    |  12 +
 drivers/ufs/host/Makefile   |   1 +
 drivers/ufs/host/ufs-sprd.c | 484 ++++++++++++++++++++++++++++++++++++
 drivers/ufs/host/ufs-sprd.h |  86 +++++++
 4 files changed, 583 insertions(+)
 create mode 100644 drivers/ufs/host/ufs-sprd.c
 create mode 100644 drivers/ufs/host/ufs-sprd.h

diff --git a/drivers/ufs/host/Kconfig b/drivers/ufs/host/Kconfig
index 4cc2dbd79ed0..90a7142ec846 100644
--- a/drivers/ufs/host/Kconfig
+++ b/drivers/ufs/host/Kconfig
@@ -124,3 +124,15 @@ config SCSI_UFS_EXYNOS
 
 	  Select this if you have UFS host controller on Samsung Exynos SoC.
 	  If unsure, say N.
+
+config SCSI_UFS_SPRD
+	tristate "Unisoc specific hooks to UFS controller platform driver"
+	depends on SCSI_UFSHCD_PLATFORM && (ARCH_SPRD || COMPILE_TEST)
+	help
+	  This selects the Unisoc specific additions to UFSHCD platform driver.
+	  UFS host on Unisoc needs some vendor specific configuration before
+	  accessing the hardware which includes PHY configuration and vendor
+	  specific registers.
+
+	  Select this if you have UFS controller on Unisoc chipset.
+	  If unsure, say N.
diff --git a/drivers/ufs/host/Makefile b/drivers/ufs/host/Makefile
index 7717ca93e7d5..a946c3b35c9d 100644
--- a/drivers/ufs/host/Makefile
+++ b/drivers/ufs/host/Makefile
@@ -13,3 +13,4 @@ obj-$(CONFIG_SCSI_UFS_HISI) += ufs-hisi.o
 obj-$(CONFIG_SCSI_UFS_MEDIATEK) += ufs-mediatek.o
 obj-$(CONFIG_SCSI_UFS_RENESAS) += ufs-renesas.o
 obj-$(CONFIG_SCSI_UFS_TI_J721E) += ti-j721e-ufs.o
+obj-$(CONFIG_SCSI_UFS_SPRD) += ufs-sprd.o
diff --git a/drivers/ufs/host/ufs-sprd.c b/drivers/ufs/host/ufs-sprd.c
new file mode 100644
index 000000000000..1f6171efb61b
--- /dev/null
+++ b/drivers/ufs/host/ufs-sprd.c
@@ -0,0 +1,484 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * UNISOC UFS Host Controller driver
+ *
+ * Copyright (C) 2022 Unisoc, Inc.
+ * Author: Zhe Wang <zhe.wang1@unisoc.com>
+ */
+
+#include <linux/arm-smccc.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+#include <linux/clk.h>
+#include <linux/regulator/consumer.h>
+
+#include <ufs/ufshcd.h>
+#include "ufshcd-pltfrm.h"
+#include "ufs-sprd.h"
+
+static const struct of_device_id ufs_sprd_of_match[];
+
+static struct ufs_sprd_priv *ufs_sprd_get_priv_data(struct ufs_hba *hba)
+{
+	struct ufs_sprd_host *host = ufshcd_get_variant(hba);
+
+	WARN_ON(!host->priv);
+	return host->priv;
+}
+
+static void ufs_sprd_regmap_update(struct ufs_sprd_priv *priv, unsigned int index,
+				unsigned int reg, unsigned int bits,  unsigned int val)
+{
+	regmap_update_bits(priv->sysci[index].regmap, reg, bits, val);
+}
+
+static void ufs_sprd_regmap_read(struct ufs_sprd_priv *priv, unsigned int index,
+				unsigned int reg, unsigned int *val)
+{
+	regmap_read(priv->sysci[index].regmap, reg, val);
+}
+
+static void ufs_sprd_get_unipro_ver(struct ufs_hba *hba)
+{
+	struct ufs_sprd_host *host = ufshcd_get_variant(hba);
+
+	if (ufshcd_dme_get(hba, UIC_ARG_MIB(PA_LOCALVERINFO), &host->unipro_ver))
+		host->unipro_ver = 0;
+}
+
+static void ufs_sprd_ctrl_uic_compl(struct ufs_hba *hba, bool enable)
+{
+	u32 set = ufshcd_readl(hba, REG_INTERRUPT_ENABLE);
+
+	if (enable == true)
+		set |= UIC_COMMAND_COMPL;
+	else
+		set &= ~UIC_COMMAND_COMPL;
+	ufshcd_writel(hba, set, REG_INTERRUPT_ENABLE);
+}
+
+static int ufs_sprd_get_clk(struct device *dev, struct ufs_sprd_clk *clki)
+{
+	clki->clk = devm_clk_get(dev, clki->name);
+	if (IS_ERR(clki->clk)) {
+		dev_err(dev, "failed to get clk:%s\n", clki->name);
+		return PTR_ERR(clki->clk);
+	}
+
+	return 0;
+}
+
+static int ufs_sprd_get_reset_ctrl(struct device *dev, struct ufs_sprd_rst *rci)
+{
+	rci->rc = devm_reset_control_get(dev, rci->name);
+	if (IS_ERR(rci->rc)) {
+		dev_err(dev, "failed to get reset ctrl:%s\n", rci->name);
+		return PTR_ERR(rci->rc);
+	}
+
+	return 0;
+}
+
+static int ufs_sprd_get_syscon_reg(struct device *dev, struct ufs_sprd_syscon *sysci)
+{
+	sysci->regmap = syscon_regmap_lookup_by_phandle(dev->of_node, sysci->name);
+	if (IS_ERR(sysci->regmap)) {
+		dev_err(dev, "failed to get ufs syscon:%s\n", sysci->name);
+		return PTR_ERR(sysci->regmap);
+	}
+
+	return 0;
+}
+
+static int ufs_sprd_get_vreg(struct device *dev, struct ufs_sprd_vreg *vregi)
+{
+	vregi->vreg = devm_regulator_get(dev, vregi->name);
+	if (IS_ERR(vregi->vreg)) {
+		dev_err(dev, "failed to get vreg:%s\n", vregi->name);
+		return PTR_ERR(vregi->vreg);
+	}
+
+	return 0;
+}
+
+static int ufs_sprd_parse_dt(struct device *dev, struct ufs_hba *hba, struct ufs_sprd_host *host)
+{
+	u32 i;
+	struct ufs_sprd_priv *priv = host->priv;
+	int ret = 0;
+
+	/* Parse UFS clk info */
+	for (i = 0; i < SPRD_UFS_CLK_MAX; i++) {
+		if (!priv->clki[i].name)
+			continue;
+		ret = ufs_sprd_get_clk(dev, &priv->clki[i]);
+		if (ret)
+			goto out;
+	}
+
+	/* Parse UFS reset ctrl info */
+	for (i = 0; i < SPRD_UFS_RST_MAX; i++) {
+		if (!priv->rci[i].name)
+			continue;
+		ret = ufs_sprd_get_reset_ctrl(dev, &priv->rci[i]);
+		if (ret)
+			goto out;
+	}
+
+	/* Parse UFS syscon reg info */
+	for (i = 0; i < SPRD_UFS_SYSCON_MAX; i++) {
+		if (!priv->sysci[i].name)
+			continue;
+		ret = ufs_sprd_get_syscon_reg(dev, &priv->sysci[i]);
+		if (ret)
+			goto out;
+	}
+
+	/* Parse UFS vreg info */
+	for (i = 0; i < SPRD_UFS_VREG_MAX; i++) {
+		if (!priv->vregi[i].name)
+			continue;
+		ret = ufs_sprd_get_vreg(dev, &priv->vregi[i]);
+		if (ret)
+			goto out;
+	}
+
+out:
+	return ret;
+}
+
+static int ufs_sprd_common_init(struct ufs_hba *hba)
+{
+	struct device *dev = hba->dev;
+	struct ufs_sprd_host *host;
+	struct platform_device *pdev = to_platform_device(dev);
+	const struct of_device_id *of_id;
+	int ret = 0;
+
+	host = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL);
+	if (!host)
+		return -ENOMEM;
+
+	of_id = of_match_node(ufs_sprd_of_match, pdev->dev.of_node);
+	if (of_id->data != NULL)
+		host->priv = container_of(of_id->data, struct ufs_sprd_priv,
+					  ufs_hba_sprd_vops);
+
+	host->hba = hba;
+	ufshcd_set_variant(hba, host);
+
+	hba->caps |= UFSHCD_CAP_CLK_GATING |
+		UFSHCD_CAP_CRYPTO |
+		UFSHCD_CAP_WB_EN;
+	hba->quirks |= UFSHCD_QUIRK_DELAY_BEFORE_DME_CMDS;
+
+	ret = ufs_sprd_parse_dt(dev, hba, host);
+
+	return ret;
+}
+
+static int sprd_ufs_pwr_change_notify(struct ufs_hba *hba,
+				      enum ufs_notify_change_status status,
+				      struct ufs_pa_layer_attr *dev_max_params,
+				      struct ufs_pa_layer_attr *dev_req_params)
+{
+	struct ufs_sprd_host *host = ufshcd_get_variant(hba);
+
+	if (status == PRE_CHANGE) {
+		memcpy(dev_req_params, dev_max_params,
+			sizeof(struct ufs_pa_layer_attr));
+		if (host->unipro_ver >= UFS_UNIPRO_VER_1_8)
+			ufshcd_dme_configure_adapt(hba, dev_req_params->gear_tx,
+						   PA_INITIAL_ADAPT);
+	}
+
+	return 0;
+}
+
+static int ufs_sprd_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op,
+			    enum ufs_notify_change_status status)
+{
+	unsigned long flags;
+
+	if (status == PRE_CHANGE) {
+		if (ufshcd_is_auto_hibern8_supported(hba)) {
+			spin_lock_irqsave(hba->host->host_lock, flags);
+			ufshcd_writel(hba, 0, REG_AUTO_HIBERNATE_IDLE_TIMER);
+			spin_unlock_irqrestore(hba->host->host_lock, flags);
+		}
+	}
+
+	return 0;
+}
+
+static void ufs_sprd_n6_host_reset(struct ufs_hba *hba)
+{
+	struct ufs_sprd_priv *priv = ufs_sprd_get_priv_data(hba);
+
+	dev_info(hba->dev, "ufs host reset!\n");
+
+	reset_control_assert(priv->rci[SPRD_UFSHCI_SOFT_RST].rc);
+	usleep_range(1000, 1100);
+	reset_control_deassert(priv->rci[SPRD_UFSHCI_SOFT_RST].rc);
+}
+
+static int ufs_sprd_n6_device_reset(struct ufs_hba *hba)
+{
+	struct ufs_sprd_priv *priv = ufs_sprd_get_priv_data(hba);
+
+	dev_info(hba->dev, "ufs device reset!\n");
+
+	reset_control_assert(priv->rci[SPRD_UFS_DEV_RST].rc);
+	usleep_range(1000, 1100);
+	reset_control_deassert(priv->rci[SPRD_UFS_DEV_RST].rc);
+
+	return 0;
+}
+
+static void ufs_sprd_n6_key_acc_enable(struct ufs_hba *hba)
+{
+	u32 val;
+	u32 retry = 10;
+	struct arm_smccc_res res;
+
+check_hce:
+	/* Key access only can be enabled under HCE enable */
+	val = ufshcd_readl(hba, REG_CONTROLLER_ENABLE);
+	if (!(val & CONTROLLER_ENABLE)) {
+		ufs_sprd_n6_host_reset(hba);
+		val |= CONTROLLER_ENABLE;
+		ufshcd_writel(hba, val, REG_CONTROLLER_ENABLE);
+		usleep_range(1000, 1100);
+		if (retry) {
+			retry--;
+			goto check_hce;
+		}
+		goto disable_crypto;
+	}
+
+	arm_smccc_smc(SPRD_SIP_SVC_STORAGE_UFS_CRYPTO_ENABLE,
+		      0, 0, 0, 0, 0, 0, 0, &res);
+	if (!res.a0)
+		return;
+
+disable_crypto:
+	dev_err(hba->dev, "key reg access enable fail, disable crypto\n");
+	hba->caps &= ~UFSHCD_CAP_CRYPTO;
+}
+
+static int ufs_sprd_n6_init(struct ufs_hba *hba)
+{
+	struct ufs_sprd_priv *priv;
+	int ret = 0;
+
+	ret = ufs_sprd_common_init(hba);
+	if (ret != 0)
+		return ret;
+
+	priv = ufs_sprd_get_priv_data(hba);
+
+	clk_set_parent(priv->clki[SPRD_UFS_HCLK].clk,
+		       priv->clki[SPRD_UFS_HCLK_SOURCE].clk);
+
+	ret = regulator_enable(priv->vregi[SPRD_UFS_VDD_MPHY].vreg);
+	if (ret)
+		return -ENODEV;
+
+	if (hba->caps & UFSHCD_CAP_CRYPTO)
+		ufs_sprd_n6_key_acc_enable(hba);
+
+	return 0;
+}
+
+static int ufs_sprd_n6_phy_init(struct ufs_hba *hba)
+{
+	int ret = 0;
+	uint32_t val = 0;
+	uint32_t retry = 10;
+	uint32_t offset;
+	struct ufs_sprd_priv *priv = ufs_sprd_get_priv_data(hba);
+
+	ufshcd_dme_set(hba, UIC_ARG_MIB(0x8132), 0x90);
+	ufshcd_dme_set(hba, UIC_ARG_MIB(0x811F), 0x01);
+	ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x8009,
+				UIC_ARG_MPHY_RX_GEN_SEL_INDEX(0)), 0x01);
+	ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x8009,
+				UIC_ARG_MPHY_RX_GEN_SEL_INDEX(1)), 0x01);
+	ufshcd_dme_set(hba, UIC_ARG_MIB(0xD085), 0x01);
+	ufshcd_dme_set(hba, UIC_ARG_MIB(0x8114), 0x01);
+
+	do {
+		/* phy_sram_init_done */
+		ufs_sprd_regmap_read(priv, SPRD_UFS_ANLG, 0xc, &val);
+		if ((val & 0x1) == 0x1) {
+			for (offset = 0x40; offset < 0x42; offset++) {
+				/* Lane afe calibration */
+				ufshcd_dme_set(hba, UIC_ARG_MIB(0x8116), 0x1c);
+				ufshcd_dme_set(hba, UIC_ARG_MIB(0x8117), offset);
+				ufshcd_dme_set(hba, UIC_ARG_MIB(0x8118), 0x04);
+				ufshcd_dme_set(hba, UIC_ARG_MIB(0x8119), 0x00);
+				ufshcd_dme_set(hba, UIC_ARG_MIB(0x811C), 0x01);
+				ufshcd_dme_set(hba, UIC_ARG_MIB(0xD085), 0x01);
+			}
+
+			goto update_phy;
+		}
+		udelay(1000);
+		retry--;
+	} while (retry > 0);
+
+	ret = -ETIMEDOUT;
+	goto out;
+
+update_phy:
+	/* phy_sram_ext_ld_done */
+	ufs_sprd_regmap_update(priv, SPRD_UFS_ANLG, 0xc, 0x2, 0);
+	ufshcd_dme_set(hba, UIC_ARG_MIB(0xD085), 0x01);
+	ufshcd_dme_set(hba, UIC_ARG_MIB(0xD0C1), 0x0);
+out:
+	return ret;
+}
+
+
+static int sprd_ufs_n6_hce_enable_notify(struct ufs_hba *hba,
+					 enum ufs_notify_change_status status)
+{
+	int err = 0;
+	struct ufs_sprd_priv *priv = ufs_sprd_get_priv_data(hba);
+
+	if (status == PRE_CHANGE) {
+		/* phy_sram_ext_ld_done */
+		ufs_sprd_regmap_update(priv, SPRD_UFS_ANLG, 0xc, 0x2, 0x2);
+		/* phy_sram_bypass */
+		ufs_sprd_regmap_update(priv, SPRD_UFS_ANLG, 0xc, 0x4, 0x4);
+
+		ufs_sprd_n6_host_reset(hba);
+
+		if (hba->caps & UFSHCD_CAP_CRYPTO)
+			ufs_sprd_n6_key_acc_enable(hba);
+	}
+
+	if (status == POST_CHANGE) {
+		err = ufs_sprd_n6_phy_init(hba);
+		if (err) {
+			dev_err(hba->dev, "Phy setup failed (%d)\n", err);
+			goto out;
+		}
+
+		ufs_sprd_get_unipro_ver(hba);
+	}
+out:
+	return err;
+}
+
+static void sprd_ufs_n6_h8_notify(struct ufs_hba *hba,
+				  enum uic_cmd_dme cmd,
+				  enum ufs_notify_change_status status)
+{
+	struct ufs_sprd_priv *priv = ufs_sprd_get_priv_data(hba);
+
+	if (status == PRE_CHANGE) {
+		if (cmd == UIC_CMD_DME_HIBER_ENTER)
+			/*
+			 * Disable UIC COMPL INTR to prevent access to UFSHCI after
+			 * checking HCS.UPMCRS
+			 */
+			ufs_sprd_ctrl_uic_compl(hba, false);
+
+		if (cmd == UIC_CMD_DME_HIBER_EXIT) {
+			ufs_sprd_regmap_update(priv, SPRD_UFS_AON_APB, APB_UFSDEV_REG,
+				APB_UFSDEV_REFCLK_EN, APB_UFSDEV_REFCLK_EN);
+			ufs_sprd_regmap_update(priv, SPRD_UFS_AON_APB, APB_USB31PLL_CTRL,
+				APB_USB31PLLV_REF2MPHY, APB_USB31PLLV_REF2MPHY);
+		}
+	}
+
+	if (status == POST_CHANGE) {
+		if (cmd == UIC_CMD_DME_HIBER_EXIT)
+			ufs_sprd_ctrl_uic_compl(hba, true);
+
+		if (cmd == UIC_CMD_DME_HIBER_ENTER) {
+			ufs_sprd_regmap_update(priv, SPRD_UFS_AON_APB, APB_UFSDEV_REG,
+				APB_UFSDEV_REFCLK_EN, 0);
+			ufs_sprd_regmap_update(priv, SPRD_UFS_AON_APB, APB_USB31PLL_CTRL,
+				APB_USB31PLLV_REF2MPHY, 0);
+		}
+	}
+}
+
+static struct ufs_sprd_priv n6_ufs = {
+	.clki[SPRD_UFS_HCLK] = { .name = "ufsh", },
+	.clki[SPRD_UFS_HCLK_SOURCE] = { .name = "ufsh_source", },
+
+	.rci[SPRD_UFSHCI_SOFT_RST] = { .name = "ufs", },
+	.rci[SPRD_UFS_DEV_RST] = { .name = "ufsdev", },
+
+	.sysci[SPRD_UFS_ANLG] = { .name = "sprd,ufs-anlg-syscon", },
+	.sysci[SPRD_UFS_AON_APB] = { .name = "sprd,aon-apb-syscon", },
+
+	.vregi[SPRD_UFS_VDD_MPHY] = { .name = "vdd-mphy", },
+
+	.ufs_hba_sprd_vops = {
+		.name = "sprd,ums9620-ufs",
+		.init = ufs_sprd_n6_init,
+		.hce_enable_notify = sprd_ufs_n6_hce_enable_notify,
+		.pwr_change_notify = sprd_ufs_pwr_change_notify,
+		.hibern8_notify = sprd_ufs_n6_h8_notify,
+		.device_reset = ufs_sprd_n6_device_reset,
+		.suspend = ufs_sprd_suspend,
+	},
+};
+
+static const struct of_device_id ufs_sprd_of_match[] = {
+	{ .compatible = "sprd,ums9620-ufs", .data = &n6_ufs.ufs_hba_sprd_vops},
+	{},
+};
+
+static int ufs_sprd_probe(struct platform_device *pdev)
+{
+	int err;
+	struct device *dev = &pdev->dev;
+	const struct of_device_id *of_id;
+
+	of_id = of_match_node(ufs_sprd_of_match, dev->of_node);
+	err = ufshcd_pltfrm_init(pdev, of_id->data);
+	if (err)
+		dev_err(dev, "ufshcd_pltfrm_init() failed %d\n", err);
+
+	return err;
+}
+
+static int ufs_sprd_remove(struct platform_device *pdev)
+{
+	struct ufs_hba *hba =  platform_get_drvdata(pdev);
+
+	pm_runtime_get_sync(&(pdev)->dev);
+	ufshcd_remove(hba);
+	return 0;
+}
+
+static const struct dev_pm_ops ufs_sprd_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(ufshcd_system_suspend, ufshcd_system_resume)
+	SET_RUNTIME_PM_OPS(ufshcd_runtime_suspend, ufshcd_runtime_resume, NULL)
+	.prepare	 = ufshcd_suspend_prepare,
+	.complete	 = ufshcd_resume_complete,
+};
+
+static struct platform_driver ufs_sprd_pltform = {
+	.probe = ufs_sprd_probe,
+	.remove = ufs_sprd_remove,
+	.shutdown = ufshcd_pltfrm_shutdown,
+	.driver = {
+		.name = "ufshcd-sprd",
+		.pm = &ufs_sprd_pm_ops,
+		.of_match_table = ufs_sprd_of_match,
+	},
+};
+module_platform_driver(ufs_sprd_pltform);
+
+MODULE_AUTHOR("Zhe Wang <zhe.wang1@unisoc.com>");
+MODULE_DESCRIPTION("Unisoc UFS Host Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/ufs/host/ufs-sprd.h b/drivers/ufs/host/ufs-sprd.h
new file mode 100644
index 000000000000..14b684dd5333
--- /dev/null
+++ b/drivers/ufs/host/ufs-sprd.h
@@ -0,0 +1,86 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * UNISOC UFS Host Controller driver
+ *
+ * Copyright (C) 2022 Unisoc, Inc.
+ * Author: Zhe Wang <zhe.wang1@unisoc.com>
+ */
+
+#ifndef _UFS_SPRD_H_
+#define _UFS_SPRD_H_
+
+#define APB_UFSDEV_REG		0xCE8
+#define APB_UFSDEV_REFCLK_EN	0x2
+#define APB_USB31PLL_CTRL	0xCFC
+#define APB_USB31PLLV_REF2MPHY	0x1
+
+#define SPRD_SIP_SVC_STORAGE_UFS_CRYPTO_ENABLE				\
+	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL,				\
+			   ARM_SMCCC_SMC_32,				\
+			   ARM_SMCCC_OWNER_SIP,				\
+			   0x0301)
+
+enum SPRD_UFS_CLK_INDEX {
+	SPRD_UFS_HCLK,
+	SPRD_UFS_HCLK_SOURCE,
+
+	SPRD_UFS_CLK_MAX
+};
+
+enum SPRD_UFS_RST_INDEX {
+	SPRD_UFSHCI_SOFT_RST,
+	SPRD_UFS_DEV_RST,
+
+	SPRD_UFS_RST_MAX
+};
+
+enum SPRD_UFS_SYSCON_INDEX {
+	SPRD_UFS_ANLG,
+	SPRD_UFS_AON_APB,
+
+	SPRD_UFS_SYSCON_MAX
+};
+
+enum SPRD_UFS_VREG_INDEX {
+	SPRD_UFS_VDD_MPHY,
+
+	SPRD_UFS_VREG_MAX
+};
+
+struct ufs_sprd_clk {
+	const char *name;
+	struct clk *clk;
+};
+
+struct ufs_sprd_rst {
+	const char *name;
+	struct reset_control *rc;
+};
+
+struct ufs_sprd_syscon {
+	const char *name;
+	struct regmap *regmap;
+};
+
+struct ufs_sprd_vreg {
+	const char *name;
+	struct regulator *vreg;
+};
+
+struct ufs_sprd_priv {
+	struct ufs_sprd_clk clki[SPRD_UFS_CLK_MAX];
+	struct ufs_sprd_rst rci[SPRD_UFS_RST_MAX];
+	struct ufs_sprd_syscon sysci[SPRD_UFS_SYSCON_MAX];
+	struct ufs_sprd_vreg vregi[SPRD_UFS_VREG_MAX];
+	const struct ufs_hba_variant_ops ufs_hba_sprd_vops;
+};
+
+struct ufs_sprd_host {
+	struct ufs_hba *hba;
+	struct ufs_sprd_priv *priv;
+	void __iomem *ufs_dbg_mmio;
+
+	enum ufs_unipro_ver unipro_ver;
+};
+
+#endif /* _UFS_SPRD_H_ */
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH v2 1/2] dt-bindings: ufs: Add document for Unisoc UFS host controller
  2022-11-16 13:31 ` [PATCH v2 1/2] dt-bindings: ufs: Add document " Zhe Wang
@ 2022-11-16 17:03   ` Krzysztof Kozlowski
  2022-11-17  8:45     ` Zhe Wang
  2022-11-20 16:49   ` Rob Herring
  1 sibling, 1 reply; 8+ messages in thread
From: Krzysztof Kozlowski @ 2022-11-16 17:03 UTC (permalink / raw)
  To: Zhe Wang, martin.petersen, jejb, krzysztof.kozlowski+dt, robh+dt,
	alim.akhtar, avri.altman
  Cc: linux-scsi, devicetree, orsonzhai, yuelin.tang, zhenxiong.lai,
	zhang.lyra

On 16/11/2022 14:31, Zhe Wang wrote:
> Add Unisoc ums9620 ufs host controller devicetree document.
> 
> Signed-off-by: Zhe Wang <zhe.wang1@unisoc.com>

Thank you for your patch. There is something to discuss/improve.

> +
> +  clock-names:
> +    items:
> +      - const: ufs_eb
> +      - const: ufs_cfg_eb
> +      - const: ufsh
> +      - const: ufsh_source
> +
> +  resets:
> +    maxItems: 2
> +
> +  reset-names:
> +    items:
> +      - const: ufs
> +      - const: ufsdev

Both clock names and resets are still not useful. "ufs" is the name of
the block, so reset name of "ufs" and "ufsdev" says nothing. This is the
dev right?

> +
> +  vdd-mphy-supply:
> +    description:
> +      Phandle to vdd-mphy supply regulator node.
> +
> +  sprd,ufs-anlg-syscon:
> +    $ref: /schemas/types.yaml#/definitions/phandle
> +    description: phandle of syscon used to control ufs analog regs.
> +
> +  sprd,aon-apb-syscon:
> +    $ref: /schemas/types.yaml#/definitions/phandle
> +    description: phandle of syscon used to control always-on regs.
> +
> +required:
> +  - compatible
> +  - reg
> +  - clocks
> +  - clock-names
> +  - resets
> +  - reset-names
> +
> +unevaluatedProperties: false
> +
> +examples:
> +  - |
> +    #include <dt-bindings/interrupt-controller/arm-gic.h>
> +
> +    ufs: ufs@22000000 {
> +        compatible = "sprd,ums9620-ufs";
> +        reg = <0x22000000 0x3000>;
> +        interrupts = <GIC_SPI 159 IRQ_TYPE_LEVEL_HIGH>;
> +        vcc-supply = <&vddemmccore>;
> +        vdd-mphy-supply = <&vddufs1v2>;
> +        clock-names = "ufs_eb", "ufs_cfg_eb", "ufsh", "ufsh_source";
> +        clocks = <&apahb_gate 5>, <&apahb_gate 22>, <&aonapb_clk 52>, <&g5l_pll 12>;

First clocks, then names.

> +        reset-names = "ufs", "ufsdev";
> +        resets = <&apahb_gate 4>, <&aonapb_gate 69>;

First resets, then names.

> +        sprd,ufs-anlg-syscon = <&anlg_phy_g12_regs>;
> +        sprd,aon-apb-syscon = <&aon_apb_regs>;
> +    };

Best regards,
Krzysztof


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v2 1/2] dt-bindings: ufs: Add document for Unisoc UFS host controller
  2022-11-16 17:03   ` Krzysztof Kozlowski
@ 2022-11-17  8:45     ` Zhe Wang
  2022-11-17  9:19       ` Krzysztof Kozlowski
  0 siblings, 1 reply; 8+ messages in thread
From: Zhe Wang @ 2022-11-17  8:45 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: Zhe Wang, martin.petersen, jejb, krzysztof.kozlowski+dt, robh+dt,
	alim.akhtar, avri.altman, linux-scsi, devicetree, orsonzhai,
	yuelin.tang, zhenxiong.lai, zhang.lyra

hi Krzysztof

On Thu, Nov 17, 2022 at 1:11 AM Krzysztof Kozlowski
<krzysztof.kozlowski@linaro.org> wrote:
>
> On 16/11/2022 14:31, Zhe Wang wrote:
> > Add Unisoc ums9620 ufs host controller devicetree document.
> >
> > Signed-off-by: Zhe Wang <zhe.wang1@unisoc.com>
>
> Thank you for your patch. There is something to discuss/improve.
>
> > +
> > +  clock-names:
> > +    items:
> > +      - const: ufs_eb
> > +      - const: ufs_cfg_eb
> > +      - const: ufsh
> > +      - const: ufsh_source
> > +
> > +  resets:
> > +    maxItems: 2
> > +
> > +  reset-names:
> > +    items:
> > +      - const: ufs
> > +      - const: ufsdev
>
> Both clock names and resets are still not useful. "ufs" is the name of
> the block, so reset name of "ufs" and "ufsdev" says nothing. This is the
> dev right?
>

Yes, this means reset on the device side. How about the modification below?

+  clock-names:
+    items:
+      - const: controller_eb
+      - const: cfg_eb
+      - const: core
+      - const: core_source
+
+  resets:
+    maxItems: 2
+
+  reset-names:
+    items:
+      - const: controller
+      - const: device

> > +
> > +  vdd-mphy-supply:
> > +    description:
> > +      Phandle to vdd-mphy supply regulator node.
> > +
> > +  sprd,ufs-anlg-syscon:
> > +    $ref: /schemas/types.yaml#/definitions/phandle
> > +    description: phandle of syscon used to control ufs analog regs.
> > +
> > +  sprd,aon-apb-syscon:
> > +    $ref: /schemas/types.yaml#/definitions/phandle
> > +    description: phandle of syscon used to control always-on regs.
> > +
> > +required:
> > +  - compatible
> > +  - reg
> > +  - clocks
> > +  - clock-names
> > +  - resets
> > +  - reset-names
> > +
> > +unevaluatedProperties: false
> > +
> > +examples:
> > +  - |
> > +    #include <dt-bindings/interrupt-controller/arm-gic.h>
> > +
> > +    ufs: ufs@22000000 {
> > +        compatible = "sprd,ums9620-ufs";
> > +        reg = <0x22000000 0x3000>;
> > +        interrupts = <GIC_SPI 159 IRQ_TYPE_LEVEL_HIGH>;
> > +        vcc-supply = <&vddemmccore>;
> > +        vdd-mphy-supply = <&vddufs1v2>;
> > +        clock-names = "ufs_eb", "ufs_cfg_eb", "ufsh", "ufsh_source";
> > +        clocks = <&apahb_gate 5>, <&apahb_gate 22>, <&aonapb_clk 52>, <&g5l_pll 12>;
>
> First clocks, then names.
>

I'll fix it.

> > +        reset-names = "ufs", "ufsdev";
> > +        resets = <&apahb_gate 4>, <&aonapb_gate 69>;
>
> First resets, then names.
>

I'll fix it.

Best regards,
Zhe

> > +        sprd,ufs-anlg-syscon = <&anlg_phy_g12_regs>;
> > +        sprd,aon-apb-syscon = <&aon_apb_regs>;
> > +    };
>
> Best regards,
> Krzysztof
>

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v2 1/2] dt-bindings: ufs: Add document for Unisoc UFS host controller
  2022-11-17  8:45     ` Zhe Wang
@ 2022-11-17  9:19       ` Krzysztof Kozlowski
  0 siblings, 0 replies; 8+ messages in thread
From: Krzysztof Kozlowski @ 2022-11-17  9:19 UTC (permalink / raw)
  To: Zhe Wang
  Cc: Zhe Wang, martin.petersen, jejb, krzysztof.kozlowski+dt, robh+dt,
	alim.akhtar, avri.altman, linux-scsi, devicetree, orsonzhai,
	yuelin.tang, zhenxiong.lai, zhang.lyra

On 17/11/2022 09:45, Zhe Wang wrote:
> hi Krzysztof
> 
> On Thu, Nov 17, 2022 at 1:11 AM Krzysztof Kozlowski
> <krzysztof.kozlowski@linaro.org> wrote:
>>
>> On 16/11/2022 14:31, Zhe Wang wrote:
>>> Add Unisoc ums9620 ufs host controller devicetree document.
>>>
>>> Signed-off-by: Zhe Wang <zhe.wang1@unisoc.com>
>>
>> Thank you for your patch. There is something to discuss/improve.
>>
>>> +
>>> +  clock-names:
>>> +    items:
>>> +      - const: ufs_eb
>>> +      - const: ufs_cfg_eb
>>> +      - const: ufsh
>>> +      - const: ufsh_source
>>> +
>>> +  resets:
>>> +    maxItems: 2
>>> +
>>> +  reset-names:
>>> +    items:
>>> +      - const: ufs
>>> +      - const: ufsdev
>>
>> Both clock names and resets are still not useful. "ufs" is the name of
>> the block, so reset name of "ufs" and "ufsdev" says nothing. This is the
>> dev right?
>>
> 
> Yes, this means reset on the device side. How about the modification below?
> 
> +  clock-names:
> +    items:
> +      - const: controller_eb
> +      - const: cfg_eb
> +      - const: core
> +      - const: core_source
> +
> +  resets:
> +    maxItems: 2
> +
> +  reset-names:
> +    items:
> +      - const: controller
> +      - const: device

That's very good, thanks.

> 

Best regards,
Krzysztof


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v2 1/2] dt-bindings: ufs: Add document for Unisoc UFS host controller
  2022-11-16 13:31 ` [PATCH v2 1/2] dt-bindings: ufs: Add document " Zhe Wang
  2022-11-16 17:03   ` Krzysztof Kozlowski
@ 2022-11-20 16:49   ` Rob Herring
  2022-11-21  6:43     ` Zhe Wang
  1 sibling, 1 reply; 8+ messages in thread
From: Rob Herring @ 2022-11-20 16:49 UTC (permalink / raw)
  To: Zhe Wang
  Cc: martin.petersen, jejb, krzysztof.kozlowski+dt, alim.akhtar,
	avri.altman, linux-scsi, devicetree, orsonzhai, yuelin.tang,
	zhenxiong.lai, zhang.lyra

On Wed, Nov 16, 2022 at 09:31:30PM +0800, Zhe Wang wrote:
> Add Unisoc ums9620 ufs host controller devicetree document.
> 
> Signed-off-by: Zhe Wang <zhe.wang1@unisoc.com>
> ---
>  .../bindings/ufs/sprd,ums9620-ufs.yaml        | 78 +++++++++++++++++++
>  1 file changed, 78 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/ufs/sprd,ums9620-ufs.yaml
> 
> diff --git a/Documentation/devicetree/bindings/ufs/sprd,ums9620-ufs.yaml b/Documentation/devicetree/bindings/ufs/sprd,ums9620-ufs.yaml
> new file mode 100644
> index 000000000000..ce9d05be1a6b
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/ufs/sprd,ums9620-ufs.yaml
> @@ -0,0 +1,78 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/ufs/sprd,ums9620-ufs.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Unisoc Universal Flash Storage (UFS) Controller
> +
> +maintainers:
> +  - Zhe Wang <zhe.wang1@unisoc.com>
> +
> +allOf:
> +  - $ref: ufs-common.yaml
> +
> +properties:
> +  compatible:
> +    const: sprd,ums9620-ufs
> +
> +  reg:
> +    maxItems: 1
> +
> +  clocks:
> +    maxItems: 4
> +
> +  clock-names:
> +    items:
> +      - const: ufs_eb
> +      - const: ufs_cfg_eb
> +      - const: ufsh
> +      - const: ufsh_source

Sounds like a parent clock to 'ufsh'? If so, it doesn't belong in 
'clocks'. Use the clock API to get the parent or use 
'assigned-clock-parents'.

Rob

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v2 1/2] dt-bindings: ufs: Add document for Unisoc UFS host controller
  2022-11-20 16:49   ` Rob Herring
@ 2022-11-21  6:43     ` Zhe Wang
  0 siblings, 0 replies; 8+ messages in thread
From: Zhe Wang @ 2022-11-21  6:43 UTC (permalink / raw)
  To: Rob Herring
  Cc: Zhe Wang, martin.petersen, jejb, krzysztof.kozlowski+dt,
	alim.akhtar, avri.altman, linux-scsi, devicetree, orsonzhai,
	yuelin.tang, zhenxiong.lai, zhang.lyra

hi Rob,

On Mon, Nov 21, 2022 at 12:54 AM Rob Herring <robh@kernel.org> wrote:
>
> On Wed, Nov 16, 2022 at 09:31:30PM +0800, Zhe Wang wrote:
> > Add Unisoc ums9620 ufs host controller devicetree document.
> >
> > Signed-off-by: Zhe Wang <zhe.wang1@unisoc.com>
> > ---
> >  .../bindings/ufs/sprd,ums9620-ufs.yaml        | 78 +++++++++++++++++++
> >  1 file changed, 78 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/ufs/sprd,ums9620-ufs.yaml
> >
> > diff --git a/Documentation/devicetree/bindings/ufs/sprd,ums9620-ufs.yaml b/Documentation/devicetree/bindings/ufs/sprd,ums9620-ufs.yaml
> > new file mode 100644
> > index 000000000000..ce9d05be1a6b
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/ufs/sprd,ums9620-ufs.yaml
> > @@ -0,0 +1,78 @@
> > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/ufs/sprd,ums9620-ufs.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: Unisoc Universal Flash Storage (UFS) Controller
> > +
> > +maintainers:
> > +  - Zhe Wang <zhe.wang1@unisoc.com>
> > +
> > +allOf:
> > +  - $ref: ufs-common.yaml
> > +
> > +properties:
> > +  compatible:
> > +    const: sprd,ums9620-ufs
> > +
> > +  reg:
> > +    maxItems: 1
> > +
> > +  clocks:
> > +    maxItems: 4
> > +
> > +  clock-names:
> > +    items:
> > +      - const: ufs_eb
> > +      - const: ufs_cfg_eb
> > +      - const: ufsh
> > +      - const: ufsh_source
>
> Sounds like a parent clock to 'ufsh'? If so, it doesn't belong in
> 'clocks'. Use the clock API to get the parent or use
> 'assigned-clock-parents'.
>
> Rob

It would be more appropriate to use 'assigned-clock-parents', I'll fix
this, thanks.

Best regards,
zhe

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2022-11-21  6:43 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-11-16 13:31 [PATCH v2 0/2] Add support for Unisoc UFS host controller Zhe Wang
2022-11-16 13:31 ` [PATCH v2 1/2] dt-bindings: ufs: Add document " Zhe Wang
2022-11-16 17:03   ` Krzysztof Kozlowski
2022-11-17  8:45     ` Zhe Wang
2022-11-17  9:19       ` Krzysztof Kozlowski
2022-11-20 16:49   ` Rob Herring
2022-11-21  6:43     ` Zhe Wang
2022-11-16 13:31 ` [PATCH v2 2/2] scsi: ufs-unisoc: Add support " Zhe Wang

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.