Skip to contentSkip to conversation

mmc: socfpga: add method to configure clk-phase

PATCH Superseded Dinh Nguyen 2 participants 6 messages Sep 22, 2022 – Sep 23, 2022

Subsystems (4)

v2 of 9 Superseded Latest is v9 →

lore
Share & tools
lore

Dinh Nguyen

author maintainer
#0 lore raw

v2 cover mmc: socfpga: add method to configure clk-phase

Hi,

This is version 2 of the patchset to configure the clk-phase for the SDMMC controller on SoCFPGA platforms.

Updates from v1:
- Documented "altr,sysmgr-syscon" binding
- Cleaned up dw_mci_socfpga_priv_init() to get the "clk-phase-sd-hs" from the DTS. Ulf Hanson recommended using mmc_of_parse_clk_phase() in this function, however, I found that using mmc_of_parse_clk_phase() is a bit more complicated than just reading the "clk-phase-sd-hs" from the DTS. Here are the reasons:
- The call to mmc_of_parse_clk_phase() takes the struct mmc_host *host structure, and in the dw_mmc driver, and this structure does not get populated until at the very end of the dw_mci_probe function, after dw_mci_init_slot() gets called.
- Also, in order to correctly extract the phase_map.phase[timing], we need to wait until set_ios() is called in order to get the host->timing parameter so it can be used for the clock phase array.

Dinh Nguyen (3):
dt-bindings: mmc: synopsys-dw-mshc: document "altr,sysmgr-syscon"
arm64: dts: socfpga: Add clk-phase-sd-hs property to the sdmmc node
mmc: dw_mmc-pltfm: socfpga: add method to configure clk-phase

 .../bindings/mmc/synopsys-dw-mshc.yaml        |  8 ++++
 .../boot/dts/altera/socfpga_stratix10.dtsi    |  1 +
 .../dts/altera/socfpga_stratix10_socdk.dts    |  1 +
 arch/arm64/boot/dts/intel/socfpga_agilex.dtsi |  1 +
 .../boot/dts/intel/socfpga_agilex_socdk.dts   |  1 +
 .../boot/dts/intel/socfpga_n5x_socdk.dts      |  1 +
 drivers/mmc/host/dw_mmc-pltfm.c               | 41 ++++++++++++++++++-
 7 files changed, 53 insertions(+), 1 deletion(-)
Signature · 1 line
2.25.1
author maintainer
#1 lore raw

PATCH v2 1/3 dt-bindings: mmc: synopsys-dw-mshc: document "altr,sysmgr-syscon"

Document the optional "altr,sysmgr-syscon" binding that is used to access the System Manager register that controls the SDMMC clock phase.

---
v2: added

---
 .../devicetree/bindings/mmc/synopsys-dw-mshc.yaml    | 12 ++++++++++++
 1 file changed, 12 insertions(+)
Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.yaml +12 -0
index ae6d6fca79e2..aece6a337262 100644
@@ -38,6 +38,18 @@ properties:
       - const: biu
       - const: ciu
 
+  altr,sysmgr-syscon:
+    $ref: /schemas/types.yaml#/definitions/phandle-array
+    items:
+      - items:
+          - description: phandle to the sysmgr node
+          - description: register offset that controls the SDMMC clock phase
+    description:
+      Contains the phandle to System Manager block that contains
+      the SDMMC clock-phase control register. The first value is the pointer
+      to the sysmgr and the 2nd value is the register offset for the SDMMC
+      clock phase register.
+
 required:
   - compatible
   - reg
Signature · 1 line
2.25.1
#2 lore raw

Re: [PATCHv2 1/3] dt-bindings: mmc: synopsys-dw-mshc: document "altr,sysmgr-syscon"

Quoted 5 lines · Dinh Nguyen

Document the optional "altr,sysmgr-syscon" binding that is used to access the System Manager register that controls the SDMMC clock phase.

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

Quoted 15 lines

---
v2: added

---
 .../devicetree/bindings/mmc/synopsys-dw-mshc.yaml    | 12 ++++++++++++
 1 file changed, 12 insertions(+)
Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.yaml +1 -0
index ae6d6fca79e2..aece6a337262 100644
@@ -38,6 +38,18 @@ properties:
       - const: biu
       - const: ciu
 
+  altr,sysmgr-syscon:

Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.yaml properties: · line 51

Quoted 10 lines
Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.yaml +10 -0
+    $ref: /schemas/types.yaml#/definitions/phandle-array
+    items:
+      - items:
+          - description: phandle to the sysmgr node
+          - description: register offset that controls the SDMMC clock phase
+    description:
+      Contains the phandle to System Manager block that contains
+      the SDMMC clock-phase control register. The first value is the pointer
+      to the sysmgr and the 2nd value is the register offset for the SDMMC
+      clock phase register.

You need to restrict it per variant (altera). Move the allOf from top of the file to place above unevaluatedProperties and add if:then: making it false for other variants.

Best regards,
Krzysztof

author maintainer
#3 lore raw

PATCH v2 2/3 arm64: dts: socfpga: Add clk-phase-sd-hs property to the sdmmc node

In reply to Dinh Nguyen

The sdmmc controller's CIU(Card Interface Unit) clock's phase can be adjusted through the register in the system manager. Add the binding "altr,sysmgr-syscon" to the SDMMC node for the driver to access the system manager. Add the "clk-phase-sd-hs" property in the SDMMC node to designate the smpsel and drvsel properties for the CIU clock.

---
v2: no changes

---
 arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi      | 1 +
 arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dts | 1 +
 arch/arm64/boot/dts/intel/socfpga_agilex.dtsi          | 1 +
 arch/arm64/boot/dts/intel/socfpga_agilex_socdk.dts     | 1 +
 arch/arm64/boot/dts/intel/socfpga_n5x_socdk.dts        | 1 +
 5 files changed, 5 insertions(+)
arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi +1 -0
index 14c220d87807..a5d08920ac81 100644
@@ -309,6 +309,7 @@ mmc: mmc@ff808000 {
 				 <&clkmgr STRATIX10_SDMMC_CLK>;
 			clock-names = "biu", "ciu";
 			iommus = <&smmu 5>;
+			altr,sysmgr-syscon = <&sysmgr 0x28 0>;
 			status = "disabled";
 		};
 
arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dts +1 -0
index 48424e459f12..19e7284b4cd5 100644
@@ -105,6 +105,7 @@ &mmc {
 	cap-mmc-highspeed;
 	broken-cd;
 	bus-width = <4>;
+	clk-phase-sd-hs = <0>, <135>;
 };
 
 &osc1 {
arch/arm64/boot/dts/intel/socfpga_agilex.dtsi +1 -0
index 7bbec8aafa62..6353f6a361f4 100644
@@ -313,6 +313,7 @@ mmc: mmc@ff808000 {
 				 <&clkmgr AGILEX_SDMMC_CLK>;
 			clock-names = "biu", "ciu";
 			iommus = <&smmu 5>;
+			altr,sysmgr-syscon = <&sysmgr 0x28 0>;
 			status = "disabled";
 		};
 
arch/arm64/boot/dts/intel/socfpga_agilex_socdk.dts +1 -0
index 26cd3c121757..07c3f8876613 100644
@@ -83,6 +83,7 @@ &mmc {
 	cap-sd-highspeed;
 	broken-cd;
 	bus-width = <4>;
+	clk-phase-sd-hs = <0>, <135>;
 };
 
 &osc1 {
arch/arm64/boot/dts/intel/socfpga_n5x_socdk.dts +1 -0
index 62c66e52b656..08c088571270 100644
@@ -74,6 +74,7 @@ &mmc {
 	cap-sd-highspeed;
 	broken-cd;
 	bus-width = <4>;
+	clk-phase-sd-hs = <0>, <135>;
 };
 
 &osc1 {
Signature · 1 line
2.25.1
author maintainer
#4 lore raw

PATCH v2 3/3 mmc: dw_mmc-pltfm: socfpga: add method to configure clk-phase

In reply to Dinh Nguyen

The clock-phase settings for the SDMMC controller in the SoCFPGA Strarix10/Agilex/N5X platforms reside in a register in the System Manager. Add a method to access that register through the syscon interface.

---
v2: simplify clk-phase calculations

---
 drivers/mmc/host/dw_mmc-pltfm.c | 41 ++++++++++++++++++++++++++++++++-
 1 file changed, 40 insertions(+), 1 deletion(-)
drivers/mmc/host/dw_mmc-pltfm.c +40 -1
index 9901208be797..5d64984d382f 100644
@@ -17,10 +17,16 @@
 #include <linux/mmc/host.h>
 #include <linux/mmc/mmc.h>
 #include <linux/of.h>
+#include <linux/mfd/altera-sysmgr.h>
+#include <linux/regmap.h>
 
 #include "dw_mmc.h"
 #include "dw_mmc-pltfm.h"
 
+#define SOCFPGA_DW_MMC_CLK_PHASE_STEP	45
+#define SYSMGR_SDMMC_CTRL_SET(smplsel, drvsel) \
+	((((smplsel) & 0x7) << 4) | (((drvsel) & 0x7) << 0))
+
 int dw_mci_pltfm_register(struct platform_device *pdev,
 			  const struct dw_mci_drv_data *drv_data)
 {
@@ -62,9 +68,42 @@ const struct dev_pm_ops dw_mci_pltfm_pmops = {
 };
 EXPORT_SYMBOL_GPL(dw_mci_pltfm_pmops);
 
+static int dw_mci_socfpga_priv_init(struct dw_mci *host)
+{
+	struct device_node *np = host->dev->of_node;
+	struct regmap *sys_mgr_base_addr;
+	u32 clk_phase[2] = {0}, reg_offset;
+	int i, rc, hs_timing;
+
+	rc = of_property_read_variable_u32_array(np, "clk-phase-sd-hs", &clk_phase[0], 2, 0);
+	if (rc) {
+		sys_mgr_base_addr =
+			altr_sysmgr_regmap_lookup_by_phandle(np, "altr,sysmgr-syscon");
+		if (IS_ERR(sys_mgr_base_addr)) {
+			pr_err("%s: failed to find altr,sys-mgr regmap!\n", __func__);
+			return 1;
+		}
+	} else
+		return 1;
+
+	of_property_read_u32_index(np, "altr,sysmgr-syscon", 1, &reg_offset);
+
+	for (i = 0; i < ARRAY_SIZE(clk_phase); i++)
+		clk_phase[i] /= SOCFPGA_DW_MMC_CLK_PHASE_STEP;
+
+	hs_timing = SYSMGR_SDMMC_CTRL_SET(clk_phase[0], clk_phase[1]);
+	regmap_write(sys_mgr_base_addr, reg_offset, hs_timing);
+
+	return 0;
+}
+
+static const struct dw_mci_drv_data socfpga_drv_data = {
+	.init		= dw_mci_socfpga_priv_init,
+};
+
 static const struct of_device_id dw_mci_pltfm_match[] = {
 	{ .compatible = "snps,dw-mshc", },
-	{ .compatible = "altr,socfpga-dw-mshc", },
+	{ .compatible = "altr,socfpga-dw-mshc", .data =&socfpga_drv_data, },
 	{ .compatible = "img,pistachio-dw-mshc", },
 	{},
 };
Signature · 1 line
2.25.1
#5 lore raw

Re: [PATCHv2 3/3] mmc: dw_mmc-pltfm: socfpga: add method to configure clk-phase

Quoted 38 lines · Dinh Nguyen

The clock-phase settings for the SDMMC controller in the SoCFPGA Strarix10/Agilex/N5X platforms reside in a register in the System Manager. Add a method to access that register through the syscon interface.

---
v2: simplify clk-phase calculations

---
 drivers/mmc/host/dw_mmc-pltfm.c | 41 ++++++++++++++++++++++++++++++++-
 1 file changed, 40 insertions(+), 1 deletion(-)
drivers/mmc/host/dw_mmc-pltfm.c +7 -0
index 9901208be797..5d64984d382f 100644
@@ -17,10 +17,16 @@
 #include <linux/mmc/host.h>
 #include <linux/mmc/mmc.h>
 #include <linux/of.h>
+#include <linux/mfd/altera-sysmgr.h>
+#include <linux/regmap.h>
 
 #include "dw_mmc.h"
 #include "dw_mmc-pltfm.h"
 
+#define SOCFPGA_DW_MMC_CLK_PHASE_STEP	45
+#define SYSMGR_SDMMC_CTRL_SET(smplsel, drvsel) \
+	((((smplsel) & 0x7) << 4) | (((drvsel) & 0x7) << 0))
+
 int dw_mci_pltfm_register(struct platform_device *pdev,
 			  const struct dw_mci_drv_data *drv_data)
 {
@@ -62,9 +68,42 @@ const struct dev_pm_ops dw_mci_pltfm_pmops = {
 };
 EXPORT_SYMBOL_GPL(dw_mci_pltfm_pmops);
 
+static int dw_mci_socfpga_priv_init(struct dw_mci *host)

drivers/mmc/host/dw_mmc-pltfm.c const struct dev_pm_ops dw_mci_pltfm_pmops = { · line 81

Quoted 10 lines
drivers/mmc/host/dw_mmc-pltfm.c +10 -0
+{
+	struct device_node *np = host->dev->of_node;
+	struct regmap *sys_mgr_base_addr;
+	u32 clk_phase[2] = {0}, reg_offset;
+	int i, rc, hs_timing;
+
+	rc = of_property_read_variable_u32_array(np, "clk-phase-sd-hs", &clk_phase[0], 2, 0);
+	if (rc) {
+		sys_mgr_base_addr =
+			altr_sysmgr_regmap_lookup_by_phandle(np, "altr,sysmgr-syscon");

I don't see the reason why this is conditional. Just creates unnecessary indentation.

drivers/mmc/host/dw_mmc-pltfm.c const struct dev_pm_ops dw_mci_pltfm_pmops = { · line 87

Quoted 6 lines
drivers/mmc/host/dw_mmc-pltfm.c +6 -0
+		if (IS_ERR(sys_mgr_base_addr)) {
+			pr_err("%s: failed to find altr,sys-mgr regmap!\n", __func__);
+			return 1;
+		}
+	} else
+		return 1;

Why not -ERRNO (or rc)?

Quoted 10 lines
drivers/mmc/host/dw_mmc-pltfm.c +10 -0
+
+	of_property_read_u32_index(np, "altr,sysmgr-syscon", 1, &reg_offset);
+
+	for (i = 0; i < ARRAY_SIZE(clk_phase); i++)
+		clk_phase[i] /= SOCFPGA_DW_MMC_CLK_PHASE_STEP;
+
+	hs_timing = SYSMGR_SDMMC_CTRL_SET(clk_phase[0], clk_phase[1]);
+	regmap_write(sys_mgr_base_addr, reg_offset, hs_timing);
+
+	return 0;

drivers/mmc/host/dw_mmc-pltfm.c const struct dev_pm_ops dw_mci_pltfm_pmops = { · line 106

Quoted 10 lines
drivers/mmc/host/dw_mmc-pltfm.c +7 -1
+}
+
+static const struct dw_mci_drv_data socfpga_drv_data = {
+	.init		= dw_mci_socfpga_priv_init,
+};
+
 static const struct of_device_id dw_mci_pltfm_match[] = {
 	{ .compatible = "snps,dw-mshc", },
-	{ .compatible = "altr,socfpga-dw-mshc", },
+	{ .compatible = "altr,socfpga-dw-mshc", .data =&socfpga_drv_data, },

Missing space before &

drivers/mmc/host/dw_mmc-pltfm.c const struct dev_pm_ops dw_mci_pltfm_pmops = { · line 109

Quoted 3 lines
drivers/mmc/host/dw_mmc-pltfm.c +0 -0
 	{ .compatible = "img,pistachio-dw-mshc", },
 	{},
 };

Best regards,
Krzysztof