All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] mtd: rawnand: meson: fix the clock after discarding sd_emmc_c_clkc
@ 2022-01-06  3:25 ` Liang Yang
  0 siblings, 0 replies; 47+ messages in thread
From: Liang Yang @ 2022-01-06  3:25 UTC (permalink / raw)
  To: Miquel Raynal, linux-mtd
  Cc: Liang Yang, Richard Weinberger, Jerome Brunet, Neil Armstrong,
	Martin Blumenstingl, Kevin Hilman, Jianxin Pan, Victor Wan,
	XianWei Zhao, Kelvin Zhang, BiChao Zheng, YongHui Yu,
	linux-arm-kernel, linux-amlogic, linux-kernel, devicetree

Because EMMC and NAND have the same control clock register, so we
implement a 'sd_emmc_c_clkc'. Previously DTS is defined as below:

	sd_emmc_c_clkc: mmc@7000 {
		compatible = "amlogic,meson-axg-mmc-clkc", "syscon";
		reg = <0x0 0x7000 0x0 0x800>;
	};

	nand-controller@7800 {
		......

		clocks = <&clkc CLKID_SD_EMMC_C>,
			<&sd_emmc_c_clkc CLKID_MMC_DIV>,
			<&sd_emmc_c_clkc CLKID_MMC_PHASE_RX>,
			<&sd_emmc_c_clkc CLKID_MMC_PHASE_TX>;
		clock-names = "core", "device", "rx", "tx";
		amlogic,mmc-syscon = <&sd_emmc_c_clkc>;

		......
	}

but in fact, above implementation is rejected. so now registering
a nand_divider.

Change-Id: Ibeb4c7ff886f5886aac4d6c664d7bbd1b1bcb997
Signed-off-by: Liang Yang <liang.yang@amlogic.com>
---
 drivers/mtd/nand/raw/meson_nand.c | 88 +++++++++++++++++--------------
 1 file changed, 49 insertions(+), 39 deletions(-)

diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c
index ac3be92872d0..4472363059c2 100644
--- a/drivers/mtd/nand/raw/meson_nand.c
+++ b/drivers/mtd/nand/raw/meson_nand.c
@@ -2,7 +2,7 @@
 /*
  * Amlogic Meson Nand Flash Controller Driver
  *
- * Copyright (c) 2018 Amlogic, inc.
+ * Copyright (c) 2018-2021 Amlogic, inc.
  * Author: Liang Yang <liang.yang@amlogic.com>
  */
 
@@ -10,6 +10,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/interrupt.h>
 #include <linux/clk.h>
+#include <linux/clk-provider.h>
 #include <linux/mtd/rawnand.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mfd/syscon.h>
@@ -55,6 +56,7 @@
 #define NFC_REG_VER		0x38
 
 #define NFC_RB_IRQ_EN		BIT(21)
+#define NFC_CMD_FIFO_RESET	BIT(31)
 
 #define CMDRWGEN(cmd_dir, ran, bch, short_mode, page_size, pages)	\
 	(								\
@@ -104,6 +106,9 @@
 
 #define PER_INFO_BYTE		8
 
+#define CLK_DIV_SHIFT		0
+#define CLK_DIV_WIDTH		6
+
 struct meson_nfc_nand_chip {
 	struct list_head node;
 	struct nand_chip nand;
@@ -151,15 +156,15 @@ struct meson_nfc {
 	struct nand_controller controller;
 	struct clk *core_clk;
 	struct clk *device_clk;
-	struct clk *phase_tx;
-	struct clk *phase_rx;
+	struct clk *nand_clk;
+	struct clk_divider nand_divider;
 
 	unsigned long clk_rate;
 	u32 bus_timing;
 
 	struct device *dev;
 	void __iomem *reg_base;
-	struct regmap *reg_clk;
+	void __iomem *reg_clk;
 	struct completion completion;
 	struct list_head chips;
 	const struct meson_nfc_data *data;
@@ -406,12 +411,14 @@ static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms)
 	cmd = NFC_CMD_RB | NFC_CMD_RB_INT
 		| nfc->param.chip_select | nfc->timing.tbers_max;
 	writel(cmd, nfc->reg_base + NFC_REG_CMD);
-
+	meson_nfc_drain_cmd(nfc);
 	ret = wait_for_completion_timeout(&nfc->completion,
 					  msecs_to_jiffies(timeout_ms));
 	if (ret == 0)
 		ret = -1;
 
+	/* reset command fifo to avoid lock */
+	writel(NFC_CMD_FIFO_RESET, nfc->reg_base + NFC_REG_CMD);
 	return ret;
 }
 
@@ -988,8 +995,9 @@ static const struct mtd_ooblayout_ops meson_ooblayout_ops = {
 static int meson_nfc_clk_init(struct meson_nfc *nfc)
 {
 	int ret;
+	struct clk_init_data init = {0};
+	const char *fix_div2_pll_name[1];
 
-	/* request core clock */
 	nfc->core_clk = devm_clk_get(nfc->dev, "core");
 	if (IS_ERR(nfc->core_clk)) {
 		dev_err(nfc->dev, "failed to get core clock\n");
@@ -1002,21 +1010,25 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
 		return PTR_ERR(nfc->device_clk);
 	}
 
-	nfc->phase_tx = devm_clk_get(nfc->dev, "tx");
-	if (IS_ERR(nfc->phase_tx)) {
-		dev_err(nfc->dev, "failed to get TX clk\n");
-		return PTR_ERR(nfc->phase_tx);
-	}
-
-	nfc->phase_rx = devm_clk_get(nfc->dev, "rx");
-	if (IS_ERR(nfc->phase_rx)) {
-		dev_err(nfc->dev, "failed to get RX clk\n");
-		return PTR_ERR(nfc->phase_rx);
-	}
+	init.name = devm_kstrdup(nfc->dev, "nfc#div", GFP_KERNEL);
+	init.ops = &clk_divider_ops;
+	fix_div2_pll_name[0] = __clk_get_name(nfc->device_clk);
+	init.parent_names = fix_div2_pll_name;
+	init.num_parents = 1;
+	nfc->nand_divider.reg = nfc->reg_clk;
+	nfc->nand_divider.shift = CLK_DIV_SHIFT;
+	nfc->nand_divider.width = CLK_DIV_WIDTH;
+	nfc->nand_divider.hw.init = &init;
+	nfc->nand_divider.flags = CLK_DIVIDER_ONE_BASED |
+				  CLK_DIVIDER_ROUND_CLOSEST |
+          			  CLK_DIVIDER_ALLOW_ZERO;
+
+	nfc->nand_clk = devm_clk_register(nfc->dev, &nfc->nand_divider.hw);
+	if (IS_ERR(nfc->nand_clk))
+		return PTR_ERR(nfc->nand_clk);
 
 	/* init SD_EMMC_CLOCK to sane defaults w/min clock rate */
-	regmap_update_bits(nfc->reg_clk,
-			   0, CLK_SELECT_NAND, CLK_SELECT_NAND);
+	writel(CLK_SELECT_NAND | readl(nfc->reg_clk), nfc->reg_clk);
 
 	ret = clk_prepare_enable(nfc->core_clk);
 	if (ret) {
@@ -1030,29 +1042,21 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
 		goto err_device_clk;
 	}
 
-	ret = clk_prepare_enable(nfc->phase_tx);
+	ret = clk_prepare_enable(nfc->nand_clk);
 	if (ret) {
-		dev_err(nfc->dev, "failed to enable TX clock\n");
-		goto err_phase_tx;
-	}
-
-	ret = clk_prepare_enable(nfc->phase_rx);
-	if (ret) {
-		dev_err(nfc->dev, "failed to enable RX clock\n");
-		goto err_phase_rx;
+		dev_err(nfc->dev, "pre enable NFC divider fail\n");
+		goto err_nand_clk;
 	}
 
 	ret = clk_set_rate(nfc->device_clk, 24000000);
 	if (ret)
-		goto err_disable_rx;
+		goto err_disable_clk;
 
 	return 0;
 
-err_disable_rx:
-	clk_disable_unprepare(nfc->phase_rx);
-err_phase_rx:
-	clk_disable_unprepare(nfc->phase_tx);
-err_phase_tx:
+err_disable_clk:
+	clk_disable_unprepare(nfc->nand_clk);
+err_nand_clk:
 	clk_disable_unprepare(nfc->device_clk);
 err_device_clk:
 	clk_disable_unprepare(nfc->core_clk);
@@ -1061,8 +1065,7 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
 
 static void meson_nfc_disable_clk(struct meson_nfc *nfc)
 {
-	clk_disable_unprepare(nfc->phase_rx);
-	clk_disable_unprepare(nfc->phase_tx);
+	clk_disable_unprepare(nfc->nand_clk);
 	clk_disable_unprepare(nfc->device_clk);
 	clk_disable_unprepare(nfc->core_clk);
 }
@@ -1375,6 +1378,7 @@ static int meson_nfc_probe(struct platform_device *pdev)
 	struct device *dev = &pdev->dev;
 	struct meson_nfc *nfc;
 	struct resource *res;
+	u32 ext_clk_reg;
 	int ret, irq;
 
 	nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL);
@@ -1396,9 +1400,15 @@ static int meson_nfc_probe(struct platform_device *pdev)
 	if (IS_ERR(nfc->reg_base))
 		return PTR_ERR(nfc->reg_base);
 
-	nfc->reg_clk =
-		syscon_regmap_lookup_by_phandle(dev->of_node,
-						"amlogic,mmc-syscon");
+	ret = of_property_read_u32(pdev->dev.of_node,
+				   "sd_emmc_c_clkc",
+				   &ext_clk_reg);
+	if (ret) {
+		dev_err(dev, "failed to get NAND external clock register\n");
+		return ret;
+	}
+
+	nfc->reg_clk = devm_ioremap(&pdev->dev, ext_clk_reg, sizeof(int));
 	if (IS_ERR(nfc->reg_clk)) {
 		dev_err(dev, "Failed to lookup clock base\n");
 		return PTR_ERR(nfc->reg_clk);
-- 
2.34.1


_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic

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

* [PATCH] mtd: rawnand: meson: fix the clock after discarding sd_emmc_c_clkc
@ 2022-01-06  3:25 ` Liang Yang
  0 siblings, 0 replies; 47+ messages in thread
From: Liang Yang @ 2022-01-06  3:25 UTC (permalink / raw)
  To: Miquel Raynal, linux-mtd
  Cc: Liang Yang, Richard Weinberger, Jerome Brunet, Neil Armstrong,
	Martin Blumenstingl, Kevin Hilman, Jianxin Pan, Victor Wan,
	XianWei Zhao, Kelvin Zhang, BiChao Zheng, YongHui Yu,
	linux-arm-kernel, linux-amlogic, linux-kernel, devicetree

Because EMMC and NAND have the same control clock register, so we
implement a 'sd_emmc_c_clkc'. Previously DTS is defined as below:

	sd_emmc_c_clkc: mmc@7000 {
		compatible = "amlogic,meson-axg-mmc-clkc", "syscon";
		reg = <0x0 0x7000 0x0 0x800>;
	};

	nand-controller@7800 {
		......

		clocks = <&clkc CLKID_SD_EMMC_C>,
			<&sd_emmc_c_clkc CLKID_MMC_DIV>,
			<&sd_emmc_c_clkc CLKID_MMC_PHASE_RX>,
			<&sd_emmc_c_clkc CLKID_MMC_PHASE_TX>;
		clock-names = "core", "device", "rx", "tx";
		amlogic,mmc-syscon = <&sd_emmc_c_clkc>;

		......
	}

but in fact, above implementation is rejected. so now registering
a nand_divider.

Change-Id: Ibeb4c7ff886f5886aac4d6c664d7bbd1b1bcb997
Signed-off-by: Liang Yang <liang.yang@amlogic.com>
---
 drivers/mtd/nand/raw/meson_nand.c | 88 +++++++++++++++++--------------
 1 file changed, 49 insertions(+), 39 deletions(-)

diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c
index ac3be92872d0..4472363059c2 100644
--- a/drivers/mtd/nand/raw/meson_nand.c
+++ b/drivers/mtd/nand/raw/meson_nand.c
@@ -2,7 +2,7 @@
 /*
  * Amlogic Meson Nand Flash Controller Driver
  *
- * Copyright (c) 2018 Amlogic, inc.
+ * Copyright (c) 2018-2021 Amlogic, inc.
  * Author: Liang Yang <liang.yang@amlogic.com>
  */
 
@@ -10,6 +10,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/interrupt.h>
 #include <linux/clk.h>
+#include <linux/clk-provider.h>
 #include <linux/mtd/rawnand.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mfd/syscon.h>
@@ -55,6 +56,7 @@
 #define NFC_REG_VER		0x38
 
 #define NFC_RB_IRQ_EN		BIT(21)
+#define NFC_CMD_FIFO_RESET	BIT(31)
 
 #define CMDRWGEN(cmd_dir, ran, bch, short_mode, page_size, pages)	\
 	(								\
@@ -104,6 +106,9 @@
 
 #define PER_INFO_BYTE		8
 
+#define CLK_DIV_SHIFT		0
+#define CLK_DIV_WIDTH		6
+
 struct meson_nfc_nand_chip {
 	struct list_head node;
 	struct nand_chip nand;
@@ -151,15 +156,15 @@ struct meson_nfc {
 	struct nand_controller controller;
 	struct clk *core_clk;
 	struct clk *device_clk;
-	struct clk *phase_tx;
-	struct clk *phase_rx;
+	struct clk *nand_clk;
+	struct clk_divider nand_divider;
 
 	unsigned long clk_rate;
 	u32 bus_timing;
 
 	struct device *dev;
 	void __iomem *reg_base;
-	struct regmap *reg_clk;
+	void __iomem *reg_clk;
 	struct completion completion;
 	struct list_head chips;
 	const struct meson_nfc_data *data;
@@ -406,12 +411,14 @@ static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms)
 	cmd = NFC_CMD_RB | NFC_CMD_RB_INT
 		| nfc->param.chip_select | nfc->timing.tbers_max;
 	writel(cmd, nfc->reg_base + NFC_REG_CMD);
-
+	meson_nfc_drain_cmd(nfc);
 	ret = wait_for_completion_timeout(&nfc->completion,
 					  msecs_to_jiffies(timeout_ms));
 	if (ret == 0)
 		ret = -1;
 
+	/* reset command fifo to avoid lock */
+	writel(NFC_CMD_FIFO_RESET, nfc->reg_base + NFC_REG_CMD);
 	return ret;
 }
 
@@ -988,8 +995,9 @@ static const struct mtd_ooblayout_ops meson_ooblayout_ops = {
 static int meson_nfc_clk_init(struct meson_nfc *nfc)
 {
 	int ret;
+	struct clk_init_data init = {0};
+	const char *fix_div2_pll_name[1];
 
-	/* request core clock */
 	nfc->core_clk = devm_clk_get(nfc->dev, "core");
 	if (IS_ERR(nfc->core_clk)) {
 		dev_err(nfc->dev, "failed to get core clock\n");
@@ -1002,21 +1010,25 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
 		return PTR_ERR(nfc->device_clk);
 	}
 
-	nfc->phase_tx = devm_clk_get(nfc->dev, "tx");
-	if (IS_ERR(nfc->phase_tx)) {
-		dev_err(nfc->dev, "failed to get TX clk\n");
-		return PTR_ERR(nfc->phase_tx);
-	}
-
-	nfc->phase_rx = devm_clk_get(nfc->dev, "rx");
-	if (IS_ERR(nfc->phase_rx)) {
-		dev_err(nfc->dev, "failed to get RX clk\n");
-		return PTR_ERR(nfc->phase_rx);
-	}
+	init.name = devm_kstrdup(nfc->dev, "nfc#div", GFP_KERNEL);
+	init.ops = &clk_divider_ops;
+	fix_div2_pll_name[0] = __clk_get_name(nfc->device_clk);
+	init.parent_names = fix_div2_pll_name;
+	init.num_parents = 1;
+	nfc->nand_divider.reg = nfc->reg_clk;
+	nfc->nand_divider.shift = CLK_DIV_SHIFT;
+	nfc->nand_divider.width = CLK_DIV_WIDTH;
+	nfc->nand_divider.hw.init = &init;
+	nfc->nand_divider.flags = CLK_DIVIDER_ONE_BASED |
+				  CLK_DIVIDER_ROUND_CLOSEST |
+          			  CLK_DIVIDER_ALLOW_ZERO;
+
+	nfc->nand_clk = devm_clk_register(nfc->dev, &nfc->nand_divider.hw);
+	if (IS_ERR(nfc->nand_clk))
+		return PTR_ERR(nfc->nand_clk);
 
 	/* init SD_EMMC_CLOCK to sane defaults w/min clock rate */
-	regmap_update_bits(nfc->reg_clk,
-			   0, CLK_SELECT_NAND, CLK_SELECT_NAND);
+	writel(CLK_SELECT_NAND | readl(nfc->reg_clk), nfc->reg_clk);
 
 	ret = clk_prepare_enable(nfc->core_clk);
 	if (ret) {
@@ -1030,29 +1042,21 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
 		goto err_device_clk;
 	}
 
-	ret = clk_prepare_enable(nfc->phase_tx);
+	ret = clk_prepare_enable(nfc->nand_clk);
 	if (ret) {
-		dev_err(nfc->dev, "failed to enable TX clock\n");
-		goto err_phase_tx;
-	}
-
-	ret = clk_prepare_enable(nfc->phase_rx);
-	if (ret) {
-		dev_err(nfc->dev, "failed to enable RX clock\n");
-		goto err_phase_rx;
+		dev_err(nfc->dev, "pre enable NFC divider fail\n");
+		goto err_nand_clk;
 	}
 
 	ret = clk_set_rate(nfc->device_clk, 24000000);
 	if (ret)
-		goto err_disable_rx;
+		goto err_disable_clk;
 
 	return 0;
 
-err_disable_rx:
-	clk_disable_unprepare(nfc->phase_rx);
-err_phase_rx:
-	clk_disable_unprepare(nfc->phase_tx);
-err_phase_tx:
+err_disable_clk:
+	clk_disable_unprepare(nfc->nand_clk);
+err_nand_clk:
 	clk_disable_unprepare(nfc->device_clk);
 err_device_clk:
 	clk_disable_unprepare(nfc->core_clk);
@@ -1061,8 +1065,7 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
 
 static void meson_nfc_disable_clk(struct meson_nfc *nfc)
 {
-	clk_disable_unprepare(nfc->phase_rx);
-	clk_disable_unprepare(nfc->phase_tx);
+	clk_disable_unprepare(nfc->nand_clk);
 	clk_disable_unprepare(nfc->device_clk);
 	clk_disable_unprepare(nfc->core_clk);
 }
@@ -1375,6 +1378,7 @@ static int meson_nfc_probe(struct platform_device *pdev)
 	struct device *dev = &pdev->dev;
 	struct meson_nfc *nfc;
 	struct resource *res;
+	u32 ext_clk_reg;
 	int ret, irq;
 
 	nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL);
@@ -1396,9 +1400,15 @@ static int meson_nfc_probe(struct platform_device *pdev)
 	if (IS_ERR(nfc->reg_base))
 		return PTR_ERR(nfc->reg_base);
 
-	nfc->reg_clk =
-		syscon_regmap_lookup_by_phandle(dev->of_node,
-						"amlogic,mmc-syscon");
+	ret = of_property_read_u32(pdev->dev.of_node,
+				   "sd_emmc_c_clkc",
+				   &ext_clk_reg);
+	if (ret) {
+		dev_err(dev, "failed to get NAND external clock register\n");
+		return ret;
+	}
+
+	nfc->reg_clk = devm_ioremap(&pdev->dev, ext_clk_reg, sizeof(int));
 	if (IS_ERR(nfc->reg_clk)) {
 		dev_err(dev, "Failed to lookup clock base\n");
 		return PTR_ERR(nfc->reg_clk);
-- 
2.34.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* [PATCH] mtd: rawnand: meson: fix the clock after discarding sd_emmc_c_clkc
@ 2022-01-06  3:25 ` Liang Yang
  0 siblings, 0 replies; 47+ messages in thread
From: Liang Yang @ 2022-01-06  3:25 UTC (permalink / raw)
  To: Miquel Raynal, linux-mtd
  Cc: Liang Yang, Richard Weinberger, Jerome Brunet, Neil Armstrong,
	Martin Blumenstingl, Kevin Hilman, Jianxin Pan, Victor Wan,
	XianWei Zhao, Kelvin Zhang, BiChao Zheng, YongHui Yu,
	linux-arm-kernel, linux-amlogic, linux-kernel, devicetree

Because EMMC and NAND have the same control clock register, so we
implement a 'sd_emmc_c_clkc'. Previously DTS is defined as below:

	sd_emmc_c_clkc: mmc@7000 {
		compatible = "amlogic,meson-axg-mmc-clkc", "syscon";
		reg = <0x0 0x7000 0x0 0x800>;
	};

	nand-controller@7800 {
		......

		clocks = <&clkc CLKID_SD_EMMC_C>,
			<&sd_emmc_c_clkc CLKID_MMC_DIV>,
			<&sd_emmc_c_clkc CLKID_MMC_PHASE_RX>,
			<&sd_emmc_c_clkc CLKID_MMC_PHASE_TX>;
		clock-names = "core", "device", "rx", "tx";
		amlogic,mmc-syscon = <&sd_emmc_c_clkc>;

		......
	}

but in fact, above implementation is rejected. so now registering
a nand_divider.

Change-Id: Ibeb4c7ff886f5886aac4d6c664d7bbd1b1bcb997
Signed-off-by: Liang Yang <liang.yang@amlogic.com>
---
 drivers/mtd/nand/raw/meson_nand.c | 88 +++++++++++++++++--------------
 1 file changed, 49 insertions(+), 39 deletions(-)

diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c
index ac3be92872d0..4472363059c2 100644
--- a/drivers/mtd/nand/raw/meson_nand.c
+++ b/drivers/mtd/nand/raw/meson_nand.c
@@ -2,7 +2,7 @@
 /*
  * Amlogic Meson Nand Flash Controller Driver
  *
- * Copyright (c) 2018 Amlogic, inc.
+ * Copyright (c) 2018-2021 Amlogic, inc.
  * Author: Liang Yang <liang.yang@amlogic.com>
  */
 
@@ -10,6 +10,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/interrupt.h>
 #include <linux/clk.h>
+#include <linux/clk-provider.h>
 #include <linux/mtd/rawnand.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mfd/syscon.h>
@@ -55,6 +56,7 @@
 #define NFC_REG_VER		0x38
 
 #define NFC_RB_IRQ_EN		BIT(21)
+#define NFC_CMD_FIFO_RESET	BIT(31)
 
 #define CMDRWGEN(cmd_dir, ran, bch, short_mode, page_size, pages)	\
 	(								\
@@ -104,6 +106,9 @@
 
 #define PER_INFO_BYTE		8
 
+#define CLK_DIV_SHIFT		0
+#define CLK_DIV_WIDTH		6
+
 struct meson_nfc_nand_chip {
 	struct list_head node;
 	struct nand_chip nand;
@@ -151,15 +156,15 @@ struct meson_nfc {
 	struct nand_controller controller;
 	struct clk *core_clk;
 	struct clk *device_clk;
-	struct clk *phase_tx;
-	struct clk *phase_rx;
+	struct clk *nand_clk;
+	struct clk_divider nand_divider;
 
 	unsigned long clk_rate;
 	u32 bus_timing;
 
 	struct device *dev;
 	void __iomem *reg_base;
-	struct regmap *reg_clk;
+	void __iomem *reg_clk;
 	struct completion completion;
 	struct list_head chips;
 	const struct meson_nfc_data *data;
@@ -406,12 +411,14 @@ static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms)
 	cmd = NFC_CMD_RB | NFC_CMD_RB_INT
 		| nfc->param.chip_select | nfc->timing.tbers_max;
 	writel(cmd, nfc->reg_base + NFC_REG_CMD);
-
+	meson_nfc_drain_cmd(nfc);
 	ret = wait_for_completion_timeout(&nfc->completion,
 					  msecs_to_jiffies(timeout_ms));
 	if (ret == 0)
 		ret = -1;
 
+	/* reset command fifo to avoid lock */
+	writel(NFC_CMD_FIFO_RESET, nfc->reg_base + NFC_REG_CMD);
 	return ret;
 }
 
@@ -988,8 +995,9 @@ static const struct mtd_ooblayout_ops meson_ooblayout_ops = {
 static int meson_nfc_clk_init(struct meson_nfc *nfc)
 {
 	int ret;
+	struct clk_init_data init = {0};
+	const char *fix_div2_pll_name[1];
 
-	/* request core clock */
 	nfc->core_clk = devm_clk_get(nfc->dev, "core");
 	if (IS_ERR(nfc->core_clk)) {
 		dev_err(nfc->dev, "failed to get core clock\n");
@@ -1002,21 +1010,25 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
 		return PTR_ERR(nfc->device_clk);
 	}
 
-	nfc->phase_tx = devm_clk_get(nfc->dev, "tx");
-	if (IS_ERR(nfc->phase_tx)) {
-		dev_err(nfc->dev, "failed to get TX clk\n");
-		return PTR_ERR(nfc->phase_tx);
-	}
-
-	nfc->phase_rx = devm_clk_get(nfc->dev, "rx");
-	if (IS_ERR(nfc->phase_rx)) {
-		dev_err(nfc->dev, "failed to get RX clk\n");
-		return PTR_ERR(nfc->phase_rx);
-	}
+	init.name = devm_kstrdup(nfc->dev, "nfc#div", GFP_KERNEL);
+	init.ops = &clk_divider_ops;
+	fix_div2_pll_name[0] = __clk_get_name(nfc->device_clk);
+	init.parent_names = fix_div2_pll_name;
+	init.num_parents = 1;
+	nfc->nand_divider.reg = nfc->reg_clk;
+	nfc->nand_divider.shift = CLK_DIV_SHIFT;
+	nfc->nand_divider.width = CLK_DIV_WIDTH;
+	nfc->nand_divider.hw.init = &init;
+	nfc->nand_divider.flags = CLK_DIVIDER_ONE_BASED |
+				  CLK_DIVIDER_ROUND_CLOSEST |
+          			  CLK_DIVIDER_ALLOW_ZERO;
+
+	nfc->nand_clk = devm_clk_register(nfc->dev, &nfc->nand_divider.hw);
+	if (IS_ERR(nfc->nand_clk))
+		return PTR_ERR(nfc->nand_clk);
 
 	/* init SD_EMMC_CLOCK to sane defaults w/min clock rate */
-	regmap_update_bits(nfc->reg_clk,
-			   0, CLK_SELECT_NAND, CLK_SELECT_NAND);
+	writel(CLK_SELECT_NAND | readl(nfc->reg_clk), nfc->reg_clk);
 
 	ret = clk_prepare_enable(nfc->core_clk);
 	if (ret) {
@@ -1030,29 +1042,21 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
 		goto err_device_clk;
 	}
 
-	ret = clk_prepare_enable(nfc->phase_tx);
+	ret = clk_prepare_enable(nfc->nand_clk);
 	if (ret) {
-		dev_err(nfc->dev, "failed to enable TX clock\n");
-		goto err_phase_tx;
-	}
-
-	ret = clk_prepare_enable(nfc->phase_rx);
-	if (ret) {
-		dev_err(nfc->dev, "failed to enable RX clock\n");
-		goto err_phase_rx;
+		dev_err(nfc->dev, "pre enable NFC divider fail\n");
+		goto err_nand_clk;
 	}
 
 	ret = clk_set_rate(nfc->device_clk, 24000000);
 	if (ret)
-		goto err_disable_rx;
+		goto err_disable_clk;
 
 	return 0;
 
-err_disable_rx:
-	clk_disable_unprepare(nfc->phase_rx);
-err_phase_rx:
-	clk_disable_unprepare(nfc->phase_tx);
-err_phase_tx:
+err_disable_clk:
+	clk_disable_unprepare(nfc->nand_clk);
+err_nand_clk:
 	clk_disable_unprepare(nfc->device_clk);
 err_device_clk:
 	clk_disable_unprepare(nfc->core_clk);
@@ -1061,8 +1065,7 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
 
 static void meson_nfc_disable_clk(struct meson_nfc *nfc)
 {
-	clk_disable_unprepare(nfc->phase_rx);
-	clk_disable_unprepare(nfc->phase_tx);
+	clk_disable_unprepare(nfc->nand_clk);
 	clk_disable_unprepare(nfc->device_clk);
 	clk_disable_unprepare(nfc->core_clk);
 }
@@ -1375,6 +1378,7 @@ static int meson_nfc_probe(struct platform_device *pdev)
 	struct device *dev = &pdev->dev;
 	struct meson_nfc *nfc;
 	struct resource *res;
+	u32 ext_clk_reg;
 	int ret, irq;
 
 	nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL);
@@ -1396,9 +1400,15 @@ static int meson_nfc_probe(struct platform_device *pdev)
 	if (IS_ERR(nfc->reg_base))
 		return PTR_ERR(nfc->reg_base);
 
-	nfc->reg_clk =
-		syscon_regmap_lookup_by_phandle(dev->of_node,
-						"amlogic,mmc-syscon");
+	ret = of_property_read_u32(pdev->dev.of_node,
+				   "sd_emmc_c_clkc",
+				   &ext_clk_reg);
+	if (ret) {
+		dev_err(dev, "failed to get NAND external clock register\n");
+		return ret;
+	}
+
+	nfc->reg_clk = devm_ioremap(&pdev->dev, ext_clk_reg, sizeof(int));
 	if (IS_ERR(nfc->reg_clk)) {
 		dev_err(dev, "Failed to lookup clock base\n");
 		return PTR_ERR(nfc->reg_clk);
-- 
2.34.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH] mtd: rawnand: meson: fix the clock after discarding sd_emmc_c_clkc
@ 2022-01-06  3:25 ` Liang Yang
  0 siblings, 0 replies; 47+ messages in thread
From: Liang Yang @ 2022-01-06  3:25 UTC (permalink / raw)
  To: Miquel Raynal, linux-mtd
  Cc: Liang Yang, Richard Weinberger, Jerome Brunet, Neil Armstrong,
	Martin Blumenstingl, Kevin Hilman, Jianxin Pan, Victor Wan,
	XianWei Zhao, Kelvin Zhang, BiChao Zheng, YongHui Yu,
	linux-arm-kernel, linux-amlogic, linux-kernel, devicetree

Because EMMC and NAND have the same control clock register, so we
implement a 'sd_emmc_c_clkc'. Previously DTS is defined as below:

	sd_emmc_c_clkc: mmc@7000 {
		compatible = "amlogic,meson-axg-mmc-clkc", "syscon";
		reg = <0x0 0x7000 0x0 0x800>;
	};

	nand-controller@7800 {
		......

		clocks = <&clkc CLKID_SD_EMMC_C>,
			<&sd_emmc_c_clkc CLKID_MMC_DIV>,
			<&sd_emmc_c_clkc CLKID_MMC_PHASE_RX>,
			<&sd_emmc_c_clkc CLKID_MMC_PHASE_TX>;
		clock-names = "core", "device", "rx", "tx";
		amlogic,mmc-syscon = <&sd_emmc_c_clkc>;

		......
	}

but in fact, above implementation is rejected. so now registering
a nand_divider.

Change-Id: Ibeb4c7ff886f5886aac4d6c664d7bbd1b1bcb997
Signed-off-by: Liang Yang <liang.yang@amlogic.com>
---
 drivers/mtd/nand/raw/meson_nand.c | 88 +++++++++++++++++--------------
 1 file changed, 49 insertions(+), 39 deletions(-)

diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c
index ac3be92872d0..4472363059c2 100644
--- a/drivers/mtd/nand/raw/meson_nand.c
+++ b/drivers/mtd/nand/raw/meson_nand.c
@@ -2,7 +2,7 @@
 /*
  * Amlogic Meson Nand Flash Controller Driver
  *
- * Copyright (c) 2018 Amlogic, inc.
+ * Copyright (c) 2018-2021 Amlogic, inc.
  * Author: Liang Yang <liang.yang@amlogic.com>
  */
 
@@ -10,6 +10,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/interrupt.h>
 #include <linux/clk.h>
+#include <linux/clk-provider.h>
 #include <linux/mtd/rawnand.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mfd/syscon.h>
@@ -55,6 +56,7 @@
 #define NFC_REG_VER		0x38
 
 #define NFC_RB_IRQ_EN		BIT(21)
+#define NFC_CMD_FIFO_RESET	BIT(31)
 
 #define CMDRWGEN(cmd_dir, ran, bch, short_mode, page_size, pages)	\
 	(								\
@@ -104,6 +106,9 @@
 
 #define PER_INFO_BYTE		8
 
+#define CLK_DIV_SHIFT		0
+#define CLK_DIV_WIDTH		6
+
 struct meson_nfc_nand_chip {
 	struct list_head node;
 	struct nand_chip nand;
@@ -151,15 +156,15 @@ struct meson_nfc {
 	struct nand_controller controller;
 	struct clk *core_clk;
 	struct clk *device_clk;
-	struct clk *phase_tx;
-	struct clk *phase_rx;
+	struct clk *nand_clk;
+	struct clk_divider nand_divider;
 
 	unsigned long clk_rate;
 	u32 bus_timing;
 
 	struct device *dev;
 	void __iomem *reg_base;
-	struct regmap *reg_clk;
+	void __iomem *reg_clk;
 	struct completion completion;
 	struct list_head chips;
 	const struct meson_nfc_data *data;
@@ -406,12 +411,14 @@ static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms)
 	cmd = NFC_CMD_RB | NFC_CMD_RB_INT
 		| nfc->param.chip_select | nfc->timing.tbers_max;
 	writel(cmd, nfc->reg_base + NFC_REG_CMD);
-
+	meson_nfc_drain_cmd(nfc);
 	ret = wait_for_completion_timeout(&nfc->completion,
 					  msecs_to_jiffies(timeout_ms));
 	if (ret == 0)
 		ret = -1;
 
+	/* reset command fifo to avoid lock */
+	writel(NFC_CMD_FIFO_RESET, nfc->reg_base + NFC_REG_CMD);
 	return ret;
 }
 
@@ -988,8 +995,9 @@ static const struct mtd_ooblayout_ops meson_ooblayout_ops = {
 static int meson_nfc_clk_init(struct meson_nfc *nfc)
 {
 	int ret;
+	struct clk_init_data init = {0};
+	const char *fix_div2_pll_name[1];
 
-	/* request core clock */
 	nfc->core_clk = devm_clk_get(nfc->dev, "core");
 	if (IS_ERR(nfc->core_clk)) {
 		dev_err(nfc->dev, "failed to get core clock\n");
@@ -1002,21 +1010,25 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
 		return PTR_ERR(nfc->device_clk);
 	}
 
-	nfc->phase_tx = devm_clk_get(nfc->dev, "tx");
-	if (IS_ERR(nfc->phase_tx)) {
-		dev_err(nfc->dev, "failed to get TX clk\n");
-		return PTR_ERR(nfc->phase_tx);
-	}
-
-	nfc->phase_rx = devm_clk_get(nfc->dev, "rx");
-	if (IS_ERR(nfc->phase_rx)) {
-		dev_err(nfc->dev, "failed to get RX clk\n");
-		return PTR_ERR(nfc->phase_rx);
-	}
+	init.name = devm_kstrdup(nfc->dev, "nfc#div", GFP_KERNEL);
+	init.ops = &clk_divider_ops;
+	fix_div2_pll_name[0] = __clk_get_name(nfc->device_clk);
+	init.parent_names = fix_div2_pll_name;
+	init.num_parents = 1;
+	nfc->nand_divider.reg = nfc->reg_clk;
+	nfc->nand_divider.shift = CLK_DIV_SHIFT;
+	nfc->nand_divider.width = CLK_DIV_WIDTH;
+	nfc->nand_divider.hw.init = &init;
+	nfc->nand_divider.flags = CLK_DIVIDER_ONE_BASED |
+				  CLK_DIVIDER_ROUND_CLOSEST |
+          			  CLK_DIVIDER_ALLOW_ZERO;
+
+	nfc->nand_clk = devm_clk_register(nfc->dev, &nfc->nand_divider.hw);
+	if (IS_ERR(nfc->nand_clk))
+		return PTR_ERR(nfc->nand_clk);
 
 	/* init SD_EMMC_CLOCK to sane defaults w/min clock rate */
-	regmap_update_bits(nfc->reg_clk,
-			   0, CLK_SELECT_NAND, CLK_SELECT_NAND);
+	writel(CLK_SELECT_NAND | readl(nfc->reg_clk), nfc->reg_clk);
 
 	ret = clk_prepare_enable(nfc->core_clk);
 	if (ret) {
@@ -1030,29 +1042,21 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
 		goto err_device_clk;
 	}
 
-	ret = clk_prepare_enable(nfc->phase_tx);
+	ret = clk_prepare_enable(nfc->nand_clk);
 	if (ret) {
-		dev_err(nfc->dev, "failed to enable TX clock\n");
-		goto err_phase_tx;
-	}
-
-	ret = clk_prepare_enable(nfc->phase_rx);
-	if (ret) {
-		dev_err(nfc->dev, "failed to enable RX clock\n");
-		goto err_phase_rx;
+		dev_err(nfc->dev, "pre enable NFC divider fail\n");
+		goto err_nand_clk;
 	}
 
 	ret = clk_set_rate(nfc->device_clk, 24000000);
 	if (ret)
-		goto err_disable_rx;
+		goto err_disable_clk;
 
 	return 0;
 
-err_disable_rx:
-	clk_disable_unprepare(nfc->phase_rx);
-err_phase_rx:
-	clk_disable_unprepare(nfc->phase_tx);
-err_phase_tx:
+err_disable_clk:
+	clk_disable_unprepare(nfc->nand_clk);
+err_nand_clk:
 	clk_disable_unprepare(nfc->device_clk);
 err_device_clk:
 	clk_disable_unprepare(nfc->core_clk);
@@ -1061,8 +1065,7 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
 
 static void meson_nfc_disable_clk(struct meson_nfc *nfc)
 {
-	clk_disable_unprepare(nfc->phase_rx);
-	clk_disable_unprepare(nfc->phase_tx);
+	clk_disable_unprepare(nfc->nand_clk);
 	clk_disable_unprepare(nfc->device_clk);
 	clk_disable_unprepare(nfc->core_clk);
 }
@@ -1375,6 +1378,7 @@ static int meson_nfc_probe(struct platform_device *pdev)
 	struct device *dev = &pdev->dev;
 	struct meson_nfc *nfc;
 	struct resource *res;
+	u32 ext_clk_reg;
 	int ret, irq;
 
 	nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL);
@@ -1396,9 +1400,15 @@ static int meson_nfc_probe(struct platform_device *pdev)
 	if (IS_ERR(nfc->reg_base))
 		return PTR_ERR(nfc->reg_base);
 
-	nfc->reg_clk =
-		syscon_regmap_lookup_by_phandle(dev->of_node,
-						"amlogic,mmc-syscon");
+	ret = of_property_read_u32(pdev->dev.of_node,
+				   "sd_emmc_c_clkc",
+				   &ext_clk_reg);
+	if (ret) {
+		dev_err(dev, "failed to get NAND external clock register\n");
+		return ret;
+	}
+
+	nfc->reg_clk = devm_ioremap(&pdev->dev, ext_clk_reg, sizeof(int));
 	if (IS_ERR(nfc->reg_clk)) {
 		dev_err(dev, "Failed to lookup clock base\n");
 		return PTR_ERR(nfc->reg_clk);
-- 
2.34.1


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

* Re: [PATCH] mtd: rawnand: meson: fix the clock after discarding sd_emmc_c_clkc
  2022-01-06  3:25 ` Liang Yang
  (?)
  (?)
@ 2022-01-06  8:08   ` Miquel Raynal
  -1 siblings, 0 replies; 47+ messages in thread
From: Miquel Raynal @ 2022-01-06  8:08 UTC (permalink / raw)
  To: Liang Yang
  Cc: linux-mtd, Richard Weinberger, Jerome Brunet, Neil Armstrong,
	Martin Blumenstingl, Kevin Hilman, Jianxin Pan, Victor Wan,
	XianWei Zhao, Kelvin Zhang, BiChao Zheng, YongHui Yu,
	linux-arm-kernel, linux-amlogic, linux-kernel, devicetree

Hi Liang,

liang.yang@amlogic.com wrote on Thu, 6 Jan 2022 11:25:04 +0800:

> Because EMMC and NAND have the same control clock register, so we
> implement a 'sd_emmc_c_clkc'. Previously DTS is defined as below:
> 
> 	sd_emmc_c_clkc: mmc@7000 {
> 		compatible = "amlogic,meson-axg-mmc-clkc", "syscon";
> 		reg = <0x0 0x7000 0x0 0x800>;
> 	};
> 
> 	nand-controller@7800 {
> 		......
> 
> 		clocks = <&clkc CLKID_SD_EMMC_C>,
> 			<&sd_emmc_c_clkc CLKID_MMC_DIV>,
> 			<&sd_emmc_c_clkc CLKID_MMC_PHASE_RX>,
> 			<&sd_emmc_c_clkc CLKID_MMC_PHASE_TX>;
> 		clock-names = "core", "device", "rx", "tx";
> 		amlogic,mmc-syscon = <&sd_emmc_c_clkc>;
> 
> 		......
> 	}
> 
> but in fact, above implementation is rejected. so now registering
> a nand_divider.

What is rejected?
Why is it rejected?
What is nand_divider?


> 
> Change-Id: Ibeb4c7ff886f5886aac4d6c664d7bbd1b1bcb997

Change Ids are not expected in the upstream kernel.

But if you fix something you should have a Fixes:.

> Signed-off-by: Liang Yang <liang.yang@amlogic.com>
> ---
>  drivers/mtd/nand/raw/meson_nand.c | 88 +++++++++++++++++--------------
>  1 file changed, 49 insertions(+), 39 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c
> index ac3be92872d0..4472363059c2 100644
> --- a/drivers/mtd/nand/raw/meson_nand.c
> +++ b/drivers/mtd/nand/raw/meson_nand.c
> @@ -2,7 +2,7 @@
>  /*
>   * Amlogic Meson Nand Flash Controller Driver
>   *
> - * Copyright (c) 2018 Amlogic, inc.
> + * Copyright (c) 2018-2021 Amlogic, inc.
>   * Author: Liang Yang <liang.yang@amlogic.com>
>   */
>  
> @@ -10,6 +10,7 @@
>  #include <linux/dma-mapping.h>
>  #include <linux/interrupt.h>
>  #include <linux/clk.h>
> +#include <linux/clk-provider.h>
>  #include <linux/mtd/rawnand.h>
>  #include <linux/mtd/mtd.h>
>  #include <linux/mfd/syscon.h>
> @@ -55,6 +56,7 @@
>  #define NFC_REG_VER		0x38
>  
>  #define NFC_RB_IRQ_EN		BIT(21)
> +#define NFC_CMD_FIFO_RESET	BIT(31)
>  
>  #define CMDRWGEN(cmd_dir, ran, bch, short_mode, page_size, pages)	\
>  	(								\
> @@ -104,6 +106,9 @@
>  
>  #define PER_INFO_BYTE		8
>  
> +#define CLK_DIV_SHIFT		0
> +#define CLK_DIV_WIDTH		6
> +
>  struct meson_nfc_nand_chip {
>  	struct list_head node;
>  	struct nand_chip nand;
> @@ -151,15 +156,15 @@ struct meson_nfc {
>  	struct nand_controller controller;
>  	struct clk *core_clk;
>  	struct clk *device_clk;
> -	struct clk *phase_tx;
> -	struct clk *phase_rx;
> +	struct clk *nand_clk;
> +	struct clk_divider nand_divider;
>  
>  	unsigned long clk_rate;
>  	u32 bus_timing;
>  
>  	struct device *dev;
>  	void __iomem *reg_base;
> -	struct regmap *reg_clk;
> +	void __iomem *reg_clk;
>  	struct completion completion;
>  	struct list_head chips;
>  	const struct meson_nfc_data *data;
> @@ -406,12 +411,14 @@ static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms)
>  	cmd = NFC_CMD_RB | NFC_CMD_RB_INT
>  		| nfc->param.chip_select | nfc->timing.tbers_max;
>  	writel(cmd, nfc->reg_base + NFC_REG_CMD);
> -
> +	meson_nfc_drain_cmd(nfc);
>  	ret = wait_for_completion_timeout(&nfc->completion,
>  					  msecs_to_jiffies(timeout_ms));
>  	if (ret == 0)
>  		ret = -1;
>  
> +	/* reset command fifo to avoid lock */
> +	writel(NFC_CMD_FIFO_RESET, nfc->reg_base + NFC_REG_CMD);
>  	return ret;
>  }
>  
> @@ -988,8 +995,9 @@ static const struct mtd_ooblayout_ops meson_ooblayout_ops = {
>  static int meson_nfc_clk_init(struct meson_nfc *nfc)
>  {
>  	int ret;
> +	struct clk_init_data init = {0};
> +	const char *fix_div2_pll_name[1];
>  
> -	/* request core clock */
>  	nfc->core_clk = devm_clk_get(nfc->dev, "core");
>  	if (IS_ERR(nfc->core_clk)) {
>  		dev_err(nfc->dev, "failed to get core clock\n");
> @@ -1002,21 +1010,25 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>  		return PTR_ERR(nfc->device_clk);
>  	}
>  
> -	nfc->phase_tx = devm_clk_get(nfc->dev, "tx");
> -	if (IS_ERR(nfc->phase_tx)) {
> -		dev_err(nfc->dev, "failed to get TX clk\n");
> -		return PTR_ERR(nfc->phase_tx);
> -	}
> -
> -	nfc->phase_rx = devm_clk_get(nfc->dev, "rx");
> -	if (IS_ERR(nfc->phase_rx)) {
> -		dev_err(nfc->dev, "failed to get RX clk\n");
> -		return PTR_ERR(nfc->phase_rx);
> -	}
> +	init.name = devm_kstrdup(nfc->dev, "nfc#div", GFP_KERNEL);
> +	init.ops = &clk_divider_ops;
> +	fix_div2_pll_name[0] = __clk_get_name(nfc->device_clk);
> +	init.parent_names = fix_div2_pll_name;
> +	init.num_parents = 1;
> +	nfc->nand_divider.reg = nfc->reg_clk;
> +	nfc->nand_divider.shift = CLK_DIV_SHIFT;
> +	nfc->nand_divider.width = CLK_DIV_WIDTH;
> +	nfc->nand_divider.hw.init = &init;
> +	nfc->nand_divider.flags = CLK_DIVIDER_ONE_BASED |
> +				  CLK_DIVIDER_ROUND_CLOSEST |
> +          			  CLK_DIVIDER_ALLOW_ZERO;
> +
> +	nfc->nand_clk = devm_clk_register(nfc->dev, &nfc->nand_divider.hw);
> +	if (IS_ERR(nfc->nand_clk))
> +		return PTR_ERR(nfc->nand_clk);
>  
>  	/* init SD_EMMC_CLOCK to sane defaults w/min clock rate */
> -	regmap_update_bits(nfc->reg_clk,
> -			   0, CLK_SELECT_NAND, CLK_SELECT_NAND);
> +	writel(CLK_SELECT_NAND | readl(nfc->reg_clk), nfc->reg_clk);
>  
>  	ret = clk_prepare_enable(nfc->core_clk);
>  	if (ret) {
> @@ -1030,29 +1042,21 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>  		goto err_device_clk;
>  	}
>  
> -	ret = clk_prepare_enable(nfc->phase_tx);
> +	ret = clk_prepare_enable(nfc->nand_clk);
>  	if (ret) {
> -		dev_err(nfc->dev, "failed to enable TX clock\n");
> -		goto err_phase_tx;
> -	}
> -
> -	ret = clk_prepare_enable(nfc->phase_rx);
> -	if (ret) {
> -		dev_err(nfc->dev, "failed to enable RX clock\n");
> -		goto err_phase_rx;
> +		dev_err(nfc->dev, "pre enable NFC divider fail\n");
> +		goto err_nand_clk;
>  	}
>  
>  	ret = clk_set_rate(nfc->device_clk, 24000000);
>  	if (ret)
> -		goto err_disable_rx;
> +		goto err_disable_clk;
>  
>  	return 0;
>  
> -err_disable_rx:
> -	clk_disable_unprepare(nfc->phase_rx);
> -err_phase_rx:
> -	clk_disable_unprepare(nfc->phase_tx);
> -err_phase_tx:
> +err_disable_clk:
> +	clk_disable_unprepare(nfc->nand_clk);
> +err_nand_clk:
>  	clk_disable_unprepare(nfc->device_clk);
>  err_device_clk:
>  	clk_disable_unprepare(nfc->core_clk);
> @@ -1061,8 +1065,7 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>  
>  static void meson_nfc_disable_clk(struct meson_nfc *nfc)
>  {
> -	clk_disable_unprepare(nfc->phase_rx);
> -	clk_disable_unprepare(nfc->phase_tx);
> +	clk_disable_unprepare(nfc->nand_clk);
>  	clk_disable_unprepare(nfc->device_clk);
>  	clk_disable_unprepare(nfc->core_clk);
>  }
> @@ -1375,6 +1378,7 @@ static int meson_nfc_probe(struct platform_device *pdev)
>  	struct device *dev = &pdev->dev;
>  	struct meson_nfc *nfc;
>  	struct resource *res;
> +	u32 ext_clk_reg;
>  	int ret, irq;
>  
>  	nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL);
> @@ -1396,9 +1400,15 @@ static int meson_nfc_probe(struct platform_device *pdev)
>  	if (IS_ERR(nfc->reg_base))
>  		return PTR_ERR(nfc->reg_base);
>  
> -	nfc->reg_clk =
> -		syscon_regmap_lookup_by_phandle(dev->of_node,
> -						"amlogic,mmc-syscon");
> +	ret = of_property_read_u32(pdev->dev.of_node,
> +				   "sd_emmc_c_clkc",
> +				   &ext_clk_reg);
> +	if (ret) {
> +		dev_err(dev, "failed to get NAND external clock register\n");
> +		return ret;
> +	}
> +
> +	nfc->reg_clk = devm_ioremap(&pdev->dev, ext_clk_reg, sizeof(int));
>  	if (IS_ERR(nfc->reg_clk)) {
>  		dev_err(dev, "Failed to lookup clock base\n");
>  		return PTR_ERR(nfc->reg_clk);


Thanks,
Miquèl

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

* Re: [PATCH] mtd: rawnand: meson: fix the clock after discarding sd_emmc_c_clkc
@ 2022-01-06  8:08   ` Miquel Raynal
  0 siblings, 0 replies; 47+ messages in thread
From: Miquel Raynal @ 2022-01-06  8:08 UTC (permalink / raw)
  To: Liang Yang
  Cc: linux-mtd, Richard Weinberger, Jerome Brunet, Neil Armstrong,
	Martin Blumenstingl, Kevin Hilman, Jianxin Pan, Victor Wan,
	XianWei Zhao, Kelvin Zhang, BiChao Zheng, YongHui Yu,
	linux-arm-kernel, linux-amlogic, linux-kernel, devicetree

Hi Liang,

liang.yang@amlogic.com wrote on Thu, 6 Jan 2022 11:25:04 +0800:

> Because EMMC and NAND have the same control clock register, so we
> implement a 'sd_emmc_c_clkc'. Previously DTS is defined as below:
> 
> 	sd_emmc_c_clkc: mmc@7000 {
> 		compatible = "amlogic,meson-axg-mmc-clkc", "syscon";
> 		reg = <0x0 0x7000 0x0 0x800>;
> 	};
> 
> 	nand-controller@7800 {
> 		......
> 
> 		clocks = <&clkc CLKID_SD_EMMC_C>,
> 			<&sd_emmc_c_clkc CLKID_MMC_DIV>,
> 			<&sd_emmc_c_clkc CLKID_MMC_PHASE_RX>,
> 			<&sd_emmc_c_clkc CLKID_MMC_PHASE_TX>;
> 		clock-names = "core", "device", "rx", "tx";
> 		amlogic,mmc-syscon = <&sd_emmc_c_clkc>;
> 
> 		......
> 	}
> 
> but in fact, above implementation is rejected. so now registering
> a nand_divider.

What is rejected?
Why is it rejected?
What is nand_divider?


> 
> Change-Id: Ibeb4c7ff886f5886aac4d6c664d7bbd1b1bcb997

Change Ids are not expected in the upstream kernel.

But if you fix something you should have a Fixes:.

> Signed-off-by: Liang Yang <liang.yang@amlogic.com>
> ---
>  drivers/mtd/nand/raw/meson_nand.c | 88 +++++++++++++++++--------------
>  1 file changed, 49 insertions(+), 39 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c
> index ac3be92872d0..4472363059c2 100644
> --- a/drivers/mtd/nand/raw/meson_nand.c
> +++ b/drivers/mtd/nand/raw/meson_nand.c
> @@ -2,7 +2,7 @@
>  /*
>   * Amlogic Meson Nand Flash Controller Driver
>   *
> - * Copyright (c) 2018 Amlogic, inc.
> + * Copyright (c) 2018-2021 Amlogic, inc.
>   * Author: Liang Yang <liang.yang@amlogic.com>
>   */
>  
> @@ -10,6 +10,7 @@
>  #include <linux/dma-mapping.h>
>  #include <linux/interrupt.h>
>  #include <linux/clk.h>
> +#include <linux/clk-provider.h>
>  #include <linux/mtd/rawnand.h>
>  #include <linux/mtd/mtd.h>
>  #include <linux/mfd/syscon.h>
> @@ -55,6 +56,7 @@
>  #define NFC_REG_VER		0x38
>  
>  #define NFC_RB_IRQ_EN		BIT(21)
> +#define NFC_CMD_FIFO_RESET	BIT(31)
>  
>  #define CMDRWGEN(cmd_dir, ran, bch, short_mode, page_size, pages)	\
>  	(								\
> @@ -104,6 +106,9 @@
>  
>  #define PER_INFO_BYTE		8
>  
> +#define CLK_DIV_SHIFT		0
> +#define CLK_DIV_WIDTH		6
> +
>  struct meson_nfc_nand_chip {
>  	struct list_head node;
>  	struct nand_chip nand;
> @@ -151,15 +156,15 @@ struct meson_nfc {
>  	struct nand_controller controller;
>  	struct clk *core_clk;
>  	struct clk *device_clk;
> -	struct clk *phase_tx;
> -	struct clk *phase_rx;
> +	struct clk *nand_clk;
> +	struct clk_divider nand_divider;
>  
>  	unsigned long clk_rate;
>  	u32 bus_timing;
>  
>  	struct device *dev;
>  	void __iomem *reg_base;
> -	struct regmap *reg_clk;
> +	void __iomem *reg_clk;
>  	struct completion completion;
>  	struct list_head chips;
>  	const struct meson_nfc_data *data;
> @@ -406,12 +411,14 @@ static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms)
>  	cmd = NFC_CMD_RB | NFC_CMD_RB_INT
>  		| nfc->param.chip_select | nfc->timing.tbers_max;
>  	writel(cmd, nfc->reg_base + NFC_REG_CMD);
> -
> +	meson_nfc_drain_cmd(nfc);
>  	ret = wait_for_completion_timeout(&nfc->completion,
>  					  msecs_to_jiffies(timeout_ms));
>  	if (ret == 0)
>  		ret = -1;
>  
> +	/* reset command fifo to avoid lock */
> +	writel(NFC_CMD_FIFO_RESET, nfc->reg_base + NFC_REG_CMD);
>  	return ret;
>  }
>  
> @@ -988,8 +995,9 @@ static const struct mtd_ooblayout_ops meson_ooblayout_ops = {
>  static int meson_nfc_clk_init(struct meson_nfc *nfc)
>  {
>  	int ret;
> +	struct clk_init_data init = {0};
> +	const char *fix_div2_pll_name[1];
>  
> -	/* request core clock */
>  	nfc->core_clk = devm_clk_get(nfc->dev, "core");
>  	if (IS_ERR(nfc->core_clk)) {
>  		dev_err(nfc->dev, "failed to get core clock\n");
> @@ -1002,21 +1010,25 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>  		return PTR_ERR(nfc->device_clk);
>  	}
>  
> -	nfc->phase_tx = devm_clk_get(nfc->dev, "tx");
> -	if (IS_ERR(nfc->phase_tx)) {
> -		dev_err(nfc->dev, "failed to get TX clk\n");
> -		return PTR_ERR(nfc->phase_tx);
> -	}
> -
> -	nfc->phase_rx = devm_clk_get(nfc->dev, "rx");
> -	if (IS_ERR(nfc->phase_rx)) {
> -		dev_err(nfc->dev, "failed to get RX clk\n");
> -		return PTR_ERR(nfc->phase_rx);
> -	}
> +	init.name = devm_kstrdup(nfc->dev, "nfc#div", GFP_KERNEL);
> +	init.ops = &clk_divider_ops;
> +	fix_div2_pll_name[0] = __clk_get_name(nfc->device_clk);
> +	init.parent_names = fix_div2_pll_name;
> +	init.num_parents = 1;
> +	nfc->nand_divider.reg = nfc->reg_clk;
> +	nfc->nand_divider.shift = CLK_DIV_SHIFT;
> +	nfc->nand_divider.width = CLK_DIV_WIDTH;
> +	nfc->nand_divider.hw.init = &init;
> +	nfc->nand_divider.flags = CLK_DIVIDER_ONE_BASED |
> +				  CLK_DIVIDER_ROUND_CLOSEST |
> +          			  CLK_DIVIDER_ALLOW_ZERO;
> +
> +	nfc->nand_clk = devm_clk_register(nfc->dev, &nfc->nand_divider.hw);
> +	if (IS_ERR(nfc->nand_clk))
> +		return PTR_ERR(nfc->nand_clk);
>  
>  	/* init SD_EMMC_CLOCK to sane defaults w/min clock rate */
> -	regmap_update_bits(nfc->reg_clk,
> -			   0, CLK_SELECT_NAND, CLK_SELECT_NAND);
> +	writel(CLK_SELECT_NAND | readl(nfc->reg_clk), nfc->reg_clk);
>  
>  	ret = clk_prepare_enable(nfc->core_clk);
>  	if (ret) {
> @@ -1030,29 +1042,21 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>  		goto err_device_clk;
>  	}
>  
> -	ret = clk_prepare_enable(nfc->phase_tx);
> +	ret = clk_prepare_enable(nfc->nand_clk);
>  	if (ret) {
> -		dev_err(nfc->dev, "failed to enable TX clock\n");
> -		goto err_phase_tx;
> -	}
> -
> -	ret = clk_prepare_enable(nfc->phase_rx);
> -	if (ret) {
> -		dev_err(nfc->dev, "failed to enable RX clock\n");
> -		goto err_phase_rx;
> +		dev_err(nfc->dev, "pre enable NFC divider fail\n");
> +		goto err_nand_clk;
>  	}
>  
>  	ret = clk_set_rate(nfc->device_clk, 24000000);
>  	if (ret)
> -		goto err_disable_rx;
> +		goto err_disable_clk;
>  
>  	return 0;
>  
> -err_disable_rx:
> -	clk_disable_unprepare(nfc->phase_rx);
> -err_phase_rx:
> -	clk_disable_unprepare(nfc->phase_tx);
> -err_phase_tx:
> +err_disable_clk:
> +	clk_disable_unprepare(nfc->nand_clk);
> +err_nand_clk:
>  	clk_disable_unprepare(nfc->device_clk);
>  err_device_clk:
>  	clk_disable_unprepare(nfc->core_clk);
> @@ -1061,8 +1065,7 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>  
>  static void meson_nfc_disable_clk(struct meson_nfc *nfc)
>  {
> -	clk_disable_unprepare(nfc->phase_rx);
> -	clk_disable_unprepare(nfc->phase_tx);
> +	clk_disable_unprepare(nfc->nand_clk);
>  	clk_disable_unprepare(nfc->device_clk);
>  	clk_disable_unprepare(nfc->core_clk);
>  }
> @@ -1375,6 +1378,7 @@ static int meson_nfc_probe(struct platform_device *pdev)
>  	struct device *dev = &pdev->dev;
>  	struct meson_nfc *nfc;
>  	struct resource *res;
> +	u32 ext_clk_reg;
>  	int ret, irq;
>  
>  	nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL);
> @@ -1396,9 +1400,15 @@ static int meson_nfc_probe(struct platform_device *pdev)
>  	if (IS_ERR(nfc->reg_base))
>  		return PTR_ERR(nfc->reg_base);
>  
> -	nfc->reg_clk =
> -		syscon_regmap_lookup_by_phandle(dev->of_node,
> -						"amlogic,mmc-syscon");
> +	ret = of_property_read_u32(pdev->dev.of_node,
> +				   "sd_emmc_c_clkc",
> +				   &ext_clk_reg);
> +	if (ret) {
> +		dev_err(dev, "failed to get NAND external clock register\n");
> +		return ret;
> +	}
> +
> +	nfc->reg_clk = devm_ioremap(&pdev->dev, ext_clk_reg, sizeof(int));
>  	if (IS_ERR(nfc->reg_clk)) {
>  		dev_err(dev, "Failed to lookup clock base\n");
>  		return PTR_ERR(nfc->reg_clk);


Thanks,
Miquèl

_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic

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

* Re: [PATCH] mtd: rawnand: meson: fix the clock after discarding sd_emmc_c_clkc
@ 2022-01-06  8:08   ` Miquel Raynal
  0 siblings, 0 replies; 47+ messages in thread
From: Miquel Raynal @ 2022-01-06  8:08 UTC (permalink / raw)
  To: Liang Yang
  Cc: linux-mtd, Richard Weinberger, Jerome Brunet, Neil Armstrong,
	Martin Blumenstingl, Kevin Hilman, Jianxin Pan, Victor Wan,
	XianWei Zhao, Kelvin Zhang, BiChao Zheng, YongHui Yu,
	linux-arm-kernel, linux-amlogic, linux-kernel, devicetree

Hi Liang,

liang.yang@amlogic.com wrote on Thu, 6 Jan 2022 11:25:04 +0800:

> Because EMMC and NAND have the same control clock register, so we
> implement a 'sd_emmc_c_clkc'. Previously DTS is defined as below:
> 
> 	sd_emmc_c_clkc: mmc@7000 {
> 		compatible = "amlogic,meson-axg-mmc-clkc", "syscon";
> 		reg = <0x0 0x7000 0x0 0x800>;
> 	};
> 
> 	nand-controller@7800 {
> 		......
> 
> 		clocks = <&clkc CLKID_SD_EMMC_C>,
> 			<&sd_emmc_c_clkc CLKID_MMC_DIV>,
> 			<&sd_emmc_c_clkc CLKID_MMC_PHASE_RX>,
> 			<&sd_emmc_c_clkc CLKID_MMC_PHASE_TX>;
> 		clock-names = "core", "device", "rx", "tx";
> 		amlogic,mmc-syscon = <&sd_emmc_c_clkc>;
> 
> 		......
> 	}
> 
> but in fact, above implementation is rejected. so now registering
> a nand_divider.

What is rejected?
Why is it rejected?
What is nand_divider?


> 
> Change-Id: Ibeb4c7ff886f5886aac4d6c664d7bbd1b1bcb997

Change Ids are not expected in the upstream kernel.

But if you fix something you should have a Fixes:.

> Signed-off-by: Liang Yang <liang.yang@amlogic.com>
> ---
>  drivers/mtd/nand/raw/meson_nand.c | 88 +++++++++++++++++--------------
>  1 file changed, 49 insertions(+), 39 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c
> index ac3be92872d0..4472363059c2 100644
> --- a/drivers/mtd/nand/raw/meson_nand.c
> +++ b/drivers/mtd/nand/raw/meson_nand.c
> @@ -2,7 +2,7 @@
>  /*
>   * Amlogic Meson Nand Flash Controller Driver
>   *
> - * Copyright (c) 2018 Amlogic, inc.
> + * Copyright (c) 2018-2021 Amlogic, inc.
>   * Author: Liang Yang <liang.yang@amlogic.com>
>   */
>  
> @@ -10,6 +10,7 @@
>  #include <linux/dma-mapping.h>
>  #include <linux/interrupt.h>
>  #include <linux/clk.h>
> +#include <linux/clk-provider.h>
>  #include <linux/mtd/rawnand.h>
>  #include <linux/mtd/mtd.h>
>  #include <linux/mfd/syscon.h>
> @@ -55,6 +56,7 @@
>  #define NFC_REG_VER		0x38
>  
>  #define NFC_RB_IRQ_EN		BIT(21)
> +#define NFC_CMD_FIFO_RESET	BIT(31)
>  
>  #define CMDRWGEN(cmd_dir, ran, bch, short_mode, page_size, pages)	\
>  	(								\
> @@ -104,6 +106,9 @@
>  
>  #define PER_INFO_BYTE		8
>  
> +#define CLK_DIV_SHIFT		0
> +#define CLK_DIV_WIDTH		6
> +
>  struct meson_nfc_nand_chip {
>  	struct list_head node;
>  	struct nand_chip nand;
> @@ -151,15 +156,15 @@ struct meson_nfc {
>  	struct nand_controller controller;
>  	struct clk *core_clk;
>  	struct clk *device_clk;
> -	struct clk *phase_tx;
> -	struct clk *phase_rx;
> +	struct clk *nand_clk;
> +	struct clk_divider nand_divider;
>  
>  	unsigned long clk_rate;
>  	u32 bus_timing;
>  
>  	struct device *dev;
>  	void __iomem *reg_base;
> -	struct regmap *reg_clk;
> +	void __iomem *reg_clk;
>  	struct completion completion;
>  	struct list_head chips;
>  	const struct meson_nfc_data *data;
> @@ -406,12 +411,14 @@ static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms)
>  	cmd = NFC_CMD_RB | NFC_CMD_RB_INT
>  		| nfc->param.chip_select | nfc->timing.tbers_max;
>  	writel(cmd, nfc->reg_base + NFC_REG_CMD);
> -
> +	meson_nfc_drain_cmd(nfc);
>  	ret = wait_for_completion_timeout(&nfc->completion,
>  					  msecs_to_jiffies(timeout_ms));
>  	if (ret == 0)
>  		ret = -1;
>  
> +	/* reset command fifo to avoid lock */
> +	writel(NFC_CMD_FIFO_RESET, nfc->reg_base + NFC_REG_CMD);
>  	return ret;
>  }
>  
> @@ -988,8 +995,9 @@ static const struct mtd_ooblayout_ops meson_ooblayout_ops = {
>  static int meson_nfc_clk_init(struct meson_nfc *nfc)
>  {
>  	int ret;
> +	struct clk_init_data init = {0};
> +	const char *fix_div2_pll_name[1];
>  
> -	/* request core clock */
>  	nfc->core_clk = devm_clk_get(nfc->dev, "core");
>  	if (IS_ERR(nfc->core_clk)) {
>  		dev_err(nfc->dev, "failed to get core clock\n");
> @@ -1002,21 +1010,25 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>  		return PTR_ERR(nfc->device_clk);
>  	}
>  
> -	nfc->phase_tx = devm_clk_get(nfc->dev, "tx");
> -	if (IS_ERR(nfc->phase_tx)) {
> -		dev_err(nfc->dev, "failed to get TX clk\n");
> -		return PTR_ERR(nfc->phase_tx);
> -	}
> -
> -	nfc->phase_rx = devm_clk_get(nfc->dev, "rx");
> -	if (IS_ERR(nfc->phase_rx)) {
> -		dev_err(nfc->dev, "failed to get RX clk\n");
> -		return PTR_ERR(nfc->phase_rx);
> -	}
> +	init.name = devm_kstrdup(nfc->dev, "nfc#div", GFP_KERNEL);
> +	init.ops = &clk_divider_ops;
> +	fix_div2_pll_name[0] = __clk_get_name(nfc->device_clk);
> +	init.parent_names = fix_div2_pll_name;
> +	init.num_parents = 1;
> +	nfc->nand_divider.reg = nfc->reg_clk;
> +	nfc->nand_divider.shift = CLK_DIV_SHIFT;
> +	nfc->nand_divider.width = CLK_DIV_WIDTH;
> +	nfc->nand_divider.hw.init = &init;
> +	nfc->nand_divider.flags = CLK_DIVIDER_ONE_BASED |
> +				  CLK_DIVIDER_ROUND_CLOSEST |
> +          			  CLK_DIVIDER_ALLOW_ZERO;
> +
> +	nfc->nand_clk = devm_clk_register(nfc->dev, &nfc->nand_divider.hw);
> +	if (IS_ERR(nfc->nand_clk))
> +		return PTR_ERR(nfc->nand_clk);
>  
>  	/* init SD_EMMC_CLOCK to sane defaults w/min clock rate */
> -	regmap_update_bits(nfc->reg_clk,
> -			   0, CLK_SELECT_NAND, CLK_SELECT_NAND);
> +	writel(CLK_SELECT_NAND | readl(nfc->reg_clk), nfc->reg_clk);
>  
>  	ret = clk_prepare_enable(nfc->core_clk);
>  	if (ret) {
> @@ -1030,29 +1042,21 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>  		goto err_device_clk;
>  	}
>  
> -	ret = clk_prepare_enable(nfc->phase_tx);
> +	ret = clk_prepare_enable(nfc->nand_clk);
>  	if (ret) {
> -		dev_err(nfc->dev, "failed to enable TX clock\n");
> -		goto err_phase_tx;
> -	}
> -
> -	ret = clk_prepare_enable(nfc->phase_rx);
> -	if (ret) {
> -		dev_err(nfc->dev, "failed to enable RX clock\n");
> -		goto err_phase_rx;
> +		dev_err(nfc->dev, "pre enable NFC divider fail\n");
> +		goto err_nand_clk;
>  	}
>  
>  	ret = clk_set_rate(nfc->device_clk, 24000000);
>  	if (ret)
> -		goto err_disable_rx;
> +		goto err_disable_clk;
>  
>  	return 0;
>  
> -err_disable_rx:
> -	clk_disable_unprepare(nfc->phase_rx);
> -err_phase_rx:
> -	clk_disable_unprepare(nfc->phase_tx);
> -err_phase_tx:
> +err_disable_clk:
> +	clk_disable_unprepare(nfc->nand_clk);
> +err_nand_clk:
>  	clk_disable_unprepare(nfc->device_clk);
>  err_device_clk:
>  	clk_disable_unprepare(nfc->core_clk);
> @@ -1061,8 +1065,7 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>  
>  static void meson_nfc_disable_clk(struct meson_nfc *nfc)
>  {
> -	clk_disable_unprepare(nfc->phase_rx);
> -	clk_disable_unprepare(nfc->phase_tx);
> +	clk_disable_unprepare(nfc->nand_clk);
>  	clk_disable_unprepare(nfc->device_clk);
>  	clk_disable_unprepare(nfc->core_clk);
>  }
> @@ -1375,6 +1378,7 @@ static int meson_nfc_probe(struct platform_device *pdev)
>  	struct device *dev = &pdev->dev;
>  	struct meson_nfc *nfc;
>  	struct resource *res;
> +	u32 ext_clk_reg;
>  	int ret, irq;
>  
>  	nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL);
> @@ -1396,9 +1400,15 @@ static int meson_nfc_probe(struct platform_device *pdev)
>  	if (IS_ERR(nfc->reg_base))
>  		return PTR_ERR(nfc->reg_base);
>  
> -	nfc->reg_clk =
> -		syscon_regmap_lookup_by_phandle(dev->of_node,
> -						"amlogic,mmc-syscon");
> +	ret = of_property_read_u32(pdev->dev.of_node,
> +				   "sd_emmc_c_clkc",
> +				   &ext_clk_reg);
> +	if (ret) {
> +		dev_err(dev, "failed to get NAND external clock register\n");
> +		return ret;
> +	}
> +
> +	nfc->reg_clk = devm_ioremap(&pdev->dev, ext_clk_reg, sizeof(int));
>  	if (IS_ERR(nfc->reg_clk)) {
>  		dev_err(dev, "Failed to lookup clock base\n");
>  		return PTR_ERR(nfc->reg_clk);


Thanks,
Miquèl

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH] mtd: rawnand: meson: fix the clock after discarding sd_emmc_c_clkc
@ 2022-01-06  8:08   ` Miquel Raynal
  0 siblings, 0 replies; 47+ messages in thread
From: Miquel Raynal @ 2022-01-06  8:08 UTC (permalink / raw)
  To: Liang Yang
  Cc: linux-mtd, Richard Weinberger, Jerome Brunet, Neil Armstrong,
	Martin Blumenstingl, Kevin Hilman, Jianxin Pan, Victor Wan,
	XianWei Zhao, Kelvin Zhang, BiChao Zheng, YongHui Yu,
	linux-arm-kernel, linux-amlogic, linux-kernel, devicetree

Hi Liang,

liang.yang@amlogic.com wrote on Thu, 6 Jan 2022 11:25:04 +0800:

> Because EMMC and NAND have the same control clock register, so we
> implement a 'sd_emmc_c_clkc'. Previously DTS is defined as below:
> 
> 	sd_emmc_c_clkc: mmc@7000 {
> 		compatible = "amlogic,meson-axg-mmc-clkc", "syscon";
> 		reg = <0x0 0x7000 0x0 0x800>;
> 	};
> 
> 	nand-controller@7800 {
> 		......
> 
> 		clocks = <&clkc CLKID_SD_EMMC_C>,
> 			<&sd_emmc_c_clkc CLKID_MMC_DIV>,
> 			<&sd_emmc_c_clkc CLKID_MMC_PHASE_RX>,
> 			<&sd_emmc_c_clkc CLKID_MMC_PHASE_TX>;
> 		clock-names = "core", "device", "rx", "tx";
> 		amlogic,mmc-syscon = <&sd_emmc_c_clkc>;
> 
> 		......
> 	}
> 
> but in fact, above implementation is rejected. so now registering
> a nand_divider.

What is rejected?
Why is it rejected?
What is nand_divider?


> 
> Change-Id: Ibeb4c7ff886f5886aac4d6c664d7bbd1b1bcb997

Change Ids are not expected in the upstream kernel.

But if you fix something you should have a Fixes:.

> Signed-off-by: Liang Yang <liang.yang@amlogic.com>
> ---
>  drivers/mtd/nand/raw/meson_nand.c | 88 +++++++++++++++++--------------
>  1 file changed, 49 insertions(+), 39 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c
> index ac3be92872d0..4472363059c2 100644
> --- a/drivers/mtd/nand/raw/meson_nand.c
> +++ b/drivers/mtd/nand/raw/meson_nand.c
> @@ -2,7 +2,7 @@
>  /*
>   * Amlogic Meson Nand Flash Controller Driver
>   *
> - * Copyright (c) 2018 Amlogic, inc.
> + * Copyright (c) 2018-2021 Amlogic, inc.
>   * Author: Liang Yang <liang.yang@amlogic.com>
>   */
>  
> @@ -10,6 +10,7 @@
>  #include <linux/dma-mapping.h>
>  #include <linux/interrupt.h>
>  #include <linux/clk.h>
> +#include <linux/clk-provider.h>
>  #include <linux/mtd/rawnand.h>
>  #include <linux/mtd/mtd.h>
>  #include <linux/mfd/syscon.h>
> @@ -55,6 +56,7 @@
>  #define NFC_REG_VER		0x38
>  
>  #define NFC_RB_IRQ_EN		BIT(21)
> +#define NFC_CMD_FIFO_RESET	BIT(31)
>  
>  #define CMDRWGEN(cmd_dir, ran, bch, short_mode, page_size, pages)	\
>  	(								\
> @@ -104,6 +106,9 @@
>  
>  #define PER_INFO_BYTE		8
>  
> +#define CLK_DIV_SHIFT		0
> +#define CLK_DIV_WIDTH		6
> +
>  struct meson_nfc_nand_chip {
>  	struct list_head node;
>  	struct nand_chip nand;
> @@ -151,15 +156,15 @@ struct meson_nfc {
>  	struct nand_controller controller;
>  	struct clk *core_clk;
>  	struct clk *device_clk;
> -	struct clk *phase_tx;
> -	struct clk *phase_rx;
> +	struct clk *nand_clk;
> +	struct clk_divider nand_divider;
>  
>  	unsigned long clk_rate;
>  	u32 bus_timing;
>  
>  	struct device *dev;
>  	void __iomem *reg_base;
> -	struct regmap *reg_clk;
> +	void __iomem *reg_clk;
>  	struct completion completion;
>  	struct list_head chips;
>  	const struct meson_nfc_data *data;
> @@ -406,12 +411,14 @@ static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms)
>  	cmd = NFC_CMD_RB | NFC_CMD_RB_INT
>  		| nfc->param.chip_select | nfc->timing.tbers_max;
>  	writel(cmd, nfc->reg_base + NFC_REG_CMD);
> -
> +	meson_nfc_drain_cmd(nfc);
>  	ret = wait_for_completion_timeout(&nfc->completion,
>  					  msecs_to_jiffies(timeout_ms));
>  	if (ret == 0)
>  		ret = -1;
>  
> +	/* reset command fifo to avoid lock */
> +	writel(NFC_CMD_FIFO_RESET, nfc->reg_base + NFC_REG_CMD);
>  	return ret;
>  }
>  
> @@ -988,8 +995,9 @@ static const struct mtd_ooblayout_ops meson_ooblayout_ops = {
>  static int meson_nfc_clk_init(struct meson_nfc *nfc)
>  {
>  	int ret;
> +	struct clk_init_data init = {0};
> +	const char *fix_div2_pll_name[1];
>  
> -	/* request core clock */
>  	nfc->core_clk = devm_clk_get(nfc->dev, "core");
>  	if (IS_ERR(nfc->core_clk)) {
>  		dev_err(nfc->dev, "failed to get core clock\n");
> @@ -1002,21 +1010,25 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>  		return PTR_ERR(nfc->device_clk);
>  	}
>  
> -	nfc->phase_tx = devm_clk_get(nfc->dev, "tx");
> -	if (IS_ERR(nfc->phase_tx)) {
> -		dev_err(nfc->dev, "failed to get TX clk\n");
> -		return PTR_ERR(nfc->phase_tx);
> -	}
> -
> -	nfc->phase_rx = devm_clk_get(nfc->dev, "rx");
> -	if (IS_ERR(nfc->phase_rx)) {
> -		dev_err(nfc->dev, "failed to get RX clk\n");
> -		return PTR_ERR(nfc->phase_rx);
> -	}
> +	init.name = devm_kstrdup(nfc->dev, "nfc#div", GFP_KERNEL);
> +	init.ops = &clk_divider_ops;
> +	fix_div2_pll_name[0] = __clk_get_name(nfc->device_clk);
> +	init.parent_names = fix_div2_pll_name;
> +	init.num_parents = 1;
> +	nfc->nand_divider.reg = nfc->reg_clk;
> +	nfc->nand_divider.shift = CLK_DIV_SHIFT;
> +	nfc->nand_divider.width = CLK_DIV_WIDTH;
> +	nfc->nand_divider.hw.init = &init;
> +	nfc->nand_divider.flags = CLK_DIVIDER_ONE_BASED |
> +				  CLK_DIVIDER_ROUND_CLOSEST |
> +          			  CLK_DIVIDER_ALLOW_ZERO;
> +
> +	nfc->nand_clk = devm_clk_register(nfc->dev, &nfc->nand_divider.hw);
> +	if (IS_ERR(nfc->nand_clk))
> +		return PTR_ERR(nfc->nand_clk);
>  
>  	/* init SD_EMMC_CLOCK to sane defaults w/min clock rate */
> -	regmap_update_bits(nfc->reg_clk,
> -			   0, CLK_SELECT_NAND, CLK_SELECT_NAND);
> +	writel(CLK_SELECT_NAND | readl(nfc->reg_clk), nfc->reg_clk);
>  
>  	ret = clk_prepare_enable(nfc->core_clk);
>  	if (ret) {
> @@ -1030,29 +1042,21 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>  		goto err_device_clk;
>  	}
>  
> -	ret = clk_prepare_enable(nfc->phase_tx);
> +	ret = clk_prepare_enable(nfc->nand_clk);
>  	if (ret) {
> -		dev_err(nfc->dev, "failed to enable TX clock\n");
> -		goto err_phase_tx;
> -	}
> -
> -	ret = clk_prepare_enable(nfc->phase_rx);
> -	if (ret) {
> -		dev_err(nfc->dev, "failed to enable RX clock\n");
> -		goto err_phase_rx;
> +		dev_err(nfc->dev, "pre enable NFC divider fail\n");
> +		goto err_nand_clk;
>  	}
>  
>  	ret = clk_set_rate(nfc->device_clk, 24000000);
>  	if (ret)
> -		goto err_disable_rx;
> +		goto err_disable_clk;
>  
>  	return 0;
>  
> -err_disable_rx:
> -	clk_disable_unprepare(nfc->phase_rx);
> -err_phase_rx:
> -	clk_disable_unprepare(nfc->phase_tx);
> -err_phase_tx:
> +err_disable_clk:
> +	clk_disable_unprepare(nfc->nand_clk);
> +err_nand_clk:
>  	clk_disable_unprepare(nfc->device_clk);
>  err_device_clk:
>  	clk_disable_unprepare(nfc->core_clk);
> @@ -1061,8 +1065,7 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>  
>  static void meson_nfc_disable_clk(struct meson_nfc *nfc)
>  {
> -	clk_disable_unprepare(nfc->phase_rx);
> -	clk_disable_unprepare(nfc->phase_tx);
> +	clk_disable_unprepare(nfc->nand_clk);
>  	clk_disable_unprepare(nfc->device_clk);
>  	clk_disable_unprepare(nfc->core_clk);
>  }
> @@ -1375,6 +1378,7 @@ static int meson_nfc_probe(struct platform_device *pdev)
>  	struct device *dev = &pdev->dev;
>  	struct meson_nfc *nfc;
>  	struct resource *res;
> +	u32 ext_clk_reg;
>  	int ret, irq;
>  
>  	nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL);
> @@ -1396,9 +1400,15 @@ static int meson_nfc_probe(struct platform_device *pdev)
>  	if (IS_ERR(nfc->reg_base))
>  		return PTR_ERR(nfc->reg_base);
>  
> -	nfc->reg_clk =
> -		syscon_regmap_lookup_by_phandle(dev->of_node,
> -						"amlogic,mmc-syscon");
> +	ret = of_property_read_u32(pdev->dev.of_node,
> +				   "sd_emmc_c_clkc",
> +				   &ext_clk_reg);
> +	if (ret) {
> +		dev_err(dev, "failed to get NAND external clock register\n");
> +		return ret;
> +	}
> +
> +	nfc->reg_clk = devm_ioremap(&pdev->dev, ext_clk_reg, sizeof(int));
>  	if (IS_ERR(nfc->reg_clk)) {
>  		dev_err(dev, "Failed to lookup clock base\n");
>  		return PTR_ERR(nfc->reg_clk);


Thanks,
Miquèl

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH] mtd: rawnand: meson: fix the clock after discarding sd_emmc_c_clkc
  2022-01-06  3:25 ` Liang Yang
  (?)
  (?)
@ 2022-01-06  8:16   ` Jerome Brunet
  -1 siblings, 0 replies; 47+ messages in thread
From: Jerome Brunet @ 2022-01-06  8:16 UTC (permalink / raw)
  To: Liang Yang, Miquel Raynal, linux-mtd
  Cc: Richard Weinberger, Neil Armstrong, Martin Blumenstingl,
	Kevin Hilman, Jianxin Pan, Victor Wan, XianWei Zhao,
	Kelvin Zhang, BiChao Zheng, YongHui Yu, linux-arm-kernel,
	linux-amlogic, linux-kernel, devicetree


On Thu 06 Jan 2022 at 11:25, Liang Yang <liang.yang@amlogic.com> wrote:

> Because EMMC and NAND have the same control clock register, so we
> implement a 'sd_emmc_c_clkc'. Previously DTS is defined as below:
>
> 	sd_emmc_c_clkc: mmc@7000 {
> 		compatible = "amlogic,meson-axg-mmc-clkc", "syscon";
> 		reg = <0x0 0x7000 0x0 0x800>;
> 	};
>
> 	nand-controller@7800 {
> 		......
>
> 		clocks = <&clkc CLKID_SD_EMMC_C>,
> 			<&sd_emmc_c_clkc CLKID_MMC_DIV>,
> 			<&sd_emmc_c_clkc CLKID_MMC_PHASE_RX>,
> 			<&sd_emmc_c_clkc CLKID_MMC_PHASE_TX>;
> 		clock-names = "core", "device", "rx", "tx";
> 		amlogic,mmc-syscon = <&sd_emmc_c_clkc>;
>
> 		......
> 	}
>
> but in fact, above implementation is rejected. so now registering
> a nand_divider.

Can you give a bit of context ? a link to the discussion rejecting this

As far as remember, things were getting done for A1 and stopped before
clock part was finished. I'm saying the change is wrong, just that a
discussion is needed before a decision is made.

>
> Change-Id: Ibeb4c7ff886f5886aac4d6c664d7bbd1b1bcb997
> Signed-off-by: Liang Yang <liang.yang@amlogic.com>
> ---
>  drivers/mtd/nand/raw/meson_nand.c | 88 +++++++++++++++++--------------
>  1 file changed, 49 insertions(+), 39 deletions(-)
>
> diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c
> index ac3be92872d0..4472363059c2 100644
> --- a/drivers/mtd/nand/raw/meson_nand.c
> +++ b/drivers/mtd/nand/raw/meson_nand.c
> @@ -2,7 +2,7 @@
>  /*
>   * Amlogic Meson Nand Flash Controller Driver
>   *
> - * Copyright (c) 2018 Amlogic, inc.
> + * Copyright (c) 2018-2021 Amlogic, inc.
>   * Author: Liang Yang <liang.yang@amlogic.com>
>   */
>  
> @@ -10,6 +10,7 @@
>  #include <linux/dma-mapping.h>
>  #include <linux/interrupt.h>
>  #include <linux/clk.h>
> +#include <linux/clk-provider.h>
>  #include <linux/mtd/rawnand.h>
>  #include <linux/mtd/mtd.h>
>  #include <linux/mfd/syscon.h>
> @@ -55,6 +56,7 @@
>  #define NFC_REG_VER		0x38
>  
>  #define NFC_RB_IRQ_EN		BIT(21)
> +#define NFC_CMD_FIFO_RESET	BIT(31)
>  
>  #define CMDRWGEN(cmd_dir, ran, bch, short_mode, page_size, pages)	\
>  	(								\
> @@ -104,6 +106,9 @@
>  
>  #define PER_INFO_BYTE		8
>  
> +#define CLK_DIV_SHIFT		0
> +#define CLK_DIV_WIDTH		6
> +
>  struct meson_nfc_nand_chip {
>  	struct list_head node;
>  	struct nand_chip nand;
> @@ -151,15 +156,15 @@ struct meson_nfc {
>  	struct nand_controller controller;
>  	struct clk *core_clk;
>  	struct clk *device_clk;
> -	struct clk *phase_tx;
> -	struct clk *phase_rx;

I would have been nice to explain why these clock are no longer
required, in the change description maybe ?

> +	struct clk *nand_clk;
> +	struct clk_divider nand_divider;
>  
>  	unsigned long clk_rate;
>  	u32 bus_timing;
>  
>  	struct device *dev;
>  	void __iomem *reg_base;
> -	struct regmap *reg_clk;
> +	void __iomem *reg_clk;
>  	struct completion completion;
>  	struct list_head chips;
>  	const struct meson_nfc_data *data;
> @@ -406,12 +411,14 @@ static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms)
>  	cmd = NFC_CMD_RB | NFC_CMD_RB_INT
>  		| nfc->param.chip_select | nfc->timing.tbers_max;
>  	writel(cmd, nfc->reg_base + NFC_REG_CMD);
> -
> +	meson_nfc_drain_cmd(nfc);

is this clock related ?

>  	ret = wait_for_completion_timeout(&nfc->completion,
>  					  msecs_to_jiffies(timeout_ms));
>  	if (ret == 0)
>  		ret = -1;
>  
> +	/* reset command fifo to avoid lock */
> +	writel(NFC_CMD_FIFO_RESET, nfc->reg_base + NFC_REG_CMD);

Again, not seem to be clock related - does not belong in this patch

>  	return ret;
>  }
>  
> @@ -988,8 +995,9 @@ static const struct mtd_ooblayout_ops meson_ooblayout_ops = {
>  static int meson_nfc_clk_init(struct meson_nfc *nfc)
>  {
>  	int ret;
> +	struct clk_init_data init = {0};
> +	const char *fix_div2_pll_name[1];
>  
> -	/* request core clock */

Why is the comment bothering you ?

>  	nfc->core_clk = devm_clk_get(nfc->dev, "core");
>  	if (IS_ERR(nfc->core_clk)) {
>  		dev_err(nfc->dev, "failed to get core clock\n");
> @@ -1002,21 +1010,25 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>  		return PTR_ERR(nfc->device_clk);
>  	}
>  
> -	nfc->phase_tx = devm_clk_get(nfc->dev, "tx");
> -	if (IS_ERR(nfc->phase_tx)) {
> -		dev_err(nfc->dev, "failed to get TX clk\n");
> -		return PTR_ERR(nfc->phase_tx);
> -	}
> -
> -	nfc->phase_rx = devm_clk_get(nfc->dev, "rx");
> -	if (IS_ERR(nfc->phase_rx)) {
> -		dev_err(nfc->dev, "failed to get RX clk\n");
> -		return PTR_ERR(nfc->phase_rx);
> -	}
> +	init.name = devm_kstrdup(nfc->dev, "nfc#div", GFP_KERNEL);
> +	init.ops = &clk_divider_ops;
> +	fix_div2_pll_name[0] = __clk_get_name(nfc->device_clk);

You should be using "fw_name" so CCF looks a DT directly, instead of this

> +	init.parent_names = fix_div2_pll_name;
> +	init.num_parents = 1;
> +	nfc->nand_divider.reg = nfc->reg_clk;
> +	nfc->nand_divider.shift = CLK_DIV_SHIFT;
> +	nfc->nand_divider.width = CLK_DIV_WIDTH;
> +	nfc->nand_divider.hw.init = &init;
> +	nfc->nand_divider.flags = CLK_DIVIDER_ONE_BASED |
> +				  CLK_DIVIDER_ROUND_CLOSEST |
> +          			  CLK_DIVIDER_ALLOW_ZERO;
> +
> +	nfc->nand_clk = devm_clk_register(nfc->dev, &nfc->nand_divider.hw);
> +	if (IS_ERR(nfc->nand_clk))
> +		return PTR_ERR(nfc->nand_clk);
>  
>  	/* init SD_EMMC_CLOCK to sane defaults w/min clock rate */
> -	regmap_update_bits(nfc->reg_clk,
> -			   0, CLK_SELECT_NAND, CLK_SELECT_NAND);
> +	writel(CLK_SELECT_NAND | readl(nfc->reg_clk), nfc->reg_clk);
>  
>  	ret = clk_prepare_enable(nfc->core_clk);
>  	if (ret) {
> @@ -1030,29 +1042,21 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>  		goto err_device_clk;
>  	}
>  
> -	ret = clk_prepare_enable(nfc->phase_tx);
> +	ret = clk_prepare_enable(nfc->nand_clk);
>  	if (ret) {
> -		dev_err(nfc->dev, "failed to enable TX clock\n");
> -		goto err_phase_tx;
> -	}
> -
> -	ret = clk_prepare_enable(nfc->phase_rx);
> -	if (ret) {
> -		dev_err(nfc->dev, "failed to enable RX clock\n");
> -		goto err_phase_rx;
> +		dev_err(nfc->dev, "pre enable NFC divider fail\n");
> +		goto err_nand_clk;
>  	}
>  
>  	ret = clk_set_rate(nfc->device_clk, 24000000);
>  	if (ret)
> -		goto err_disable_rx;
> +		goto err_disable_clk;
>  
>  	return 0;
>  
> -err_disable_rx:
> -	clk_disable_unprepare(nfc->phase_rx);
> -err_phase_rx:
> -	clk_disable_unprepare(nfc->phase_tx);
> -err_phase_tx:
> +err_disable_clk:
> +	clk_disable_unprepare(nfc->nand_clk);
> +err_nand_clk:
>  	clk_disable_unprepare(nfc->device_clk);
>  err_device_clk:
>  	clk_disable_unprepare(nfc->core_clk);
> @@ -1061,8 +1065,7 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>  
>  static void meson_nfc_disable_clk(struct meson_nfc *nfc)
>  {
> -	clk_disable_unprepare(nfc->phase_rx);
> -	clk_disable_unprepare(nfc->phase_tx);
> +	clk_disable_unprepare(nfc->nand_clk);
>  	clk_disable_unprepare(nfc->device_clk);
>  	clk_disable_unprepare(nfc->core_clk);
>  }
> @@ -1375,6 +1378,7 @@ static int meson_nfc_probe(struct platform_device *pdev)
>  	struct device *dev = &pdev->dev;
>  	struct meson_nfc *nfc;
>  	struct resource *res;
> +	u32 ext_clk_reg;
>  	int ret, irq;
>  
>  	nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL);
> @@ -1396,9 +1400,15 @@ static int meson_nfc_probe(struct platform_device *pdev)
>  	if (IS_ERR(nfc->reg_base))
>  		return PTR_ERR(nfc->reg_base);
>  
> -	nfc->reg_clk =
> -		syscon_regmap_lookup_by_phandle(dev->of_node,
> -						"amlogic,mmc-syscon");
> +	ret = of_property_read_u32(pdev->dev.of_node,
> +				   "sd_emmc_c_clkc",
> +				   &ext_clk_reg);
> +	if (ret) {
> +		dev_err(dev, "failed to get NAND external clock register\n");
> +		return ret;
> +	}
> +
> +	nfc->reg_clk = devm_ioremap(&pdev->dev, ext_clk_reg, sizeof(int));

That's how you should get a register region.
If you want an example of a device claiming several region on amlogic,
have a look at the pinctrl driver. 

>  	if (IS_ERR(nfc->reg_clk)) {
>  		dev_err(dev, "Failed to lookup clock base\n");
>  		return PTR_ERR(nfc->reg_clk);


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

* Re: [PATCH] mtd: rawnand: meson: fix the clock after discarding sd_emmc_c_clkc
@ 2022-01-06  8:16   ` Jerome Brunet
  0 siblings, 0 replies; 47+ messages in thread
From: Jerome Brunet @ 2022-01-06  8:16 UTC (permalink / raw)
  To: Liang Yang, Miquel Raynal, linux-mtd
  Cc: Richard Weinberger, Neil Armstrong, Martin Blumenstingl,
	Kevin Hilman, Jianxin Pan, Victor Wan, XianWei Zhao,
	Kelvin Zhang, BiChao Zheng, YongHui Yu, linux-arm-kernel,
	linux-amlogic, linux-kernel, devicetree


On Thu 06 Jan 2022 at 11:25, Liang Yang <liang.yang@amlogic.com> wrote:

> Because EMMC and NAND have the same control clock register, so we
> implement a 'sd_emmc_c_clkc'. Previously DTS is defined as below:
>
> 	sd_emmc_c_clkc: mmc@7000 {
> 		compatible = "amlogic,meson-axg-mmc-clkc", "syscon";
> 		reg = <0x0 0x7000 0x0 0x800>;
> 	};
>
> 	nand-controller@7800 {
> 		......
>
> 		clocks = <&clkc CLKID_SD_EMMC_C>,
> 			<&sd_emmc_c_clkc CLKID_MMC_DIV>,
> 			<&sd_emmc_c_clkc CLKID_MMC_PHASE_RX>,
> 			<&sd_emmc_c_clkc CLKID_MMC_PHASE_TX>;
> 		clock-names = "core", "device", "rx", "tx";
> 		amlogic,mmc-syscon = <&sd_emmc_c_clkc>;
>
> 		......
> 	}
>
> but in fact, above implementation is rejected. so now registering
> a nand_divider.

Can you give a bit of context ? a link to the discussion rejecting this

As far as remember, things were getting done for A1 and stopped before
clock part was finished. I'm saying the change is wrong, just that a
discussion is needed before a decision is made.

>
> Change-Id: Ibeb4c7ff886f5886aac4d6c664d7bbd1b1bcb997
> Signed-off-by: Liang Yang <liang.yang@amlogic.com>
> ---
>  drivers/mtd/nand/raw/meson_nand.c | 88 +++++++++++++++++--------------
>  1 file changed, 49 insertions(+), 39 deletions(-)
>
> diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c
> index ac3be92872d0..4472363059c2 100644
> --- a/drivers/mtd/nand/raw/meson_nand.c
> +++ b/drivers/mtd/nand/raw/meson_nand.c
> @@ -2,7 +2,7 @@
>  /*
>   * Amlogic Meson Nand Flash Controller Driver
>   *
> - * Copyright (c) 2018 Amlogic, inc.
> + * Copyright (c) 2018-2021 Amlogic, inc.
>   * Author: Liang Yang <liang.yang@amlogic.com>
>   */
>  
> @@ -10,6 +10,7 @@
>  #include <linux/dma-mapping.h>
>  #include <linux/interrupt.h>
>  #include <linux/clk.h>
> +#include <linux/clk-provider.h>
>  #include <linux/mtd/rawnand.h>
>  #include <linux/mtd/mtd.h>
>  #include <linux/mfd/syscon.h>
> @@ -55,6 +56,7 @@
>  #define NFC_REG_VER		0x38
>  
>  #define NFC_RB_IRQ_EN		BIT(21)
> +#define NFC_CMD_FIFO_RESET	BIT(31)
>  
>  #define CMDRWGEN(cmd_dir, ran, bch, short_mode, page_size, pages)	\
>  	(								\
> @@ -104,6 +106,9 @@
>  
>  #define PER_INFO_BYTE		8
>  
> +#define CLK_DIV_SHIFT		0
> +#define CLK_DIV_WIDTH		6
> +
>  struct meson_nfc_nand_chip {
>  	struct list_head node;
>  	struct nand_chip nand;
> @@ -151,15 +156,15 @@ struct meson_nfc {
>  	struct nand_controller controller;
>  	struct clk *core_clk;
>  	struct clk *device_clk;
> -	struct clk *phase_tx;
> -	struct clk *phase_rx;

I would have been nice to explain why these clock are no longer
required, in the change description maybe ?

> +	struct clk *nand_clk;
> +	struct clk_divider nand_divider;
>  
>  	unsigned long clk_rate;
>  	u32 bus_timing;
>  
>  	struct device *dev;
>  	void __iomem *reg_base;
> -	struct regmap *reg_clk;
> +	void __iomem *reg_clk;
>  	struct completion completion;
>  	struct list_head chips;
>  	const struct meson_nfc_data *data;
> @@ -406,12 +411,14 @@ static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms)
>  	cmd = NFC_CMD_RB | NFC_CMD_RB_INT
>  		| nfc->param.chip_select | nfc->timing.tbers_max;
>  	writel(cmd, nfc->reg_base + NFC_REG_CMD);
> -
> +	meson_nfc_drain_cmd(nfc);

is this clock related ?

>  	ret = wait_for_completion_timeout(&nfc->completion,
>  					  msecs_to_jiffies(timeout_ms));
>  	if (ret == 0)
>  		ret = -1;
>  
> +	/* reset command fifo to avoid lock */
> +	writel(NFC_CMD_FIFO_RESET, nfc->reg_base + NFC_REG_CMD);

Again, not seem to be clock related - does not belong in this patch

>  	return ret;
>  }
>  
> @@ -988,8 +995,9 @@ static const struct mtd_ooblayout_ops meson_ooblayout_ops = {
>  static int meson_nfc_clk_init(struct meson_nfc *nfc)
>  {
>  	int ret;
> +	struct clk_init_data init = {0};
> +	const char *fix_div2_pll_name[1];
>  
> -	/* request core clock */

Why is the comment bothering you ?

>  	nfc->core_clk = devm_clk_get(nfc->dev, "core");
>  	if (IS_ERR(nfc->core_clk)) {
>  		dev_err(nfc->dev, "failed to get core clock\n");
> @@ -1002,21 +1010,25 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>  		return PTR_ERR(nfc->device_clk);
>  	}
>  
> -	nfc->phase_tx = devm_clk_get(nfc->dev, "tx");
> -	if (IS_ERR(nfc->phase_tx)) {
> -		dev_err(nfc->dev, "failed to get TX clk\n");
> -		return PTR_ERR(nfc->phase_tx);
> -	}
> -
> -	nfc->phase_rx = devm_clk_get(nfc->dev, "rx");
> -	if (IS_ERR(nfc->phase_rx)) {
> -		dev_err(nfc->dev, "failed to get RX clk\n");
> -		return PTR_ERR(nfc->phase_rx);
> -	}
> +	init.name = devm_kstrdup(nfc->dev, "nfc#div", GFP_KERNEL);
> +	init.ops = &clk_divider_ops;
> +	fix_div2_pll_name[0] = __clk_get_name(nfc->device_clk);

You should be using "fw_name" so CCF looks a DT directly, instead of this

> +	init.parent_names = fix_div2_pll_name;
> +	init.num_parents = 1;
> +	nfc->nand_divider.reg = nfc->reg_clk;
> +	nfc->nand_divider.shift = CLK_DIV_SHIFT;
> +	nfc->nand_divider.width = CLK_DIV_WIDTH;
> +	nfc->nand_divider.hw.init = &init;
> +	nfc->nand_divider.flags = CLK_DIVIDER_ONE_BASED |
> +				  CLK_DIVIDER_ROUND_CLOSEST |
> +          			  CLK_DIVIDER_ALLOW_ZERO;
> +
> +	nfc->nand_clk = devm_clk_register(nfc->dev, &nfc->nand_divider.hw);
> +	if (IS_ERR(nfc->nand_clk))
> +		return PTR_ERR(nfc->nand_clk);
>  
>  	/* init SD_EMMC_CLOCK to sane defaults w/min clock rate */
> -	regmap_update_bits(nfc->reg_clk,
> -			   0, CLK_SELECT_NAND, CLK_SELECT_NAND);
> +	writel(CLK_SELECT_NAND | readl(nfc->reg_clk), nfc->reg_clk);
>  
>  	ret = clk_prepare_enable(nfc->core_clk);
>  	if (ret) {
> @@ -1030,29 +1042,21 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>  		goto err_device_clk;
>  	}
>  
> -	ret = clk_prepare_enable(nfc->phase_tx);
> +	ret = clk_prepare_enable(nfc->nand_clk);
>  	if (ret) {
> -		dev_err(nfc->dev, "failed to enable TX clock\n");
> -		goto err_phase_tx;
> -	}
> -
> -	ret = clk_prepare_enable(nfc->phase_rx);
> -	if (ret) {
> -		dev_err(nfc->dev, "failed to enable RX clock\n");
> -		goto err_phase_rx;
> +		dev_err(nfc->dev, "pre enable NFC divider fail\n");
> +		goto err_nand_clk;
>  	}
>  
>  	ret = clk_set_rate(nfc->device_clk, 24000000);
>  	if (ret)
> -		goto err_disable_rx;
> +		goto err_disable_clk;
>  
>  	return 0;
>  
> -err_disable_rx:
> -	clk_disable_unprepare(nfc->phase_rx);
> -err_phase_rx:
> -	clk_disable_unprepare(nfc->phase_tx);
> -err_phase_tx:
> +err_disable_clk:
> +	clk_disable_unprepare(nfc->nand_clk);
> +err_nand_clk:
>  	clk_disable_unprepare(nfc->device_clk);
>  err_device_clk:
>  	clk_disable_unprepare(nfc->core_clk);
> @@ -1061,8 +1065,7 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>  
>  static void meson_nfc_disable_clk(struct meson_nfc *nfc)
>  {
> -	clk_disable_unprepare(nfc->phase_rx);
> -	clk_disable_unprepare(nfc->phase_tx);
> +	clk_disable_unprepare(nfc->nand_clk);
>  	clk_disable_unprepare(nfc->device_clk);
>  	clk_disable_unprepare(nfc->core_clk);
>  }
> @@ -1375,6 +1378,7 @@ static int meson_nfc_probe(struct platform_device *pdev)
>  	struct device *dev = &pdev->dev;
>  	struct meson_nfc *nfc;
>  	struct resource *res;
> +	u32 ext_clk_reg;
>  	int ret, irq;
>  
>  	nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL);
> @@ -1396,9 +1400,15 @@ static int meson_nfc_probe(struct platform_device *pdev)
>  	if (IS_ERR(nfc->reg_base))
>  		return PTR_ERR(nfc->reg_base);
>  
> -	nfc->reg_clk =
> -		syscon_regmap_lookup_by_phandle(dev->of_node,
> -						"amlogic,mmc-syscon");
> +	ret = of_property_read_u32(pdev->dev.of_node,
> +				   "sd_emmc_c_clkc",
> +				   &ext_clk_reg);
> +	if (ret) {
> +		dev_err(dev, "failed to get NAND external clock register\n");
> +		return ret;
> +	}
> +
> +	nfc->reg_clk = devm_ioremap(&pdev->dev, ext_clk_reg, sizeof(int));

That's how you should get a register region.
If you want an example of a device claiming several region on amlogic,
have a look at the pinctrl driver. 

>  	if (IS_ERR(nfc->reg_clk)) {
>  		dev_err(dev, "Failed to lookup clock base\n");
>  		return PTR_ERR(nfc->reg_clk);


_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic

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

* Re: [PATCH] mtd: rawnand: meson: fix the clock after discarding sd_emmc_c_clkc
@ 2022-01-06  8:16   ` Jerome Brunet
  0 siblings, 0 replies; 47+ messages in thread
From: Jerome Brunet @ 2022-01-06  8:16 UTC (permalink / raw)
  To: Liang Yang, Miquel Raynal, linux-mtd
  Cc: Richard Weinberger, Neil Armstrong, Martin Blumenstingl,
	Kevin Hilman, Jianxin Pan, Victor Wan, XianWei Zhao,
	Kelvin Zhang, BiChao Zheng, YongHui Yu, linux-arm-kernel,
	linux-amlogic, linux-kernel, devicetree


On Thu 06 Jan 2022 at 11:25, Liang Yang <liang.yang@amlogic.com> wrote:

> Because EMMC and NAND have the same control clock register, so we
> implement a 'sd_emmc_c_clkc'. Previously DTS is defined as below:
>
> 	sd_emmc_c_clkc: mmc@7000 {
> 		compatible = "amlogic,meson-axg-mmc-clkc", "syscon";
> 		reg = <0x0 0x7000 0x0 0x800>;
> 	};
>
> 	nand-controller@7800 {
> 		......
>
> 		clocks = <&clkc CLKID_SD_EMMC_C>,
> 			<&sd_emmc_c_clkc CLKID_MMC_DIV>,
> 			<&sd_emmc_c_clkc CLKID_MMC_PHASE_RX>,
> 			<&sd_emmc_c_clkc CLKID_MMC_PHASE_TX>;
> 		clock-names = "core", "device", "rx", "tx";
> 		amlogic,mmc-syscon = <&sd_emmc_c_clkc>;
>
> 		......
> 	}
>
> but in fact, above implementation is rejected. so now registering
> a nand_divider.

Can you give a bit of context ? a link to the discussion rejecting this

As far as remember, things were getting done for A1 and stopped before
clock part was finished. I'm saying the change is wrong, just that a
discussion is needed before a decision is made.

>
> Change-Id: Ibeb4c7ff886f5886aac4d6c664d7bbd1b1bcb997
> Signed-off-by: Liang Yang <liang.yang@amlogic.com>
> ---
>  drivers/mtd/nand/raw/meson_nand.c | 88 +++++++++++++++++--------------
>  1 file changed, 49 insertions(+), 39 deletions(-)
>
> diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c
> index ac3be92872d0..4472363059c2 100644
> --- a/drivers/mtd/nand/raw/meson_nand.c
> +++ b/drivers/mtd/nand/raw/meson_nand.c
> @@ -2,7 +2,7 @@
>  /*
>   * Amlogic Meson Nand Flash Controller Driver
>   *
> - * Copyright (c) 2018 Amlogic, inc.
> + * Copyright (c) 2018-2021 Amlogic, inc.
>   * Author: Liang Yang <liang.yang@amlogic.com>
>   */
>  
> @@ -10,6 +10,7 @@
>  #include <linux/dma-mapping.h>
>  #include <linux/interrupt.h>
>  #include <linux/clk.h>
> +#include <linux/clk-provider.h>
>  #include <linux/mtd/rawnand.h>
>  #include <linux/mtd/mtd.h>
>  #include <linux/mfd/syscon.h>
> @@ -55,6 +56,7 @@
>  #define NFC_REG_VER		0x38
>  
>  #define NFC_RB_IRQ_EN		BIT(21)
> +#define NFC_CMD_FIFO_RESET	BIT(31)
>  
>  #define CMDRWGEN(cmd_dir, ran, bch, short_mode, page_size, pages)	\
>  	(								\
> @@ -104,6 +106,9 @@
>  
>  #define PER_INFO_BYTE		8
>  
> +#define CLK_DIV_SHIFT		0
> +#define CLK_DIV_WIDTH		6
> +
>  struct meson_nfc_nand_chip {
>  	struct list_head node;
>  	struct nand_chip nand;
> @@ -151,15 +156,15 @@ struct meson_nfc {
>  	struct nand_controller controller;
>  	struct clk *core_clk;
>  	struct clk *device_clk;
> -	struct clk *phase_tx;
> -	struct clk *phase_rx;

I would have been nice to explain why these clock are no longer
required, in the change description maybe ?

> +	struct clk *nand_clk;
> +	struct clk_divider nand_divider;
>  
>  	unsigned long clk_rate;
>  	u32 bus_timing;
>  
>  	struct device *dev;
>  	void __iomem *reg_base;
> -	struct regmap *reg_clk;
> +	void __iomem *reg_clk;
>  	struct completion completion;
>  	struct list_head chips;
>  	const struct meson_nfc_data *data;
> @@ -406,12 +411,14 @@ static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms)
>  	cmd = NFC_CMD_RB | NFC_CMD_RB_INT
>  		| nfc->param.chip_select | nfc->timing.tbers_max;
>  	writel(cmd, nfc->reg_base + NFC_REG_CMD);
> -
> +	meson_nfc_drain_cmd(nfc);

is this clock related ?

>  	ret = wait_for_completion_timeout(&nfc->completion,
>  					  msecs_to_jiffies(timeout_ms));
>  	if (ret == 0)
>  		ret = -1;
>  
> +	/* reset command fifo to avoid lock */
> +	writel(NFC_CMD_FIFO_RESET, nfc->reg_base + NFC_REG_CMD);

Again, not seem to be clock related - does not belong in this patch

>  	return ret;
>  }
>  
> @@ -988,8 +995,9 @@ static const struct mtd_ooblayout_ops meson_ooblayout_ops = {
>  static int meson_nfc_clk_init(struct meson_nfc *nfc)
>  {
>  	int ret;
> +	struct clk_init_data init = {0};
> +	const char *fix_div2_pll_name[1];
>  
> -	/* request core clock */

Why is the comment bothering you ?

>  	nfc->core_clk = devm_clk_get(nfc->dev, "core");
>  	if (IS_ERR(nfc->core_clk)) {
>  		dev_err(nfc->dev, "failed to get core clock\n");
> @@ -1002,21 +1010,25 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>  		return PTR_ERR(nfc->device_clk);
>  	}
>  
> -	nfc->phase_tx = devm_clk_get(nfc->dev, "tx");
> -	if (IS_ERR(nfc->phase_tx)) {
> -		dev_err(nfc->dev, "failed to get TX clk\n");
> -		return PTR_ERR(nfc->phase_tx);
> -	}
> -
> -	nfc->phase_rx = devm_clk_get(nfc->dev, "rx");
> -	if (IS_ERR(nfc->phase_rx)) {
> -		dev_err(nfc->dev, "failed to get RX clk\n");
> -		return PTR_ERR(nfc->phase_rx);
> -	}
> +	init.name = devm_kstrdup(nfc->dev, "nfc#div", GFP_KERNEL);
> +	init.ops = &clk_divider_ops;
> +	fix_div2_pll_name[0] = __clk_get_name(nfc->device_clk);

You should be using "fw_name" so CCF looks a DT directly, instead of this

> +	init.parent_names = fix_div2_pll_name;
> +	init.num_parents = 1;
> +	nfc->nand_divider.reg = nfc->reg_clk;
> +	nfc->nand_divider.shift = CLK_DIV_SHIFT;
> +	nfc->nand_divider.width = CLK_DIV_WIDTH;
> +	nfc->nand_divider.hw.init = &init;
> +	nfc->nand_divider.flags = CLK_DIVIDER_ONE_BASED |
> +				  CLK_DIVIDER_ROUND_CLOSEST |
> +          			  CLK_DIVIDER_ALLOW_ZERO;
> +
> +	nfc->nand_clk = devm_clk_register(nfc->dev, &nfc->nand_divider.hw);
> +	if (IS_ERR(nfc->nand_clk))
> +		return PTR_ERR(nfc->nand_clk);
>  
>  	/* init SD_EMMC_CLOCK to sane defaults w/min clock rate */
> -	regmap_update_bits(nfc->reg_clk,
> -			   0, CLK_SELECT_NAND, CLK_SELECT_NAND);
> +	writel(CLK_SELECT_NAND | readl(nfc->reg_clk), nfc->reg_clk);
>  
>  	ret = clk_prepare_enable(nfc->core_clk);
>  	if (ret) {
> @@ -1030,29 +1042,21 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>  		goto err_device_clk;
>  	}
>  
> -	ret = clk_prepare_enable(nfc->phase_tx);
> +	ret = clk_prepare_enable(nfc->nand_clk);
>  	if (ret) {
> -		dev_err(nfc->dev, "failed to enable TX clock\n");
> -		goto err_phase_tx;
> -	}
> -
> -	ret = clk_prepare_enable(nfc->phase_rx);
> -	if (ret) {
> -		dev_err(nfc->dev, "failed to enable RX clock\n");
> -		goto err_phase_rx;
> +		dev_err(nfc->dev, "pre enable NFC divider fail\n");
> +		goto err_nand_clk;
>  	}
>  
>  	ret = clk_set_rate(nfc->device_clk, 24000000);
>  	if (ret)
> -		goto err_disable_rx;
> +		goto err_disable_clk;
>  
>  	return 0;
>  
> -err_disable_rx:
> -	clk_disable_unprepare(nfc->phase_rx);
> -err_phase_rx:
> -	clk_disable_unprepare(nfc->phase_tx);
> -err_phase_tx:
> +err_disable_clk:
> +	clk_disable_unprepare(nfc->nand_clk);
> +err_nand_clk:
>  	clk_disable_unprepare(nfc->device_clk);
>  err_device_clk:
>  	clk_disable_unprepare(nfc->core_clk);
> @@ -1061,8 +1065,7 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>  
>  static void meson_nfc_disable_clk(struct meson_nfc *nfc)
>  {
> -	clk_disable_unprepare(nfc->phase_rx);
> -	clk_disable_unprepare(nfc->phase_tx);
> +	clk_disable_unprepare(nfc->nand_clk);
>  	clk_disable_unprepare(nfc->device_clk);
>  	clk_disable_unprepare(nfc->core_clk);
>  }
> @@ -1375,6 +1378,7 @@ static int meson_nfc_probe(struct platform_device *pdev)
>  	struct device *dev = &pdev->dev;
>  	struct meson_nfc *nfc;
>  	struct resource *res;
> +	u32 ext_clk_reg;
>  	int ret, irq;
>  
>  	nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL);
> @@ -1396,9 +1400,15 @@ static int meson_nfc_probe(struct platform_device *pdev)
>  	if (IS_ERR(nfc->reg_base))
>  		return PTR_ERR(nfc->reg_base);
>  
> -	nfc->reg_clk =
> -		syscon_regmap_lookup_by_phandle(dev->of_node,
> -						"amlogic,mmc-syscon");
> +	ret = of_property_read_u32(pdev->dev.of_node,
> +				   "sd_emmc_c_clkc",
> +				   &ext_clk_reg);
> +	if (ret) {
> +		dev_err(dev, "failed to get NAND external clock register\n");
> +		return ret;
> +	}
> +
> +	nfc->reg_clk = devm_ioremap(&pdev->dev, ext_clk_reg, sizeof(int));

That's how you should get a register region.
If you want an example of a device claiming several region on amlogic,
have a look at the pinctrl driver. 

>  	if (IS_ERR(nfc->reg_clk)) {
>  		dev_err(dev, "Failed to lookup clock base\n");
>  		return PTR_ERR(nfc->reg_clk);


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH] mtd: rawnand: meson: fix the clock after discarding sd_emmc_c_clkc
@ 2022-01-06  8:16   ` Jerome Brunet
  0 siblings, 0 replies; 47+ messages in thread
From: Jerome Brunet @ 2022-01-06  8:16 UTC (permalink / raw)
  To: Liang Yang, Miquel Raynal, linux-mtd
  Cc: Richard Weinberger, Neil Armstrong, Martin Blumenstingl,
	Kevin Hilman, Jianxin Pan, Victor Wan, XianWei Zhao,
	Kelvin Zhang, BiChao Zheng, YongHui Yu, linux-arm-kernel,
	linux-amlogic, linux-kernel, devicetree


On Thu 06 Jan 2022 at 11:25, Liang Yang <liang.yang@amlogic.com> wrote:

> Because EMMC and NAND have the same control clock register, so we
> implement a 'sd_emmc_c_clkc'. Previously DTS is defined as below:
>
> 	sd_emmc_c_clkc: mmc@7000 {
> 		compatible = "amlogic,meson-axg-mmc-clkc", "syscon";
> 		reg = <0x0 0x7000 0x0 0x800>;
> 	};
>
> 	nand-controller@7800 {
> 		......
>
> 		clocks = <&clkc CLKID_SD_EMMC_C>,
> 			<&sd_emmc_c_clkc CLKID_MMC_DIV>,
> 			<&sd_emmc_c_clkc CLKID_MMC_PHASE_RX>,
> 			<&sd_emmc_c_clkc CLKID_MMC_PHASE_TX>;
> 		clock-names = "core", "device", "rx", "tx";
> 		amlogic,mmc-syscon = <&sd_emmc_c_clkc>;
>
> 		......
> 	}
>
> but in fact, above implementation is rejected. so now registering
> a nand_divider.

Can you give a bit of context ? a link to the discussion rejecting this

As far as remember, things were getting done for A1 and stopped before
clock part was finished. I'm saying the change is wrong, just that a
discussion is needed before a decision is made.

>
> Change-Id: Ibeb4c7ff886f5886aac4d6c664d7bbd1b1bcb997
> Signed-off-by: Liang Yang <liang.yang@amlogic.com>
> ---
>  drivers/mtd/nand/raw/meson_nand.c | 88 +++++++++++++++++--------------
>  1 file changed, 49 insertions(+), 39 deletions(-)
>
> diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c
> index ac3be92872d0..4472363059c2 100644
> --- a/drivers/mtd/nand/raw/meson_nand.c
> +++ b/drivers/mtd/nand/raw/meson_nand.c
> @@ -2,7 +2,7 @@
>  /*
>   * Amlogic Meson Nand Flash Controller Driver
>   *
> - * Copyright (c) 2018 Amlogic, inc.
> + * Copyright (c) 2018-2021 Amlogic, inc.
>   * Author: Liang Yang <liang.yang@amlogic.com>
>   */
>  
> @@ -10,6 +10,7 @@
>  #include <linux/dma-mapping.h>
>  #include <linux/interrupt.h>
>  #include <linux/clk.h>
> +#include <linux/clk-provider.h>
>  #include <linux/mtd/rawnand.h>
>  #include <linux/mtd/mtd.h>
>  #include <linux/mfd/syscon.h>
> @@ -55,6 +56,7 @@
>  #define NFC_REG_VER		0x38
>  
>  #define NFC_RB_IRQ_EN		BIT(21)
> +#define NFC_CMD_FIFO_RESET	BIT(31)
>  
>  #define CMDRWGEN(cmd_dir, ran, bch, short_mode, page_size, pages)	\
>  	(								\
> @@ -104,6 +106,9 @@
>  
>  #define PER_INFO_BYTE		8
>  
> +#define CLK_DIV_SHIFT		0
> +#define CLK_DIV_WIDTH		6
> +
>  struct meson_nfc_nand_chip {
>  	struct list_head node;
>  	struct nand_chip nand;
> @@ -151,15 +156,15 @@ struct meson_nfc {
>  	struct nand_controller controller;
>  	struct clk *core_clk;
>  	struct clk *device_clk;
> -	struct clk *phase_tx;
> -	struct clk *phase_rx;

I would have been nice to explain why these clock are no longer
required, in the change description maybe ?

> +	struct clk *nand_clk;
> +	struct clk_divider nand_divider;
>  
>  	unsigned long clk_rate;
>  	u32 bus_timing;
>  
>  	struct device *dev;
>  	void __iomem *reg_base;
> -	struct regmap *reg_clk;
> +	void __iomem *reg_clk;
>  	struct completion completion;
>  	struct list_head chips;
>  	const struct meson_nfc_data *data;
> @@ -406,12 +411,14 @@ static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms)
>  	cmd = NFC_CMD_RB | NFC_CMD_RB_INT
>  		| nfc->param.chip_select | nfc->timing.tbers_max;
>  	writel(cmd, nfc->reg_base + NFC_REG_CMD);
> -
> +	meson_nfc_drain_cmd(nfc);

is this clock related ?

>  	ret = wait_for_completion_timeout(&nfc->completion,
>  					  msecs_to_jiffies(timeout_ms));
>  	if (ret == 0)
>  		ret = -1;
>  
> +	/* reset command fifo to avoid lock */
> +	writel(NFC_CMD_FIFO_RESET, nfc->reg_base + NFC_REG_CMD);

Again, not seem to be clock related - does not belong in this patch

>  	return ret;
>  }
>  
> @@ -988,8 +995,9 @@ static const struct mtd_ooblayout_ops meson_ooblayout_ops = {
>  static int meson_nfc_clk_init(struct meson_nfc *nfc)
>  {
>  	int ret;
> +	struct clk_init_data init = {0};
> +	const char *fix_div2_pll_name[1];
>  
> -	/* request core clock */

Why is the comment bothering you ?

>  	nfc->core_clk = devm_clk_get(nfc->dev, "core");
>  	if (IS_ERR(nfc->core_clk)) {
>  		dev_err(nfc->dev, "failed to get core clock\n");
> @@ -1002,21 +1010,25 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>  		return PTR_ERR(nfc->device_clk);
>  	}
>  
> -	nfc->phase_tx = devm_clk_get(nfc->dev, "tx");
> -	if (IS_ERR(nfc->phase_tx)) {
> -		dev_err(nfc->dev, "failed to get TX clk\n");
> -		return PTR_ERR(nfc->phase_tx);
> -	}
> -
> -	nfc->phase_rx = devm_clk_get(nfc->dev, "rx");
> -	if (IS_ERR(nfc->phase_rx)) {
> -		dev_err(nfc->dev, "failed to get RX clk\n");
> -		return PTR_ERR(nfc->phase_rx);
> -	}
> +	init.name = devm_kstrdup(nfc->dev, "nfc#div", GFP_KERNEL);
> +	init.ops = &clk_divider_ops;
> +	fix_div2_pll_name[0] = __clk_get_name(nfc->device_clk);

You should be using "fw_name" so CCF looks a DT directly, instead of this

> +	init.parent_names = fix_div2_pll_name;
> +	init.num_parents = 1;
> +	nfc->nand_divider.reg = nfc->reg_clk;
> +	nfc->nand_divider.shift = CLK_DIV_SHIFT;
> +	nfc->nand_divider.width = CLK_DIV_WIDTH;
> +	nfc->nand_divider.hw.init = &init;
> +	nfc->nand_divider.flags = CLK_DIVIDER_ONE_BASED |
> +				  CLK_DIVIDER_ROUND_CLOSEST |
> +          			  CLK_DIVIDER_ALLOW_ZERO;
> +
> +	nfc->nand_clk = devm_clk_register(nfc->dev, &nfc->nand_divider.hw);
> +	if (IS_ERR(nfc->nand_clk))
> +		return PTR_ERR(nfc->nand_clk);
>  
>  	/* init SD_EMMC_CLOCK to sane defaults w/min clock rate */
> -	regmap_update_bits(nfc->reg_clk,
> -			   0, CLK_SELECT_NAND, CLK_SELECT_NAND);
> +	writel(CLK_SELECT_NAND | readl(nfc->reg_clk), nfc->reg_clk);
>  
>  	ret = clk_prepare_enable(nfc->core_clk);
>  	if (ret) {
> @@ -1030,29 +1042,21 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>  		goto err_device_clk;
>  	}
>  
> -	ret = clk_prepare_enable(nfc->phase_tx);
> +	ret = clk_prepare_enable(nfc->nand_clk);
>  	if (ret) {
> -		dev_err(nfc->dev, "failed to enable TX clock\n");
> -		goto err_phase_tx;
> -	}
> -
> -	ret = clk_prepare_enable(nfc->phase_rx);
> -	if (ret) {
> -		dev_err(nfc->dev, "failed to enable RX clock\n");
> -		goto err_phase_rx;
> +		dev_err(nfc->dev, "pre enable NFC divider fail\n");
> +		goto err_nand_clk;
>  	}
>  
>  	ret = clk_set_rate(nfc->device_clk, 24000000);
>  	if (ret)
> -		goto err_disable_rx;
> +		goto err_disable_clk;
>  
>  	return 0;
>  
> -err_disable_rx:
> -	clk_disable_unprepare(nfc->phase_rx);
> -err_phase_rx:
> -	clk_disable_unprepare(nfc->phase_tx);
> -err_phase_tx:
> +err_disable_clk:
> +	clk_disable_unprepare(nfc->nand_clk);
> +err_nand_clk:
>  	clk_disable_unprepare(nfc->device_clk);
>  err_device_clk:
>  	clk_disable_unprepare(nfc->core_clk);
> @@ -1061,8 +1065,7 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>  
>  static void meson_nfc_disable_clk(struct meson_nfc *nfc)
>  {
> -	clk_disable_unprepare(nfc->phase_rx);
> -	clk_disable_unprepare(nfc->phase_tx);
> +	clk_disable_unprepare(nfc->nand_clk);
>  	clk_disable_unprepare(nfc->device_clk);
>  	clk_disable_unprepare(nfc->core_clk);
>  }
> @@ -1375,6 +1378,7 @@ static int meson_nfc_probe(struct platform_device *pdev)
>  	struct device *dev = &pdev->dev;
>  	struct meson_nfc *nfc;
>  	struct resource *res;
> +	u32 ext_clk_reg;
>  	int ret, irq;
>  
>  	nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL);
> @@ -1396,9 +1400,15 @@ static int meson_nfc_probe(struct platform_device *pdev)
>  	if (IS_ERR(nfc->reg_base))
>  		return PTR_ERR(nfc->reg_base);
>  
> -	nfc->reg_clk =
> -		syscon_regmap_lookup_by_phandle(dev->of_node,
> -						"amlogic,mmc-syscon");
> +	ret = of_property_read_u32(pdev->dev.of_node,
> +				   "sd_emmc_c_clkc",
> +				   &ext_clk_reg);
> +	if (ret) {
> +		dev_err(dev, "failed to get NAND external clock register\n");
> +		return ret;
> +	}
> +
> +	nfc->reg_clk = devm_ioremap(&pdev->dev, ext_clk_reg, sizeof(int));

That's how you should get a register region.
If you want an example of a device claiming several region on amlogic,
have a look at the pinctrl driver. 

>  	if (IS_ERR(nfc->reg_clk)) {
>  		dev_err(dev, "Failed to lookup clock base\n");
>  		return PTR_ERR(nfc->reg_clk);


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH] mtd: rawnand: meson: fix the clock after discarding sd_emmc_c_clkc
  2022-01-06  3:25 ` Liang Yang
@ 2022-01-06 14:03   ` kernel test robot
  -1 siblings, 0 replies; 47+ messages in thread
From: kernel test robot @ 2022-01-06 14:03 UTC (permalink / raw)
  To: Liang Yang, Miquel Raynal, linux-mtd
  Cc: kbuild-all, Liang Yang, Richard Weinberger, Jerome Brunet,
	Neil Armstrong, Martin Blumenstingl, Kevin Hilman, Jianxin Pan,
	Victor Wan

Hi Liang,

I love your patch! Yet something to improve:

[auto build test ERROR on mtd/nand/next]
[also build test ERROR on v5.16-rc8 next-20220105]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Liang-Yang/mtd-rawnand-meson-fix-the-clock-after-discarding-sd_emmc_c_clkc/20220106-114103
base:   https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git nand/next
config: openrisc-randconfig-r012-20220105 (https://download.01.org/0day-ci/archive/20220106/202201062140.24LB23iM-lkp@intel.com/config)
compiler: or1k-linux-gcc (GCC) 11.2.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/a7e02cbd62a38e6fcbdcafe806b129bb287e7cf6
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Liang-Yang/mtd-rawnand-meson-fix-the-clock-after-discarding-sd_emmc_c_clkc/20220106-114103
        git checkout a7e02cbd62a38e6fcbdcafe806b129bb287e7cf6
        # save the config file to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross O=build_dir ARCH=openrisc SHELL=/bin/bash

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   or1k-linux-ld: drivers/mtd/nand/raw/meson_nand.o: in function `meson_nfc_probe':
>> meson_nand.c:(.text+0x21a0): undefined reference to `clk_divider_ops'
>> or1k-linux-ld: meson_nand.c:(.text+0x21a4): undefined reference to `clk_divider_ops'
>> or1k-linux-ld: meson_nand.c:(.text+0x21b0): undefined reference to `__clk_get_name'
   meson_nand.c:(.text+0x21b0): relocation truncated to fit: R_OR1K_INSN_REL_26 against undefined symbol `__clk_get_name'
>> or1k-linux-ld: meson_nand.c:(.text+0x21ec): undefined reference to `devm_clk_register'
   meson_nand.c:(.text+0x21ec): relocation truncated to fit: R_OR1K_INSN_REL_26 against undefined symbol `devm_clk_register'

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH] mtd: rawnand: meson: fix the clock after discarding sd_emmc_c_clkc
@ 2022-01-06 14:03   ` kernel test robot
  0 siblings, 0 replies; 47+ messages in thread
From: kernel test robot @ 2022-01-06 14:03 UTC (permalink / raw)
  To: kbuild-all

[-- Attachment #1: Type: text/plain, Size: 2422 bytes --]

Hi Liang,

I love your patch! Yet something to improve:

[auto build test ERROR on mtd/nand/next]
[also build test ERROR on v5.16-rc8 next-20220105]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Liang-Yang/mtd-rawnand-meson-fix-the-clock-after-discarding-sd_emmc_c_clkc/20220106-114103
base:   https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git nand/next
config: openrisc-randconfig-r012-20220105 (https://download.01.org/0day-ci/archive/20220106/202201062140.24LB23iM-lkp(a)intel.com/config)
compiler: or1k-linux-gcc (GCC) 11.2.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/a7e02cbd62a38e6fcbdcafe806b129bb287e7cf6
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Liang-Yang/mtd-rawnand-meson-fix-the-clock-after-discarding-sd_emmc_c_clkc/20220106-114103
        git checkout a7e02cbd62a38e6fcbdcafe806b129bb287e7cf6
        # save the config file to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross O=build_dir ARCH=openrisc SHELL=/bin/bash

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   or1k-linux-ld: drivers/mtd/nand/raw/meson_nand.o: in function `meson_nfc_probe':
>> meson_nand.c:(.text+0x21a0): undefined reference to `clk_divider_ops'
>> or1k-linux-ld: meson_nand.c:(.text+0x21a4): undefined reference to `clk_divider_ops'
>> or1k-linux-ld: meson_nand.c:(.text+0x21b0): undefined reference to `__clk_get_name'
   meson_nand.c:(.text+0x21b0): relocation truncated to fit: R_OR1K_INSN_REL_26 against undefined symbol `__clk_get_name'
>> or1k-linux-ld: meson_nand.c:(.text+0x21ec): undefined reference to `devm_clk_register'
   meson_nand.c:(.text+0x21ec): relocation truncated to fit: R_OR1K_INSN_REL_26 against undefined symbol `devm_clk_register'

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

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

* Re: [PATCH] mtd: rawnand: meson: fix the clock after discarding sd_emmc_c_clkc
  2022-01-06  3:25 ` Liang Yang
  (?)
@ 2022-01-06 20:40   ` kernel test robot
  -1 siblings, 0 replies; 47+ messages in thread
From: kernel test robot @ 2022-01-06 20:40 UTC (permalink / raw)
  To: Liang Yang, Miquel Raynal, linux-mtd
  Cc: llvm, kbuild-all, Liang Yang, Richard Weinberger, Jerome Brunet,
	Neil Armstrong, Martin Blumenstingl, Kevin Hilman, Jianxin Pan,
	Victor Wan

Hi Liang,

I love your patch! Yet something to improve:

[auto build test ERROR on mtd/nand/next]
[also build test ERROR on v5.16-rc8 next-20220106]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Liang-Yang/mtd-rawnand-meson-fix-the-clock-after-discarding-sd_emmc_c_clkc/20220106-114103
base:   https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git nand/next
config: hexagon-randconfig-r045-20220106 (https://download.01.org/0day-ci/archive/20220107/202201070440.ncSR3Xpb-lkp@intel.com/config)
compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project ca7ffe09dc6e525109e3cd570cc5182ce568be13)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/a7e02cbd62a38e6fcbdcafe806b129bb287e7cf6
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Liang-Yang/mtd-rawnand-meson-fix-the-clock-after-discarding-sd_emmc_c_clkc/20220106-114103
        git checkout a7e02cbd62a38e6fcbdcafe806b129bb287e7cf6
        # save the config file to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=hexagon SHELL=/bin/bash

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

>> ld.lld: error: undefined symbol: __clk_get_name
   >>> referenced by meson_nand.c
   >>> mtd/nand/raw/meson_nand.o:(meson_nfc_probe) in archive drivers/built-in.a
   >>> referenced by meson_nand.c
   >>> mtd/nand/raw/meson_nand.o:(meson_nfc_probe) in archive drivers/built-in.a
--
>> ld.lld: error: undefined symbol: clk_divider_ops
   >>> referenced by meson_nand.c
   >>> mtd/nand/raw/meson_nand.o:(meson_nfc_probe) in archive drivers/built-in.a
   >>> referenced by meson_nand.c
   >>> mtd/nand/raw/meson_nand.o:(meson_nfc_probe) in archive drivers/built-in.a
--
>> ld.lld: error: undefined symbol: devm_clk_register
   >>> referenced by meson_nand.c
   >>> mtd/nand/raw/meson_nand.o:(meson_nfc_probe) in archive drivers/built-in.a
   >>> referenced by meson_nand.c
   >>> mtd/nand/raw/meson_nand.o:(meson_nfc_probe) in archive drivers/built-in.a

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

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

* Re: [PATCH] mtd: rawnand: meson: fix the clock after discarding sd_emmc_c_clkc
@ 2022-01-06 20:40   ` kernel test robot
  0 siblings, 0 replies; 47+ messages in thread
From: kernel test robot @ 2022-01-06 20:40 UTC (permalink / raw)
  To: Liang Yang, Miquel Raynal, linux-mtd
  Cc: llvm, kbuild-all, Liang Yang, Richard Weinberger, Jerome Brunet,
	Neil Armstrong, Martin Blumenstingl, Kevin Hilman, Jianxin Pan,
	Victor Wan

Hi Liang,

I love your patch! Yet something to improve:

[auto build test ERROR on mtd/nand/next]
[also build test ERROR on v5.16-rc8 next-20220106]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Liang-Yang/mtd-rawnand-meson-fix-the-clock-after-discarding-sd_emmc_c_clkc/20220106-114103
base:   https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git nand/next
config: hexagon-randconfig-r045-20220106 (https://download.01.org/0day-ci/archive/20220107/202201070440.ncSR3Xpb-lkp@intel.com/config)
compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project ca7ffe09dc6e525109e3cd570cc5182ce568be13)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/a7e02cbd62a38e6fcbdcafe806b129bb287e7cf6
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Liang-Yang/mtd-rawnand-meson-fix-the-clock-after-discarding-sd_emmc_c_clkc/20220106-114103
        git checkout a7e02cbd62a38e6fcbdcafe806b129bb287e7cf6
        # save the config file to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=hexagon SHELL=/bin/bash

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

>> ld.lld: error: undefined symbol: __clk_get_name
   >>> referenced by meson_nand.c
   >>> mtd/nand/raw/meson_nand.o:(meson_nfc_probe) in archive drivers/built-in.a
   >>> referenced by meson_nand.c
   >>> mtd/nand/raw/meson_nand.o:(meson_nfc_probe) in archive drivers/built-in.a
--
>> ld.lld: error: undefined symbol: clk_divider_ops
   >>> referenced by meson_nand.c
   >>> mtd/nand/raw/meson_nand.o:(meson_nfc_probe) in archive drivers/built-in.a
   >>> referenced by meson_nand.c
   >>> mtd/nand/raw/meson_nand.o:(meson_nfc_probe) in archive drivers/built-in.a
--
>> ld.lld: error: undefined symbol: devm_clk_register
   >>> referenced by meson_nand.c
   >>> mtd/nand/raw/meson_nand.o:(meson_nfc_probe) in archive drivers/built-in.a
   >>> referenced by meson_nand.c
   >>> mtd/nand/raw/meson_nand.o:(meson_nfc_probe) in archive drivers/built-in.a

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH] mtd: rawnand: meson: fix the clock after discarding sd_emmc_c_clkc
@ 2022-01-06 20:40   ` kernel test robot
  0 siblings, 0 replies; 47+ messages in thread
From: kernel test robot @ 2022-01-06 20:40 UTC (permalink / raw)
  To: kbuild-all

[-- Attachment #1: Type: text/plain, Size: 2686 bytes --]

Hi Liang,

I love your patch! Yet something to improve:

[auto build test ERROR on mtd/nand/next]
[also build test ERROR on v5.16-rc8 next-20220106]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Liang-Yang/mtd-rawnand-meson-fix-the-clock-after-discarding-sd_emmc_c_clkc/20220106-114103
base:   https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git nand/next
config: hexagon-randconfig-r045-20220106 (https://download.01.org/0day-ci/archive/20220107/202201070440.ncSR3Xpb-lkp(a)intel.com/config)
compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project ca7ffe09dc6e525109e3cd570cc5182ce568be13)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/a7e02cbd62a38e6fcbdcafe806b129bb287e7cf6
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Liang-Yang/mtd-rawnand-meson-fix-the-clock-after-discarding-sd_emmc_c_clkc/20220106-114103
        git checkout a7e02cbd62a38e6fcbdcafe806b129bb287e7cf6
        # save the config file to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=hexagon SHELL=/bin/bash

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

>> ld.lld: error: undefined symbol: __clk_get_name
   >>> referenced by meson_nand.c
   >>> mtd/nand/raw/meson_nand.o:(meson_nfc_probe) in archive drivers/built-in.a
   >>> referenced by meson_nand.c
   >>> mtd/nand/raw/meson_nand.o:(meson_nfc_probe) in archive drivers/built-in.a
--
>> ld.lld: error: undefined symbol: clk_divider_ops
   >>> referenced by meson_nand.c
   >>> mtd/nand/raw/meson_nand.o:(meson_nfc_probe) in archive drivers/built-in.a
   >>> referenced by meson_nand.c
   >>> mtd/nand/raw/meson_nand.o:(meson_nfc_probe) in archive drivers/built-in.a
--
>> ld.lld: error: undefined symbol: devm_clk_register
   >>> referenced by meson_nand.c
   >>> mtd/nand/raw/meson_nand.o:(meson_nfc_probe) in archive drivers/built-in.a
   >>> referenced by meson_nand.c
   >>> mtd/nand/raw/meson_nand.o:(meson_nfc_probe) in archive drivers/built-in.a

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

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

* Re: [PATCH] mtd: rawnand: meson: fix the clock after discarding sd_emmc_c_clkc
  2022-01-06  3:25 ` Liang Yang
@ 2022-01-06 21:21   ` kernel test robot
  -1 siblings, 0 replies; 47+ messages in thread
From: kernel test robot @ 2022-01-06 21:21 UTC (permalink / raw)
  To: Liang Yang, Miquel Raynal, linux-mtd
  Cc: kbuild-all, Liang Yang, Richard Weinberger, Jerome Brunet,
	Neil Armstrong, Martin Blumenstingl, Kevin Hilman, Jianxin Pan,
	Victor Wan

Hi Liang,

I love your patch! Yet something to improve:

[auto build test ERROR on mtd/nand/next]
[also build test ERROR on v5.16-rc8 next-20220106]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Liang-Yang/mtd-rawnand-meson-fix-the-clock-after-discarding-sd_emmc_c_clkc/20220106-114103
base:   https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git nand/next
config: ia64-randconfig-r035-20220106 (https://download.01.org/0day-ci/archive/20220107/202201070543.goUXCEdh-lkp@intel.com/config)
compiler: ia64-linux-gcc (GCC) 11.2.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/a7e02cbd62a38e6fcbdcafe806b129bb287e7cf6
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Liang-Yang/mtd-rawnand-meson-fix-the-clock-after-discarding-sd_emmc_c_clkc/20220106-114103
        git checkout a7e02cbd62a38e6fcbdcafe806b129bb287e7cf6
        # save the config file to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross O=build_dir ARCH=ia64 SHELL=/bin/bash

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   ia64-linux-ld: drivers/mtd/nand/raw/meson_nand.o: in function `meson_nfc_probe':
   meson_nand.c:(.text+0x3410): undefined reference to `clk_divider_ops'
>> ia64-linux-ld: meson_nand.c:(.text+0x3430): undefined reference to `clk_divider_ops'
>> ia64-linux-ld: meson_nand.c:(.text+0x3442): undefined reference to `__clk_get_name'
>> ia64-linux-ld: meson_nand.c:(.text+0x34d2): undefined reference to `devm_clk_register'

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH] mtd: rawnand: meson: fix the clock after discarding sd_emmc_c_clkc
@ 2022-01-06 21:21   ` kernel test robot
  0 siblings, 0 replies; 47+ messages in thread
From: kernel test robot @ 2022-01-06 21:21 UTC (permalink / raw)
  To: kbuild-all

[-- Attachment #1: Type: text/plain, Size: 2165 bytes --]

Hi Liang,

I love your patch! Yet something to improve:

[auto build test ERROR on mtd/nand/next]
[also build test ERROR on v5.16-rc8 next-20220106]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Liang-Yang/mtd-rawnand-meson-fix-the-clock-after-discarding-sd_emmc_c_clkc/20220106-114103
base:   https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git nand/next
config: ia64-randconfig-r035-20220106 (https://download.01.org/0day-ci/archive/20220107/202201070543.goUXCEdh-lkp(a)intel.com/config)
compiler: ia64-linux-gcc (GCC) 11.2.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/a7e02cbd62a38e6fcbdcafe806b129bb287e7cf6
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Liang-Yang/mtd-rawnand-meson-fix-the-clock-after-discarding-sd_emmc_c_clkc/20220106-114103
        git checkout a7e02cbd62a38e6fcbdcafe806b129bb287e7cf6
        # save the config file to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross O=build_dir ARCH=ia64 SHELL=/bin/bash

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   ia64-linux-ld: drivers/mtd/nand/raw/meson_nand.o: in function `meson_nfc_probe':
   meson_nand.c:(.text+0x3410): undefined reference to `clk_divider_ops'
>> ia64-linux-ld: meson_nand.c:(.text+0x3430): undefined reference to `clk_divider_ops'
>> ia64-linux-ld: meson_nand.c:(.text+0x3442): undefined reference to `__clk_get_name'
>> ia64-linux-ld: meson_nand.c:(.text+0x34d2): undefined reference to `devm_clk_register'

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

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

* Re: [PATCH] mtd: rawnand: meson: fix the clock after discarding sd_emmc_c_clkc
  2022-01-06  8:08   ` Miquel Raynal
  (?)
  (?)
@ 2022-01-07  2:40     ` Liang Yang
  -1 siblings, 0 replies; 47+ messages in thread
From: Liang Yang @ 2022-01-07  2:40 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: linux-mtd, Richard Weinberger, Jerome Brunet, Neil Armstrong,
	Martin Blumenstingl, Kevin Hilman, Jianxin Pan, Victor Wan,
	XianWei Zhao, Kelvin Zhang, BiChao Zheng, YongHui Yu,
	linux-arm-kernel, linux-amlogic, linux-kernel, devicetree

Hi Miquel,

Meson NFC clock depends on the implementation of sd_emmc_c_clkc, but i 
don't find the commit in
linux mainline. then the information i got from 
[jianxin.pan@amlogic.com] is the rejection of
serial patches. I just look into the corresponding emails in link:
 
https://lore.kernel.org/all/86789d73-5a6c-7729-ecd1-dcd342b2fcde@amlogic.com/
it seems the patch never go on since V6, so [jianxin.pan@amlogic.com], 
could you help to clear it?
let us address the discussion in another email from [jbrunet@baylibre.com].

On 2022/1/6 16:08, Miquel Raynal wrote:
> [ EXTERNAL EMAIL ]
> 
> Hi Liang,
> 
> liang.yang@amlogic.com wrote on Thu, 6 Jan 2022 11:25:04 +0800:
> 
>> Because EMMC and NAND have the same control clock register, so we
>> implement a 'sd_emmc_c_clkc'. Previously DTS is defined as below:
>>
>> 	sd_emmc_c_clkc: mmc@7000 {
>> 		compatible = "amlogic,meson-axg-mmc-clkc", "syscon";
>> 		reg = <0x0 0x7000 0x0 0x800>;
>> 	};
>>
>> 	nand-controller@7800 {
>> 		......
>>
>> 		clocks = <&clkc CLKID_SD_EMMC_C>,
>> 			<&sd_emmc_c_clkc CLKID_MMC_DIV>,
>> 			<&sd_emmc_c_clkc CLKID_MMC_PHASE_RX>,
>> 			<&sd_emmc_c_clkc CLKID_MMC_PHASE_TX>;
>> 		clock-names = "core", "device", "rx", "tx";
>> 		amlogic,mmc-syscon = <&sd_emmc_c_clkc>;
>>
>> 		......
>> 	}
>>
>> but in fact, above implementation is rejected. so now registering
>> a nand_divider.
> 
> What is rejected?
> Why is it rejected?
> What is nand_divider?
i simplify our clock framework below, so nand divider is 
SD_EMMC_CLOCK[5:0] here.
			   -----          -----		    -----
	   the other------|	\        |     |	   |	 |
          		  | mux	| -----  |  N  | ----------| NFC/|
	   FCLK_DIV2------|     |        |     |	   | EMMC|
			   -----/         ----- 	    -----
		    SD_EMMC_CLOCK[7:6] SD_EMMC_CLOCK[5:0]
> 
> 
>>
>> Change-Id: Ibeb4c7ff886f5886aac4d6c664d7bbd1b1bcb997
> 
> Change Ids are not expected in the upstream kernel.
> 
> But if you fix something you should have a Fixes:.
> 
>> Signed-off-by: Liang Yang <liang.yang@amlogic.com>
>> ---
>>   drivers/mtd/nand/raw/meson_nand.c | 88 +++++++++++++++++--------------
>>   1 file changed, 49 insertions(+), 39 deletions(-)
>>
>> diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c
>> index ac3be92872d0..4472363059c2 100644
>> --- a/drivers/mtd/nand/raw/meson_nand.c
>> +++ b/drivers/mtd/nand/raw/meson_nand.c
>> @@ -2,7 +2,7 @@
>>   /*
>>    * Amlogic Meson Nand Flash Controller Driver
>>    *
>> - * Copyright (c) 2018 Amlogic, inc.
>> + * Copyright (c) 2018-2021 Amlogic, inc.
>>    * Author: Liang Yang <liang.yang@amlogic.com>
>>    */
>>   
>> @@ -10,6 +10,7 @@
>>   #include <linux/dma-mapping.h>
>>   #include <linux/interrupt.h>
>>   #include <linux/clk.h>
>> +#include <linux/clk-provider.h>
>>   #include <linux/mtd/rawnand.h>
>>   #include <linux/mtd/mtd.h>
>>   #include <linux/mfd/syscon.h>
>> @@ -55,6 +56,7 @@
>>   #define NFC_REG_VER		0x38
>>   
>>   #define NFC_RB_IRQ_EN		BIT(21)
>> +#define NFC_CMD_FIFO_RESET	BIT(31)
>>   
>>   #define CMDRWGEN(cmd_dir, ran, bch, short_mode, page_size, pages)	\
>>   	(								\
>> @@ -104,6 +106,9 @@
>>   
>>   #define PER_INFO_BYTE		8
>>   
>> +#define CLK_DIV_SHIFT		0
>> +#define CLK_DIV_WIDTH		6
>> +
>>   struct meson_nfc_nand_chip {
>>   	struct list_head node;
>>   	struct nand_chip nand;
>> @@ -151,15 +156,15 @@ struct meson_nfc {
>>   	struct nand_controller controller;
>>   	struct clk *core_clk;
>>   	struct clk *device_clk;
>> -	struct clk *phase_tx;
>> -	struct clk *phase_rx;
>> +	struct clk *nand_clk;
>> +	struct clk_divider nand_divider;
>>   
>>   	unsigned long clk_rate;
>>   	u32 bus_timing;
>>   
>>   	struct device *dev;
>>   	void __iomem *reg_base;
>> -	struct regmap *reg_clk;
>> +	void __iomem *reg_clk;
>>   	struct completion completion;
>>   	struct list_head chips;
>>   	const struct meson_nfc_data *data;
>> @@ -406,12 +411,14 @@ static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms)
>>   	cmd = NFC_CMD_RB | NFC_CMD_RB_INT
>>   		| nfc->param.chip_select | nfc->timing.tbers_max;
>>   	writel(cmd, nfc->reg_base + NFC_REG_CMD);
>> -
>> +	meson_nfc_drain_cmd(nfc);
>>   	ret = wait_for_completion_timeout(&nfc->completion,
>>   					  msecs_to_jiffies(timeout_ms));
>>   	if (ret == 0)
>>   		ret = -1;
>>   
>> +	/* reset command fifo to avoid lock */
>> +	writel(NFC_CMD_FIFO_RESET, nfc->reg_base + NFC_REG_CMD);
>>   	return ret;
>>   }
>>   
>> @@ -988,8 +995,9 @@ static const struct mtd_ooblayout_ops meson_ooblayout_ops = {
>>   static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>   {
>>   	int ret;
>> +	struct clk_init_data init = {0};
>> +	const char *fix_div2_pll_name[1];
>>   
>> -	/* request core clock */
>>   	nfc->core_clk = devm_clk_get(nfc->dev, "core");
>>   	if (IS_ERR(nfc->core_clk)) {
>>   		dev_err(nfc->dev, "failed to get core clock\n");
>> @@ -1002,21 +1010,25 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>   		return PTR_ERR(nfc->device_clk);
>>   	}
>>   
>> -	nfc->phase_tx = devm_clk_get(nfc->dev, "tx");
>> -	if (IS_ERR(nfc->phase_tx)) {
>> -		dev_err(nfc->dev, "failed to get TX clk\n");
>> -		return PTR_ERR(nfc->phase_tx);
>> -	}
>> -
>> -	nfc->phase_rx = devm_clk_get(nfc->dev, "rx");
>> -	if (IS_ERR(nfc->phase_rx)) {
>> -		dev_err(nfc->dev, "failed to get RX clk\n");
>> -		return PTR_ERR(nfc->phase_rx);
>> -	}
>> +	init.name = devm_kstrdup(nfc->dev, "nfc#div", GFP_KERNEL);
>> +	init.ops = &clk_divider_ops;
>> +	fix_div2_pll_name[0] = __clk_get_name(nfc->device_clk);
>> +	init.parent_names = fix_div2_pll_name;
>> +	init.num_parents = 1;
>> +	nfc->nand_divider.reg = nfc->reg_clk;
>> +	nfc->nand_divider.shift = CLK_DIV_SHIFT;
>> +	nfc->nand_divider.width = CLK_DIV_WIDTH;
>> +	nfc->nand_divider.hw.init = &init;
>> +	nfc->nand_divider.flags = CLK_DIVIDER_ONE_BASED |
>> +				  CLK_DIVIDER_ROUND_CLOSEST |
>> +          			  CLK_DIVIDER_ALLOW_ZERO;
>> +
>> +	nfc->nand_clk = devm_clk_register(nfc->dev, &nfc->nand_divider.hw);
>> +	if (IS_ERR(nfc->nand_clk))
>> +		return PTR_ERR(nfc->nand_clk);
>>   
>>   	/* init SD_EMMC_CLOCK to sane defaults w/min clock rate */
>> -	regmap_update_bits(nfc->reg_clk,
>> -			   0, CLK_SELECT_NAND, CLK_SELECT_NAND);
>> +	writel(CLK_SELECT_NAND | readl(nfc->reg_clk), nfc->reg_clk);
>>   
>>   	ret = clk_prepare_enable(nfc->core_clk);
>>   	if (ret) {
>> @@ -1030,29 +1042,21 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>   		goto err_device_clk;
>>   	}
>>   
>> -	ret = clk_prepare_enable(nfc->phase_tx);
>> +	ret = clk_prepare_enable(nfc->nand_clk);
>>   	if (ret) {
>> -		dev_err(nfc->dev, "failed to enable TX clock\n");
>> -		goto err_phase_tx;
>> -	}
>> -
>> -	ret = clk_prepare_enable(nfc->phase_rx);
>> -	if (ret) {
>> -		dev_err(nfc->dev, "failed to enable RX clock\n");
>> -		goto err_phase_rx;
>> +		dev_err(nfc->dev, "pre enable NFC divider fail\n");
>> +		goto err_nand_clk;
>>   	}
>>   
>>   	ret = clk_set_rate(nfc->device_clk, 24000000);
>>   	if (ret)
>> -		goto err_disable_rx;
>> +		goto err_disable_clk;
>>   
>>   	return 0;
>>   
>> -err_disable_rx:
>> -	clk_disable_unprepare(nfc->phase_rx);
>> -err_phase_rx:
>> -	clk_disable_unprepare(nfc->phase_tx);
>> -err_phase_tx:
>> +err_disable_clk:
>> +	clk_disable_unprepare(nfc->nand_clk);
>> +err_nand_clk:
>>   	clk_disable_unprepare(nfc->device_clk);
>>   err_device_clk:
>>   	clk_disable_unprepare(nfc->core_clk);
>> @@ -1061,8 +1065,7 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>   
>>   static void meson_nfc_disable_clk(struct meson_nfc *nfc)
>>   {
>> -	clk_disable_unprepare(nfc->phase_rx);
>> -	clk_disable_unprepare(nfc->phase_tx);
>> +	clk_disable_unprepare(nfc->nand_clk);
>>   	clk_disable_unprepare(nfc->device_clk);
>>   	clk_disable_unprepare(nfc->core_clk);
>>   }
>> @@ -1375,6 +1378,7 @@ static int meson_nfc_probe(struct platform_device *pdev)
>>   	struct device *dev = &pdev->dev;
>>   	struct meson_nfc *nfc;
>>   	struct resource *res;
>> +	u32 ext_clk_reg;
>>   	int ret, irq;
>>   
>>   	nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL);
>> @@ -1396,9 +1400,15 @@ static int meson_nfc_probe(struct platform_device *pdev)
>>   	if (IS_ERR(nfc->reg_base))
>>   		return PTR_ERR(nfc->reg_base);
>>   
>> -	nfc->reg_clk =
>> -		syscon_regmap_lookup_by_phandle(dev->of_node,
>> -						"amlogic,mmc-syscon");
>> +	ret = of_property_read_u32(pdev->dev.of_node,
>> +				   "sd_emmc_c_clkc",
>> +				   &ext_clk_reg);
>> +	if (ret) {
>> +		dev_err(dev, "failed to get NAND external clock register\n");
>> +		return ret;
>> +	}
>> +
>> +	nfc->reg_clk = devm_ioremap(&pdev->dev, ext_clk_reg, sizeof(int));
>>   	if (IS_ERR(nfc->reg_clk)) {
>>   		dev_err(dev, "Failed to lookup clock base\n");
>>   		return PTR_ERR(nfc->reg_clk);
> 
> 
> Thanks,
> Miquèl
> 
> .

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

* Re: [PATCH] mtd: rawnand: meson: fix the clock after discarding sd_emmc_c_clkc
@ 2022-01-07  2:40     ` Liang Yang
  0 siblings, 0 replies; 47+ messages in thread
From: Liang Yang @ 2022-01-07  2:40 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: linux-mtd, Richard Weinberger, Jerome Brunet, Neil Armstrong,
	Martin Blumenstingl, Kevin Hilman, Jianxin Pan, Victor Wan,
	XianWei Zhao, Kelvin Zhang, BiChao Zheng, YongHui Yu,
	linux-arm-kernel, linux-amlogic, linux-kernel, devicetree

Hi Miquel,

Meson NFC clock depends on the implementation of sd_emmc_c_clkc, but i 
don't find the commit in
linux mainline. then the information i got from 
[jianxin.pan@amlogic.com] is the rejection of
serial patches. I just look into the corresponding emails in link:
 
https://lore.kernel.org/all/86789d73-5a6c-7729-ecd1-dcd342b2fcde@amlogic.com/
it seems the patch never go on since V6, so [jianxin.pan@amlogic.com], 
could you help to clear it?
let us address the discussion in another email from [jbrunet@baylibre.com].

On 2022/1/6 16:08, Miquel Raynal wrote:
> [ EXTERNAL EMAIL ]
> 
> Hi Liang,
> 
> liang.yang@amlogic.com wrote on Thu, 6 Jan 2022 11:25:04 +0800:
> 
>> Because EMMC and NAND have the same control clock register, so we
>> implement a 'sd_emmc_c_clkc'. Previously DTS is defined as below:
>>
>> 	sd_emmc_c_clkc: mmc@7000 {
>> 		compatible = "amlogic,meson-axg-mmc-clkc", "syscon";
>> 		reg = <0x0 0x7000 0x0 0x800>;
>> 	};
>>
>> 	nand-controller@7800 {
>> 		......
>>
>> 		clocks = <&clkc CLKID_SD_EMMC_C>,
>> 			<&sd_emmc_c_clkc CLKID_MMC_DIV>,
>> 			<&sd_emmc_c_clkc CLKID_MMC_PHASE_RX>,
>> 			<&sd_emmc_c_clkc CLKID_MMC_PHASE_TX>;
>> 		clock-names = "core", "device", "rx", "tx";
>> 		amlogic,mmc-syscon = <&sd_emmc_c_clkc>;
>>
>> 		......
>> 	}
>>
>> but in fact, above implementation is rejected. so now registering
>> a nand_divider.
> 
> What is rejected?
> Why is it rejected?
> What is nand_divider?
i simplify our clock framework below, so nand divider is 
SD_EMMC_CLOCK[5:0] here.
			   -----          -----		    -----
	   the other------|	\        |     |	   |	 |
          		  | mux	| -----  |  N  | ----------| NFC/|
	   FCLK_DIV2------|     |        |     |	   | EMMC|
			   -----/         ----- 	    -----
		    SD_EMMC_CLOCK[7:6] SD_EMMC_CLOCK[5:0]
> 
> 
>>
>> Change-Id: Ibeb4c7ff886f5886aac4d6c664d7bbd1b1bcb997
> 
> Change Ids are not expected in the upstream kernel.
> 
> But if you fix something you should have a Fixes:.
> 
>> Signed-off-by: Liang Yang <liang.yang@amlogic.com>
>> ---
>>   drivers/mtd/nand/raw/meson_nand.c | 88 +++++++++++++++++--------------
>>   1 file changed, 49 insertions(+), 39 deletions(-)
>>
>> diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c
>> index ac3be92872d0..4472363059c2 100644
>> --- a/drivers/mtd/nand/raw/meson_nand.c
>> +++ b/drivers/mtd/nand/raw/meson_nand.c
>> @@ -2,7 +2,7 @@
>>   /*
>>    * Amlogic Meson Nand Flash Controller Driver
>>    *
>> - * Copyright (c) 2018 Amlogic, inc.
>> + * Copyright (c) 2018-2021 Amlogic, inc.
>>    * Author: Liang Yang <liang.yang@amlogic.com>
>>    */
>>   
>> @@ -10,6 +10,7 @@
>>   #include <linux/dma-mapping.h>
>>   #include <linux/interrupt.h>
>>   #include <linux/clk.h>
>> +#include <linux/clk-provider.h>
>>   #include <linux/mtd/rawnand.h>
>>   #include <linux/mtd/mtd.h>
>>   #include <linux/mfd/syscon.h>
>> @@ -55,6 +56,7 @@
>>   #define NFC_REG_VER		0x38
>>   
>>   #define NFC_RB_IRQ_EN		BIT(21)
>> +#define NFC_CMD_FIFO_RESET	BIT(31)
>>   
>>   #define CMDRWGEN(cmd_dir, ran, bch, short_mode, page_size, pages)	\
>>   	(								\
>> @@ -104,6 +106,9 @@
>>   
>>   #define PER_INFO_BYTE		8
>>   
>> +#define CLK_DIV_SHIFT		0
>> +#define CLK_DIV_WIDTH		6
>> +
>>   struct meson_nfc_nand_chip {
>>   	struct list_head node;
>>   	struct nand_chip nand;
>> @@ -151,15 +156,15 @@ struct meson_nfc {
>>   	struct nand_controller controller;
>>   	struct clk *core_clk;
>>   	struct clk *device_clk;
>> -	struct clk *phase_tx;
>> -	struct clk *phase_rx;
>> +	struct clk *nand_clk;
>> +	struct clk_divider nand_divider;
>>   
>>   	unsigned long clk_rate;
>>   	u32 bus_timing;
>>   
>>   	struct device *dev;
>>   	void __iomem *reg_base;
>> -	struct regmap *reg_clk;
>> +	void __iomem *reg_clk;
>>   	struct completion completion;
>>   	struct list_head chips;
>>   	const struct meson_nfc_data *data;
>> @@ -406,12 +411,14 @@ static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms)
>>   	cmd = NFC_CMD_RB | NFC_CMD_RB_INT
>>   		| nfc->param.chip_select | nfc->timing.tbers_max;
>>   	writel(cmd, nfc->reg_base + NFC_REG_CMD);
>> -
>> +	meson_nfc_drain_cmd(nfc);
>>   	ret = wait_for_completion_timeout(&nfc->completion,
>>   					  msecs_to_jiffies(timeout_ms));
>>   	if (ret == 0)
>>   		ret = -1;
>>   
>> +	/* reset command fifo to avoid lock */
>> +	writel(NFC_CMD_FIFO_RESET, nfc->reg_base + NFC_REG_CMD);
>>   	return ret;
>>   }
>>   
>> @@ -988,8 +995,9 @@ static const struct mtd_ooblayout_ops meson_ooblayout_ops = {
>>   static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>   {
>>   	int ret;
>> +	struct clk_init_data init = {0};
>> +	const char *fix_div2_pll_name[1];
>>   
>> -	/* request core clock */
>>   	nfc->core_clk = devm_clk_get(nfc->dev, "core");
>>   	if (IS_ERR(nfc->core_clk)) {
>>   		dev_err(nfc->dev, "failed to get core clock\n");
>> @@ -1002,21 +1010,25 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>   		return PTR_ERR(nfc->device_clk);
>>   	}
>>   
>> -	nfc->phase_tx = devm_clk_get(nfc->dev, "tx");
>> -	if (IS_ERR(nfc->phase_tx)) {
>> -		dev_err(nfc->dev, "failed to get TX clk\n");
>> -		return PTR_ERR(nfc->phase_tx);
>> -	}
>> -
>> -	nfc->phase_rx = devm_clk_get(nfc->dev, "rx");
>> -	if (IS_ERR(nfc->phase_rx)) {
>> -		dev_err(nfc->dev, "failed to get RX clk\n");
>> -		return PTR_ERR(nfc->phase_rx);
>> -	}
>> +	init.name = devm_kstrdup(nfc->dev, "nfc#div", GFP_KERNEL);
>> +	init.ops = &clk_divider_ops;
>> +	fix_div2_pll_name[0] = __clk_get_name(nfc->device_clk);
>> +	init.parent_names = fix_div2_pll_name;
>> +	init.num_parents = 1;
>> +	nfc->nand_divider.reg = nfc->reg_clk;
>> +	nfc->nand_divider.shift = CLK_DIV_SHIFT;
>> +	nfc->nand_divider.width = CLK_DIV_WIDTH;
>> +	nfc->nand_divider.hw.init = &init;
>> +	nfc->nand_divider.flags = CLK_DIVIDER_ONE_BASED |
>> +				  CLK_DIVIDER_ROUND_CLOSEST |
>> +          			  CLK_DIVIDER_ALLOW_ZERO;
>> +
>> +	nfc->nand_clk = devm_clk_register(nfc->dev, &nfc->nand_divider.hw);
>> +	if (IS_ERR(nfc->nand_clk))
>> +		return PTR_ERR(nfc->nand_clk);
>>   
>>   	/* init SD_EMMC_CLOCK to sane defaults w/min clock rate */
>> -	regmap_update_bits(nfc->reg_clk,
>> -			   0, CLK_SELECT_NAND, CLK_SELECT_NAND);
>> +	writel(CLK_SELECT_NAND | readl(nfc->reg_clk), nfc->reg_clk);
>>   
>>   	ret = clk_prepare_enable(nfc->core_clk);
>>   	if (ret) {
>> @@ -1030,29 +1042,21 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>   		goto err_device_clk;
>>   	}
>>   
>> -	ret = clk_prepare_enable(nfc->phase_tx);
>> +	ret = clk_prepare_enable(nfc->nand_clk);
>>   	if (ret) {
>> -		dev_err(nfc->dev, "failed to enable TX clock\n");
>> -		goto err_phase_tx;
>> -	}
>> -
>> -	ret = clk_prepare_enable(nfc->phase_rx);
>> -	if (ret) {
>> -		dev_err(nfc->dev, "failed to enable RX clock\n");
>> -		goto err_phase_rx;
>> +		dev_err(nfc->dev, "pre enable NFC divider fail\n");
>> +		goto err_nand_clk;
>>   	}
>>   
>>   	ret = clk_set_rate(nfc->device_clk, 24000000);
>>   	if (ret)
>> -		goto err_disable_rx;
>> +		goto err_disable_clk;
>>   
>>   	return 0;
>>   
>> -err_disable_rx:
>> -	clk_disable_unprepare(nfc->phase_rx);
>> -err_phase_rx:
>> -	clk_disable_unprepare(nfc->phase_tx);
>> -err_phase_tx:
>> +err_disable_clk:
>> +	clk_disable_unprepare(nfc->nand_clk);
>> +err_nand_clk:
>>   	clk_disable_unprepare(nfc->device_clk);
>>   err_device_clk:
>>   	clk_disable_unprepare(nfc->core_clk);
>> @@ -1061,8 +1065,7 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>   
>>   static void meson_nfc_disable_clk(struct meson_nfc *nfc)
>>   {
>> -	clk_disable_unprepare(nfc->phase_rx);
>> -	clk_disable_unprepare(nfc->phase_tx);
>> +	clk_disable_unprepare(nfc->nand_clk);
>>   	clk_disable_unprepare(nfc->device_clk);
>>   	clk_disable_unprepare(nfc->core_clk);
>>   }
>> @@ -1375,6 +1378,7 @@ static int meson_nfc_probe(struct platform_device *pdev)
>>   	struct device *dev = &pdev->dev;
>>   	struct meson_nfc *nfc;
>>   	struct resource *res;
>> +	u32 ext_clk_reg;
>>   	int ret, irq;
>>   
>>   	nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL);
>> @@ -1396,9 +1400,15 @@ static int meson_nfc_probe(struct platform_device *pdev)
>>   	if (IS_ERR(nfc->reg_base))
>>   		return PTR_ERR(nfc->reg_base);
>>   
>> -	nfc->reg_clk =
>> -		syscon_regmap_lookup_by_phandle(dev->of_node,
>> -						"amlogic,mmc-syscon");
>> +	ret = of_property_read_u32(pdev->dev.of_node,
>> +				   "sd_emmc_c_clkc",
>> +				   &ext_clk_reg);
>> +	if (ret) {
>> +		dev_err(dev, "failed to get NAND external clock register\n");
>> +		return ret;
>> +	}
>> +
>> +	nfc->reg_clk = devm_ioremap(&pdev->dev, ext_clk_reg, sizeof(int));
>>   	if (IS_ERR(nfc->reg_clk)) {
>>   		dev_err(dev, "Failed to lookup clock base\n");
>>   		return PTR_ERR(nfc->reg_clk);
> 
> 
> Thanks,
> Miquèl
> 
> .

_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic

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

* Re: [PATCH] mtd: rawnand: meson: fix the clock after discarding sd_emmc_c_clkc
@ 2022-01-07  2:40     ` Liang Yang
  0 siblings, 0 replies; 47+ messages in thread
From: Liang Yang @ 2022-01-07  2:40 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: linux-mtd, Richard Weinberger, Jerome Brunet, Neil Armstrong,
	Martin Blumenstingl, Kevin Hilman, Jianxin Pan, Victor Wan,
	XianWei Zhao, Kelvin Zhang, BiChao Zheng, YongHui Yu,
	linux-arm-kernel, linux-amlogic, linux-kernel, devicetree

Hi Miquel,

Meson NFC clock depends on the implementation of sd_emmc_c_clkc, but i 
don't find the commit in
linux mainline. then the information i got from 
[jianxin.pan@amlogic.com] is the rejection of
serial patches. I just look into the corresponding emails in link:
 
https://lore.kernel.org/all/86789d73-5a6c-7729-ecd1-dcd342b2fcde@amlogic.com/
it seems the patch never go on since V6, so [jianxin.pan@amlogic.com], 
could you help to clear it?
let us address the discussion in another email from [jbrunet@baylibre.com].

On 2022/1/6 16:08, Miquel Raynal wrote:
> [ EXTERNAL EMAIL ]
> 
> Hi Liang,
> 
> liang.yang@amlogic.com wrote on Thu, 6 Jan 2022 11:25:04 +0800:
> 
>> Because EMMC and NAND have the same control clock register, so we
>> implement a 'sd_emmc_c_clkc'. Previously DTS is defined as below:
>>
>> 	sd_emmc_c_clkc: mmc@7000 {
>> 		compatible = "amlogic,meson-axg-mmc-clkc", "syscon";
>> 		reg = <0x0 0x7000 0x0 0x800>;
>> 	};
>>
>> 	nand-controller@7800 {
>> 		......
>>
>> 		clocks = <&clkc CLKID_SD_EMMC_C>,
>> 			<&sd_emmc_c_clkc CLKID_MMC_DIV>,
>> 			<&sd_emmc_c_clkc CLKID_MMC_PHASE_RX>,
>> 			<&sd_emmc_c_clkc CLKID_MMC_PHASE_TX>;
>> 		clock-names = "core", "device", "rx", "tx";
>> 		amlogic,mmc-syscon = <&sd_emmc_c_clkc>;
>>
>> 		......
>> 	}
>>
>> but in fact, above implementation is rejected. so now registering
>> a nand_divider.
> 
> What is rejected?
> Why is it rejected?
> What is nand_divider?
i simplify our clock framework below, so nand divider is 
SD_EMMC_CLOCK[5:0] here.
			   -----          -----		    -----
	   the other------|	\        |     |	   |	 |
          		  | mux	| -----  |  N  | ----------| NFC/|
	   FCLK_DIV2------|     |        |     |	   | EMMC|
			   -----/         ----- 	    -----
		    SD_EMMC_CLOCK[7:6] SD_EMMC_CLOCK[5:0]
> 
> 
>>
>> Change-Id: Ibeb4c7ff886f5886aac4d6c664d7bbd1b1bcb997
> 
> Change Ids are not expected in the upstream kernel.
> 
> But if you fix something you should have a Fixes:.
> 
>> Signed-off-by: Liang Yang <liang.yang@amlogic.com>
>> ---
>>   drivers/mtd/nand/raw/meson_nand.c | 88 +++++++++++++++++--------------
>>   1 file changed, 49 insertions(+), 39 deletions(-)
>>
>> diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c
>> index ac3be92872d0..4472363059c2 100644
>> --- a/drivers/mtd/nand/raw/meson_nand.c
>> +++ b/drivers/mtd/nand/raw/meson_nand.c
>> @@ -2,7 +2,7 @@
>>   /*
>>    * Amlogic Meson Nand Flash Controller Driver
>>    *
>> - * Copyright (c) 2018 Amlogic, inc.
>> + * Copyright (c) 2018-2021 Amlogic, inc.
>>    * Author: Liang Yang <liang.yang@amlogic.com>
>>    */
>>   
>> @@ -10,6 +10,7 @@
>>   #include <linux/dma-mapping.h>
>>   #include <linux/interrupt.h>
>>   #include <linux/clk.h>
>> +#include <linux/clk-provider.h>
>>   #include <linux/mtd/rawnand.h>
>>   #include <linux/mtd/mtd.h>
>>   #include <linux/mfd/syscon.h>
>> @@ -55,6 +56,7 @@
>>   #define NFC_REG_VER		0x38
>>   
>>   #define NFC_RB_IRQ_EN		BIT(21)
>> +#define NFC_CMD_FIFO_RESET	BIT(31)
>>   
>>   #define CMDRWGEN(cmd_dir, ran, bch, short_mode, page_size, pages)	\
>>   	(								\
>> @@ -104,6 +106,9 @@
>>   
>>   #define PER_INFO_BYTE		8
>>   
>> +#define CLK_DIV_SHIFT		0
>> +#define CLK_DIV_WIDTH		6
>> +
>>   struct meson_nfc_nand_chip {
>>   	struct list_head node;
>>   	struct nand_chip nand;
>> @@ -151,15 +156,15 @@ struct meson_nfc {
>>   	struct nand_controller controller;
>>   	struct clk *core_clk;
>>   	struct clk *device_clk;
>> -	struct clk *phase_tx;
>> -	struct clk *phase_rx;
>> +	struct clk *nand_clk;
>> +	struct clk_divider nand_divider;
>>   
>>   	unsigned long clk_rate;
>>   	u32 bus_timing;
>>   
>>   	struct device *dev;
>>   	void __iomem *reg_base;
>> -	struct regmap *reg_clk;
>> +	void __iomem *reg_clk;
>>   	struct completion completion;
>>   	struct list_head chips;
>>   	const struct meson_nfc_data *data;
>> @@ -406,12 +411,14 @@ static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms)
>>   	cmd = NFC_CMD_RB | NFC_CMD_RB_INT
>>   		| nfc->param.chip_select | nfc->timing.tbers_max;
>>   	writel(cmd, nfc->reg_base + NFC_REG_CMD);
>> -
>> +	meson_nfc_drain_cmd(nfc);
>>   	ret = wait_for_completion_timeout(&nfc->completion,
>>   					  msecs_to_jiffies(timeout_ms));
>>   	if (ret == 0)
>>   		ret = -1;
>>   
>> +	/* reset command fifo to avoid lock */
>> +	writel(NFC_CMD_FIFO_RESET, nfc->reg_base + NFC_REG_CMD);
>>   	return ret;
>>   }
>>   
>> @@ -988,8 +995,9 @@ static const struct mtd_ooblayout_ops meson_ooblayout_ops = {
>>   static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>   {
>>   	int ret;
>> +	struct clk_init_data init = {0};
>> +	const char *fix_div2_pll_name[1];
>>   
>> -	/* request core clock */
>>   	nfc->core_clk = devm_clk_get(nfc->dev, "core");
>>   	if (IS_ERR(nfc->core_clk)) {
>>   		dev_err(nfc->dev, "failed to get core clock\n");
>> @@ -1002,21 +1010,25 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>   		return PTR_ERR(nfc->device_clk);
>>   	}
>>   
>> -	nfc->phase_tx = devm_clk_get(nfc->dev, "tx");
>> -	if (IS_ERR(nfc->phase_tx)) {
>> -		dev_err(nfc->dev, "failed to get TX clk\n");
>> -		return PTR_ERR(nfc->phase_tx);
>> -	}
>> -
>> -	nfc->phase_rx = devm_clk_get(nfc->dev, "rx");
>> -	if (IS_ERR(nfc->phase_rx)) {
>> -		dev_err(nfc->dev, "failed to get RX clk\n");
>> -		return PTR_ERR(nfc->phase_rx);
>> -	}
>> +	init.name = devm_kstrdup(nfc->dev, "nfc#div", GFP_KERNEL);
>> +	init.ops = &clk_divider_ops;
>> +	fix_div2_pll_name[0] = __clk_get_name(nfc->device_clk);
>> +	init.parent_names = fix_div2_pll_name;
>> +	init.num_parents = 1;
>> +	nfc->nand_divider.reg = nfc->reg_clk;
>> +	nfc->nand_divider.shift = CLK_DIV_SHIFT;
>> +	nfc->nand_divider.width = CLK_DIV_WIDTH;
>> +	nfc->nand_divider.hw.init = &init;
>> +	nfc->nand_divider.flags = CLK_DIVIDER_ONE_BASED |
>> +				  CLK_DIVIDER_ROUND_CLOSEST |
>> +          			  CLK_DIVIDER_ALLOW_ZERO;
>> +
>> +	nfc->nand_clk = devm_clk_register(nfc->dev, &nfc->nand_divider.hw);
>> +	if (IS_ERR(nfc->nand_clk))
>> +		return PTR_ERR(nfc->nand_clk);
>>   
>>   	/* init SD_EMMC_CLOCK to sane defaults w/min clock rate */
>> -	regmap_update_bits(nfc->reg_clk,
>> -			   0, CLK_SELECT_NAND, CLK_SELECT_NAND);
>> +	writel(CLK_SELECT_NAND | readl(nfc->reg_clk), nfc->reg_clk);
>>   
>>   	ret = clk_prepare_enable(nfc->core_clk);
>>   	if (ret) {
>> @@ -1030,29 +1042,21 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>   		goto err_device_clk;
>>   	}
>>   
>> -	ret = clk_prepare_enable(nfc->phase_tx);
>> +	ret = clk_prepare_enable(nfc->nand_clk);
>>   	if (ret) {
>> -		dev_err(nfc->dev, "failed to enable TX clock\n");
>> -		goto err_phase_tx;
>> -	}
>> -
>> -	ret = clk_prepare_enable(nfc->phase_rx);
>> -	if (ret) {
>> -		dev_err(nfc->dev, "failed to enable RX clock\n");
>> -		goto err_phase_rx;
>> +		dev_err(nfc->dev, "pre enable NFC divider fail\n");
>> +		goto err_nand_clk;
>>   	}
>>   
>>   	ret = clk_set_rate(nfc->device_clk, 24000000);
>>   	if (ret)
>> -		goto err_disable_rx;
>> +		goto err_disable_clk;
>>   
>>   	return 0;
>>   
>> -err_disable_rx:
>> -	clk_disable_unprepare(nfc->phase_rx);
>> -err_phase_rx:
>> -	clk_disable_unprepare(nfc->phase_tx);
>> -err_phase_tx:
>> +err_disable_clk:
>> +	clk_disable_unprepare(nfc->nand_clk);
>> +err_nand_clk:
>>   	clk_disable_unprepare(nfc->device_clk);
>>   err_device_clk:
>>   	clk_disable_unprepare(nfc->core_clk);
>> @@ -1061,8 +1065,7 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>   
>>   static void meson_nfc_disable_clk(struct meson_nfc *nfc)
>>   {
>> -	clk_disable_unprepare(nfc->phase_rx);
>> -	clk_disable_unprepare(nfc->phase_tx);
>> +	clk_disable_unprepare(nfc->nand_clk);
>>   	clk_disable_unprepare(nfc->device_clk);
>>   	clk_disable_unprepare(nfc->core_clk);
>>   }
>> @@ -1375,6 +1378,7 @@ static int meson_nfc_probe(struct platform_device *pdev)
>>   	struct device *dev = &pdev->dev;
>>   	struct meson_nfc *nfc;
>>   	struct resource *res;
>> +	u32 ext_clk_reg;
>>   	int ret, irq;
>>   
>>   	nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL);
>> @@ -1396,9 +1400,15 @@ static int meson_nfc_probe(struct platform_device *pdev)
>>   	if (IS_ERR(nfc->reg_base))
>>   		return PTR_ERR(nfc->reg_base);
>>   
>> -	nfc->reg_clk =
>> -		syscon_regmap_lookup_by_phandle(dev->of_node,
>> -						"amlogic,mmc-syscon");
>> +	ret = of_property_read_u32(pdev->dev.of_node,
>> +				   "sd_emmc_c_clkc",
>> +				   &ext_clk_reg);
>> +	if (ret) {
>> +		dev_err(dev, "failed to get NAND external clock register\n");
>> +		return ret;
>> +	}
>> +
>> +	nfc->reg_clk = devm_ioremap(&pdev->dev, ext_clk_reg, sizeof(int));
>>   	if (IS_ERR(nfc->reg_clk)) {
>>   		dev_err(dev, "Failed to lookup clock base\n");
>>   		return PTR_ERR(nfc->reg_clk);
> 
> 
> Thanks,
> Miquèl
> 
> .

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH] mtd: rawnand: meson: fix the clock after discarding sd_emmc_c_clkc
@ 2022-01-07  2:40     ` Liang Yang
  0 siblings, 0 replies; 47+ messages in thread
From: Liang Yang @ 2022-01-07  2:40 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: linux-mtd, Richard Weinberger, Jerome Brunet, Neil Armstrong,
	Martin Blumenstingl, Kevin Hilman, Jianxin Pan, Victor Wan,
	XianWei Zhao, Kelvin Zhang, BiChao Zheng, YongHui Yu,
	linux-arm-kernel, linux-amlogic, linux-kernel, devicetree

Hi Miquel,

Meson NFC clock depends on the implementation of sd_emmc_c_clkc, but i 
don't find the commit in
linux mainline. then the information i got from 
[jianxin.pan@amlogic.com] is the rejection of
serial patches. I just look into the corresponding emails in link:
 
https://lore.kernel.org/all/86789d73-5a6c-7729-ecd1-dcd342b2fcde@amlogic.com/
it seems the patch never go on since V6, so [jianxin.pan@amlogic.com], 
could you help to clear it?
let us address the discussion in another email from [jbrunet@baylibre.com].

On 2022/1/6 16:08, Miquel Raynal wrote:
> [ EXTERNAL EMAIL ]
> 
> Hi Liang,
> 
> liang.yang@amlogic.com wrote on Thu, 6 Jan 2022 11:25:04 +0800:
> 
>> Because EMMC and NAND have the same control clock register, so we
>> implement a 'sd_emmc_c_clkc'. Previously DTS is defined as below:
>>
>> 	sd_emmc_c_clkc: mmc@7000 {
>> 		compatible = "amlogic,meson-axg-mmc-clkc", "syscon";
>> 		reg = <0x0 0x7000 0x0 0x800>;
>> 	};
>>
>> 	nand-controller@7800 {
>> 		......
>>
>> 		clocks = <&clkc CLKID_SD_EMMC_C>,
>> 			<&sd_emmc_c_clkc CLKID_MMC_DIV>,
>> 			<&sd_emmc_c_clkc CLKID_MMC_PHASE_RX>,
>> 			<&sd_emmc_c_clkc CLKID_MMC_PHASE_TX>;
>> 		clock-names = "core", "device", "rx", "tx";
>> 		amlogic,mmc-syscon = <&sd_emmc_c_clkc>;
>>
>> 		......
>> 	}
>>
>> but in fact, above implementation is rejected. so now registering
>> a nand_divider.
> 
> What is rejected?
> Why is it rejected?
> What is nand_divider?
i simplify our clock framework below, so nand divider is 
SD_EMMC_CLOCK[5:0] here.
			   -----          -----		    -----
	   the other------|	\        |     |	   |	 |
          		  | mux	| -----  |  N  | ----------| NFC/|
	   FCLK_DIV2------|     |        |     |	   | EMMC|
			   -----/         ----- 	    -----
		    SD_EMMC_CLOCK[7:6] SD_EMMC_CLOCK[5:0]
> 
> 
>>
>> Change-Id: Ibeb4c7ff886f5886aac4d6c664d7bbd1b1bcb997
> 
> Change Ids are not expected in the upstream kernel.
> 
> But if you fix something you should have a Fixes:.
> 
>> Signed-off-by: Liang Yang <liang.yang@amlogic.com>
>> ---
>>   drivers/mtd/nand/raw/meson_nand.c | 88 +++++++++++++++++--------------
>>   1 file changed, 49 insertions(+), 39 deletions(-)
>>
>> diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c
>> index ac3be92872d0..4472363059c2 100644
>> --- a/drivers/mtd/nand/raw/meson_nand.c
>> +++ b/drivers/mtd/nand/raw/meson_nand.c
>> @@ -2,7 +2,7 @@
>>   /*
>>    * Amlogic Meson Nand Flash Controller Driver
>>    *
>> - * Copyright (c) 2018 Amlogic, inc.
>> + * Copyright (c) 2018-2021 Amlogic, inc.
>>    * Author: Liang Yang <liang.yang@amlogic.com>
>>    */
>>   
>> @@ -10,6 +10,7 @@
>>   #include <linux/dma-mapping.h>
>>   #include <linux/interrupt.h>
>>   #include <linux/clk.h>
>> +#include <linux/clk-provider.h>
>>   #include <linux/mtd/rawnand.h>
>>   #include <linux/mtd/mtd.h>
>>   #include <linux/mfd/syscon.h>
>> @@ -55,6 +56,7 @@
>>   #define NFC_REG_VER		0x38
>>   
>>   #define NFC_RB_IRQ_EN		BIT(21)
>> +#define NFC_CMD_FIFO_RESET	BIT(31)
>>   
>>   #define CMDRWGEN(cmd_dir, ran, bch, short_mode, page_size, pages)	\
>>   	(								\
>> @@ -104,6 +106,9 @@
>>   
>>   #define PER_INFO_BYTE		8
>>   
>> +#define CLK_DIV_SHIFT		0
>> +#define CLK_DIV_WIDTH		6
>> +
>>   struct meson_nfc_nand_chip {
>>   	struct list_head node;
>>   	struct nand_chip nand;
>> @@ -151,15 +156,15 @@ struct meson_nfc {
>>   	struct nand_controller controller;
>>   	struct clk *core_clk;
>>   	struct clk *device_clk;
>> -	struct clk *phase_tx;
>> -	struct clk *phase_rx;
>> +	struct clk *nand_clk;
>> +	struct clk_divider nand_divider;
>>   
>>   	unsigned long clk_rate;
>>   	u32 bus_timing;
>>   
>>   	struct device *dev;
>>   	void __iomem *reg_base;
>> -	struct regmap *reg_clk;
>> +	void __iomem *reg_clk;
>>   	struct completion completion;
>>   	struct list_head chips;
>>   	const struct meson_nfc_data *data;
>> @@ -406,12 +411,14 @@ static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms)
>>   	cmd = NFC_CMD_RB | NFC_CMD_RB_INT
>>   		| nfc->param.chip_select | nfc->timing.tbers_max;
>>   	writel(cmd, nfc->reg_base + NFC_REG_CMD);
>> -
>> +	meson_nfc_drain_cmd(nfc);
>>   	ret = wait_for_completion_timeout(&nfc->completion,
>>   					  msecs_to_jiffies(timeout_ms));
>>   	if (ret == 0)
>>   		ret = -1;
>>   
>> +	/* reset command fifo to avoid lock */
>> +	writel(NFC_CMD_FIFO_RESET, nfc->reg_base + NFC_REG_CMD);
>>   	return ret;
>>   }
>>   
>> @@ -988,8 +995,9 @@ static const struct mtd_ooblayout_ops meson_ooblayout_ops = {
>>   static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>   {
>>   	int ret;
>> +	struct clk_init_data init = {0};
>> +	const char *fix_div2_pll_name[1];
>>   
>> -	/* request core clock */
>>   	nfc->core_clk = devm_clk_get(nfc->dev, "core");
>>   	if (IS_ERR(nfc->core_clk)) {
>>   		dev_err(nfc->dev, "failed to get core clock\n");
>> @@ -1002,21 +1010,25 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>   		return PTR_ERR(nfc->device_clk);
>>   	}
>>   
>> -	nfc->phase_tx = devm_clk_get(nfc->dev, "tx");
>> -	if (IS_ERR(nfc->phase_tx)) {
>> -		dev_err(nfc->dev, "failed to get TX clk\n");
>> -		return PTR_ERR(nfc->phase_tx);
>> -	}
>> -
>> -	nfc->phase_rx = devm_clk_get(nfc->dev, "rx");
>> -	if (IS_ERR(nfc->phase_rx)) {
>> -		dev_err(nfc->dev, "failed to get RX clk\n");
>> -		return PTR_ERR(nfc->phase_rx);
>> -	}
>> +	init.name = devm_kstrdup(nfc->dev, "nfc#div", GFP_KERNEL);
>> +	init.ops = &clk_divider_ops;
>> +	fix_div2_pll_name[0] = __clk_get_name(nfc->device_clk);
>> +	init.parent_names = fix_div2_pll_name;
>> +	init.num_parents = 1;
>> +	nfc->nand_divider.reg = nfc->reg_clk;
>> +	nfc->nand_divider.shift = CLK_DIV_SHIFT;
>> +	nfc->nand_divider.width = CLK_DIV_WIDTH;
>> +	nfc->nand_divider.hw.init = &init;
>> +	nfc->nand_divider.flags = CLK_DIVIDER_ONE_BASED |
>> +				  CLK_DIVIDER_ROUND_CLOSEST |
>> +          			  CLK_DIVIDER_ALLOW_ZERO;
>> +
>> +	nfc->nand_clk = devm_clk_register(nfc->dev, &nfc->nand_divider.hw);
>> +	if (IS_ERR(nfc->nand_clk))
>> +		return PTR_ERR(nfc->nand_clk);
>>   
>>   	/* init SD_EMMC_CLOCK to sane defaults w/min clock rate */
>> -	regmap_update_bits(nfc->reg_clk,
>> -			   0, CLK_SELECT_NAND, CLK_SELECT_NAND);
>> +	writel(CLK_SELECT_NAND | readl(nfc->reg_clk), nfc->reg_clk);
>>   
>>   	ret = clk_prepare_enable(nfc->core_clk);
>>   	if (ret) {
>> @@ -1030,29 +1042,21 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>   		goto err_device_clk;
>>   	}
>>   
>> -	ret = clk_prepare_enable(nfc->phase_tx);
>> +	ret = clk_prepare_enable(nfc->nand_clk);
>>   	if (ret) {
>> -		dev_err(nfc->dev, "failed to enable TX clock\n");
>> -		goto err_phase_tx;
>> -	}
>> -
>> -	ret = clk_prepare_enable(nfc->phase_rx);
>> -	if (ret) {
>> -		dev_err(nfc->dev, "failed to enable RX clock\n");
>> -		goto err_phase_rx;
>> +		dev_err(nfc->dev, "pre enable NFC divider fail\n");
>> +		goto err_nand_clk;
>>   	}
>>   
>>   	ret = clk_set_rate(nfc->device_clk, 24000000);
>>   	if (ret)
>> -		goto err_disable_rx;
>> +		goto err_disable_clk;
>>   
>>   	return 0;
>>   
>> -err_disable_rx:
>> -	clk_disable_unprepare(nfc->phase_rx);
>> -err_phase_rx:
>> -	clk_disable_unprepare(nfc->phase_tx);
>> -err_phase_tx:
>> +err_disable_clk:
>> +	clk_disable_unprepare(nfc->nand_clk);
>> +err_nand_clk:
>>   	clk_disable_unprepare(nfc->device_clk);
>>   err_device_clk:
>>   	clk_disable_unprepare(nfc->core_clk);
>> @@ -1061,8 +1065,7 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>   
>>   static void meson_nfc_disable_clk(struct meson_nfc *nfc)
>>   {
>> -	clk_disable_unprepare(nfc->phase_rx);
>> -	clk_disable_unprepare(nfc->phase_tx);
>> +	clk_disable_unprepare(nfc->nand_clk);
>>   	clk_disable_unprepare(nfc->device_clk);
>>   	clk_disable_unprepare(nfc->core_clk);
>>   }
>> @@ -1375,6 +1378,7 @@ static int meson_nfc_probe(struct platform_device *pdev)
>>   	struct device *dev = &pdev->dev;
>>   	struct meson_nfc *nfc;
>>   	struct resource *res;
>> +	u32 ext_clk_reg;
>>   	int ret, irq;
>>   
>>   	nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL);
>> @@ -1396,9 +1400,15 @@ static int meson_nfc_probe(struct platform_device *pdev)
>>   	if (IS_ERR(nfc->reg_base))
>>   		return PTR_ERR(nfc->reg_base);
>>   
>> -	nfc->reg_clk =
>> -		syscon_regmap_lookup_by_phandle(dev->of_node,
>> -						"amlogic,mmc-syscon");
>> +	ret = of_property_read_u32(pdev->dev.of_node,
>> +				   "sd_emmc_c_clkc",
>> +				   &ext_clk_reg);
>> +	if (ret) {
>> +		dev_err(dev, "failed to get NAND external clock register\n");
>> +		return ret;
>> +	}
>> +
>> +	nfc->reg_clk = devm_ioremap(&pdev->dev, ext_clk_reg, sizeof(int));
>>   	if (IS_ERR(nfc->reg_clk)) {
>>   		dev_err(dev, "Failed to lookup clock base\n");
>>   		return PTR_ERR(nfc->reg_clk);
> 
> 
> Thanks,
> Miquèl
> 
> .

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH] mtd: rawnand: meson: fix the clock after discarding sd_emmc_c_clkc
  2022-01-06  8:16   ` Jerome Brunet
  (?)
  (?)
@ 2022-01-07  4:04     ` Liang Yang
  -1 siblings, 0 replies; 47+ messages in thread
From: Liang Yang @ 2022-01-07  4:04 UTC (permalink / raw)
  To: Jerome Brunet, Miquel Raynal, linux-mtd
  Cc: Richard Weinberger, Neil Armstrong, Martin Blumenstingl,
	Kevin Hilman, Jianxin Pan, Victor Wan, XianWei Zhao,
	Kelvin Zhang, BiChao Zheng, YongHui Yu, linux-arm-kernel,
	linux-amlogic, linux-kernel, devicetree

Hi Jerome,

On 2022/1/6 16:16, Jerome Brunet wrote:
> [ EXTERNAL EMAIL ]
> 
> 
> On Thu 06 Jan 2022 at 11:25, Liang Yang <liang.yang@amlogic.com> wrote:
> 
>> Because EMMC and NAND have the same control clock register, so we
>> implement a 'sd_emmc_c_clkc'. Previously DTS is defined as below:
>>
>> 	sd_emmc_c_clkc: mmc@7000 {
>> 		compatible = "amlogic,meson-axg-mmc-clkc", "syscon";
>> 		reg = <0x0 0x7000 0x0 0x800>;
>> 	};
>>
>> 	nand-controller@7800 {
>> 		......
>>
>> 		clocks = <&clkc CLKID_SD_EMMC_C>,
>> 			<&sd_emmc_c_clkc CLKID_MMC_DIV>,
>> 			<&sd_emmc_c_clkc CLKID_MMC_PHASE_RX>,
>> 			<&sd_emmc_c_clkc CLKID_MMC_PHASE_TX>;
>> 		clock-names = "core", "device", "rx", "tx";
>> 		amlogic,mmc-syscon = <&sd_emmc_c_clkc>;
>>
>> 		......
>> 	}
>>
>> but in fact, above implementation is rejected. so now registering
>> a nand_divider.
> 
> Can you give a bit of context ? a link to the discussion rejecting this
> 
Maybe I mistake the meaning of [jianxin.pan@amlogic.com], so i need him 
to clarify it.
> As far as remember, things were getting done for A1 and stopped before
> clock part was finished. I'm saying the change is wrong, just that a
> discussion is needed before a decision is made.
>
ok.
previous discussion in this link:
https://lore.kernel.org/all/86789d73-5a6c-7729-ecd1-dcd342b2fcde@amlogic.com/
it never go on since v6.

>>
>> Change-Id: Ibeb4c7ff886f5886aac4d6c664d7bbd1b1bcb997
>> Signed-off-by: Liang Yang <liang.yang@amlogic.com>
>> ---
>>   drivers/mtd/nand/raw/meson_nand.c | 88 +++++++++++++++++--------------
>>   1 file changed, 49 insertions(+), 39 deletions(-)
>>
>> diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c
>> index ac3be92872d0..4472363059c2 100644
>> --- a/drivers/mtd/nand/raw/meson_nand.c
>> +++ b/drivers/mtd/nand/raw/meson_nand.c
>> @@ -2,7 +2,7 @@
>>   /*
>>    * Amlogic Meson Nand Flash Controller Driver
>>    *
>> - * Copyright (c) 2018 Amlogic, inc.
>> + * Copyright (c) 2018-2021 Amlogic, inc.
>>    * Author: Liang Yang <liang.yang@amlogic.com>
>>    */
>>   
>> @@ -10,6 +10,7 @@
>>   #include <linux/dma-mapping.h>
>>   #include <linux/interrupt.h>
>>   #include <linux/clk.h>
>> +#include <linux/clk-provider.h>
>>   #include <linux/mtd/rawnand.h>
>>   #include <linux/mtd/mtd.h>
>>   #include <linux/mfd/syscon.h>
>> @@ -55,6 +56,7 @@
>>   #define NFC_REG_VER		0x38
>>   
>>   #define NFC_RB_IRQ_EN		BIT(21)
>> +#define NFC_CMD_FIFO_RESET	BIT(31)
>>   
>>   #define CMDRWGEN(cmd_dir, ran, bch, short_mode, page_size, pages)	\
>>   	(								\
>> @@ -104,6 +106,9 @@
>>   
>>   #define PER_INFO_BYTE		8
>>   
>> +#define CLK_DIV_SHIFT		0
>> +#define CLK_DIV_WIDTH		6
>> +
>>   struct meson_nfc_nand_chip {
>>   	struct list_head node;
>>   	struct nand_chip nand;
>> @@ -151,15 +156,15 @@ struct meson_nfc {
>>   	struct nand_controller controller;
>>   	struct clk *core_clk;
>>   	struct clk *device_clk;
>> -	struct clk *phase_tx;
>> -	struct clk *phase_rx;
> 
> I would have been nice to explain why these clock are no longer
> required, in the change description maybe ?

i got the reply from our vlsi members that rx and tx doesn't make sense 
to meson NFC timing. so previous commit about this should be wrong.
> 
>> +	struct clk *nand_clk;
>> +	struct clk_divider nand_divider;
>>   
>>   	unsigned long clk_rate;
>>   	u32 bus_timing;
>>   
>>   	struct device *dev;
>>   	void __iomem *reg_base;
>> -	struct regmap *reg_clk;
>> +	void __iomem *reg_clk;
>>   	struct completion completion;
>>   	struct list_head chips;
>>   	const struct meson_nfc_data *data;
>> @@ -406,12 +411,14 @@ static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms)
>>   	cmd = NFC_CMD_RB | NFC_CMD_RB_INT
>>   		| nfc->param.chip_select | nfc->timing.tbers_max;
>>   	writel(cmd, nfc->reg_base + NFC_REG_CMD);
>> -
>> +	meson_nfc_drain_cmd(nfc);
> 
> is this clock related ?
ok, i will split it in another patch.
> 
>>   	ret = wait_for_completion_timeout(&nfc->completion,
>>   					  msecs_to_jiffies(timeout_ms));
>>   	if (ret == 0)
>>   		ret = -1;
>>   
>> +	/* reset command fifo to avoid lock */
>> +	writel(NFC_CMD_FIFO_RESET, nfc->reg_base + NFC_REG_CMD);
> 
> Again, not seem to be clock related - does not belong in this patch
ok, i will split it in another patch.
> 
>>   	return ret;
>>   }
>>   
>> @@ -988,8 +995,9 @@ static const struct mtd_ooblayout_ops meson_ooblayout_ops = {
>>   static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>   {
>>   	int ret;
>> +	struct clk_init_data init = {0};
>> +	const char *fix_div2_pll_name[1];
>>   
>> -	/* request core clock */
> 
> Why is the comment bothering you ?
> 
>>   	nfc->core_clk = devm_clk_get(nfc->dev, "core");
>>   	if (IS_ERR(nfc->core_clk)) {
>>   		dev_err(nfc->dev, "failed to get core clock\n");
>> @@ -1002,21 +1010,25 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>   		return PTR_ERR(nfc->device_clk);
>>   	}
>>   
>> -	nfc->phase_tx = devm_clk_get(nfc->dev, "tx");
>> -	if (IS_ERR(nfc->phase_tx)) {
>> -		dev_err(nfc->dev, "failed to get TX clk\n");
>> -		return PTR_ERR(nfc->phase_tx);
>> -	}
>> -
>> -	nfc->phase_rx = devm_clk_get(nfc->dev, "rx");
>> -	if (IS_ERR(nfc->phase_rx)) {
>> -		dev_err(nfc->dev, "failed to get RX clk\n");
>> -		return PTR_ERR(nfc->phase_rx);
>> -	}
>> +	init.name = devm_kstrdup(nfc->dev, "nfc#div", GFP_KERNEL);
>> +	init.ops = &clk_divider_ops;
>> +	fix_div2_pll_name[0] = __clk_get_name(nfc->device_clk);
> 
> You should be using "fw_name" so CCF looks a DT directly, instead of this
ok
> 
>> +	init.parent_names = fix_div2_pll_name;
>> +	init.num_parents = 1;
>> +	nfc->nand_divider.reg = nfc->reg_clk;
>> +	nfc->nand_divider.shift = CLK_DIV_SHIFT;
>> +	nfc->nand_divider.width = CLK_DIV_WIDTH;
>> +	nfc->nand_divider.hw.init = &init;
>> +	nfc->nand_divider.flags = CLK_DIVIDER_ONE_BASED |
>> +				  CLK_DIVIDER_ROUND_CLOSEST |
>> +          			  CLK_DIVIDER_ALLOW_ZERO;
>> +
>> +	nfc->nand_clk = devm_clk_register(nfc->dev, &nfc->nand_divider.hw);
>> +	if (IS_ERR(nfc->nand_clk))
>> +		return PTR_ERR(nfc->nand_clk);
>>   
>>   	/* init SD_EMMC_CLOCK to sane defaults w/min clock rate */
>> -	regmap_update_bits(nfc->reg_clk,
>> -			   0, CLK_SELECT_NAND, CLK_SELECT_NAND);
>> +	writel(CLK_SELECT_NAND | readl(nfc->reg_clk), nfc->reg_clk);
>>   
>>   	ret = clk_prepare_enable(nfc->core_clk);
>>   	if (ret) {
>> @@ -1030,29 +1042,21 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>   		goto err_device_clk;
>>   	}
>>   
>> -	ret = clk_prepare_enable(nfc->phase_tx);
>> +	ret = clk_prepare_enable(nfc->nand_clk);
>>   	if (ret) {
>> -		dev_err(nfc->dev, "failed to enable TX clock\n");
>> -		goto err_phase_tx;
>> -	}
>> -
>> -	ret = clk_prepare_enable(nfc->phase_rx);
>> -	if (ret) {
>> -		dev_err(nfc->dev, "failed to enable RX clock\n");
>> -		goto err_phase_rx;
>> +		dev_err(nfc->dev, "pre enable NFC divider fail\n");
>> +		goto err_nand_clk;
>>   	}
>>   
>>   	ret = clk_set_rate(nfc->device_clk, 24000000);
>>   	if (ret)
>> -		goto err_disable_rx;
>> +		goto err_disable_clk;
>>   
>>   	return 0;
>>   
>> -err_disable_rx:
>> -	clk_disable_unprepare(nfc->phase_rx);
>> -err_phase_rx:
>> -	clk_disable_unprepare(nfc->phase_tx);
>> -err_phase_tx:
>> +err_disable_clk:
>> +	clk_disable_unprepare(nfc->nand_clk);
>> +err_nand_clk:
>>   	clk_disable_unprepare(nfc->device_clk);
>>   err_device_clk:
>>   	clk_disable_unprepare(nfc->core_clk);
>> @@ -1061,8 +1065,7 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>   
>>   static void meson_nfc_disable_clk(struct meson_nfc *nfc)
>>   {
>> -	clk_disable_unprepare(nfc->phase_rx);
>> -	clk_disable_unprepare(nfc->phase_tx);
>> +	clk_disable_unprepare(nfc->nand_clk);
>>   	clk_disable_unprepare(nfc->device_clk);
>>   	clk_disable_unprepare(nfc->core_clk);
>>   }
>> @@ -1375,6 +1378,7 @@ static int meson_nfc_probe(struct platform_device *pdev)
>>   	struct device *dev = &pdev->dev;
>>   	struct meson_nfc *nfc;
>>   	struct resource *res;
>> +	u32 ext_clk_reg;
>>   	int ret, irq;
>>   
>>   	nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL);
>> @@ -1396,9 +1400,15 @@ static int meson_nfc_probe(struct platform_device *pdev)
>>   	if (IS_ERR(nfc->reg_base))
>>   		return PTR_ERR(nfc->reg_base);
>>   
>> -	nfc->reg_clk =
>> -		syscon_regmap_lookup_by_phandle(dev->of_node,
>> -						"amlogic,mmc-syscon");
>> +	ret = of_property_read_u32(pdev->dev.of_node,
>> +				   "sd_emmc_c_clkc",
>> +				   &ext_clk_reg);
>> +	if (ret) {
>> +		dev_err(dev, "failed to get NAND external clock register\n");
>> +		return ret;
>> +	}
>> +
>> +	nfc->reg_clk = devm_ioremap(&pdev->dev, ext_clk_reg, sizeof(int));
> 
> That's how you should get a register region.
> If you want an example of a device claiming several region on amlogic,
> have a look at the pinctrl driver.
ok
> 
>>   	if (IS_ERR(nfc->reg_clk)) {
>>   		dev_err(dev, "Failed to lookup clock base\n");
>>   		return PTR_ERR(nfc->reg_clk);
> 
> .

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

* Re: [PATCH] mtd: rawnand: meson: fix the clock after discarding sd_emmc_c_clkc
@ 2022-01-07  4:04     ` Liang Yang
  0 siblings, 0 replies; 47+ messages in thread
From: Liang Yang @ 2022-01-07  4:04 UTC (permalink / raw)
  To: Jerome Brunet, Miquel Raynal, linux-mtd
  Cc: Richard Weinberger, Neil Armstrong, Martin Blumenstingl,
	Kevin Hilman, Jianxin Pan, Victor Wan, XianWei Zhao,
	Kelvin Zhang, BiChao Zheng, YongHui Yu, linux-arm-kernel,
	linux-amlogic, linux-kernel, devicetree

Hi Jerome,

On 2022/1/6 16:16, Jerome Brunet wrote:
> [ EXTERNAL EMAIL ]
> 
> 
> On Thu 06 Jan 2022 at 11:25, Liang Yang <liang.yang@amlogic.com> wrote:
> 
>> Because EMMC and NAND have the same control clock register, so we
>> implement a 'sd_emmc_c_clkc'. Previously DTS is defined as below:
>>
>> 	sd_emmc_c_clkc: mmc@7000 {
>> 		compatible = "amlogic,meson-axg-mmc-clkc", "syscon";
>> 		reg = <0x0 0x7000 0x0 0x800>;
>> 	};
>>
>> 	nand-controller@7800 {
>> 		......
>>
>> 		clocks = <&clkc CLKID_SD_EMMC_C>,
>> 			<&sd_emmc_c_clkc CLKID_MMC_DIV>,
>> 			<&sd_emmc_c_clkc CLKID_MMC_PHASE_RX>,
>> 			<&sd_emmc_c_clkc CLKID_MMC_PHASE_TX>;
>> 		clock-names = "core", "device", "rx", "tx";
>> 		amlogic,mmc-syscon = <&sd_emmc_c_clkc>;
>>
>> 		......
>> 	}
>>
>> but in fact, above implementation is rejected. so now registering
>> a nand_divider.
> 
> Can you give a bit of context ? a link to the discussion rejecting this
> 
Maybe I mistake the meaning of [jianxin.pan@amlogic.com], so i need him 
to clarify it.
> As far as remember, things were getting done for A1 and stopped before
> clock part was finished. I'm saying the change is wrong, just that a
> discussion is needed before a decision is made.
>
ok.
previous discussion in this link:
https://lore.kernel.org/all/86789d73-5a6c-7729-ecd1-dcd342b2fcde@amlogic.com/
it never go on since v6.

>>
>> Change-Id: Ibeb4c7ff886f5886aac4d6c664d7bbd1b1bcb997
>> Signed-off-by: Liang Yang <liang.yang@amlogic.com>
>> ---
>>   drivers/mtd/nand/raw/meson_nand.c | 88 +++++++++++++++++--------------
>>   1 file changed, 49 insertions(+), 39 deletions(-)
>>
>> diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c
>> index ac3be92872d0..4472363059c2 100644
>> --- a/drivers/mtd/nand/raw/meson_nand.c
>> +++ b/drivers/mtd/nand/raw/meson_nand.c
>> @@ -2,7 +2,7 @@
>>   /*
>>    * Amlogic Meson Nand Flash Controller Driver
>>    *
>> - * Copyright (c) 2018 Amlogic, inc.
>> + * Copyright (c) 2018-2021 Amlogic, inc.
>>    * Author: Liang Yang <liang.yang@amlogic.com>
>>    */
>>   
>> @@ -10,6 +10,7 @@
>>   #include <linux/dma-mapping.h>
>>   #include <linux/interrupt.h>
>>   #include <linux/clk.h>
>> +#include <linux/clk-provider.h>
>>   #include <linux/mtd/rawnand.h>
>>   #include <linux/mtd/mtd.h>
>>   #include <linux/mfd/syscon.h>
>> @@ -55,6 +56,7 @@
>>   #define NFC_REG_VER		0x38
>>   
>>   #define NFC_RB_IRQ_EN		BIT(21)
>> +#define NFC_CMD_FIFO_RESET	BIT(31)
>>   
>>   #define CMDRWGEN(cmd_dir, ran, bch, short_mode, page_size, pages)	\
>>   	(								\
>> @@ -104,6 +106,9 @@
>>   
>>   #define PER_INFO_BYTE		8
>>   
>> +#define CLK_DIV_SHIFT		0
>> +#define CLK_DIV_WIDTH		6
>> +
>>   struct meson_nfc_nand_chip {
>>   	struct list_head node;
>>   	struct nand_chip nand;
>> @@ -151,15 +156,15 @@ struct meson_nfc {
>>   	struct nand_controller controller;
>>   	struct clk *core_clk;
>>   	struct clk *device_clk;
>> -	struct clk *phase_tx;
>> -	struct clk *phase_rx;
> 
> I would have been nice to explain why these clock are no longer
> required, in the change description maybe ?

i got the reply from our vlsi members that rx and tx doesn't make sense 
to meson NFC timing. so previous commit about this should be wrong.
> 
>> +	struct clk *nand_clk;
>> +	struct clk_divider nand_divider;
>>   
>>   	unsigned long clk_rate;
>>   	u32 bus_timing;
>>   
>>   	struct device *dev;
>>   	void __iomem *reg_base;
>> -	struct regmap *reg_clk;
>> +	void __iomem *reg_clk;
>>   	struct completion completion;
>>   	struct list_head chips;
>>   	const struct meson_nfc_data *data;
>> @@ -406,12 +411,14 @@ static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms)
>>   	cmd = NFC_CMD_RB | NFC_CMD_RB_INT
>>   		| nfc->param.chip_select | nfc->timing.tbers_max;
>>   	writel(cmd, nfc->reg_base + NFC_REG_CMD);
>> -
>> +	meson_nfc_drain_cmd(nfc);
> 
> is this clock related ?
ok, i will split it in another patch.
> 
>>   	ret = wait_for_completion_timeout(&nfc->completion,
>>   					  msecs_to_jiffies(timeout_ms));
>>   	if (ret == 0)
>>   		ret = -1;
>>   
>> +	/* reset command fifo to avoid lock */
>> +	writel(NFC_CMD_FIFO_RESET, nfc->reg_base + NFC_REG_CMD);
> 
> Again, not seem to be clock related - does not belong in this patch
ok, i will split it in another patch.
> 
>>   	return ret;
>>   }
>>   
>> @@ -988,8 +995,9 @@ static const struct mtd_ooblayout_ops meson_ooblayout_ops = {
>>   static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>   {
>>   	int ret;
>> +	struct clk_init_data init = {0};
>> +	const char *fix_div2_pll_name[1];
>>   
>> -	/* request core clock */
> 
> Why is the comment bothering you ?
> 
>>   	nfc->core_clk = devm_clk_get(nfc->dev, "core");
>>   	if (IS_ERR(nfc->core_clk)) {
>>   		dev_err(nfc->dev, "failed to get core clock\n");
>> @@ -1002,21 +1010,25 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>   		return PTR_ERR(nfc->device_clk);
>>   	}
>>   
>> -	nfc->phase_tx = devm_clk_get(nfc->dev, "tx");
>> -	if (IS_ERR(nfc->phase_tx)) {
>> -		dev_err(nfc->dev, "failed to get TX clk\n");
>> -		return PTR_ERR(nfc->phase_tx);
>> -	}
>> -
>> -	nfc->phase_rx = devm_clk_get(nfc->dev, "rx");
>> -	if (IS_ERR(nfc->phase_rx)) {
>> -		dev_err(nfc->dev, "failed to get RX clk\n");
>> -		return PTR_ERR(nfc->phase_rx);
>> -	}
>> +	init.name = devm_kstrdup(nfc->dev, "nfc#div", GFP_KERNEL);
>> +	init.ops = &clk_divider_ops;
>> +	fix_div2_pll_name[0] = __clk_get_name(nfc->device_clk);
> 
> You should be using "fw_name" so CCF looks a DT directly, instead of this
ok
> 
>> +	init.parent_names = fix_div2_pll_name;
>> +	init.num_parents = 1;
>> +	nfc->nand_divider.reg = nfc->reg_clk;
>> +	nfc->nand_divider.shift = CLK_DIV_SHIFT;
>> +	nfc->nand_divider.width = CLK_DIV_WIDTH;
>> +	nfc->nand_divider.hw.init = &init;
>> +	nfc->nand_divider.flags = CLK_DIVIDER_ONE_BASED |
>> +				  CLK_DIVIDER_ROUND_CLOSEST |
>> +          			  CLK_DIVIDER_ALLOW_ZERO;
>> +
>> +	nfc->nand_clk = devm_clk_register(nfc->dev, &nfc->nand_divider.hw);
>> +	if (IS_ERR(nfc->nand_clk))
>> +		return PTR_ERR(nfc->nand_clk);
>>   
>>   	/* init SD_EMMC_CLOCK to sane defaults w/min clock rate */
>> -	regmap_update_bits(nfc->reg_clk,
>> -			   0, CLK_SELECT_NAND, CLK_SELECT_NAND);
>> +	writel(CLK_SELECT_NAND | readl(nfc->reg_clk), nfc->reg_clk);
>>   
>>   	ret = clk_prepare_enable(nfc->core_clk);
>>   	if (ret) {
>> @@ -1030,29 +1042,21 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>   		goto err_device_clk;
>>   	}
>>   
>> -	ret = clk_prepare_enable(nfc->phase_tx);
>> +	ret = clk_prepare_enable(nfc->nand_clk);
>>   	if (ret) {
>> -		dev_err(nfc->dev, "failed to enable TX clock\n");
>> -		goto err_phase_tx;
>> -	}
>> -
>> -	ret = clk_prepare_enable(nfc->phase_rx);
>> -	if (ret) {
>> -		dev_err(nfc->dev, "failed to enable RX clock\n");
>> -		goto err_phase_rx;
>> +		dev_err(nfc->dev, "pre enable NFC divider fail\n");
>> +		goto err_nand_clk;
>>   	}
>>   
>>   	ret = clk_set_rate(nfc->device_clk, 24000000);
>>   	if (ret)
>> -		goto err_disable_rx;
>> +		goto err_disable_clk;
>>   
>>   	return 0;
>>   
>> -err_disable_rx:
>> -	clk_disable_unprepare(nfc->phase_rx);
>> -err_phase_rx:
>> -	clk_disable_unprepare(nfc->phase_tx);
>> -err_phase_tx:
>> +err_disable_clk:
>> +	clk_disable_unprepare(nfc->nand_clk);
>> +err_nand_clk:
>>   	clk_disable_unprepare(nfc->device_clk);
>>   err_device_clk:
>>   	clk_disable_unprepare(nfc->core_clk);
>> @@ -1061,8 +1065,7 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>   
>>   static void meson_nfc_disable_clk(struct meson_nfc *nfc)
>>   {
>> -	clk_disable_unprepare(nfc->phase_rx);
>> -	clk_disable_unprepare(nfc->phase_tx);
>> +	clk_disable_unprepare(nfc->nand_clk);
>>   	clk_disable_unprepare(nfc->device_clk);
>>   	clk_disable_unprepare(nfc->core_clk);
>>   }
>> @@ -1375,6 +1378,7 @@ static int meson_nfc_probe(struct platform_device *pdev)
>>   	struct device *dev = &pdev->dev;
>>   	struct meson_nfc *nfc;
>>   	struct resource *res;
>> +	u32 ext_clk_reg;
>>   	int ret, irq;
>>   
>>   	nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL);
>> @@ -1396,9 +1400,15 @@ static int meson_nfc_probe(struct platform_device *pdev)
>>   	if (IS_ERR(nfc->reg_base))
>>   		return PTR_ERR(nfc->reg_base);
>>   
>> -	nfc->reg_clk =
>> -		syscon_regmap_lookup_by_phandle(dev->of_node,
>> -						"amlogic,mmc-syscon");
>> +	ret = of_property_read_u32(pdev->dev.of_node,
>> +				   "sd_emmc_c_clkc",
>> +				   &ext_clk_reg);
>> +	if (ret) {
>> +		dev_err(dev, "failed to get NAND external clock register\n");
>> +		return ret;
>> +	}
>> +
>> +	nfc->reg_clk = devm_ioremap(&pdev->dev, ext_clk_reg, sizeof(int));
> 
> That's how you should get a register region.
> If you want an example of a device claiming several region on amlogic,
> have a look at the pinctrl driver.
ok
> 
>>   	if (IS_ERR(nfc->reg_clk)) {
>>   		dev_err(dev, "Failed to lookup clock base\n");
>>   		return PTR_ERR(nfc->reg_clk);
> 
> .

_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic

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

* Re: [PATCH] mtd: rawnand: meson: fix the clock after discarding sd_emmc_c_clkc
@ 2022-01-07  4:04     ` Liang Yang
  0 siblings, 0 replies; 47+ messages in thread
From: Liang Yang @ 2022-01-07  4:04 UTC (permalink / raw)
  To: Jerome Brunet, Miquel Raynal, linux-mtd
  Cc: Richard Weinberger, Neil Armstrong, Martin Blumenstingl,
	Kevin Hilman, Jianxin Pan, Victor Wan, XianWei Zhao,
	Kelvin Zhang, BiChao Zheng, YongHui Yu, linux-arm-kernel,
	linux-amlogic, linux-kernel, devicetree

Hi Jerome,

On 2022/1/6 16:16, Jerome Brunet wrote:
> [ EXTERNAL EMAIL ]
> 
> 
> On Thu 06 Jan 2022 at 11:25, Liang Yang <liang.yang@amlogic.com> wrote:
> 
>> Because EMMC and NAND have the same control clock register, so we
>> implement a 'sd_emmc_c_clkc'. Previously DTS is defined as below:
>>
>> 	sd_emmc_c_clkc: mmc@7000 {
>> 		compatible = "amlogic,meson-axg-mmc-clkc", "syscon";
>> 		reg = <0x0 0x7000 0x0 0x800>;
>> 	};
>>
>> 	nand-controller@7800 {
>> 		......
>>
>> 		clocks = <&clkc CLKID_SD_EMMC_C>,
>> 			<&sd_emmc_c_clkc CLKID_MMC_DIV>,
>> 			<&sd_emmc_c_clkc CLKID_MMC_PHASE_RX>,
>> 			<&sd_emmc_c_clkc CLKID_MMC_PHASE_TX>;
>> 		clock-names = "core", "device", "rx", "tx";
>> 		amlogic,mmc-syscon = <&sd_emmc_c_clkc>;
>>
>> 		......
>> 	}
>>
>> but in fact, above implementation is rejected. so now registering
>> a nand_divider.
> 
> Can you give a bit of context ? a link to the discussion rejecting this
> 
Maybe I mistake the meaning of [jianxin.pan@amlogic.com], so i need him 
to clarify it.
> As far as remember, things were getting done for A1 and stopped before
> clock part was finished. I'm saying the change is wrong, just that a
> discussion is needed before a decision is made.
>
ok.
previous discussion in this link:
https://lore.kernel.org/all/86789d73-5a6c-7729-ecd1-dcd342b2fcde@amlogic.com/
it never go on since v6.

>>
>> Change-Id: Ibeb4c7ff886f5886aac4d6c664d7bbd1b1bcb997
>> Signed-off-by: Liang Yang <liang.yang@amlogic.com>
>> ---
>>   drivers/mtd/nand/raw/meson_nand.c | 88 +++++++++++++++++--------------
>>   1 file changed, 49 insertions(+), 39 deletions(-)
>>
>> diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c
>> index ac3be92872d0..4472363059c2 100644
>> --- a/drivers/mtd/nand/raw/meson_nand.c
>> +++ b/drivers/mtd/nand/raw/meson_nand.c
>> @@ -2,7 +2,7 @@
>>   /*
>>    * Amlogic Meson Nand Flash Controller Driver
>>    *
>> - * Copyright (c) 2018 Amlogic, inc.
>> + * Copyright (c) 2018-2021 Amlogic, inc.
>>    * Author: Liang Yang <liang.yang@amlogic.com>
>>    */
>>   
>> @@ -10,6 +10,7 @@
>>   #include <linux/dma-mapping.h>
>>   #include <linux/interrupt.h>
>>   #include <linux/clk.h>
>> +#include <linux/clk-provider.h>
>>   #include <linux/mtd/rawnand.h>
>>   #include <linux/mtd/mtd.h>
>>   #include <linux/mfd/syscon.h>
>> @@ -55,6 +56,7 @@
>>   #define NFC_REG_VER		0x38
>>   
>>   #define NFC_RB_IRQ_EN		BIT(21)
>> +#define NFC_CMD_FIFO_RESET	BIT(31)
>>   
>>   #define CMDRWGEN(cmd_dir, ran, bch, short_mode, page_size, pages)	\
>>   	(								\
>> @@ -104,6 +106,9 @@
>>   
>>   #define PER_INFO_BYTE		8
>>   
>> +#define CLK_DIV_SHIFT		0
>> +#define CLK_DIV_WIDTH		6
>> +
>>   struct meson_nfc_nand_chip {
>>   	struct list_head node;
>>   	struct nand_chip nand;
>> @@ -151,15 +156,15 @@ struct meson_nfc {
>>   	struct nand_controller controller;
>>   	struct clk *core_clk;
>>   	struct clk *device_clk;
>> -	struct clk *phase_tx;
>> -	struct clk *phase_rx;
> 
> I would have been nice to explain why these clock are no longer
> required, in the change description maybe ?

i got the reply from our vlsi members that rx and tx doesn't make sense 
to meson NFC timing. so previous commit about this should be wrong.
> 
>> +	struct clk *nand_clk;
>> +	struct clk_divider nand_divider;
>>   
>>   	unsigned long clk_rate;
>>   	u32 bus_timing;
>>   
>>   	struct device *dev;
>>   	void __iomem *reg_base;
>> -	struct regmap *reg_clk;
>> +	void __iomem *reg_clk;
>>   	struct completion completion;
>>   	struct list_head chips;
>>   	const struct meson_nfc_data *data;
>> @@ -406,12 +411,14 @@ static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms)
>>   	cmd = NFC_CMD_RB | NFC_CMD_RB_INT
>>   		| nfc->param.chip_select | nfc->timing.tbers_max;
>>   	writel(cmd, nfc->reg_base + NFC_REG_CMD);
>> -
>> +	meson_nfc_drain_cmd(nfc);
> 
> is this clock related ?
ok, i will split it in another patch.
> 
>>   	ret = wait_for_completion_timeout(&nfc->completion,
>>   					  msecs_to_jiffies(timeout_ms));
>>   	if (ret == 0)
>>   		ret = -1;
>>   
>> +	/* reset command fifo to avoid lock */
>> +	writel(NFC_CMD_FIFO_RESET, nfc->reg_base + NFC_REG_CMD);
> 
> Again, not seem to be clock related - does not belong in this patch
ok, i will split it in another patch.
> 
>>   	return ret;
>>   }
>>   
>> @@ -988,8 +995,9 @@ static const struct mtd_ooblayout_ops meson_ooblayout_ops = {
>>   static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>   {
>>   	int ret;
>> +	struct clk_init_data init = {0};
>> +	const char *fix_div2_pll_name[1];
>>   
>> -	/* request core clock */
> 
> Why is the comment bothering you ?
> 
>>   	nfc->core_clk = devm_clk_get(nfc->dev, "core");
>>   	if (IS_ERR(nfc->core_clk)) {
>>   		dev_err(nfc->dev, "failed to get core clock\n");
>> @@ -1002,21 +1010,25 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>   		return PTR_ERR(nfc->device_clk);
>>   	}
>>   
>> -	nfc->phase_tx = devm_clk_get(nfc->dev, "tx");
>> -	if (IS_ERR(nfc->phase_tx)) {
>> -		dev_err(nfc->dev, "failed to get TX clk\n");
>> -		return PTR_ERR(nfc->phase_tx);
>> -	}
>> -
>> -	nfc->phase_rx = devm_clk_get(nfc->dev, "rx");
>> -	if (IS_ERR(nfc->phase_rx)) {
>> -		dev_err(nfc->dev, "failed to get RX clk\n");
>> -		return PTR_ERR(nfc->phase_rx);
>> -	}
>> +	init.name = devm_kstrdup(nfc->dev, "nfc#div", GFP_KERNEL);
>> +	init.ops = &clk_divider_ops;
>> +	fix_div2_pll_name[0] = __clk_get_name(nfc->device_clk);
> 
> You should be using "fw_name" so CCF looks a DT directly, instead of this
ok
> 
>> +	init.parent_names = fix_div2_pll_name;
>> +	init.num_parents = 1;
>> +	nfc->nand_divider.reg = nfc->reg_clk;
>> +	nfc->nand_divider.shift = CLK_DIV_SHIFT;
>> +	nfc->nand_divider.width = CLK_DIV_WIDTH;
>> +	nfc->nand_divider.hw.init = &init;
>> +	nfc->nand_divider.flags = CLK_DIVIDER_ONE_BASED |
>> +				  CLK_DIVIDER_ROUND_CLOSEST |
>> +          			  CLK_DIVIDER_ALLOW_ZERO;
>> +
>> +	nfc->nand_clk = devm_clk_register(nfc->dev, &nfc->nand_divider.hw);
>> +	if (IS_ERR(nfc->nand_clk))
>> +		return PTR_ERR(nfc->nand_clk);
>>   
>>   	/* init SD_EMMC_CLOCK to sane defaults w/min clock rate */
>> -	regmap_update_bits(nfc->reg_clk,
>> -			   0, CLK_SELECT_NAND, CLK_SELECT_NAND);
>> +	writel(CLK_SELECT_NAND | readl(nfc->reg_clk), nfc->reg_clk);
>>   
>>   	ret = clk_prepare_enable(nfc->core_clk);
>>   	if (ret) {
>> @@ -1030,29 +1042,21 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>   		goto err_device_clk;
>>   	}
>>   
>> -	ret = clk_prepare_enable(nfc->phase_tx);
>> +	ret = clk_prepare_enable(nfc->nand_clk);
>>   	if (ret) {
>> -		dev_err(nfc->dev, "failed to enable TX clock\n");
>> -		goto err_phase_tx;
>> -	}
>> -
>> -	ret = clk_prepare_enable(nfc->phase_rx);
>> -	if (ret) {
>> -		dev_err(nfc->dev, "failed to enable RX clock\n");
>> -		goto err_phase_rx;
>> +		dev_err(nfc->dev, "pre enable NFC divider fail\n");
>> +		goto err_nand_clk;
>>   	}
>>   
>>   	ret = clk_set_rate(nfc->device_clk, 24000000);
>>   	if (ret)
>> -		goto err_disable_rx;
>> +		goto err_disable_clk;
>>   
>>   	return 0;
>>   
>> -err_disable_rx:
>> -	clk_disable_unprepare(nfc->phase_rx);
>> -err_phase_rx:
>> -	clk_disable_unprepare(nfc->phase_tx);
>> -err_phase_tx:
>> +err_disable_clk:
>> +	clk_disable_unprepare(nfc->nand_clk);
>> +err_nand_clk:
>>   	clk_disable_unprepare(nfc->device_clk);
>>   err_device_clk:
>>   	clk_disable_unprepare(nfc->core_clk);
>> @@ -1061,8 +1065,7 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>   
>>   static void meson_nfc_disable_clk(struct meson_nfc *nfc)
>>   {
>> -	clk_disable_unprepare(nfc->phase_rx);
>> -	clk_disable_unprepare(nfc->phase_tx);
>> +	clk_disable_unprepare(nfc->nand_clk);
>>   	clk_disable_unprepare(nfc->device_clk);
>>   	clk_disable_unprepare(nfc->core_clk);
>>   }
>> @@ -1375,6 +1378,7 @@ static int meson_nfc_probe(struct platform_device *pdev)
>>   	struct device *dev = &pdev->dev;
>>   	struct meson_nfc *nfc;
>>   	struct resource *res;
>> +	u32 ext_clk_reg;
>>   	int ret, irq;
>>   
>>   	nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL);
>> @@ -1396,9 +1400,15 @@ static int meson_nfc_probe(struct platform_device *pdev)
>>   	if (IS_ERR(nfc->reg_base))
>>   		return PTR_ERR(nfc->reg_base);
>>   
>> -	nfc->reg_clk =
>> -		syscon_regmap_lookup_by_phandle(dev->of_node,
>> -						"amlogic,mmc-syscon");
>> +	ret = of_property_read_u32(pdev->dev.of_node,
>> +				   "sd_emmc_c_clkc",
>> +				   &ext_clk_reg);
>> +	if (ret) {
>> +		dev_err(dev, "failed to get NAND external clock register\n");
>> +		return ret;
>> +	}
>> +
>> +	nfc->reg_clk = devm_ioremap(&pdev->dev, ext_clk_reg, sizeof(int));
> 
> That's how you should get a register region.
> If you want an example of a device claiming several region on amlogic,
> have a look at the pinctrl driver.
ok
> 
>>   	if (IS_ERR(nfc->reg_clk)) {
>>   		dev_err(dev, "Failed to lookup clock base\n");
>>   		return PTR_ERR(nfc->reg_clk);
> 
> .

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH] mtd: rawnand: meson: fix the clock after discarding sd_emmc_c_clkc
@ 2022-01-07  4:04     ` Liang Yang
  0 siblings, 0 replies; 47+ messages in thread
From: Liang Yang @ 2022-01-07  4:04 UTC (permalink / raw)
  To: Jerome Brunet, Miquel Raynal, linux-mtd
  Cc: Richard Weinberger, Neil Armstrong, Martin Blumenstingl,
	Kevin Hilman, Jianxin Pan, Victor Wan, XianWei Zhao,
	Kelvin Zhang, BiChao Zheng, YongHui Yu, linux-arm-kernel,
	linux-amlogic, linux-kernel, devicetree

Hi Jerome,

On 2022/1/6 16:16, Jerome Brunet wrote:
> [ EXTERNAL EMAIL ]
> 
> 
> On Thu 06 Jan 2022 at 11:25, Liang Yang <liang.yang@amlogic.com> wrote:
> 
>> Because EMMC and NAND have the same control clock register, so we
>> implement a 'sd_emmc_c_clkc'. Previously DTS is defined as below:
>>
>> 	sd_emmc_c_clkc: mmc@7000 {
>> 		compatible = "amlogic,meson-axg-mmc-clkc", "syscon";
>> 		reg = <0x0 0x7000 0x0 0x800>;
>> 	};
>>
>> 	nand-controller@7800 {
>> 		......
>>
>> 		clocks = <&clkc CLKID_SD_EMMC_C>,
>> 			<&sd_emmc_c_clkc CLKID_MMC_DIV>,
>> 			<&sd_emmc_c_clkc CLKID_MMC_PHASE_RX>,
>> 			<&sd_emmc_c_clkc CLKID_MMC_PHASE_TX>;
>> 		clock-names = "core", "device", "rx", "tx";
>> 		amlogic,mmc-syscon = <&sd_emmc_c_clkc>;
>>
>> 		......
>> 	}
>>
>> but in fact, above implementation is rejected. so now registering
>> a nand_divider.
> 
> Can you give a bit of context ? a link to the discussion rejecting this
> 
Maybe I mistake the meaning of [jianxin.pan@amlogic.com], so i need him 
to clarify it.
> As far as remember, things were getting done for A1 and stopped before
> clock part was finished. I'm saying the change is wrong, just that a
> discussion is needed before a decision is made.
>
ok.
previous discussion in this link:
https://lore.kernel.org/all/86789d73-5a6c-7729-ecd1-dcd342b2fcde@amlogic.com/
it never go on since v6.

>>
>> Change-Id: Ibeb4c7ff886f5886aac4d6c664d7bbd1b1bcb997
>> Signed-off-by: Liang Yang <liang.yang@amlogic.com>
>> ---
>>   drivers/mtd/nand/raw/meson_nand.c | 88 +++++++++++++++++--------------
>>   1 file changed, 49 insertions(+), 39 deletions(-)
>>
>> diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c
>> index ac3be92872d0..4472363059c2 100644
>> --- a/drivers/mtd/nand/raw/meson_nand.c
>> +++ b/drivers/mtd/nand/raw/meson_nand.c
>> @@ -2,7 +2,7 @@
>>   /*
>>    * Amlogic Meson Nand Flash Controller Driver
>>    *
>> - * Copyright (c) 2018 Amlogic, inc.
>> + * Copyright (c) 2018-2021 Amlogic, inc.
>>    * Author: Liang Yang <liang.yang@amlogic.com>
>>    */
>>   
>> @@ -10,6 +10,7 @@
>>   #include <linux/dma-mapping.h>
>>   #include <linux/interrupt.h>
>>   #include <linux/clk.h>
>> +#include <linux/clk-provider.h>
>>   #include <linux/mtd/rawnand.h>
>>   #include <linux/mtd/mtd.h>
>>   #include <linux/mfd/syscon.h>
>> @@ -55,6 +56,7 @@
>>   #define NFC_REG_VER		0x38
>>   
>>   #define NFC_RB_IRQ_EN		BIT(21)
>> +#define NFC_CMD_FIFO_RESET	BIT(31)
>>   
>>   #define CMDRWGEN(cmd_dir, ran, bch, short_mode, page_size, pages)	\
>>   	(								\
>> @@ -104,6 +106,9 @@
>>   
>>   #define PER_INFO_BYTE		8
>>   
>> +#define CLK_DIV_SHIFT		0
>> +#define CLK_DIV_WIDTH		6
>> +
>>   struct meson_nfc_nand_chip {
>>   	struct list_head node;
>>   	struct nand_chip nand;
>> @@ -151,15 +156,15 @@ struct meson_nfc {
>>   	struct nand_controller controller;
>>   	struct clk *core_clk;
>>   	struct clk *device_clk;
>> -	struct clk *phase_tx;
>> -	struct clk *phase_rx;
> 
> I would have been nice to explain why these clock are no longer
> required, in the change description maybe ?

i got the reply from our vlsi members that rx and tx doesn't make sense 
to meson NFC timing. so previous commit about this should be wrong.
> 
>> +	struct clk *nand_clk;
>> +	struct clk_divider nand_divider;
>>   
>>   	unsigned long clk_rate;
>>   	u32 bus_timing;
>>   
>>   	struct device *dev;
>>   	void __iomem *reg_base;
>> -	struct regmap *reg_clk;
>> +	void __iomem *reg_clk;
>>   	struct completion completion;
>>   	struct list_head chips;
>>   	const struct meson_nfc_data *data;
>> @@ -406,12 +411,14 @@ static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms)
>>   	cmd = NFC_CMD_RB | NFC_CMD_RB_INT
>>   		| nfc->param.chip_select | nfc->timing.tbers_max;
>>   	writel(cmd, nfc->reg_base + NFC_REG_CMD);
>> -
>> +	meson_nfc_drain_cmd(nfc);
> 
> is this clock related ?
ok, i will split it in another patch.
> 
>>   	ret = wait_for_completion_timeout(&nfc->completion,
>>   					  msecs_to_jiffies(timeout_ms));
>>   	if (ret == 0)
>>   		ret = -1;
>>   
>> +	/* reset command fifo to avoid lock */
>> +	writel(NFC_CMD_FIFO_RESET, nfc->reg_base + NFC_REG_CMD);
> 
> Again, not seem to be clock related - does not belong in this patch
ok, i will split it in another patch.
> 
>>   	return ret;
>>   }
>>   
>> @@ -988,8 +995,9 @@ static const struct mtd_ooblayout_ops meson_ooblayout_ops = {
>>   static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>   {
>>   	int ret;
>> +	struct clk_init_data init = {0};
>> +	const char *fix_div2_pll_name[1];
>>   
>> -	/* request core clock */
> 
> Why is the comment bothering you ?
> 
>>   	nfc->core_clk = devm_clk_get(nfc->dev, "core");
>>   	if (IS_ERR(nfc->core_clk)) {
>>   		dev_err(nfc->dev, "failed to get core clock\n");
>> @@ -1002,21 +1010,25 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>   		return PTR_ERR(nfc->device_clk);
>>   	}
>>   
>> -	nfc->phase_tx = devm_clk_get(nfc->dev, "tx");
>> -	if (IS_ERR(nfc->phase_tx)) {
>> -		dev_err(nfc->dev, "failed to get TX clk\n");
>> -		return PTR_ERR(nfc->phase_tx);
>> -	}
>> -
>> -	nfc->phase_rx = devm_clk_get(nfc->dev, "rx");
>> -	if (IS_ERR(nfc->phase_rx)) {
>> -		dev_err(nfc->dev, "failed to get RX clk\n");
>> -		return PTR_ERR(nfc->phase_rx);
>> -	}
>> +	init.name = devm_kstrdup(nfc->dev, "nfc#div", GFP_KERNEL);
>> +	init.ops = &clk_divider_ops;
>> +	fix_div2_pll_name[0] = __clk_get_name(nfc->device_clk);
> 
> You should be using "fw_name" so CCF looks a DT directly, instead of this
ok
> 
>> +	init.parent_names = fix_div2_pll_name;
>> +	init.num_parents = 1;
>> +	nfc->nand_divider.reg = nfc->reg_clk;
>> +	nfc->nand_divider.shift = CLK_DIV_SHIFT;
>> +	nfc->nand_divider.width = CLK_DIV_WIDTH;
>> +	nfc->nand_divider.hw.init = &init;
>> +	nfc->nand_divider.flags = CLK_DIVIDER_ONE_BASED |
>> +				  CLK_DIVIDER_ROUND_CLOSEST |
>> +          			  CLK_DIVIDER_ALLOW_ZERO;
>> +
>> +	nfc->nand_clk = devm_clk_register(nfc->dev, &nfc->nand_divider.hw);
>> +	if (IS_ERR(nfc->nand_clk))
>> +		return PTR_ERR(nfc->nand_clk);
>>   
>>   	/* init SD_EMMC_CLOCK to sane defaults w/min clock rate */
>> -	regmap_update_bits(nfc->reg_clk,
>> -			   0, CLK_SELECT_NAND, CLK_SELECT_NAND);
>> +	writel(CLK_SELECT_NAND | readl(nfc->reg_clk), nfc->reg_clk);
>>   
>>   	ret = clk_prepare_enable(nfc->core_clk);
>>   	if (ret) {
>> @@ -1030,29 +1042,21 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>   		goto err_device_clk;
>>   	}
>>   
>> -	ret = clk_prepare_enable(nfc->phase_tx);
>> +	ret = clk_prepare_enable(nfc->nand_clk);
>>   	if (ret) {
>> -		dev_err(nfc->dev, "failed to enable TX clock\n");
>> -		goto err_phase_tx;
>> -	}
>> -
>> -	ret = clk_prepare_enable(nfc->phase_rx);
>> -	if (ret) {
>> -		dev_err(nfc->dev, "failed to enable RX clock\n");
>> -		goto err_phase_rx;
>> +		dev_err(nfc->dev, "pre enable NFC divider fail\n");
>> +		goto err_nand_clk;
>>   	}
>>   
>>   	ret = clk_set_rate(nfc->device_clk, 24000000);
>>   	if (ret)
>> -		goto err_disable_rx;
>> +		goto err_disable_clk;
>>   
>>   	return 0;
>>   
>> -err_disable_rx:
>> -	clk_disable_unprepare(nfc->phase_rx);
>> -err_phase_rx:
>> -	clk_disable_unprepare(nfc->phase_tx);
>> -err_phase_tx:
>> +err_disable_clk:
>> +	clk_disable_unprepare(nfc->nand_clk);
>> +err_nand_clk:
>>   	clk_disable_unprepare(nfc->device_clk);
>>   err_device_clk:
>>   	clk_disable_unprepare(nfc->core_clk);
>> @@ -1061,8 +1065,7 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>   
>>   static void meson_nfc_disable_clk(struct meson_nfc *nfc)
>>   {
>> -	clk_disable_unprepare(nfc->phase_rx);
>> -	clk_disable_unprepare(nfc->phase_tx);
>> +	clk_disable_unprepare(nfc->nand_clk);
>>   	clk_disable_unprepare(nfc->device_clk);
>>   	clk_disable_unprepare(nfc->core_clk);
>>   }
>> @@ -1375,6 +1378,7 @@ static int meson_nfc_probe(struct platform_device *pdev)
>>   	struct device *dev = &pdev->dev;
>>   	struct meson_nfc *nfc;
>>   	struct resource *res;
>> +	u32 ext_clk_reg;
>>   	int ret, irq;
>>   
>>   	nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL);
>> @@ -1396,9 +1400,15 @@ static int meson_nfc_probe(struct platform_device *pdev)
>>   	if (IS_ERR(nfc->reg_base))
>>   		return PTR_ERR(nfc->reg_base);
>>   
>> -	nfc->reg_clk =
>> -		syscon_regmap_lookup_by_phandle(dev->of_node,
>> -						"amlogic,mmc-syscon");
>> +	ret = of_property_read_u32(pdev->dev.of_node,
>> +				   "sd_emmc_c_clkc",
>> +				   &ext_clk_reg);
>> +	if (ret) {
>> +		dev_err(dev, "failed to get NAND external clock register\n");
>> +		return ret;
>> +	}
>> +
>> +	nfc->reg_clk = devm_ioremap(&pdev->dev, ext_clk_reg, sizeof(int));
> 
> That's how you should get a register region.
> If you want an example of a device claiming several region on amlogic,
> have a look at the pinctrl driver.
ok
> 
>>   	if (IS_ERR(nfc->reg_clk)) {
>>   		dev_err(dev, "Failed to lookup clock base\n");
>>   		return PTR_ERR(nfc->reg_clk);
> 
> .

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH] mtd: rawnand: meson: fix the clock after discarding sd_emmc_c_clkc
  2022-01-07  2:40     ` Liang Yang
  (?)
  (?)
@ 2022-01-07  4:08       ` Liang Yang
  -1 siblings, 0 replies; 47+ messages in thread
From: Liang Yang @ 2022-01-07  4:08 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: linux-mtd, Richard Weinberger, Jerome Brunet, Neil Armstrong,
	Martin Blumenstingl, Kevin Hilman, Jianxin Pan, Victor Wan,
	XianWei Zhao, Kelvin Zhang, BiChao Zheng, YongHui Yu,
	linux-arm-kernel, linux-amlogic, linux-kernel, devicetree

Hi Miquel,

refine the clock framework diagram.

On 2022/1/7 10:40, Liang Yang wrote:
>> What is nand_divider?
> i simplify our clock framework below, so nand divider is 
> SD_EMMC_CLOCK[5:0] here.
>                 -----          -----            -----
>         the other------|    \        |     |       |     |
>                     | mux    | -----  |  N  | ----------| NFC/|
>         FCLK_DIV2------|     |        |     |       | EMMC|
>                 -----/         -----         -----
>              SD_EMMC_CLOCK[7:6] SD_EMMC_CLOCK[5:0]


                          -----           -------         --------
               the other-|      \        |       |       |        |
                         | mux  |--------|  N    |-------|   NFC/ |
                         |      |        |       |       |   EMMC |
               fclk_div2-|      /        |       |       |        |
                          -----           -------         --------
                   SD_EMMC_CLOCK[7:6]   SD_EMMC_CLOCK[5:0]

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

* Re: [PATCH] mtd: rawnand: meson: fix the clock after discarding sd_emmc_c_clkc
@ 2022-01-07  4:08       ` Liang Yang
  0 siblings, 0 replies; 47+ messages in thread
From: Liang Yang @ 2022-01-07  4:08 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: linux-mtd, Richard Weinberger, Jerome Brunet, Neil Armstrong,
	Martin Blumenstingl, Kevin Hilman, Jianxin Pan, Victor Wan,
	XianWei Zhao, Kelvin Zhang, BiChao Zheng, YongHui Yu,
	linux-arm-kernel, linux-amlogic, linux-kernel, devicetree

Hi Miquel,

refine the clock framework diagram.

On 2022/1/7 10:40, Liang Yang wrote:
>> What is nand_divider?
> i simplify our clock framework below, so nand divider is 
> SD_EMMC_CLOCK[5:0] here.
>                 -----          -----            -----
>         the other------|    \        |     |       |     |
>                     | mux    | -----  |  N  | ----------| NFC/|
>         FCLK_DIV2------|     |        |     |       | EMMC|
>                 -----/         -----         -----
>              SD_EMMC_CLOCK[7:6] SD_EMMC_CLOCK[5:0]


                          -----           -------         --------
               the other-|      \        |       |       |        |
                         | mux  |--------|  N    |-------|   NFC/ |
                         |      |        |       |       |   EMMC |
               fclk_div2-|      /        |       |       |        |
                          -----           -------         --------
                   SD_EMMC_CLOCK[7:6]   SD_EMMC_CLOCK[5:0]

_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic

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

* Re: [PATCH] mtd: rawnand: meson: fix the clock after discarding sd_emmc_c_clkc
@ 2022-01-07  4:08       ` Liang Yang
  0 siblings, 0 replies; 47+ messages in thread
From: Liang Yang @ 2022-01-07  4:08 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: linux-mtd, Richard Weinberger, Jerome Brunet, Neil Armstrong,
	Martin Blumenstingl, Kevin Hilman, Jianxin Pan, Victor Wan,
	XianWei Zhao, Kelvin Zhang, BiChao Zheng, YongHui Yu,
	linux-arm-kernel, linux-amlogic, linux-kernel, devicetree

Hi Miquel,

refine the clock framework diagram.

On 2022/1/7 10:40, Liang Yang wrote:
>> What is nand_divider?
> i simplify our clock framework below, so nand divider is 
> SD_EMMC_CLOCK[5:0] here.
>                 -----          -----            -----
>         the other------|    \        |     |       |     |
>                     | mux    | -----  |  N  | ----------| NFC/|
>         FCLK_DIV2------|     |        |     |       | EMMC|
>                 -----/         -----         -----
>              SD_EMMC_CLOCK[7:6] SD_EMMC_CLOCK[5:0]


                          -----           -------         --------
               the other-|      \        |       |       |        |
                         | mux  |--------|  N    |-------|   NFC/ |
                         |      |        |       |       |   EMMC |
               fclk_div2-|      /        |       |       |        |
                          -----           -------         --------
                   SD_EMMC_CLOCK[7:6]   SD_EMMC_CLOCK[5:0]

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH] mtd: rawnand: meson: fix the clock after discarding sd_emmc_c_clkc
@ 2022-01-07  4:08       ` Liang Yang
  0 siblings, 0 replies; 47+ messages in thread
From: Liang Yang @ 2022-01-07  4:08 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: linux-mtd, Richard Weinberger, Jerome Brunet, Neil Armstrong,
	Martin Blumenstingl, Kevin Hilman, Jianxin Pan, Victor Wan,
	XianWei Zhao, Kelvin Zhang, BiChao Zheng, YongHui Yu,
	linux-arm-kernel, linux-amlogic, linux-kernel, devicetree

Hi Miquel,

refine the clock framework diagram.

On 2022/1/7 10:40, Liang Yang wrote:
>> What is nand_divider?
> i simplify our clock framework below, so nand divider is 
> SD_EMMC_CLOCK[5:0] here.
>                 -----          -----            -----
>         the other------|    \        |     |       |     |
>                     | mux    | -----  |  N  | ----------| NFC/|
>         FCLK_DIV2------|     |        |     |       | EMMC|
>                 -----/         -----         -----
>              SD_EMMC_CLOCK[7:6] SD_EMMC_CLOCK[5:0]


                          -----           -------         --------
               the other-|      \        |       |       |        |
                         | mux  |--------|  N    |-------|   NFC/ |
                         |      |        |       |       |   EMMC |
               fclk_div2-|      /        |       |       |        |
                          -----           -------         --------
                   SD_EMMC_CLOCK[7:6]   SD_EMMC_CLOCK[5:0]

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH] mtd: rawnand: meson: fix the clock after discarding sd_emmc_c_clkc
  2022-01-07  2:40     ` Liang Yang
  (?)
  (?)
@ 2022-01-07  7:54       ` Jerome Brunet
  -1 siblings, 0 replies; 47+ messages in thread
From: Jerome Brunet @ 2022-01-07  7:54 UTC (permalink / raw)
  To: Liang Yang, Miquel Raynal
  Cc: linux-mtd, Richard Weinberger, Neil Armstrong,
	Martin Blumenstingl, Kevin Hilman, Jianxin Pan, Victor Wan,
	XianWei Zhao, Kelvin Zhang, BiChao Zheng, YongHui Yu,
	linux-arm-kernel, linux-amlogic, linux-kernel, devicetree


On Fri 07 Jan 2022 at 10:40, Liang Yang <liang.yang@amlogic.com> wrote:

> Hi Miquel,
>
> Meson NFC clock depends on the implementation of sd_emmc_c_clkc, but i
> don't find the commit in
> linux mainline. then the information i got from [jianxin.pan@amlogic.com]
> is the rejection of
> serial patches. I just look into the corresponding emails in link:
>
> https://lore.kernel.org/all/86789d73-5a6c-7729-ecd1-dcd342b2fcde@amlogic.com/
> it seems the patch never go on since V6, so [jianxin.pan@amlogic.com],
> could you help to clear it?
> let us address the discussion in another email from
> [jbrunet@baylibre.com].

That V6 was "rejected" because some comments from thre V5 were still not
addressed. 

>
> On 2022/1/6 16:08, Miquel Raynal wrote:
>> [ EXTERNAL EMAIL ]
>> Hi Liang,
>> liang.yang@amlogic.com wrote on Thu, 6 Jan 2022 11:25:04 +0800:
>> 
>>> Because EMMC and NAND have the same control clock register, so we
>>> implement a 'sd_emmc_c_clkc'. Previously DTS is defined as below:
>>>
>>> 	sd_emmc_c_clkc: mmc@7000 {
>>> 		compatible = "amlogic,meson-axg-mmc-clkc", "syscon";
>>> 		reg = <0x0 0x7000 0x0 0x800>;
>>> 	};
>>>
>>> 	nand-controller@7800 {
>>> 		......
>>>
>>> 		clocks = <&clkc CLKID_SD_EMMC_C>,
>>> 			<&sd_emmc_c_clkc CLKID_MMC_DIV>,
>>> 			<&sd_emmc_c_clkc CLKID_MMC_PHASE_RX>,
>>> 			<&sd_emmc_c_clkc CLKID_MMC_PHASE_TX>;
>>> 		clock-names = "core", "device", "rx", "tx";
>>> 		amlogic,mmc-syscon = <&sd_emmc_c_clkc>;
>>>
>>> 		......
>>> 	}
>>>
>>> but in fact, above implementation is rejected. so now registering
>>> a nand_divider.
>> What is rejected?
>> Why is it rejected?
>> What is nand_divider?
> i simplify our clock framework below, so nand divider is SD_EMMC_CLOCK[5:0]
> here.
> 			   -----          -----		    -----
> 	   the other------|	\        |     |	   |	 |
>          		  | mux	| -----  |  N  | ----------| NFC/|
> 	   FCLK_DIV2------|     |        |     |	   | EMMC|
> 			   -----/         ----- 	    -----
> 		    SD_EMMC_CLOCK[7:6] SD_EMMC_CLOCK[5:0]
>> 
>>>
>>> Change-Id: Ibeb4c7ff886f5886aac4d6c664d7bbd1b1bcb997
>> Change Ids are not expected in the upstream kernel.
>> But if you fix something you should have a Fixes:.
>> 
>>> Signed-off-by: Liang Yang <liang.yang@amlogic.com>
>>> ---
>>>   drivers/mtd/nand/raw/meson_nand.c | 88 +++++++++++++++++--------------
>>>   1 file changed, 49 insertions(+), 39 deletions(-)
>>>
>>> diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c
>>> index ac3be92872d0..4472363059c2 100644
>>> --- a/drivers/mtd/nand/raw/meson_nand.c
>>> +++ b/drivers/mtd/nand/raw/meson_nand.c
>>> @@ -2,7 +2,7 @@
>>>   /*
>>>    * Amlogic Meson Nand Flash Controller Driver
>>>    *
>>> - * Copyright (c) 2018 Amlogic, inc.
>>> + * Copyright (c) 2018-2021 Amlogic, inc.
>>>    * Author: Liang Yang <liang.yang@amlogic.com>
>>>    */
>>>   @@ -10,6 +10,7 @@
>>>   #include <linux/dma-mapping.h>
>>>   #include <linux/interrupt.h>
>>>   #include <linux/clk.h>
>>> +#include <linux/clk-provider.h>
>>>   #include <linux/mtd/rawnand.h>
>>>   #include <linux/mtd/mtd.h>
>>>   #include <linux/mfd/syscon.h>
>>> @@ -55,6 +56,7 @@
>>>   #define NFC_REG_VER		0x38
>>>     #define NFC_RB_IRQ_EN		BIT(21)
>>> +#define NFC_CMD_FIFO_RESET	BIT(31)
>>>     #define CMDRWGEN(cmd_dir, ran, bch, short_mode, page_size, pages)
>>> \
>>>   	(								\
>>> @@ -104,6 +106,9 @@
>>>     #define PER_INFO_BYTE		8
>>>   +#define CLK_DIV_SHIFT		0
>>> +#define CLK_DIV_WIDTH		6
>>> +
>>>   struct meson_nfc_nand_chip {
>>>   	struct list_head node;
>>>   	struct nand_chip nand;
>>> @@ -151,15 +156,15 @@ struct meson_nfc {
>>>   	struct nand_controller controller;
>>>   	struct clk *core_clk;
>>>   	struct clk *device_clk;
>>> -	struct clk *phase_tx;
>>> -	struct clk *phase_rx;
>>> +	struct clk *nand_clk;
>>> +	struct clk_divider nand_divider;
>>>     	unsigned long clk_rate;
>>>   	u32 bus_timing;
>>>     	struct device *dev;
>>>   	void __iomem *reg_base;
>>> -	struct regmap *reg_clk;
>>> +	void __iomem *reg_clk;
>>>   	struct completion completion;
>>>   	struct list_head chips;
>>>   	const struct meson_nfc_data *data;
>>> @@ -406,12 +411,14 @@ static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms)
>>>   	cmd = NFC_CMD_RB | NFC_CMD_RB_INT
>>>   		| nfc->param.chip_select | nfc->timing.tbers_max;
>>>   	writel(cmd, nfc->reg_base + NFC_REG_CMD);
>>> -
>>> +	meson_nfc_drain_cmd(nfc);
>>>   	ret = wait_for_completion_timeout(&nfc->completion,
>>>   					  msecs_to_jiffies(timeout_ms));
>>>   	if (ret == 0)
>>>   		ret = -1;
>>>   +	/* reset command fifo to avoid lock */
>>> +	writel(NFC_CMD_FIFO_RESET, nfc->reg_base + NFC_REG_CMD);
>>>   	return ret;
>>>   }
>>>   @@ -988,8 +995,9 @@ static const struct mtd_ooblayout_ops
>>> meson_ooblayout_ops = {
>>>   static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>   {
>>>   	int ret;
>>> +	struct clk_init_data init = {0};
>>> +	const char *fix_div2_pll_name[1];
>>>   -	/* request core clock */
>>>   	nfc->core_clk = devm_clk_get(nfc->dev, "core");
>>>   	if (IS_ERR(nfc->core_clk)) {
>>>   		dev_err(nfc->dev, "failed to get core clock\n");
>>> @@ -1002,21 +1010,25 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>   		return PTR_ERR(nfc->device_clk);
>>>   	}
>>>   -	nfc->phase_tx = devm_clk_get(nfc->dev, "tx");
>>> -	if (IS_ERR(nfc->phase_tx)) {
>>> -		dev_err(nfc->dev, "failed to get TX clk\n");
>>> -		return PTR_ERR(nfc->phase_tx);
>>> -	}
>>> -
>>> -	nfc->phase_rx = devm_clk_get(nfc->dev, "rx");
>>> -	if (IS_ERR(nfc->phase_rx)) {
>>> -		dev_err(nfc->dev, "failed to get RX clk\n");
>>> -		return PTR_ERR(nfc->phase_rx);
>>> -	}
>>> +	init.name = devm_kstrdup(nfc->dev, "nfc#div", GFP_KERNEL);
>>> +	init.ops = &clk_divider_ops;
>>> +	fix_div2_pll_name[0] = __clk_get_name(nfc->device_clk);
>>> +	init.parent_names = fix_div2_pll_name;
>>> +	init.num_parents = 1;
>>> +	nfc->nand_divider.reg = nfc->reg_clk;
>>> +	nfc->nand_divider.shift = CLK_DIV_SHIFT;
>>> +	nfc->nand_divider.width = CLK_DIV_WIDTH;
>>> +	nfc->nand_divider.hw.init = &init;
>>> +	nfc->nand_divider.flags = CLK_DIVIDER_ONE_BASED |
>>> +				  CLK_DIVIDER_ROUND_CLOSEST |
>>> +          			  CLK_DIVIDER_ALLOW_ZERO;
>>> +
>>> +	nfc->nand_clk = devm_clk_register(nfc->dev, &nfc->nand_divider.hw);
>>> +	if (IS_ERR(nfc->nand_clk))
>>> +		return PTR_ERR(nfc->nand_clk);
>>>     	/* init SD_EMMC_CLOCK to sane defaults w/min clock rate */
>>> -	regmap_update_bits(nfc->reg_clk,
>>> -			   0, CLK_SELECT_NAND, CLK_SELECT_NAND);
>>> +	writel(CLK_SELECT_NAND | readl(nfc->reg_clk), nfc->reg_clk);
>>>     	ret = clk_prepare_enable(nfc->core_clk);
>>>   	if (ret) {
>>> @@ -1030,29 +1042,21 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>   		goto err_device_clk;
>>>   	}
>>>   -	ret = clk_prepare_enable(nfc->phase_tx);
>>> +	ret = clk_prepare_enable(nfc->nand_clk);
>>>   	if (ret) {
>>> -		dev_err(nfc->dev, "failed to enable TX clock\n");
>>> -		goto err_phase_tx;
>>> -	}
>>> -
>>> -	ret = clk_prepare_enable(nfc->phase_rx);
>>> -	if (ret) {
>>> -		dev_err(nfc->dev, "failed to enable RX clock\n");
>>> -		goto err_phase_rx;
>>> +		dev_err(nfc->dev, "pre enable NFC divider fail\n");
>>> +		goto err_nand_clk;
>>>   	}
>>>     	ret = clk_set_rate(nfc->device_clk, 24000000);
>>>   	if (ret)
>>> -		goto err_disable_rx;
>>> +		goto err_disable_clk;
>>>     	return 0;
>>>   -err_disable_rx:
>>> -	clk_disable_unprepare(nfc->phase_rx);
>>> -err_phase_rx:
>>> -	clk_disable_unprepare(nfc->phase_tx);
>>> -err_phase_tx:
>>> +err_disable_clk:
>>> +	clk_disable_unprepare(nfc->nand_clk);
>>> +err_nand_clk:
>>>   	clk_disable_unprepare(nfc->device_clk);
>>>   err_device_clk:
>>>   	clk_disable_unprepare(nfc->core_clk);
>>> @@ -1061,8 +1065,7 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>     static void meson_nfc_disable_clk(struct meson_nfc *nfc)
>>>   {
>>> -	clk_disable_unprepare(nfc->phase_rx);
>>> -	clk_disable_unprepare(nfc->phase_tx);
>>> +	clk_disable_unprepare(nfc->nand_clk);
>>>   	clk_disable_unprepare(nfc->device_clk);
>>>   	clk_disable_unprepare(nfc->core_clk);
>>>   }
>>> @@ -1375,6 +1378,7 @@ static int meson_nfc_probe(struct platform_device *pdev)
>>>   	struct device *dev = &pdev->dev;
>>>   	struct meson_nfc *nfc;
>>>   	struct resource *res;
>>> +	u32 ext_clk_reg;
>>>   	int ret, irq;
>>>     	nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL);
>>> @@ -1396,9 +1400,15 @@ static int meson_nfc_probe(struct platform_device *pdev)
>>>   	if (IS_ERR(nfc->reg_base))
>>>   		return PTR_ERR(nfc->reg_base);
>>>   -	nfc->reg_clk =
>>> -		syscon_regmap_lookup_by_phandle(dev->of_node,
>>> -						"amlogic,mmc-syscon");
>>> +	ret = of_property_read_u32(pdev->dev.of_node,
>>> +				   "sd_emmc_c_clkc",
>>> +				   &ext_clk_reg);
>>> +	if (ret) {
>>> +		dev_err(dev, "failed to get NAND external clock register\n");
>>> +		return ret;
>>> +	}
>>> +
>>> +	nfc->reg_clk = devm_ioremap(&pdev->dev, ext_clk_reg, sizeof(int));
>>>   	if (IS_ERR(nfc->reg_clk)) {
>>>   		dev_err(dev, "Failed to lookup clock base\n");
>>>   		return PTR_ERR(nfc->reg_clk);
>> 
>> Thanks,
>> Miquèl
>> .


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

* Re: [PATCH] mtd: rawnand: meson: fix the clock after discarding sd_emmc_c_clkc
@ 2022-01-07  7:54       ` Jerome Brunet
  0 siblings, 0 replies; 47+ messages in thread
From: Jerome Brunet @ 2022-01-07  7:54 UTC (permalink / raw)
  To: Liang Yang, Miquel Raynal
  Cc: linux-mtd, Richard Weinberger, Neil Armstrong,
	Martin Blumenstingl, Kevin Hilman, Jianxin Pan, Victor Wan,
	XianWei Zhao, Kelvin Zhang, BiChao Zheng, YongHui Yu,
	linux-arm-kernel, linux-amlogic, linux-kernel, devicetree


On Fri 07 Jan 2022 at 10:40, Liang Yang <liang.yang@amlogic.com> wrote:

> Hi Miquel,
>
> Meson NFC clock depends on the implementation of sd_emmc_c_clkc, but i
> don't find the commit in
> linux mainline. then the information i got from [jianxin.pan@amlogic.com]
> is the rejection of
> serial patches. I just look into the corresponding emails in link:
>
> https://lore.kernel.org/all/86789d73-5a6c-7729-ecd1-dcd342b2fcde@amlogic.com/
> it seems the patch never go on since V6, so [jianxin.pan@amlogic.com],
> could you help to clear it?
> let us address the discussion in another email from
> [jbrunet@baylibre.com].

That V6 was "rejected" because some comments from thre V5 were still not
addressed. 

>
> On 2022/1/6 16:08, Miquel Raynal wrote:
>> [ EXTERNAL EMAIL ]
>> Hi Liang,
>> liang.yang@amlogic.com wrote on Thu, 6 Jan 2022 11:25:04 +0800:
>> 
>>> Because EMMC and NAND have the same control clock register, so we
>>> implement a 'sd_emmc_c_clkc'. Previously DTS is defined as below:
>>>
>>> 	sd_emmc_c_clkc: mmc@7000 {
>>> 		compatible = "amlogic,meson-axg-mmc-clkc", "syscon";
>>> 		reg = <0x0 0x7000 0x0 0x800>;
>>> 	};
>>>
>>> 	nand-controller@7800 {
>>> 		......
>>>
>>> 		clocks = <&clkc CLKID_SD_EMMC_C>,
>>> 			<&sd_emmc_c_clkc CLKID_MMC_DIV>,
>>> 			<&sd_emmc_c_clkc CLKID_MMC_PHASE_RX>,
>>> 			<&sd_emmc_c_clkc CLKID_MMC_PHASE_TX>;
>>> 		clock-names = "core", "device", "rx", "tx";
>>> 		amlogic,mmc-syscon = <&sd_emmc_c_clkc>;
>>>
>>> 		......
>>> 	}
>>>
>>> but in fact, above implementation is rejected. so now registering
>>> a nand_divider.
>> What is rejected?
>> Why is it rejected?
>> What is nand_divider?
> i simplify our clock framework below, so nand divider is SD_EMMC_CLOCK[5:0]
> here.
> 			   -----          -----		    -----
> 	   the other------|	\        |     |	   |	 |
>          		  | mux	| -----  |  N  | ----------| NFC/|
> 	   FCLK_DIV2------|     |        |     |	   | EMMC|
> 			   -----/         ----- 	    -----
> 		    SD_EMMC_CLOCK[7:6] SD_EMMC_CLOCK[5:0]
>> 
>>>
>>> Change-Id: Ibeb4c7ff886f5886aac4d6c664d7bbd1b1bcb997
>> Change Ids are not expected in the upstream kernel.
>> But if you fix something you should have a Fixes:.
>> 
>>> Signed-off-by: Liang Yang <liang.yang@amlogic.com>
>>> ---
>>>   drivers/mtd/nand/raw/meson_nand.c | 88 +++++++++++++++++--------------
>>>   1 file changed, 49 insertions(+), 39 deletions(-)
>>>
>>> diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c
>>> index ac3be92872d0..4472363059c2 100644
>>> --- a/drivers/mtd/nand/raw/meson_nand.c
>>> +++ b/drivers/mtd/nand/raw/meson_nand.c
>>> @@ -2,7 +2,7 @@
>>>   /*
>>>    * Amlogic Meson Nand Flash Controller Driver
>>>    *
>>> - * Copyright (c) 2018 Amlogic, inc.
>>> + * Copyright (c) 2018-2021 Amlogic, inc.
>>>    * Author: Liang Yang <liang.yang@amlogic.com>
>>>    */
>>>   @@ -10,6 +10,7 @@
>>>   #include <linux/dma-mapping.h>
>>>   #include <linux/interrupt.h>
>>>   #include <linux/clk.h>
>>> +#include <linux/clk-provider.h>
>>>   #include <linux/mtd/rawnand.h>
>>>   #include <linux/mtd/mtd.h>
>>>   #include <linux/mfd/syscon.h>
>>> @@ -55,6 +56,7 @@
>>>   #define NFC_REG_VER		0x38
>>>     #define NFC_RB_IRQ_EN		BIT(21)
>>> +#define NFC_CMD_FIFO_RESET	BIT(31)
>>>     #define CMDRWGEN(cmd_dir, ran, bch, short_mode, page_size, pages)
>>> \
>>>   	(								\
>>> @@ -104,6 +106,9 @@
>>>     #define PER_INFO_BYTE		8
>>>   +#define CLK_DIV_SHIFT		0
>>> +#define CLK_DIV_WIDTH		6
>>> +
>>>   struct meson_nfc_nand_chip {
>>>   	struct list_head node;
>>>   	struct nand_chip nand;
>>> @@ -151,15 +156,15 @@ struct meson_nfc {
>>>   	struct nand_controller controller;
>>>   	struct clk *core_clk;
>>>   	struct clk *device_clk;
>>> -	struct clk *phase_tx;
>>> -	struct clk *phase_rx;
>>> +	struct clk *nand_clk;
>>> +	struct clk_divider nand_divider;
>>>     	unsigned long clk_rate;
>>>   	u32 bus_timing;
>>>     	struct device *dev;
>>>   	void __iomem *reg_base;
>>> -	struct regmap *reg_clk;
>>> +	void __iomem *reg_clk;
>>>   	struct completion completion;
>>>   	struct list_head chips;
>>>   	const struct meson_nfc_data *data;
>>> @@ -406,12 +411,14 @@ static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms)
>>>   	cmd = NFC_CMD_RB | NFC_CMD_RB_INT
>>>   		| nfc->param.chip_select | nfc->timing.tbers_max;
>>>   	writel(cmd, nfc->reg_base + NFC_REG_CMD);
>>> -
>>> +	meson_nfc_drain_cmd(nfc);
>>>   	ret = wait_for_completion_timeout(&nfc->completion,
>>>   					  msecs_to_jiffies(timeout_ms));
>>>   	if (ret == 0)
>>>   		ret = -1;
>>>   +	/* reset command fifo to avoid lock */
>>> +	writel(NFC_CMD_FIFO_RESET, nfc->reg_base + NFC_REG_CMD);
>>>   	return ret;
>>>   }
>>>   @@ -988,8 +995,9 @@ static const struct mtd_ooblayout_ops
>>> meson_ooblayout_ops = {
>>>   static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>   {
>>>   	int ret;
>>> +	struct clk_init_data init = {0};
>>> +	const char *fix_div2_pll_name[1];
>>>   -	/* request core clock */
>>>   	nfc->core_clk = devm_clk_get(nfc->dev, "core");
>>>   	if (IS_ERR(nfc->core_clk)) {
>>>   		dev_err(nfc->dev, "failed to get core clock\n");
>>> @@ -1002,21 +1010,25 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>   		return PTR_ERR(nfc->device_clk);
>>>   	}
>>>   -	nfc->phase_tx = devm_clk_get(nfc->dev, "tx");
>>> -	if (IS_ERR(nfc->phase_tx)) {
>>> -		dev_err(nfc->dev, "failed to get TX clk\n");
>>> -		return PTR_ERR(nfc->phase_tx);
>>> -	}
>>> -
>>> -	nfc->phase_rx = devm_clk_get(nfc->dev, "rx");
>>> -	if (IS_ERR(nfc->phase_rx)) {
>>> -		dev_err(nfc->dev, "failed to get RX clk\n");
>>> -		return PTR_ERR(nfc->phase_rx);
>>> -	}
>>> +	init.name = devm_kstrdup(nfc->dev, "nfc#div", GFP_KERNEL);
>>> +	init.ops = &clk_divider_ops;
>>> +	fix_div2_pll_name[0] = __clk_get_name(nfc->device_clk);
>>> +	init.parent_names = fix_div2_pll_name;
>>> +	init.num_parents = 1;
>>> +	nfc->nand_divider.reg = nfc->reg_clk;
>>> +	nfc->nand_divider.shift = CLK_DIV_SHIFT;
>>> +	nfc->nand_divider.width = CLK_DIV_WIDTH;
>>> +	nfc->nand_divider.hw.init = &init;
>>> +	nfc->nand_divider.flags = CLK_DIVIDER_ONE_BASED |
>>> +				  CLK_DIVIDER_ROUND_CLOSEST |
>>> +          			  CLK_DIVIDER_ALLOW_ZERO;
>>> +
>>> +	nfc->nand_clk = devm_clk_register(nfc->dev, &nfc->nand_divider.hw);
>>> +	if (IS_ERR(nfc->nand_clk))
>>> +		return PTR_ERR(nfc->nand_clk);
>>>     	/* init SD_EMMC_CLOCK to sane defaults w/min clock rate */
>>> -	regmap_update_bits(nfc->reg_clk,
>>> -			   0, CLK_SELECT_NAND, CLK_SELECT_NAND);
>>> +	writel(CLK_SELECT_NAND | readl(nfc->reg_clk), nfc->reg_clk);
>>>     	ret = clk_prepare_enable(nfc->core_clk);
>>>   	if (ret) {
>>> @@ -1030,29 +1042,21 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>   		goto err_device_clk;
>>>   	}
>>>   -	ret = clk_prepare_enable(nfc->phase_tx);
>>> +	ret = clk_prepare_enable(nfc->nand_clk);
>>>   	if (ret) {
>>> -		dev_err(nfc->dev, "failed to enable TX clock\n");
>>> -		goto err_phase_tx;
>>> -	}
>>> -
>>> -	ret = clk_prepare_enable(nfc->phase_rx);
>>> -	if (ret) {
>>> -		dev_err(nfc->dev, "failed to enable RX clock\n");
>>> -		goto err_phase_rx;
>>> +		dev_err(nfc->dev, "pre enable NFC divider fail\n");
>>> +		goto err_nand_clk;
>>>   	}
>>>     	ret = clk_set_rate(nfc->device_clk, 24000000);
>>>   	if (ret)
>>> -		goto err_disable_rx;
>>> +		goto err_disable_clk;
>>>     	return 0;
>>>   -err_disable_rx:
>>> -	clk_disable_unprepare(nfc->phase_rx);
>>> -err_phase_rx:
>>> -	clk_disable_unprepare(nfc->phase_tx);
>>> -err_phase_tx:
>>> +err_disable_clk:
>>> +	clk_disable_unprepare(nfc->nand_clk);
>>> +err_nand_clk:
>>>   	clk_disable_unprepare(nfc->device_clk);
>>>   err_device_clk:
>>>   	clk_disable_unprepare(nfc->core_clk);
>>> @@ -1061,8 +1065,7 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>     static void meson_nfc_disable_clk(struct meson_nfc *nfc)
>>>   {
>>> -	clk_disable_unprepare(nfc->phase_rx);
>>> -	clk_disable_unprepare(nfc->phase_tx);
>>> +	clk_disable_unprepare(nfc->nand_clk);
>>>   	clk_disable_unprepare(nfc->device_clk);
>>>   	clk_disable_unprepare(nfc->core_clk);
>>>   }
>>> @@ -1375,6 +1378,7 @@ static int meson_nfc_probe(struct platform_device *pdev)
>>>   	struct device *dev = &pdev->dev;
>>>   	struct meson_nfc *nfc;
>>>   	struct resource *res;
>>> +	u32 ext_clk_reg;
>>>   	int ret, irq;
>>>     	nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL);
>>> @@ -1396,9 +1400,15 @@ static int meson_nfc_probe(struct platform_device *pdev)
>>>   	if (IS_ERR(nfc->reg_base))
>>>   		return PTR_ERR(nfc->reg_base);
>>>   -	nfc->reg_clk =
>>> -		syscon_regmap_lookup_by_phandle(dev->of_node,
>>> -						"amlogic,mmc-syscon");
>>> +	ret = of_property_read_u32(pdev->dev.of_node,
>>> +				   "sd_emmc_c_clkc",
>>> +				   &ext_clk_reg);
>>> +	if (ret) {
>>> +		dev_err(dev, "failed to get NAND external clock register\n");
>>> +		return ret;
>>> +	}
>>> +
>>> +	nfc->reg_clk = devm_ioremap(&pdev->dev, ext_clk_reg, sizeof(int));
>>>   	if (IS_ERR(nfc->reg_clk)) {
>>>   		dev_err(dev, "Failed to lookup clock base\n");
>>>   		return PTR_ERR(nfc->reg_clk);
>> 
>> Thanks,
>> Miquèl
>> .


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH] mtd: rawnand: meson: fix the clock after discarding sd_emmc_c_clkc
@ 2022-01-07  7:54       ` Jerome Brunet
  0 siblings, 0 replies; 47+ messages in thread
From: Jerome Brunet @ 2022-01-07  7:54 UTC (permalink / raw)
  To: Liang Yang, Miquel Raynal
  Cc: linux-mtd, Richard Weinberger, Neil Armstrong,
	Martin Blumenstingl, Kevin Hilman, Jianxin Pan, Victor Wan,
	XianWei Zhao, Kelvin Zhang, BiChao Zheng, YongHui Yu,
	linux-arm-kernel, linux-amlogic, linux-kernel, devicetree


On Fri 07 Jan 2022 at 10:40, Liang Yang <liang.yang@amlogic.com> wrote:

> Hi Miquel,
>
> Meson NFC clock depends on the implementation of sd_emmc_c_clkc, but i
> don't find the commit in
> linux mainline. then the information i got from [jianxin.pan@amlogic.com]
> is the rejection of
> serial patches. I just look into the corresponding emails in link:
>
> https://lore.kernel.org/all/86789d73-5a6c-7729-ecd1-dcd342b2fcde@amlogic.com/
> it seems the patch never go on since V6, so [jianxin.pan@amlogic.com],
> could you help to clear it?
> let us address the discussion in another email from
> [jbrunet@baylibre.com].

That V6 was "rejected" because some comments from thre V5 were still not
addressed. 

>
> On 2022/1/6 16:08, Miquel Raynal wrote:
>> [ EXTERNAL EMAIL ]
>> Hi Liang,
>> liang.yang@amlogic.com wrote on Thu, 6 Jan 2022 11:25:04 +0800:
>> 
>>> Because EMMC and NAND have the same control clock register, so we
>>> implement a 'sd_emmc_c_clkc'. Previously DTS is defined as below:
>>>
>>> 	sd_emmc_c_clkc: mmc@7000 {
>>> 		compatible = "amlogic,meson-axg-mmc-clkc", "syscon";
>>> 		reg = <0x0 0x7000 0x0 0x800>;
>>> 	};
>>>
>>> 	nand-controller@7800 {
>>> 		......
>>>
>>> 		clocks = <&clkc CLKID_SD_EMMC_C>,
>>> 			<&sd_emmc_c_clkc CLKID_MMC_DIV>,
>>> 			<&sd_emmc_c_clkc CLKID_MMC_PHASE_RX>,
>>> 			<&sd_emmc_c_clkc CLKID_MMC_PHASE_TX>;
>>> 		clock-names = "core", "device", "rx", "tx";
>>> 		amlogic,mmc-syscon = <&sd_emmc_c_clkc>;
>>>
>>> 		......
>>> 	}
>>>
>>> but in fact, above implementation is rejected. so now registering
>>> a nand_divider.
>> What is rejected?
>> Why is it rejected?
>> What is nand_divider?
> i simplify our clock framework below, so nand divider is SD_EMMC_CLOCK[5:0]
> here.
> 			   -----          -----		    -----
> 	   the other------|	\        |     |	   |	 |
>          		  | mux	| -----  |  N  | ----------| NFC/|
> 	   FCLK_DIV2------|     |        |     |	   | EMMC|
> 			   -----/         ----- 	    -----
> 		    SD_EMMC_CLOCK[7:6] SD_EMMC_CLOCK[5:0]
>> 
>>>
>>> Change-Id: Ibeb4c7ff886f5886aac4d6c664d7bbd1b1bcb997
>> Change Ids are not expected in the upstream kernel.
>> But if you fix something you should have a Fixes:.
>> 
>>> Signed-off-by: Liang Yang <liang.yang@amlogic.com>
>>> ---
>>>   drivers/mtd/nand/raw/meson_nand.c | 88 +++++++++++++++++--------------
>>>   1 file changed, 49 insertions(+), 39 deletions(-)
>>>
>>> diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c
>>> index ac3be92872d0..4472363059c2 100644
>>> --- a/drivers/mtd/nand/raw/meson_nand.c
>>> +++ b/drivers/mtd/nand/raw/meson_nand.c
>>> @@ -2,7 +2,7 @@
>>>   /*
>>>    * Amlogic Meson Nand Flash Controller Driver
>>>    *
>>> - * Copyright (c) 2018 Amlogic, inc.
>>> + * Copyright (c) 2018-2021 Amlogic, inc.
>>>    * Author: Liang Yang <liang.yang@amlogic.com>
>>>    */
>>>   @@ -10,6 +10,7 @@
>>>   #include <linux/dma-mapping.h>
>>>   #include <linux/interrupt.h>
>>>   #include <linux/clk.h>
>>> +#include <linux/clk-provider.h>
>>>   #include <linux/mtd/rawnand.h>
>>>   #include <linux/mtd/mtd.h>
>>>   #include <linux/mfd/syscon.h>
>>> @@ -55,6 +56,7 @@
>>>   #define NFC_REG_VER		0x38
>>>     #define NFC_RB_IRQ_EN		BIT(21)
>>> +#define NFC_CMD_FIFO_RESET	BIT(31)
>>>     #define CMDRWGEN(cmd_dir, ran, bch, short_mode, page_size, pages)
>>> \
>>>   	(								\
>>> @@ -104,6 +106,9 @@
>>>     #define PER_INFO_BYTE		8
>>>   +#define CLK_DIV_SHIFT		0
>>> +#define CLK_DIV_WIDTH		6
>>> +
>>>   struct meson_nfc_nand_chip {
>>>   	struct list_head node;
>>>   	struct nand_chip nand;
>>> @@ -151,15 +156,15 @@ struct meson_nfc {
>>>   	struct nand_controller controller;
>>>   	struct clk *core_clk;
>>>   	struct clk *device_clk;
>>> -	struct clk *phase_tx;
>>> -	struct clk *phase_rx;
>>> +	struct clk *nand_clk;
>>> +	struct clk_divider nand_divider;
>>>     	unsigned long clk_rate;
>>>   	u32 bus_timing;
>>>     	struct device *dev;
>>>   	void __iomem *reg_base;
>>> -	struct regmap *reg_clk;
>>> +	void __iomem *reg_clk;
>>>   	struct completion completion;
>>>   	struct list_head chips;
>>>   	const struct meson_nfc_data *data;
>>> @@ -406,12 +411,14 @@ static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms)
>>>   	cmd = NFC_CMD_RB | NFC_CMD_RB_INT
>>>   		| nfc->param.chip_select | nfc->timing.tbers_max;
>>>   	writel(cmd, nfc->reg_base + NFC_REG_CMD);
>>> -
>>> +	meson_nfc_drain_cmd(nfc);
>>>   	ret = wait_for_completion_timeout(&nfc->completion,
>>>   					  msecs_to_jiffies(timeout_ms));
>>>   	if (ret == 0)
>>>   		ret = -1;
>>>   +	/* reset command fifo to avoid lock */
>>> +	writel(NFC_CMD_FIFO_RESET, nfc->reg_base + NFC_REG_CMD);
>>>   	return ret;
>>>   }
>>>   @@ -988,8 +995,9 @@ static const struct mtd_ooblayout_ops
>>> meson_ooblayout_ops = {
>>>   static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>   {
>>>   	int ret;
>>> +	struct clk_init_data init = {0};
>>> +	const char *fix_div2_pll_name[1];
>>>   -	/* request core clock */
>>>   	nfc->core_clk = devm_clk_get(nfc->dev, "core");
>>>   	if (IS_ERR(nfc->core_clk)) {
>>>   		dev_err(nfc->dev, "failed to get core clock\n");
>>> @@ -1002,21 +1010,25 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>   		return PTR_ERR(nfc->device_clk);
>>>   	}
>>>   -	nfc->phase_tx = devm_clk_get(nfc->dev, "tx");
>>> -	if (IS_ERR(nfc->phase_tx)) {
>>> -		dev_err(nfc->dev, "failed to get TX clk\n");
>>> -		return PTR_ERR(nfc->phase_tx);
>>> -	}
>>> -
>>> -	nfc->phase_rx = devm_clk_get(nfc->dev, "rx");
>>> -	if (IS_ERR(nfc->phase_rx)) {
>>> -		dev_err(nfc->dev, "failed to get RX clk\n");
>>> -		return PTR_ERR(nfc->phase_rx);
>>> -	}
>>> +	init.name = devm_kstrdup(nfc->dev, "nfc#div", GFP_KERNEL);
>>> +	init.ops = &clk_divider_ops;
>>> +	fix_div2_pll_name[0] = __clk_get_name(nfc->device_clk);
>>> +	init.parent_names = fix_div2_pll_name;
>>> +	init.num_parents = 1;
>>> +	nfc->nand_divider.reg = nfc->reg_clk;
>>> +	nfc->nand_divider.shift = CLK_DIV_SHIFT;
>>> +	nfc->nand_divider.width = CLK_DIV_WIDTH;
>>> +	nfc->nand_divider.hw.init = &init;
>>> +	nfc->nand_divider.flags = CLK_DIVIDER_ONE_BASED |
>>> +				  CLK_DIVIDER_ROUND_CLOSEST |
>>> +          			  CLK_DIVIDER_ALLOW_ZERO;
>>> +
>>> +	nfc->nand_clk = devm_clk_register(nfc->dev, &nfc->nand_divider.hw);
>>> +	if (IS_ERR(nfc->nand_clk))
>>> +		return PTR_ERR(nfc->nand_clk);
>>>     	/* init SD_EMMC_CLOCK to sane defaults w/min clock rate */
>>> -	regmap_update_bits(nfc->reg_clk,
>>> -			   0, CLK_SELECT_NAND, CLK_SELECT_NAND);
>>> +	writel(CLK_SELECT_NAND | readl(nfc->reg_clk), nfc->reg_clk);
>>>     	ret = clk_prepare_enable(nfc->core_clk);
>>>   	if (ret) {
>>> @@ -1030,29 +1042,21 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>   		goto err_device_clk;
>>>   	}
>>>   -	ret = clk_prepare_enable(nfc->phase_tx);
>>> +	ret = clk_prepare_enable(nfc->nand_clk);
>>>   	if (ret) {
>>> -		dev_err(nfc->dev, "failed to enable TX clock\n");
>>> -		goto err_phase_tx;
>>> -	}
>>> -
>>> -	ret = clk_prepare_enable(nfc->phase_rx);
>>> -	if (ret) {
>>> -		dev_err(nfc->dev, "failed to enable RX clock\n");
>>> -		goto err_phase_rx;
>>> +		dev_err(nfc->dev, "pre enable NFC divider fail\n");
>>> +		goto err_nand_clk;
>>>   	}
>>>     	ret = clk_set_rate(nfc->device_clk, 24000000);
>>>   	if (ret)
>>> -		goto err_disable_rx;
>>> +		goto err_disable_clk;
>>>     	return 0;
>>>   -err_disable_rx:
>>> -	clk_disable_unprepare(nfc->phase_rx);
>>> -err_phase_rx:
>>> -	clk_disable_unprepare(nfc->phase_tx);
>>> -err_phase_tx:
>>> +err_disable_clk:
>>> +	clk_disable_unprepare(nfc->nand_clk);
>>> +err_nand_clk:
>>>   	clk_disable_unprepare(nfc->device_clk);
>>>   err_device_clk:
>>>   	clk_disable_unprepare(nfc->core_clk);
>>> @@ -1061,8 +1065,7 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>     static void meson_nfc_disable_clk(struct meson_nfc *nfc)
>>>   {
>>> -	clk_disable_unprepare(nfc->phase_rx);
>>> -	clk_disable_unprepare(nfc->phase_tx);
>>> +	clk_disable_unprepare(nfc->nand_clk);
>>>   	clk_disable_unprepare(nfc->device_clk);
>>>   	clk_disable_unprepare(nfc->core_clk);
>>>   }
>>> @@ -1375,6 +1378,7 @@ static int meson_nfc_probe(struct platform_device *pdev)
>>>   	struct device *dev = &pdev->dev;
>>>   	struct meson_nfc *nfc;
>>>   	struct resource *res;
>>> +	u32 ext_clk_reg;
>>>   	int ret, irq;
>>>     	nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL);
>>> @@ -1396,9 +1400,15 @@ static int meson_nfc_probe(struct platform_device *pdev)
>>>   	if (IS_ERR(nfc->reg_base))
>>>   		return PTR_ERR(nfc->reg_base);
>>>   -	nfc->reg_clk =
>>> -		syscon_regmap_lookup_by_phandle(dev->of_node,
>>> -						"amlogic,mmc-syscon");
>>> +	ret = of_property_read_u32(pdev->dev.of_node,
>>> +				   "sd_emmc_c_clkc",
>>> +				   &ext_clk_reg);
>>> +	if (ret) {
>>> +		dev_err(dev, "failed to get NAND external clock register\n");
>>> +		return ret;
>>> +	}
>>> +
>>> +	nfc->reg_clk = devm_ioremap(&pdev->dev, ext_clk_reg, sizeof(int));
>>>   	if (IS_ERR(nfc->reg_clk)) {
>>>   		dev_err(dev, "Failed to lookup clock base\n");
>>>   		return PTR_ERR(nfc->reg_clk);
>> 
>> Thanks,
>> Miquèl
>> .


_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic

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

* Re: [PATCH] mtd: rawnand: meson: fix the clock after discarding sd_emmc_c_clkc
@ 2022-01-07  7:54       ` Jerome Brunet
  0 siblings, 0 replies; 47+ messages in thread
From: Jerome Brunet @ 2022-01-07  7:54 UTC (permalink / raw)
  To: Liang Yang, Miquel Raynal
  Cc: linux-mtd, Richard Weinberger, Neil Armstrong,
	Martin Blumenstingl, Kevin Hilman, Jianxin Pan, Victor Wan,
	XianWei Zhao, Kelvin Zhang, BiChao Zheng, YongHui Yu,
	linux-arm-kernel, linux-amlogic, linux-kernel, devicetree


On Fri 07 Jan 2022 at 10:40, Liang Yang <liang.yang@amlogic.com> wrote:

> Hi Miquel,
>
> Meson NFC clock depends on the implementation of sd_emmc_c_clkc, but i
> don't find the commit in
> linux mainline. then the information i got from [jianxin.pan@amlogic.com]
> is the rejection of
> serial patches. I just look into the corresponding emails in link:
>
> https://lore.kernel.org/all/86789d73-5a6c-7729-ecd1-dcd342b2fcde@amlogic.com/
> it seems the patch never go on since V6, so [jianxin.pan@amlogic.com],
> could you help to clear it?
> let us address the discussion in another email from
> [jbrunet@baylibre.com].

That V6 was "rejected" because some comments from thre V5 were still not
addressed. 

>
> On 2022/1/6 16:08, Miquel Raynal wrote:
>> [ EXTERNAL EMAIL ]
>> Hi Liang,
>> liang.yang@amlogic.com wrote on Thu, 6 Jan 2022 11:25:04 +0800:
>> 
>>> Because EMMC and NAND have the same control clock register, so we
>>> implement a 'sd_emmc_c_clkc'. Previously DTS is defined as below:
>>>
>>> 	sd_emmc_c_clkc: mmc@7000 {
>>> 		compatible = "amlogic,meson-axg-mmc-clkc", "syscon";
>>> 		reg = <0x0 0x7000 0x0 0x800>;
>>> 	};
>>>
>>> 	nand-controller@7800 {
>>> 		......
>>>
>>> 		clocks = <&clkc CLKID_SD_EMMC_C>,
>>> 			<&sd_emmc_c_clkc CLKID_MMC_DIV>,
>>> 			<&sd_emmc_c_clkc CLKID_MMC_PHASE_RX>,
>>> 			<&sd_emmc_c_clkc CLKID_MMC_PHASE_TX>;
>>> 		clock-names = "core", "device", "rx", "tx";
>>> 		amlogic,mmc-syscon = <&sd_emmc_c_clkc>;
>>>
>>> 		......
>>> 	}
>>>
>>> but in fact, above implementation is rejected. so now registering
>>> a nand_divider.
>> What is rejected?
>> Why is it rejected?
>> What is nand_divider?
> i simplify our clock framework below, so nand divider is SD_EMMC_CLOCK[5:0]
> here.
> 			   -----          -----		    -----
> 	   the other------|	\        |     |	   |	 |
>          		  | mux	| -----  |  N  | ----------| NFC/|
> 	   FCLK_DIV2------|     |        |     |	   | EMMC|
> 			   -----/         ----- 	    -----
> 		    SD_EMMC_CLOCK[7:6] SD_EMMC_CLOCK[5:0]
>> 
>>>
>>> Change-Id: Ibeb4c7ff886f5886aac4d6c664d7bbd1b1bcb997
>> Change Ids are not expected in the upstream kernel.
>> But if you fix something you should have a Fixes:.
>> 
>>> Signed-off-by: Liang Yang <liang.yang@amlogic.com>
>>> ---
>>>   drivers/mtd/nand/raw/meson_nand.c | 88 +++++++++++++++++--------------
>>>   1 file changed, 49 insertions(+), 39 deletions(-)
>>>
>>> diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c
>>> index ac3be92872d0..4472363059c2 100644
>>> --- a/drivers/mtd/nand/raw/meson_nand.c
>>> +++ b/drivers/mtd/nand/raw/meson_nand.c
>>> @@ -2,7 +2,7 @@
>>>   /*
>>>    * Amlogic Meson Nand Flash Controller Driver
>>>    *
>>> - * Copyright (c) 2018 Amlogic, inc.
>>> + * Copyright (c) 2018-2021 Amlogic, inc.
>>>    * Author: Liang Yang <liang.yang@amlogic.com>
>>>    */
>>>   @@ -10,6 +10,7 @@
>>>   #include <linux/dma-mapping.h>
>>>   #include <linux/interrupt.h>
>>>   #include <linux/clk.h>
>>> +#include <linux/clk-provider.h>
>>>   #include <linux/mtd/rawnand.h>
>>>   #include <linux/mtd/mtd.h>
>>>   #include <linux/mfd/syscon.h>
>>> @@ -55,6 +56,7 @@
>>>   #define NFC_REG_VER		0x38
>>>     #define NFC_RB_IRQ_EN		BIT(21)
>>> +#define NFC_CMD_FIFO_RESET	BIT(31)
>>>     #define CMDRWGEN(cmd_dir, ran, bch, short_mode, page_size, pages)
>>> \
>>>   	(								\
>>> @@ -104,6 +106,9 @@
>>>     #define PER_INFO_BYTE		8
>>>   +#define CLK_DIV_SHIFT		0
>>> +#define CLK_DIV_WIDTH		6
>>> +
>>>   struct meson_nfc_nand_chip {
>>>   	struct list_head node;
>>>   	struct nand_chip nand;
>>> @@ -151,15 +156,15 @@ struct meson_nfc {
>>>   	struct nand_controller controller;
>>>   	struct clk *core_clk;
>>>   	struct clk *device_clk;
>>> -	struct clk *phase_tx;
>>> -	struct clk *phase_rx;
>>> +	struct clk *nand_clk;
>>> +	struct clk_divider nand_divider;
>>>     	unsigned long clk_rate;
>>>   	u32 bus_timing;
>>>     	struct device *dev;
>>>   	void __iomem *reg_base;
>>> -	struct regmap *reg_clk;
>>> +	void __iomem *reg_clk;
>>>   	struct completion completion;
>>>   	struct list_head chips;
>>>   	const struct meson_nfc_data *data;
>>> @@ -406,12 +411,14 @@ static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms)
>>>   	cmd = NFC_CMD_RB | NFC_CMD_RB_INT
>>>   		| nfc->param.chip_select | nfc->timing.tbers_max;
>>>   	writel(cmd, nfc->reg_base + NFC_REG_CMD);
>>> -
>>> +	meson_nfc_drain_cmd(nfc);
>>>   	ret = wait_for_completion_timeout(&nfc->completion,
>>>   					  msecs_to_jiffies(timeout_ms));
>>>   	if (ret == 0)
>>>   		ret = -1;
>>>   +	/* reset command fifo to avoid lock */
>>> +	writel(NFC_CMD_FIFO_RESET, nfc->reg_base + NFC_REG_CMD);
>>>   	return ret;
>>>   }
>>>   @@ -988,8 +995,9 @@ static const struct mtd_ooblayout_ops
>>> meson_ooblayout_ops = {
>>>   static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>   {
>>>   	int ret;
>>> +	struct clk_init_data init = {0};
>>> +	const char *fix_div2_pll_name[1];
>>>   -	/* request core clock */
>>>   	nfc->core_clk = devm_clk_get(nfc->dev, "core");
>>>   	if (IS_ERR(nfc->core_clk)) {
>>>   		dev_err(nfc->dev, "failed to get core clock\n");
>>> @@ -1002,21 +1010,25 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>   		return PTR_ERR(nfc->device_clk);
>>>   	}
>>>   -	nfc->phase_tx = devm_clk_get(nfc->dev, "tx");
>>> -	if (IS_ERR(nfc->phase_tx)) {
>>> -		dev_err(nfc->dev, "failed to get TX clk\n");
>>> -		return PTR_ERR(nfc->phase_tx);
>>> -	}
>>> -
>>> -	nfc->phase_rx = devm_clk_get(nfc->dev, "rx");
>>> -	if (IS_ERR(nfc->phase_rx)) {
>>> -		dev_err(nfc->dev, "failed to get RX clk\n");
>>> -		return PTR_ERR(nfc->phase_rx);
>>> -	}
>>> +	init.name = devm_kstrdup(nfc->dev, "nfc#div", GFP_KERNEL);
>>> +	init.ops = &clk_divider_ops;
>>> +	fix_div2_pll_name[0] = __clk_get_name(nfc->device_clk);
>>> +	init.parent_names = fix_div2_pll_name;
>>> +	init.num_parents = 1;
>>> +	nfc->nand_divider.reg = nfc->reg_clk;
>>> +	nfc->nand_divider.shift = CLK_DIV_SHIFT;
>>> +	nfc->nand_divider.width = CLK_DIV_WIDTH;
>>> +	nfc->nand_divider.hw.init = &init;
>>> +	nfc->nand_divider.flags = CLK_DIVIDER_ONE_BASED |
>>> +				  CLK_DIVIDER_ROUND_CLOSEST |
>>> +          			  CLK_DIVIDER_ALLOW_ZERO;
>>> +
>>> +	nfc->nand_clk = devm_clk_register(nfc->dev, &nfc->nand_divider.hw);
>>> +	if (IS_ERR(nfc->nand_clk))
>>> +		return PTR_ERR(nfc->nand_clk);
>>>     	/* init SD_EMMC_CLOCK to sane defaults w/min clock rate */
>>> -	regmap_update_bits(nfc->reg_clk,
>>> -			   0, CLK_SELECT_NAND, CLK_SELECT_NAND);
>>> +	writel(CLK_SELECT_NAND | readl(nfc->reg_clk), nfc->reg_clk);
>>>     	ret = clk_prepare_enable(nfc->core_clk);
>>>   	if (ret) {
>>> @@ -1030,29 +1042,21 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>   		goto err_device_clk;
>>>   	}
>>>   -	ret = clk_prepare_enable(nfc->phase_tx);
>>> +	ret = clk_prepare_enable(nfc->nand_clk);
>>>   	if (ret) {
>>> -		dev_err(nfc->dev, "failed to enable TX clock\n");
>>> -		goto err_phase_tx;
>>> -	}
>>> -
>>> -	ret = clk_prepare_enable(nfc->phase_rx);
>>> -	if (ret) {
>>> -		dev_err(nfc->dev, "failed to enable RX clock\n");
>>> -		goto err_phase_rx;
>>> +		dev_err(nfc->dev, "pre enable NFC divider fail\n");
>>> +		goto err_nand_clk;
>>>   	}
>>>     	ret = clk_set_rate(nfc->device_clk, 24000000);
>>>   	if (ret)
>>> -		goto err_disable_rx;
>>> +		goto err_disable_clk;
>>>     	return 0;
>>>   -err_disable_rx:
>>> -	clk_disable_unprepare(nfc->phase_rx);
>>> -err_phase_rx:
>>> -	clk_disable_unprepare(nfc->phase_tx);
>>> -err_phase_tx:
>>> +err_disable_clk:
>>> +	clk_disable_unprepare(nfc->nand_clk);
>>> +err_nand_clk:
>>>   	clk_disable_unprepare(nfc->device_clk);
>>>   err_device_clk:
>>>   	clk_disable_unprepare(nfc->core_clk);
>>> @@ -1061,8 +1065,7 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>     static void meson_nfc_disable_clk(struct meson_nfc *nfc)
>>>   {
>>> -	clk_disable_unprepare(nfc->phase_rx);
>>> -	clk_disable_unprepare(nfc->phase_tx);
>>> +	clk_disable_unprepare(nfc->nand_clk);
>>>   	clk_disable_unprepare(nfc->device_clk);
>>>   	clk_disable_unprepare(nfc->core_clk);
>>>   }
>>> @@ -1375,6 +1378,7 @@ static int meson_nfc_probe(struct platform_device *pdev)
>>>   	struct device *dev = &pdev->dev;
>>>   	struct meson_nfc *nfc;
>>>   	struct resource *res;
>>> +	u32 ext_clk_reg;
>>>   	int ret, irq;
>>>     	nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL);
>>> @@ -1396,9 +1400,15 @@ static int meson_nfc_probe(struct platform_device *pdev)
>>>   	if (IS_ERR(nfc->reg_base))
>>>   		return PTR_ERR(nfc->reg_base);
>>>   -	nfc->reg_clk =
>>> -		syscon_regmap_lookup_by_phandle(dev->of_node,
>>> -						"amlogic,mmc-syscon");
>>> +	ret = of_property_read_u32(pdev->dev.of_node,
>>> +				   "sd_emmc_c_clkc",
>>> +				   &ext_clk_reg);
>>> +	if (ret) {
>>> +		dev_err(dev, "failed to get NAND external clock register\n");
>>> +		return ret;
>>> +	}
>>> +
>>> +	nfc->reg_clk = devm_ioremap(&pdev->dev, ext_clk_reg, sizeof(int));
>>>   	if (IS_ERR(nfc->reg_clk)) {
>>>   		dev_err(dev, "Failed to lookup clock base\n");
>>>   		return PTR_ERR(nfc->reg_clk);
>> 
>> Thanks,
>> Miquèl
>> .


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH] mtd: rawnand: meson: fix the clock after discarding sd_emmc_c_clkc
  2022-01-07  4:04     ` Liang Yang
  (?)
  (?)
@ 2022-01-07  9:57       ` Neil Armstrong
  -1 siblings, 0 replies; 47+ messages in thread
From: Neil Armstrong @ 2022-01-07  9:57 UTC (permalink / raw)
  To: Liang Yang, Jerome Brunet, Miquel Raynal, linux-mtd
  Cc: Richard Weinberger, Martin Blumenstingl, Kevin Hilman,
	Jianxin Pan, Victor Wan, XianWei Zhao, Kelvin Zhang,
	BiChao Zheng, YongHui Yu, linux-arm-kernel, linux-amlogic,
	linux-kernel, devicetree

Hi,

On 07/01/2022 05:04, Liang Yang wrote:
> Hi Jerome,
> 
> On 2022/1/6 16:16, Jerome Brunet wrote:
>> [ EXTERNAL EMAIL ]
>>
>>
>> On Thu 06 Jan 2022 at 11:25, Liang Yang <liang.yang@amlogic.com> wrote:
>>
>>> Because EMMC and NAND have the same control clock register, so we
>>> implement a 'sd_emmc_c_clkc'. Previously DTS is defined as below:
>>>
>>>     sd_emmc_c_clkc: mmc@7000 {
>>>         compatible = "amlogic,meson-axg-mmc-clkc", "syscon";
>>>         reg = <0x0 0x7000 0x0 0x800>;
>>>     };
>>>
>>>     nand-controller@7800 {
>>>         ......
>>>
>>>         clocks = <&clkc CLKID_SD_EMMC_C>,
>>>             <&sd_emmc_c_clkc CLKID_MMC_DIV>,
>>>             <&sd_emmc_c_clkc CLKID_MMC_PHASE_RX>,
>>>             <&sd_emmc_c_clkc CLKID_MMC_PHASE_TX>;
>>>         clock-names = "core", "device", "rx", "tx";
>>>         amlogic,mmc-syscon = <&sd_emmc_c_clkc>;
>>>
>>>         ......
>>>     }
>>>
>>> but in fact, above implementation is rejected. so now registering
>>> a nand_divider.
>>
>> Can you give a bit of context ? a link to the discussion rejecting this
>>
> Maybe I mistake the meaning of [jianxin.pan@amlogic.com], so i need him to clarify it.
>> As far as remember, things were getting done for A1 and stopped before
>> clock part was finished. I'm saying the change is wrong, just that a
>> discussion is needed before a decision is made.
>>
> ok.
> previous discussion in this link:
> https://lore.kernel.org/all/86789d73-5a6c-7729-ecd1-dcd342b2fcde@amlogic.com/
> it never go on since v6.

Looking at the serie I don't see any major blockers, if you're willing to take ownership
of this patchset and send a v6 with all issues/comments addressed, it would be easier than
restarting the whole design discussion

Neil

> 
>>>
>>> Change-Id: Ibeb4c7ff886f5886aac4d6c664d7bbd1b1bcb997
>>> Signed-off-by: Liang Yang <liang.yang@amlogic.com>
>>> ---
>>>   drivers/mtd/nand/raw/meson_nand.c | 88 +++++++++++++++++--------------
>>>   1 file changed, 49 insertions(+), 39 deletions(-)
>>>
>>> diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c
>>> index ac3be92872d0..4472363059c2 100644
>>> --- a/drivers/mtd/nand/raw/meson_nand.c
>>> +++ b/drivers/mtd/nand/raw/meson_nand.c
>>> @@ -2,7 +2,7 @@
>>>   /*
>>>    * Amlogic Meson Nand Flash Controller Driver
>>>    *
>>> - * Copyright (c) 2018 Amlogic, inc.
>>> + * Copyright (c) 2018-2021 Amlogic, inc.
>>>    * Author: Liang Yang <liang.yang@amlogic.com>
>>>    */
>>>   @@ -10,6 +10,7 @@
>>>   #include <linux/dma-mapping.h>
>>>   #include <linux/interrupt.h>
>>>   #include <linux/clk.h>
>>> +#include <linux/clk-provider.h>
>>>   #include <linux/mtd/rawnand.h>
>>>   #include <linux/mtd/mtd.h>
>>>   #include <linux/mfd/syscon.h>
>>> @@ -55,6 +56,7 @@
>>>   #define NFC_REG_VER        0x38
>>>     #define NFC_RB_IRQ_EN        BIT(21)
>>> +#define NFC_CMD_FIFO_RESET    BIT(31)
>>>     #define CMDRWGEN(cmd_dir, ran, bch, short_mode, page_size, pages)    \
>>>       (                                \
>>> @@ -104,6 +106,9 @@
>>>     #define PER_INFO_BYTE        8
>>>   +#define CLK_DIV_SHIFT        0
>>> +#define CLK_DIV_WIDTH        6
>>> +
>>>   struct meson_nfc_nand_chip {
>>>       struct list_head node;
>>>       struct nand_chip nand;
>>> @@ -151,15 +156,15 @@ struct meson_nfc {
>>>       struct nand_controller controller;
>>>       struct clk *core_clk;
>>>       struct clk *device_clk;
>>> -    struct clk *phase_tx;
>>> -    struct clk *phase_rx;
>>
>> I would have been nice to explain why these clock are no longer
>> required, in the change description maybe ?
> 
> i got the reply from our vlsi members that rx and tx doesn't make sense to meson NFC timing. so previous commit about this should be wrong.
>>
>>> +    struct clk *nand_clk;
>>> +    struct clk_divider nand_divider;
>>>         unsigned long clk_rate;
>>>       u32 bus_timing;
>>>         struct device *dev;
>>>       void __iomem *reg_base;
>>> -    struct regmap *reg_clk;
>>> +    void __iomem *reg_clk;
>>>       struct completion completion;
>>>       struct list_head chips;
>>>       const struct meson_nfc_data *data;
>>> @@ -406,12 +411,14 @@ static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms)
>>>       cmd = NFC_CMD_RB | NFC_CMD_RB_INT
>>>           | nfc->param.chip_select | nfc->timing.tbers_max;
>>>       writel(cmd, nfc->reg_base + NFC_REG_CMD);
>>> -
>>> +    meson_nfc_drain_cmd(nfc);
>>
>> is this clock related ?
> ok, i will split it in another patch.
>>
>>>       ret = wait_for_completion_timeout(&nfc->completion,
>>>                         msecs_to_jiffies(timeout_ms));
>>>       if (ret == 0)
>>>           ret = -1;
>>>   +    /* reset command fifo to avoid lock */
>>> +    writel(NFC_CMD_FIFO_RESET, nfc->reg_base + NFC_REG_CMD);
>>
>> Again, not seem to be clock related - does not belong in this patch
> ok, i will split it in another patch.
>>
>>>       return ret;
>>>   }
>>>   @@ -988,8 +995,9 @@ static const struct mtd_ooblayout_ops meson_ooblayout_ops = {
>>>   static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>   {
>>>       int ret;
>>> +    struct clk_init_data init = {0};
>>> +    const char *fix_div2_pll_name[1];
>>>   -    /* request core clock */
>>
>> Why is the comment bothering you ?
>>
>>>       nfc->core_clk = devm_clk_get(nfc->dev, "core");
>>>       if (IS_ERR(nfc->core_clk)) {
>>>           dev_err(nfc->dev, "failed to get core clock\n");
>>> @@ -1002,21 +1010,25 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>           return PTR_ERR(nfc->device_clk);
>>>       }
>>>   -    nfc->phase_tx = devm_clk_get(nfc->dev, "tx");
>>> -    if (IS_ERR(nfc->phase_tx)) {
>>> -        dev_err(nfc->dev, "failed to get TX clk\n");
>>> -        return PTR_ERR(nfc->phase_tx);
>>> -    }
>>> -
>>> -    nfc->phase_rx = devm_clk_get(nfc->dev, "rx");
>>> -    if (IS_ERR(nfc->phase_rx)) {
>>> -        dev_err(nfc->dev, "failed to get RX clk\n");
>>> -        return PTR_ERR(nfc->phase_rx);
>>> -    }
>>> +    init.name = devm_kstrdup(nfc->dev, "nfc#div", GFP_KERNEL);
>>> +    init.ops = &clk_divider_ops;
>>> +    fix_div2_pll_name[0] = __clk_get_name(nfc->device_clk);
>>
>> You should be using "fw_name" so CCF looks a DT directly, instead of this
> ok
>>
>>> +    init.parent_names = fix_div2_pll_name;
>>> +    init.num_parents = 1;
>>> +    nfc->nand_divider.reg = nfc->reg_clk;
>>> +    nfc->nand_divider.shift = CLK_DIV_SHIFT;
>>> +    nfc->nand_divider.width = CLK_DIV_WIDTH;
>>> +    nfc->nand_divider.hw.init = &init;
>>> +    nfc->nand_divider.flags = CLK_DIVIDER_ONE_BASED |
>>> +                  CLK_DIVIDER_ROUND_CLOSEST |
>>> +                        CLK_DIVIDER_ALLOW_ZERO;
>>> +
>>> +    nfc->nand_clk = devm_clk_register(nfc->dev, &nfc->nand_divider.hw);
>>> +    if (IS_ERR(nfc->nand_clk))
>>> +        return PTR_ERR(nfc->nand_clk);
>>>         /* init SD_EMMC_CLOCK to sane defaults w/min clock rate */
>>> -    regmap_update_bits(nfc->reg_clk,
>>> -               0, CLK_SELECT_NAND, CLK_SELECT_NAND);
>>> +    writel(CLK_SELECT_NAND | readl(nfc->reg_clk), nfc->reg_clk);
>>>         ret = clk_prepare_enable(nfc->core_clk);
>>>       if (ret) {
>>> @@ -1030,29 +1042,21 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>           goto err_device_clk;
>>>       }
>>>   -    ret = clk_prepare_enable(nfc->phase_tx);
>>> +    ret = clk_prepare_enable(nfc->nand_clk);
>>>       if (ret) {
>>> -        dev_err(nfc->dev, "failed to enable TX clock\n");
>>> -        goto err_phase_tx;
>>> -    }
>>> -
>>> -    ret = clk_prepare_enable(nfc->phase_rx);
>>> -    if (ret) {
>>> -        dev_err(nfc->dev, "failed to enable RX clock\n");
>>> -        goto err_phase_rx;
>>> +        dev_err(nfc->dev, "pre enable NFC divider fail\n");
>>> +        goto err_nand_clk;
>>>       }
>>>         ret = clk_set_rate(nfc->device_clk, 24000000);
>>>       if (ret)
>>> -        goto err_disable_rx;
>>> +        goto err_disable_clk;
>>>         return 0;
>>>   -err_disable_rx:
>>> -    clk_disable_unprepare(nfc->phase_rx);
>>> -err_phase_rx:
>>> -    clk_disable_unprepare(nfc->phase_tx);
>>> -err_phase_tx:
>>> +err_disable_clk:
>>> +    clk_disable_unprepare(nfc->nand_clk);
>>> +err_nand_clk:
>>>       clk_disable_unprepare(nfc->device_clk);
>>>   err_device_clk:
>>>       clk_disable_unprepare(nfc->core_clk);
>>> @@ -1061,8 +1065,7 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>     static void meson_nfc_disable_clk(struct meson_nfc *nfc)
>>>   {
>>> -    clk_disable_unprepare(nfc->phase_rx);
>>> -    clk_disable_unprepare(nfc->phase_tx);
>>> +    clk_disable_unprepare(nfc->nand_clk);
>>>       clk_disable_unprepare(nfc->device_clk);
>>>       clk_disable_unprepare(nfc->core_clk);
>>>   }
>>> @@ -1375,6 +1378,7 @@ static int meson_nfc_probe(struct platform_device *pdev)
>>>       struct device *dev = &pdev->dev;
>>>       struct meson_nfc *nfc;
>>>       struct resource *res;
>>> +    u32 ext_clk_reg;
>>>       int ret, irq;
>>>         nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL);
>>> @@ -1396,9 +1400,15 @@ static int meson_nfc_probe(struct platform_device *pdev)
>>>       if (IS_ERR(nfc->reg_base))
>>>           return PTR_ERR(nfc->reg_base);
>>>   -    nfc->reg_clk =
>>> -        syscon_regmap_lookup_by_phandle(dev->of_node,
>>> -                        "amlogic,mmc-syscon");
>>> +    ret = of_property_read_u32(pdev->dev.of_node,
>>> +                   "sd_emmc_c_clkc",
>>> +                   &ext_clk_reg);
>>> +    if (ret) {
>>> +        dev_err(dev, "failed to get NAND external clock register\n");
>>> +        return ret;
>>> +    }
>>> +
>>> +    nfc->reg_clk = devm_ioremap(&pdev->dev, ext_clk_reg, sizeof(int));
>>
>> That's how you should get a register region.
>> If you want an example of a device claiming several region on amlogic,
>> have a look at the pinctrl driver.
> ok
>>
>>>       if (IS_ERR(nfc->reg_clk)) {
>>>           dev_err(dev, "Failed to lookup clock base\n");
>>>           return PTR_ERR(nfc->reg_clk);
>>
>> .


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

* Re: [PATCH] mtd: rawnand: meson: fix the clock after discarding sd_emmc_c_clkc
@ 2022-01-07  9:57       ` Neil Armstrong
  0 siblings, 0 replies; 47+ messages in thread
From: Neil Armstrong @ 2022-01-07  9:57 UTC (permalink / raw)
  To: Liang Yang, Jerome Brunet, Miquel Raynal, linux-mtd
  Cc: Richard Weinberger, Martin Blumenstingl, Kevin Hilman,
	Jianxin Pan, Victor Wan, XianWei Zhao, Kelvin Zhang,
	BiChao Zheng, YongHui Yu, linux-arm-kernel, linux-amlogic,
	linux-kernel, devicetree

Hi,

On 07/01/2022 05:04, Liang Yang wrote:
> Hi Jerome,
> 
> On 2022/1/6 16:16, Jerome Brunet wrote:
>> [ EXTERNAL EMAIL ]
>>
>>
>> On Thu 06 Jan 2022 at 11:25, Liang Yang <liang.yang@amlogic.com> wrote:
>>
>>> Because EMMC and NAND have the same control clock register, so we
>>> implement a 'sd_emmc_c_clkc'. Previously DTS is defined as below:
>>>
>>>     sd_emmc_c_clkc: mmc@7000 {
>>>         compatible = "amlogic,meson-axg-mmc-clkc", "syscon";
>>>         reg = <0x0 0x7000 0x0 0x800>;
>>>     };
>>>
>>>     nand-controller@7800 {
>>>         ......
>>>
>>>         clocks = <&clkc CLKID_SD_EMMC_C>,
>>>             <&sd_emmc_c_clkc CLKID_MMC_DIV>,
>>>             <&sd_emmc_c_clkc CLKID_MMC_PHASE_RX>,
>>>             <&sd_emmc_c_clkc CLKID_MMC_PHASE_TX>;
>>>         clock-names = "core", "device", "rx", "tx";
>>>         amlogic,mmc-syscon = <&sd_emmc_c_clkc>;
>>>
>>>         ......
>>>     }
>>>
>>> but in fact, above implementation is rejected. so now registering
>>> a nand_divider.
>>
>> Can you give a bit of context ? a link to the discussion rejecting this
>>
> Maybe I mistake the meaning of [jianxin.pan@amlogic.com], so i need him to clarify it.
>> As far as remember, things were getting done for A1 and stopped before
>> clock part was finished. I'm saying the change is wrong, just that a
>> discussion is needed before a decision is made.
>>
> ok.
> previous discussion in this link:
> https://lore.kernel.org/all/86789d73-5a6c-7729-ecd1-dcd342b2fcde@amlogic.com/
> it never go on since v6.

Looking at the serie I don't see any major blockers, if you're willing to take ownership
of this patchset and send a v6 with all issues/comments addressed, it would be easier than
restarting the whole design discussion

Neil

> 
>>>
>>> Change-Id: Ibeb4c7ff886f5886aac4d6c664d7bbd1b1bcb997
>>> Signed-off-by: Liang Yang <liang.yang@amlogic.com>
>>> ---
>>>   drivers/mtd/nand/raw/meson_nand.c | 88 +++++++++++++++++--------------
>>>   1 file changed, 49 insertions(+), 39 deletions(-)
>>>
>>> diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c
>>> index ac3be92872d0..4472363059c2 100644
>>> --- a/drivers/mtd/nand/raw/meson_nand.c
>>> +++ b/drivers/mtd/nand/raw/meson_nand.c
>>> @@ -2,7 +2,7 @@
>>>   /*
>>>    * Amlogic Meson Nand Flash Controller Driver
>>>    *
>>> - * Copyright (c) 2018 Amlogic, inc.
>>> + * Copyright (c) 2018-2021 Amlogic, inc.
>>>    * Author: Liang Yang <liang.yang@amlogic.com>
>>>    */
>>>   @@ -10,6 +10,7 @@
>>>   #include <linux/dma-mapping.h>
>>>   #include <linux/interrupt.h>
>>>   #include <linux/clk.h>
>>> +#include <linux/clk-provider.h>
>>>   #include <linux/mtd/rawnand.h>
>>>   #include <linux/mtd/mtd.h>
>>>   #include <linux/mfd/syscon.h>
>>> @@ -55,6 +56,7 @@
>>>   #define NFC_REG_VER        0x38
>>>     #define NFC_RB_IRQ_EN        BIT(21)
>>> +#define NFC_CMD_FIFO_RESET    BIT(31)
>>>     #define CMDRWGEN(cmd_dir, ran, bch, short_mode, page_size, pages)    \
>>>       (                                \
>>> @@ -104,6 +106,9 @@
>>>     #define PER_INFO_BYTE        8
>>>   +#define CLK_DIV_SHIFT        0
>>> +#define CLK_DIV_WIDTH        6
>>> +
>>>   struct meson_nfc_nand_chip {
>>>       struct list_head node;
>>>       struct nand_chip nand;
>>> @@ -151,15 +156,15 @@ struct meson_nfc {
>>>       struct nand_controller controller;
>>>       struct clk *core_clk;
>>>       struct clk *device_clk;
>>> -    struct clk *phase_tx;
>>> -    struct clk *phase_rx;
>>
>> I would have been nice to explain why these clock are no longer
>> required, in the change description maybe ?
> 
> i got the reply from our vlsi members that rx and tx doesn't make sense to meson NFC timing. so previous commit about this should be wrong.
>>
>>> +    struct clk *nand_clk;
>>> +    struct clk_divider nand_divider;
>>>         unsigned long clk_rate;
>>>       u32 bus_timing;
>>>         struct device *dev;
>>>       void __iomem *reg_base;
>>> -    struct regmap *reg_clk;
>>> +    void __iomem *reg_clk;
>>>       struct completion completion;
>>>       struct list_head chips;
>>>       const struct meson_nfc_data *data;
>>> @@ -406,12 +411,14 @@ static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms)
>>>       cmd = NFC_CMD_RB | NFC_CMD_RB_INT
>>>           | nfc->param.chip_select | nfc->timing.tbers_max;
>>>       writel(cmd, nfc->reg_base + NFC_REG_CMD);
>>> -
>>> +    meson_nfc_drain_cmd(nfc);
>>
>> is this clock related ?
> ok, i will split it in another patch.
>>
>>>       ret = wait_for_completion_timeout(&nfc->completion,
>>>                         msecs_to_jiffies(timeout_ms));
>>>       if (ret == 0)
>>>           ret = -1;
>>>   +    /* reset command fifo to avoid lock */
>>> +    writel(NFC_CMD_FIFO_RESET, nfc->reg_base + NFC_REG_CMD);
>>
>> Again, not seem to be clock related - does not belong in this patch
> ok, i will split it in another patch.
>>
>>>       return ret;
>>>   }
>>>   @@ -988,8 +995,9 @@ static const struct mtd_ooblayout_ops meson_ooblayout_ops = {
>>>   static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>   {
>>>       int ret;
>>> +    struct clk_init_data init = {0};
>>> +    const char *fix_div2_pll_name[1];
>>>   -    /* request core clock */
>>
>> Why is the comment bothering you ?
>>
>>>       nfc->core_clk = devm_clk_get(nfc->dev, "core");
>>>       if (IS_ERR(nfc->core_clk)) {
>>>           dev_err(nfc->dev, "failed to get core clock\n");
>>> @@ -1002,21 +1010,25 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>           return PTR_ERR(nfc->device_clk);
>>>       }
>>>   -    nfc->phase_tx = devm_clk_get(nfc->dev, "tx");
>>> -    if (IS_ERR(nfc->phase_tx)) {
>>> -        dev_err(nfc->dev, "failed to get TX clk\n");
>>> -        return PTR_ERR(nfc->phase_tx);
>>> -    }
>>> -
>>> -    nfc->phase_rx = devm_clk_get(nfc->dev, "rx");
>>> -    if (IS_ERR(nfc->phase_rx)) {
>>> -        dev_err(nfc->dev, "failed to get RX clk\n");
>>> -        return PTR_ERR(nfc->phase_rx);
>>> -    }
>>> +    init.name = devm_kstrdup(nfc->dev, "nfc#div", GFP_KERNEL);
>>> +    init.ops = &clk_divider_ops;
>>> +    fix_div2_pll_name[0] = __clk_get_name(nfc->device_clk);
>>
>> You should be using "fw_name" so CCF looks a DT directly, instead of this
> ok
>>
>>> +    init.parent_names = fix_div2_pll_name;
>>> +    init.num_parents = 1;
>>> +    nfc->nand_divider.reg = nfc->reg_clk;
>>> +    nfc->nand_divider.shift = CLK_DIV_SHIFT;
>>> +    nfc->nand_divider.width = CLK_DIV_WIDTH;
>>> +    nfc->nand_divider.hw.init = &init;
>>> +    nfc->nand_divider.flags = CLK_DIVIDER_ONE_BASED |
>>> +                  CLK_DIVIDER_ROUND_CLOSEST |
>>> +                        CLK_DIVIDER_ALLOW_ZERO;
>>> +
>>> +    nfc->nand_clk = devm_clk_register(nfc->dev, &nfc->nand_divider.hw);
>>> +    if (IS_ERR(nfc->nand_clk))
>>> +        return PTR_ERR(nfc->nand_clk);
>>>         /* init SD_EMMC_CLOCK to sane defaults w/min clock rate */
>>> -    regmap_update_bits(nfc->reg_clk,
>>> -               0, CLK_SELECT_NAND, CLK_SELECT_NAND);
>>> +    writel(CLK_SELECT_NAND | readl(nfc->reg_clk), nfc->reg_clk);
>>>         ret = clk_prepare_enable(nfc->core_clk);
>>>       if (ret) {
>>> @@ -1030,29 +1042,21 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>           goto err_device_clk;
>>>       }
>>>   -    ret = clk_prepare_enable(nfc->phase_tx);
>>> +    ret = clk_prepare_enable(nfc->nand_clk);
>>>       if (ret) {
>>> -        dev_err(nfc->dev, "failed to enable TX clock\n");
>>> -        goto err_phase_tx;
>>> -    }
>>> -
>>> -    ret = clk_prepare_enable(nfc->phase_rx);
>>> -    if (ret) {
>>> -        dev_err(nfc->dev, "failed to enable RX clock\n");
>>> -        goto err_phase_rx;
>>> +        dev_err(nfc->dev, "pre enable NFC divider fail\n");
>>> +        goto err_nand_clk;
>>>       }
>>>         ret = clk_set_rate(nfc->device_clk, 24000000);
>>>       if (ret)
>>> -        goto err_disable_rx;
>>> +        goto err_disable_clk;
>>>         return 0;
>>>   -err_disable_rx:
>>> -    clk_disable_unprepare(nfc->phase_rx);
>>> -err_phase_rx:
>>> -    clk_disable_unprepare(nfc->phase_tx);
>>> -err_phase_tx:
>>> +err_disable_clk:
>>> +    clk_disable_unprepare(nfc->nand_clk);
>>> +err_nand_clk:
>>>       clk_disable_unprepare(nfc->device_clk);
>>>   err_device_clk:
>>>       clk_disable_unprepare(nfc->core_clk);
>>> @@ -1061,8 +1065,7 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>     static void meson_nfc_disable_clk(struct meson_nfc *nfc)
>>>   {
>>> -    clk_disable_unprepare(nfc->phase_rx);
>>> -    clk_disable_unprepare(nfc->phase_tx);
>>> +    clk_disable_unprepare(nfc->nand_clk);
>>>       clk_disable_unprepare(nfc->device_clk);
>>>       clk_disable_unprepare(nfc->core_clk);
>>>   }
>>> @@ -1375,6 +1378,7 @@ static int meson_nfc_probe(struct platform_device *pdev)
>>>       struct device *dev = &pdev->dev;
>>>       struct meson_nfc *nfc;
>>>       struct resource *res;
>>> +    u32 ext_clk_reg;
>>>       int ret, irq;
>>>         nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL);
>>> @@ -1396,9 +1400,15 @@ static int meson_nfc_probe(struct platform_device *pdev)
>>>       if (IS_ERR(nfc->reg_base))
>>>           return PTR_ERR(nfc->reg_base);
>>>   -    nfc->reg_clk =
>>> -        syscon_regmap_lookup_by_phandle(dev->of_node,
>>> -                        "amlogic,mmc-syscon");
>>> +    ret = of_property_read_u32(pdev->dev.of_node,
>>> +                   "sd_emmc_c_clkc",
>>> +                   &ext_clk_reg);
>>> +    if (ret) {
>>> +        dev_err(dev, "failed to get NAND external clock register\n");
>>> +        return ret;
>>> +    }
>>> +
>>> +    nfc->reg_clk = devm_ioremap(&pdev->dev, ext_clk_reg, sizeof(int));
>>
>> That's how you should get a register region.
>> If you want an example of a device claiming several region on amlogic,
>> have a look at the pinctrl driver.
> ok
>>
>>>       if (IS_ERR(nfc->reg_clk)) {
>>>           dev_err(dev, "Failed to lookup clock base\n");
>>>           return PTR_ERR(nfc->reg_clk);
>>
>> .


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH] mtd: rawnand: meson: fix the clock after discarding sd_emmc_c_clkc
@ 2022-01-07  9:57       ` Neil Armstrong
  0 siblings, 0 replies; 47+ messages in thread
From: Neil Armstrong @ 2022-01-07  9:57 UTC (permalink / raw)
  To: Liang Yang, Jerome Brunet, Miquel Raynal, linux-mtd
  Cc: Richard Weinberger, Martin Blumenstingl, Kevin Hilman,
	Jianxin Pan, Victor Wan, XianWei Zhao, Kelvin Zhang,
	BiChao Zheng, YongHui Yu, linux-arm-kernel, linux-amlogic,
	linux-kernel, devicetree

Hi,

On 07/01/2022 05:04, Liang Yang wrote:
> Hi Jerome,
> 
> On 2022/1/6 16:16, Jerome Brunet wrote:
>> [ EXTERNAL EMAIL ]
>>
>>
>> On Thu 06 Jan 2022 at 11:25, Liang Yang <liang.yang@amlogic.com> wrote:
>>
>>> Because EMMC and NAND have the same control clock register, so we
>>> implement a 'sd_emmc_c_clkc'. Previously DTS is defined as below:
>>>
>>>     sd_emmc_c_clkc: mmc@7000 {
>>>         compatible = "amlogic,meson-axg-mmc-clkc", "syscon";
>>>         reg = <0x0 0x7000 0x0 0x800>;
>>>     };
>>>
>>>     nand-controller@7800 {
>>>         ......
>>>
>>>         clocks = <&clkc CLKID_SD_EMMC_C>,
>>>             <&sd_emmc_c_clkc CLKID_MMC_DIV>,
>>>             <&sd_emmc_c_clkc CLKID_MMC_PHASE_RX>,
>>>             <&sd_emmc_c_clkc CLKID_MMC_PHASE_TX>;
>>>         clock-names = "core", "device", "rx", "tx";
>>>         amlogic,mmc-syscon = <&sd_emmc_c_clkc>;
>>>
>>>         ......
>>>     }
>>>
>>> but in fact, above implementation is rejected. so now registering
>>> a nand_divider.
>>
>> Can you give a bit of context ? a link to the discussion rejecting this
>>
> Maybe I mistake the meaning of [jianxin.pan@amlogic.com], so i need him to clarify it.
>> As far as remember, things were getting done for A1 and stopped before
>> clock part was finished. I'm saying the change is wrong, just that a
>> discussion is needed before a decision is made.
>>
> ok.
> previous discussion in this link:
> https://lore.kernel.org/all/86789d73-5a6c-7729-ecd1-dcd342b2fcde@amlogic.com/
> it never go on since v6.

Looking at the serie I don't see any major blockers, if you're willing to take ownership
of this patchset and send a v6 with all issues/comments addressed, it would be easier than
restarting the whole design discussion

Neil

> 
>>>
>>> Change-Id: Ibeb4c7ff886f5886aac4d6c664d7bbd1b1bcb997
>>> Signed-off-by: Liang Yang <liang.yang@amlogic.com>
>>> ---
>>>   drivers/mtd/nand/raw/meson_nand.c | 88 +++++++++++++++++--------------
>>>   1 file changed, 49 insertions(+), 39 deletions(-)
>>>
>>> diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c
>>> index ac3be92872d0..4472363059c2 100644
>>> --- a/drivers/mtd/nand/raw/meson_nand.c
>>> +++ b/drivers/mtd/nand/raw/meson_nand.c
>>> @@ -2,7 +2,7 @@
>>>   /*
>>>    * Amlogic Meson Nand Flash Controller Driver
>>>    *
>>> - * Copyright (c) 2018 Amlogic, inc.
>>> + * Copyright (c) 2018-2021 Amlogic, inc.
>>>    * Author: Liang Yang <liang.yang@amlogic.com>
>>>    */
>>>   @@ -10,6 +10,7 @@
>>>   #include <linux/dma-mapping.h>
>>>   #include <linux/interrupt.h>
>>>   #include <linux/clk.h>
>>> +#include <linux/clk-provider.h>
>>>   #include <linux/mtd/rawnand.h>
>>>   #include <linux/mtd/mtd.h>
>>>   #include <linux/mfd/syscon.h>
>>> @@ -55,6 +56,7 @@
>>>   #define NFC_REG_VER        0x38
>>>     #define NFC_RB_IRQ_EN        BIT(21)
>>> +#define NFC_CMD_FIFO_RESET    BIT(31)
>>>     #define CMDRWGEN(cmd_dir, ran, bch, short_mode, page_size, pages)    \
>>>       (                                \
>>> @@ -104,6 +106,9 @@
>>>     #define PER_INFO_BYTE        8
>>>   +#define CLK_DIV_SHIFT        0
>>> +#define CLK_DIV_WIDTH        6
>>> +
>>>   struct meson_nfc_nand_chip {
>>>       struct list_head node;
>>>       struct nand_chip nand;
>>> @@ -151,15 +156,15 @@ struct meson_nfc {
>>>       struct nand_controller controller;
>>>       struct clk *core_clk;
>>>       struct clk *device_clk;
>>> -    struct clk *phase_tx;
>>> -    struct clk *phase_rx;
>>
>> I would have been nice to explain why these clock are no longer
>> required, in the change description maybe ?
> 
> i got the reply from our vlsi members that rx and tx doesn't make sense to meson NFC timing. so previous commit about this should be wrong.
>>
>>> +    struct clk *nand_clk;
>>> +    struct clk_divider nand_divider;
>>>         unsigned long clk_rate;
>>>       u32 bus_timing;
>>>         struct device *dev;
>>>       void __iomem *reg_base;
>>> -    struct regmap *reg_clk;
>>> +    void __iomem *reg_clk;
>>>       struct completion completion;
>>>       struct list_head chips;
>>>       const struct meson_nfc_data *data;
>>> @@ -406,12 +411,14 @@ static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms)
>>>       cmd = NFC_CMD_RB | NFC_CMD_RB_INT
>>>           | nfc->param.chip_select | nfc->timing.tbers_max;
>>>       writel(cmd, nfc->reg_base + NFC_REG_CMD);
>>> -
>>> +    meson_nfc_drain_cmd(nfc);
>>
>> is this clock related ?
> ok, i will split it in another patch.
>>
>>>       ret = wait_for_completion_timeout(&nfc->completion,
>>>                         msecs_to_jiffies(timeout_ms));
>>>       if (ret == 0)
>>>           ret = -1;
>>>   +    /* reset command fifo to avoid lock */
>>> +    writel(NFC_CMD_FIFO_RESET, nfc->reg_base + NFC_REG_CMD);
>>
>> Again, not seem to be clock related - does not belong in this patch
> ok, i will split it in another patch.
>>
>>>       return ret;
>>>   }
>>>   @@ -988,8 +995,9 @@ static const struct mtd_ooblayout_ops meson_ooblayout_ops = {
>>>   static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>   {
>>>       int ret;
>>> +    struct clk_init_data init = {0};
>>> +    const char *fix_div2_pll_name[1];
>>>   -    /* request core clock */
>>
>> Why is the comment bothering you ?
>>
>>>       nfc->core_clk = devm_clk_get(nfc->dev, "core");
>>>       if (IS_ERR(nfc->core_clk)) {
>>>           dev_err(nfc->dev, "failed to get core clock\n");
>>> @@ -1002,21 +1010,25 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>           return PTR_ERR(nfc->device_clk);
>>>       }
>>>   -    nfc->phase_tx = devm_clk_get(nfc->dev, "tx");
>>> -    if (IS_ERR(nfc->phase_tx)) {
>>> -        dev_err(nfc->dev, "failed to get TX clk\n");
>>> -        return PTR_ERR(nfc->phase_tx);
>>> -    }
>>> -
>>> -    nfc->phase_rx = devm_clk_get(nfc->dev, "rx");
>>> -    if (IS_ERR(nfc->phase_rx)) {
>>> -        dev_err(nfc->dev, "failed to get RX clk\n");
>>> -        return PTR_ERR(nfc->phase_rx);
>>> -    }
>>> +    init.name = devm_kstrdup(nfc->dev, "nfc#div", GFP_KERNEL);
>>> +    init.ops = &clk_divider_ops;
>>> +    fix_div2_pll_name[0] = __clk_get_name(nfc->device_clk);
>>
>> You should be using "fw_name" so CCF looks a DT directly, instead of this
> ok
>>
>>> +    init.parent_names = fix_div2_pll_name;
>>> +    init.num_parents = 1;
>>> +    nfc->nand_divider.reg = nfc->reg_clk;
>>> +    nfc->nand_divider.shift = CLK_DIV_SHIFT;
>>> +    nfc->nand_divider.width = CLK_DIV_WIDTH;
>>> +    nfc->nand_divider.hw.init = &init;
>>> +    nfc->nand_divider.flags = CLK_DIVIDER_ONE_BASED |
>>> +                  CLK_DIVIDER_ROUND_CLOSEST |
>>> +                        CLK_DIVIDER_ALLOW_ZERO;
>>> +
>>> +    nfc->nand_clk = devm_clk_register(nfc->dev, &nfc->nand_divider.hw);
>>> +    if (IS_ERR(nfc->nand_clk))
>>> +        return PTR_ERR(nfc->nand_clk);
>>>         /* init SD_EMMC_CLOCK to sane defaults w/min clock rate */
>>> -    regmap_update_bits(nfc->reg_clk,
>>> -               0, CLK_SELECT_NAND, CLK_SELECT_NAND);
>>> +    writel(CLK_SELECT_NAND | readl(nfc->reg_clk), nfc->reg_clk);
>>>         ret = clk_prepare_enable(nfc->core_clk);
>>>       if (ret) {
>>> @@ -1030,29 +1042,21 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>           goto err_device_clk;
>>>       }
>>>   -    ret = clk_prepare_enable(nfc->phase_tx);
>>> +    ret = clk_prepare_enable(nfc->nand_clk);
>>>       if (ret) {
>>> -        dev_err(nfc->dev, "failed to enable TX clock\n");
>>> -        goto err_phase_tx;
>>> -    }
>>> -
>>> -    ret = clk_prepare_enable(nfc->phase_rx);
>>> -    if (ret) {
>>> -        dev_err(nfc->dev, "failed to enable RX clock\n");
>>> -        goto err_phase_rx;
>>> +        dev_err(nfc->dev, "pre enable NFC divider fail\n");
>>> +        goto err_nand_clk;
>>>       }
>>>         ret = clk_set_rate(nfc->device_clk, 24000000);
>>>       if (ret)
>>> -        goto err_disable_rx;
>>> +        goto err_disable_clk;
>>>         return 0;
>>>   -err_disable_rx:
>>> -    clk_disable_unprepare(nfc->phase_rx);
>>> -err_phase_rx:
>>> -    clk_disable_unprepare(nfc->phase_tx);
>>> -err_phase_tx:
>>> +err_disable_clk:
>>> +    clk_disable_unprepare(nfc->nand_clk);
>>> +err_nand_clk:
>>>       clk_disable_unprepare(nfc->device_clk);
>>>   err_device_clk:
>>>       clk_disable_unprepare(nfc->core_clk);
>>> @@ -1061,8 +1065,7 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>     static void meson_nfc_disable_clk(struct meson_nfc *nfc)
>>>   {
>>> -    clk_disable_unprepare(nfc->phase_rx);
>>> -    clk_disable_unprepare(nfc->phase_tx);
>>> +    clk_disable_unprepare(nfc->nand_clk);
>>>       clk_disable_unprepare(nfc->device_clk);
>>>       clk_disable_unprepare(nfc->core_clk);
>>>   }
>>> @@ -1375,6 +1378,7 @@ static int meson_nfc_probe(struct platform_device *pdev)
>>>       struct device *dev = &pdev->dev;
>>>       struct meson_nfc *nfc;
>>>       struct resource *res;
>>> +    u32 ext_clk_reg;
>>>       int ret, irq;
>>>         nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL);
>>> @@ -1396,9 +1400,15 @@ static int meson_nfc_probe(struct platform_device *pdev)
>>>       if (IS_ERR(nfc->reg_base))
>>>           return PTR_ERR(nfc->reg_base);
>>>   -    nfc->reg_clk =
>>> -        syscon_regmap_lookup_by_phandle(dev->of_node,
>>> -                        "amlogic,mmc-syscon");
>>> +    ret = of_property_read_u32(pdev->dev.of_node,
>>> +                   "sd_emmc_c_clkc",
>>> +                   &ext_clk_reg);
>>> +    if (ret) {
>>> +        dev_err(dev, "failed to get NAND external clock register\n");
>>> +        return ret;
>>> +    }
>>> +
>>> +    nfc->reg_clk = devm_ioremap(&pdev->dev, ext_clk_reg, sizeof(int));
>>
>> That's how you should get a register region.
>> If you want an example of a device claiming several region on amlogic,
>> have a look at the pinctrl driver.
> ok
>>
>>>       if (IS_ERR(nfc->reg_clk)) {
>>>           dev_err(dev, "Failed to lookup clock base\n");
>>>           return PTR_ERR(nfc->reg_clk);
>>
>> .


_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic

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

* Re: [PATCH] mtd: rawnand: meson: fix the clock after discarding sd_emmc_c_clkc
@ 2022-01-07  9:57       ` Neil Armstrong
  0 siblings, 0 replies; 47+ messages in thread
From: Neil Armstrong @ 2022-01-07  9:57 UTC (permalink / raw)
  To: Liang Yang, Jerome Brunet, Miquel Raynal, linux-mtd
  Cc: Richard Weinberger, Martin Blumenstingl, Kevin Hilman,
	Jianxin Pan, Victor Wan, XianWei Zhao, Kelvin Zhang,
	BiChao Zheng, YongHui Yu, linux-arm-kernel, linux-amlogic,
	linux-kernel, devicetree

Hi,

On 07/01/2022 05:04, Liang Yang wrote:
> Hi Jerome,
> 
> On 2022/1/6 16:16, Jerome Brunet wrote:
>> [ EXTERNAL EMAIL ]
>>
>>
>> On Thu 06 Jan 2022 at 11:25, Liang Yang <liang.yang@amlogic.com> wrote:
>>
>>> Because EMMC and NAND have the same control clock register, so we
>>> implement a 'sd_emmc_c_clkc'. Previously DTS is defined as below:
>>>
>>>     sd_emmc_c_clkc: mmc@7000 {
>>>         compatible = "amlogic,meson-axg-mmc-clkc", "syscon";
>>>         reg = <0x0 0x7000 0x0 0x800>;
>>>     };
>>>
>>>     nand-controller@7800 {
>>>         ......
>>>
>>>         clocks = <&clkc CLKID_SD_EMMC_C>,
>>>             <&sd_emmc_c_clkc CLKID_MMC_DIV>,
>>>             <&sd_emmc_c_clkc CLKID_MMC_PHASE_RX>,
>>>             <&sd_emmc_c_clkc CLKID_MMC_PHASE_TX>;
>>>         clock-names = "core", "device", "rx", "tx";
>>>         amlogic,mmc-syscon = <&sd_emmc_c_clkc>;
>>>
>>>         ......
>>>     }
>>>
>>> but in fact, above implementation is rejected. so now registering
>>> a nand_divider.
>>
>> Can you give a bit of context ? a link to the discussion rejecting this
>>
> Maybe I mistake the meaning of [jianxin.pan@amlogic.com], so i need him to clarify it.
>> As far as remember, things were getting done for A1 and stopped before
>> clock part was finished. I'm saying the change is wrong, just that a
>> discussion is needed before a decision is made.
>>
> ok.
> previous discussion in this link:
> https://lore.kernel.org/all/86789d73-5a6c-7729-ecd1-dcd342b2fcde@amlogic.com/
> it never go on since v6.

Looking at the serie I don't see any major blockers, if you're willing to take ownership
of this patchset and send a v6 with all issues/comments addressed, it would be easier than
restarting the whole design discussion

Neil

> 
>>>
>>> Change-Id: Ibeb4c7ff886f5886aac4d6c664d7bbd1b1bcb997
>>> Signed-off-by: Liang Yang <liang.yang@amlogic.com>
>>> ---
>>>   drivers/mtd/nand/raw/meson_nand.c | 88 +++++++++++++++++--------------
>>>   1 file changed, 49 insertions(+), 39 deletions(-)
>>>
>>> diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c
>>> index ac3be92872d0..4472363059c2 100644
>>> --- a/drivers/mtd/nand/raw/meson_nand.c
>>> +++ b/drivers/mtd/nand/raw/meson_nand.c
>>> @@ -2,7 +2,7 @@
>>>   /*
>>>    * Amlogic Meson Nand Flash Controller Driver
>>>    *
>>> - * Copyright (c) 2018 Amlogic, inc.
>>> + * Copyright (c) 2018-2021 Amlogic, inc.
>>>    * Author: Liang Yang <liang.yang@amlogic.com>
>>>    */
>>>   @@ -10,6 +10,7 @@
>>>   #include <linux/dma-mapping.h>
>>>   #include <linux/interrupt.h>
>>>   #include <linux/clk.h>
>>> +#include <linux/clk-provider.h>
>>>   #include <linux/mtd/rawnand.h>
>>>   #include <linux/mtd/mtd.h>
>>>   #include <linux/mfd/syscon.h>
>>> @@ -55,6 +56,7 @@
>>>   #define NFC_REG_VER        0x38
>>>     #define NFC_RB_IRQ_EN        BIT(21)
>>> +#define NFC_CMD_FIFO_RESET    BIT(31)
>>>     #define CMDRWGEN(cmd_dir, ran, bch, short_mode, page_size, pages)    \
>>>       (                                \
>>> @@ -104,6 +106,9 @@
>>>     #define PER_INFO_BYTE        8
>>>   +#define CLK_DIV_SHIFT        0
>>> +#define CLK_DIV_WIDTH        6
>>> +
>>>   struct meson_nfc_nand_chip {
>>>       struct list_head node;
>>>       struct nand_chip nand;
>>> @@ -151,15 +156,15 @@ struct meson_nfc {
>>>       struct nand_controller controller;
>>>       struct clk *core_clk;
>>>       struct clk *device_clk;
>>> -    struct clk *phase_tx;
>>> -    struct clk *phase_rx;
>>
>> I would have been nice to explain why these clock are no longer
>> required, in the change description maybe ?
> 
> i got the reply from our vlsi members that rx and tx doesn't make sense to meson NFC timing. so previous commit about this should be wrong.
>>
>>> +    struct clk *nand_clk;
>>> +    struct clk_divider nand_divider;
>>>         unsigned long clk_rate;
>>>       u32 bus_timing;
>>>         struct device *dev;
>>>       void __iomem *reg_base;
>>> -    struct regmap *reg_clk;
>>> +    void __iomem *reg_clk;
>>>       struct completion completion;
>>>       struct list_head chips;
>>>       const struct meson_nfc_data *data;
>>> @@ -406,12 +411,14 @@ static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms)
>>>       cmd = NFC_CMD_RB | NFC_CMD_RB_INT
>>>           | nfc->param.chip_select | nfc->timing.tbers_max;
>>>       writel(cmd, nfc->reg_base + NFC_REG_CMD);
>>> -
>>> +    meson_nfc_drain_cmd(nfc);
>>
>> is this clock related ?
> ok, i will split it in another patch.
>>
>>>       ret = wait_for_completion_timeout(&nfc->completion,
>>>                         msecs_to_jiffies(timeout_ms));
>>>       if (ret == 0)
>>>           ret = -1;
>>>   +    /* reset command fifo to avoid lock */
>>> +    writel(NFC_CMD_FIFO_RESET, nfc->reg_base + NFC_REG_CMD);
>>
>> Again, not seem to be clock related - does not belong in this patch
> ok, i will split it in another patch.
>>
>>>       return ret;
>>>   }
>>>   @@ -988,8 +995,9 @@ static const struct mtd_ooblayout_ops meson_ooblayout_ops = {
>>>   static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>   {
>>>       int ret;
>>> +    struct clk_init_data init = {0};
>>> +    const char *fix_div2_pll_name[1];
>>>   -    /* request core clock */
>>
>> Why is the comment bothering you ?
>>
>>>       nfc->core_clk = devm_clk_get(nfc->dev, "core");
>>>       if (IS_ERR(nfc->core_clk)) {
>>>           dev_err(nfc->dev, "failed to get core clock\n");
>>> @@ -1002,21 +1010,25 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>           return PTR_ERR(nfc->device_clk);
>>>       }
>>>   -    nfc->phase_tx = devm_clk_get(nfc->dev, "tx");
>>> -    if (IS_ERR(nfc->phase_tx)) {
>>> -        dev_err(nfc->dev, "failed to get TX clk\n");
>>> -        return PTR_ERR(nfc->phase_tx);
>>> -    }
>>> -
>>> -    nfc->phase_rx = devm_clk_get(nfc->dev, "rx");
>>> -    if (IS_ERR(nfc->phase_rx)) {
>>> -        dev_err(nfc->dev, "failed to get RX clk\n");
>>> -        return PTR_ERR(nfc->phase_rx);
>>> -    }
>>> +    init.name = devm_kstrdup(nfc->dev, "nfc#div", GFP_KERNEL);
>>> +    init.ops = &clk_divider_ops;
>>> +    fix_div2_pll_name[0] = __clk_get_name(nfc->device_clk);
>>
>> You should be using "fw_name" so CCF looks a DT directly, instead of this
> ok
>>
>>> +    init.parent_names = fix_div2_pll_name;
>>> +    init.num_parents = 1;
>>> +    nfc->nand_divider.reg = nfc->reg_clk;
>>> +    nfc->nand_divider.shift = CLK_DIV_SHIFT;
>>> +    nfc->nand_divider.width = CLK_DIV_WIDTH;
>>> +    nfc->nand_divider.hw.init = &init;
>>> +    nfc->nand_divider.flags = CLK_DIVIDER_ONE_BASED |
>>> +                  CLK_DIVIDER_ROUND_CLOSEST |
>>> +                        CLK_DIVIDER_ALLOW_ZERO;
>>> +
>>> +    nfc->nand_clk = devm_clk_register(nfc->dev, &nfc->nand_divider.hw);
>>> +    if (IS_ERR(nfc->nand_clk))
>>> +        return PTR_ERR(nfc->nand_clk);
>>>         /* init SD_EMMC_CLOCK to sane defaults w/min clock rate */
>>> -    regmap_update_bits(nfc->reg_clk,
>>> -               0, CLK_SELECT_NAND, CLK_SELECT_NAND);
>>> +    writel(CLK_SELECT_NAND | readl(nfc->reg_clk), nfc->reg_clk);
>>>         ret = clk_prepare_enable(nfc->core_clk);
>>>       if (ret) {
>>> @@ -1030,29 +1042,21 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>           goto err_device_clk;
>>>       }
>>>   -    ret = clk_prepare_enable(nfc->phase_tx);
>>> +    ret = clk_prepare_enable(nfc->nand_clk);
>>>       if (ret) {
>>> -        dev_err(nfc->dev, "failed to enable TX clock\n");
>>> -        goto err_phase_tx;
>>> -    }
>>> -
>>> -    ret = clk_prepare_enable(nfc->phase_rx);
>>> -    if (ret) {
>>> -        dev_err(nfc->dev, "failed to enable RX clock\n");
>>> -        goto err_phase_rx;
>>> +        dev_err(nfc->dev, "pre enable NFC divider fail\n");
>>> +        goto err_nand_clk;
>>>       }
>>>         ret = clk_set_rate(nfc->device_clk, 24000000);
>>>       if (ret)
>>> -        goto err_disable_rx;
>>> +        goto err_disable_clk;
>>>         return 0;
>>>   -err_disable_rx:
>>> -    clk_disable_unprepare(nfc->phase_rx);
>>> -err_phase_rx:
>>> -    clk_disable_unprepare(nfc->phase_tx);
>>> -err_phase_tx:
>>> +err_disable_clk:
>>> +    clk_disable_unprepare(nfc->nand_clk);
>>> +err_nand_clk:
>>>       clk_disable_unprepare(nfc->device_clk);
>>>   err_device_clk:
>>>       clk_disable_unprepare(nfc->core_clk);
>>> @@ -1061,8 +1065,7 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>     static void meson_nfc_disable_clk(struct meson_nfc *nfc)
>>>   {
>>> -    clk_disable_unprepare(nfc->phase_rx);
>>> -    clk_disable_unprepare(nfc->phase_tx);
>>> +    clk_disable_unprepare(nfc->nand_clk);
>>>       clk_disable_unprepare(nfc->device_clk);
>>>       clk_disable_unprepare(nfc->core_clk);
>>>   }
>>> @@ -1375,6 +1378,7 @@ static int meson_nfc_probe(struct platform_device *pdev)
>>>       struct device *dev = &pdev->dev;
>>>       struct meson_nfc *nfc;
>>>       struct resource *res;
>>> +    u32 ext_clk_reg;
>>>       int ret, irq;
>>>         nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL);
>>> @@ -1396,9 +1400,15 @@ static int meson_nfc_probe(struct platform_device *pdev)
>>>       if (IS_ERR(nfc->reg_base))
>>>           return PTR_ERR(nfc->reg_base);
>>>   -    nfc->reg_clk =
>>> -        syscon_regmap_lookup_by_phandle(dev->of_node,
>>> -                        "amlogic,mmc-syscon");
>>> +    ret = of_property_read_u32(pdev->dev.of_node,
>>> +                   "sd_emmc_c_clkc",
>>> +                   &ext_clk_reg);
>>> +    if (ret) {
>>> +        dev_err(dev, "failed to get NAND external clock register\n");
>>> +        return ret;
>>> +    }
>>> +
>>> +    nfc->reg_clk = devm_ioremap(&pdev->dev, ext_clk_reg, sizeof(int));
>>
>> That's how you should get a register region.
>> If you want an example of a device claiming several region on amlogic,
>> have a look at the pinctrl driver.
> ok
>>
>>>       if (IS_ERR(nfc->reg_clk)) {
>>>           dev_err(dev, "Failed to lookup clock base\n");
>>>           return PTR_ERR(nfc->reg_clk);
>>
>> .


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH] mtd: rawnand: meson: fix the clock after discarding sd_emmc_c_clkc
  2022-01-07  9:57       ` Neil Armstrong
  (?)
  (?)
@ 2022-01-10  3:28         ` Liang Yang
  -1 siblings, 0 replies; 47+ messages in thread
From: Liang Yang @ 2022-01-10  3:28 UTC (permalink / raw)
  To: Neil Armstrong, Jerome Brunet, Miquel Raynal, linux-mtd
  Cc: Richard Weinberger, Martin Blumenstingl, Kevin Hilman,
	Jianxin Pan, Victor Wan, XianWei Zhao, Kelvin Zhang,
	BiChao Zheng, YongHui Yu, linux-arm-kernel, linux-amlogic,
	linux-kernel, devicetree

Hi,

On 2022/1/7 17:57, Neil Armstrong wrote:
> [ EXTERNAL EMAIL ]
> 
> Hi,
> 
> On 07/01/2022 05:04, Liang Yang wrote:
>> Hi Jerome,
>>
>> On 2022/1/6 16:16, Jerome Brunet wrote:
>>> [ EXTERNAL EMAIL ]
>>>
>>>
>>> On Thu 06 Jan 2022 at 11:25, Liang Yang <liang.yang@amlogic.com> wrote:
>>>
>>>> Because EMMC and NAND have the same control clock register, so we
>>>> implement a 'sd_emmc_c_clkc'. Previously DTS is defined as below:
>>>>
>>>>      sd_emmc_c_clkc: mmc@7000 {
>>>>          compatible = "amlogic,meson-axg-mmc-clkc", "syscon";
>>>>          reg = <0x0 0x7000 0x0 0x800>;
>>>>      };
>>>>
>>>>      nand-controller@7800 {
>>>>          ......
>>>>
>>>>          clocks = <&clkc CLKID_SD_EMMC_C>,
>>>>              <&sd_emmc_c_clkc CLKID_MMC_DIV>,
>>>>              <&sd_emmc_c_clkc CLKID_MMC_PHASE_RX>,
>>>>              <&sd_emmc_c_clkc CLKID_MMC_PHASE_TX>;
>>>>          clock-names = "core", "device", "rx", "tx";
>>>>          amlogic,mmc-syscon = <&sd_emmc_c_clkc>;
>>>>
>>>>          ......
>>>>      }
>>>>
>>>> but in fact, above implementation is rejected. so now registering
>>>> a nand_divider.
>>>
>>> Can you give a bit of context ? a link to the discussion rejecting this
>>>
>> Maybe I mistake the meaning of [jianxin.pan@amlogic.com], so i need him to clarify it.
>>> As far as remember, things were getting done for A1 and stopped before
>>> clock part was finished. I'm saying the change is wrong, just that a
>>> discussion is needed before a decision is made.
>>>
>> ok.
>> previous discussion in this link:
>> https://lore.kernel.org/all/86789d73-5a6c-7729-ecd1-dcd342b2fcde@amlogic.com/
>> it never go on since v6.
> 
> Looking at the serie I don't see any major blockers, if you're willing to take ownership
> of this patchset and send a v6 with all issues/comments addressed, it would be easier than
> restarting the whole design discussion
> 
> Neil


Hi Neil, thanks for your advice.
After talking with [jianxin.pan], form this link 
<https://lkml.org/lkml/2019/1/8/441>, it already moves futher and on v9, 
so we decide to continue to work hard on it.

> 
>>
>>>>
>>>> Change-Id: Ibeb4c7ff886f5886aac4d6c664d7bbd1b1bcb997
>>>> Signed-off-by: Liang Yang <liang.yang@amlogic.com>
>>>> ---
>>>>    drivers/mtd/nand/raw/meson_nand.c | 88 +++++++++++++++++--------------
>>>>    1 file changed, 49 insertions(+), 39 deletions(-)
>>>>
>>>> diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c
>>>> index ac3be92872d0..4472363059c2 100644
>>>> --- a/drivers/mtd/nand/raw/meson_nand.c
>>>> +++ b/drivers/mtd/nand/raw/meson_nand.c
>>>> @@ -2,7 +2,7 @@
>>>>    /*
>>>>     * Amlogic Meson Nand Flash Controller Driver
>>>>     *
>>>> - * Copyright (c) 2018 Amlogic, inc.
>>>> + * Copyright (c) 2018-2021 Amlogic, inc.
>>>>     * Author: Liang Yang <liang.yang@amlogic.com>
>>>>     */
>>>>    @@ -10,6 +10,7 @@
>>>>    #include <linux/dma-mapping.h>
>>>>    #include <linux/interrupt.h>
>>>>    #include <linux/clk.h>
>>>> +#include <linux/clk-provider.h>
>>>>    #include <linux/mtd/rawnand.h>
>>>>    #include <linux/mtd/mtd.h>
>>>>    #include <linux/mfd/syscon.h>
>>>> @@ -55,6 +56,7 @@
>>>>    #define NFC_REG_VER        0x38
>>>>      #define NFC_RB_IRQ_EN        BIT(21)
>>>> +#define NFC_CMD_FIFO_RESET    BIT(31)
>>>>      #define CMDRWGEN(cmd_dir, ran, bch, short_mode, page_size, pages)    \
>>>>        (                                \
>>>> @@ -104,6 +106,9 @@
>>>>      #define PER_INFO_BYTE        8
>>>>    +#define CLK_DIV_SHIFT        0
>>>> +#define CLK_DIV_WIDTH        6
>>>> +
>>>>    struct meson_nfc_nand_chip {
>>>>        struct list_head node;
>>>>        struct nand_chip nand;
>>>> @@ -151,15 +156,15 @@ struct meson_nfc {
>>>>        struct nand_controller controller;
>>>>        struct clk *core_clk;
>>>>        struct clk *device_clk;
>>>> -    struct clk *phase_tx;
>>>> -    struct clk *phase_rx;
>>>
>>> I would have been nice to explain why these clock are no longer
>>> required, in the change description maybe ?
>>
>> i got the reply from our vlsi members that rx and tx doesn't make sense to meson NFC timing. so previous commit about this should be wrong.
>>>
>>>> +    struct clk *nand_clk;
>>>> +    struct clk_divider nand_divider;
>>>>          unsigned long clk_rate;
>>>>        u32 bus_timing;
>>>>          struct device *dev;
>>>>        void __iomem *reg_base;
>>>> -    struct regmap *reg_clk;
>>>> +    void __iomem *reg_clk;
>>>>        struct completion completion;
>>>>        struct list_head chips;
>>>>        const struct meson_nfc_data *data;
>>>> @@ -406,12 +411,14 @@ static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms)
>>>>        cmd = NFC_CMD_RB | NFC_CMD_RB_INT
>>>>            | nfc->param.chip_select | nfc->timing.tbers_max;
>>>>        writel(cmd, nfc->reg_base + NFC_REG_CMD);
>>>> -
>>>> +    meson_nfc_drain_cmd(nfc);
>>>
>>> is this clock related ?
>> ok, i will split it in another patch.
>>>
>>>>        ret = wait_for_completion_timeout(&nfc->completion,
>>>>                          msecs_to_jiffies(timeout_ms));
>>>>        if (ret == 0)
>>>>            ret = -1;
>>>>    +    /* reset command fifo to avoid lock */
>>>> +    writel(NFC_CMD_FIFO_RESET, nfc->reg_base + NFC_REG_CMD);
>>>
>>> Again, not seem to be clock related - does not belong in this patch
>> ok, i will split it in another patch.
>>>
>>>>        return ret;
>>>>    }
>>>>    @@ -988,8 +995,9 @@ static const struct mtd_ooblayout_ops meson_ooblayout_ops = {
>>>>    static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>>    {
>>>>        int ret;
>>>> +    struct clk_init_data init = {0};
>>>> +    const char *fix_div2_pll_name[1];
>>>>    -    /* request core clock */
>>>
>>> Why is the comment bothering you ?
>>>
>>>>        nfc->core_clk = devm_clk_get(nfc->dev, "core");
>>>>        if (IS_ERR(nfc->core_clk)) {
>>>>            dev_err(nfc->dev, "failed to get core clock\n");
>>>> @@ -1002,21 +1010,25 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>>            return PTR_ERR(nfc->device_clk);
>>>>        }
>>>>    -    nfc->phase_tx = devm_clk_get(nfc->dev, "tx");
>>>> -    if (IS_ERR(nfc->phase_tx)) {
>>>> -        dev_err(nfc->dev, "failed to get TX clk\n");
>>>> -        return PTR_ERR(nfc->phase_tx);
>>>> -    }
>>>> -
>>>> -    nfc->phase_rx = devm_clk_get(nfc->dev, "rx");
>>>> -    if (IS_ERR(nfc->phase_rx)) {
>>>> -        dev_err(nfc->dev, "failed to get RX clk\n");
>>>> -        return PTR_ERR(nfc->phase_rx);
>>>> -    }
>>>> +    init.name = devm_kstrdup(nfc->dev, "nfc#div", GFP_KERNEL);
>>>> +    init.ops = &clk_divider_ops;
>>>> +    fix_div2_pll_name[0] = __clk_get_name(nfc->device_clk);
>>>
>>> You should be using "fw_name" so CCF looks a DT directly, instead of this
>> ok
>>>
>>>> +    init.parent_names = fix_div2_pll_name;
>>>> +    init.num_parents = 1;
>>>> +    nfc->nand_divider.reg = nfc->reg_clk;
>>>> +    nfc->nand_divider.shift = CLK_DIV_SHIFT;
>>>> +    nfc->nand_divider.width = CLK_DIV_WIDTH;
>>>> +    nfc->nand_divider.hw.init = &init;
>>>> +    nfc->nand_divider.flags = CLK_DIVIDER_ONE_BASED |
>>>> +                  CLK_DIVIDER_ROUND_CLOSEST |
>>>> +                        CLK_DIVIDER_ALLOW_ZERO;
>>>> +
>>>> +    nfc->nand_clk = devm_clk_register(nfc->dev, &nfc->nand_divider.hw);
>>>> +    if (IS_ERR(nfc->nand_clk))
>>>> +        return PTR_ERR(nfc->nand_clk);
>>>>          /* init SD_EMMC_CLOCK to sane defaults w/min clock rate */
>>>> -    regmap_update_bits(nfc->reg_clk,
>>>> -               0, CLK_SELECT_NAND, CLK_SELECT_NAND);
>>>> +    writel(CLK_SELECT_NAND | readl(nfc->reg_clk), nfc->reg_clk);
>>>>          ret = clk_prepare_enable(nfc->core_clk);
>>>>        if (ret) {
>>>> @@ -1030,29 +1042,21 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>>            goto err_device_clk;
>>>>        }
>>>>    -    ret = clk_prepare_enable(nfc->phase_tx);
>>>> +    ret = clk_prepare_enable(nfc->nand_clk);
>>>>        if (ret) {
>>>> -        dev_err(nfc->dev, "failed to enable TX clock\n");
>>>> -        goto err_phase_tx;
>>>> -    }
>>>> -
>>>> -    ret = clk_prepare_enable(nfc->phase_rx);
>>>> -    if (ret) {
>>>> -        dev_err(nfc->dev, "failed to enable RX clock\n");
>>>> -        goto err_phase_rx;
>>>> +        dev_err(nfc->dev, "pre enable NFC divider fail\n");
>>>> +        goto err_nand_clk;
>>>>        }
>>>>          ret = clk_set_rate(nfc->device_clk, 24000000);
>>>>        if (ret)
>>>> -        goto err_disable_rx;
>>>> +        goto err_disable_clk;
>>>>          return 0;
>>>>    -err_disable_rx:
>>>> -    clk_disable_unprepare(nfc->phase_rx);
>>>> -err_phase_rx:
>>>> -    clk_disable_unprepare(nfc->phase_tx);
>>>> -err_phase_tx:
>>>> +err_disable_clk:
>>>> +    clk_disable_unprepare(nfc->nand_clk);
>>>> +err_nand_clk:
>>>>        clk_disable_unprepare(nfc->device_clk);
>>>>    err_device_clk:
>>>>        clk_disable_unprepare(nfc->core_clk);
>>>> @@ -1061,8 +1065,7 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>>      static void meson_nfc_disable_clk(struct meson_nfc *nfc)
>>>>    {
>>>> -    clk_disable_unprepare(nfc->phase_rx);
>>>> -    clk_disable_unprepare(nfc->phase_tx);
>>>> +    clk_disable_unprepare(nfc->nand_clk);
>>>>        clk_disable_unprepare(nfc->device_clk);
>>>>        clk_disable_unprepare(nfc->core_clk);
>>>>    }
>>>> @@ -1375,6 +1378,7 @@ static int meson_nfc_probe(struct platform_device *pdev)
>>>>        struct device *dev = &pdev->dev;
>>>>        struct meson_nfc *nfc;
>>>>        struct resource *res;
>>>> +    u32 ext_clk_reg;
>>>>        int ret, irq;
>>>>          nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL);
>>>> @@ -1396,9 +1400,15 @@ static int meson_nfc_probe(struct platform_device *pdev)
>>>>        if (IS_ERR(nfc->reg_base))
>>>>            return PTR_ERR(nfc->reg_base);
>>>>    -    nfc->reg_clk =
>>>> -        syscon_regmap_lookup_by_phandle(dev->of_node,
>>>> -                        "amlogic,mmc-syscon");
>>>> +    ret = of_property_read_u32(pdev->dev.of_node,
>>>> +                   "sd_emmc_c_clkc",
>>>> +                   &ext_clk_reg);
>>>> +    if (ret) {
>>>> +        dev_err(dev, "failed to get NAND external clock register\n");
>>>> +        return ret;
>>>> +    }
>>>> +
>>>> +    nfc->reg_clk = devm_ioremap(&pdev->dev, ext_clk_reg, sizeof(int));
>>>
>>> That's how you should get a register region.
>>> If you want an example of a device claiming several region on amlogic,
>>> have a look at the pinctrl driver.
>> ok
>>>
>>>>        if (IS_ERR(nfc->reg_clk)) {
>>>>            dev_err(dev, "Failed to lookup clock base\n");
>>>>            return PTR_ERR(nfc->reg_clk);
>>>
>>> .
> 
> .

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

* Re: [PATCH] mtd: rawnand: meson: fix the clock after discarding sd_emmc_c_clkc
@ 2022-01-10  3:28         ` Liang Yang
  0 siblings, 0 replies; 47+ messages in thread
From: Liang Yang @ 2022-01-10  3:28 UTC (permalink / raw)
  To: Neil Armstrong, Jerome Brunet, Miquel Raynal, linux-mtd
  Cc: Richard Weinberger, Martin Blumenstingl, Kevin Hilman,
	Jianxin Pan, Victor Wan, XianWei Zhao, Kelvin Zhang,
	BiChao Zheng, YongHui Yu, linux-arm-kernel, linux-amlogic,
	linux-kernel, devicetree

Hi,

On 2022/1/7 17:57, Neil Armstrong wrote:
> [ EXTERNAL EMAIL ]
> 
> Hi,
> 
> On 07/01/2022 05:04, Liang Yang wrote:
>> Hi Jerome,
>>
>> On 2022/1/6 16:16, Jerome Brunet wrote:
>>> [ EXTERNAL EMAIL ]
>>>
>>>
>>> On Thu 06 Jan 2022 at 11:25, Liang Yang <liang.yang@amlogic.com> wrote:
>>>
>>>> Because EMMC and NAND have the same control clock register, so we
>>>> implement a 'sd_emmc_c_clkc'. Previously DTS is defined as below:
>>>>
>>>>      sd_emmc_c_clkc: mmc@7000 {
>>>>          compatible = "amlogic,meson-axg-mmc-clkc", "syscon";
>>>>          reg = <0x0 0x7000 0x0 0x800>;
>>>>      };
>>>>
>>>>      nand-controller@7800 {
>>>>          ......
>>>>
>>>>          clocks = <&clkc CLKID_SD_EMMC_C>,
>>>>              <&sd_emmc_c_clkc CLKID_MMC_DIV>,
>>>>              <&sd_emmc_c_clkc CLKID_MMC_PHASE_RX>,
>>>>              <&sd_emmc_c_clkc CLKID_MMC_PHASE_TX>;
>>>>          clock-names = "core", "device", "rx", "tx";
>>>>          amlogic,mmc-syscon = <&sd_emmc_c_clkc>;
>>>>
>>>>          ......
>>>>      }
>>>>
>>>> but in fact, above implementation is rejected. so now registering
>>>> a nand_divider.
>>>
>>> Can you give a bit of context ? a link to the discussion rejecting this
>>>
>> Maybe I mistake the meaning of [jianxin.pan@amlogic.com], so i need him to clarify it.
>>> As far as remember, things were getting done for A1 and stopped before
>>> clock part was finished. I'm saying the change is wrong, just that a
>>> discussion is needed before a decision is made.
>>>
>> ok.
>> previous discussion in this link:
>> https://lore.kernel.org/all/86789d73-5a6c-7729-ecd1-dcd342b2fcde@amlogic.com/
>> it never go on since v6.
> 
> Looking at the serie I don't see any major blockers, if you're willing to take ownership
> of this patchset and send a v6 with all issues/comments addressed, it would be easier than
> restarting the whole design discussion
> 
> Neil


Hi Neil, thanks for your advice.
After talking with [jianxin.pan], form this link 
<https://lkml.org/lkml/2019/1/8/441>, it already moves futher and on v9, 
so we decide to continue to work hard on it.

> 
>>
>>>>
>>>> Change-Id: Ibeb4c7ff886f5886aac4d6c664d7bbd1b1bcb997
>>>> Signed-off-by: Liang Yang <liang.yang@amlogic.com>
>>>> ---
>>>>    drivers/mtd/nand/raw/meson_nand.c | 88 +++++++++++++++++--------------
>>>>    1 file changed, 49 insertions(+), 39 deletions(-)
>>>>
>>>> diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c
>>>> index ac3be92872d0..4472363059c2 100644
>>>> --- a/drivers/mtd/nand/raw/meson_nand.c
>>>> +++ b/drivers/mtd/nand/raw/meson_nand.c
>>>> @@ -2,7 +2,7 @@
>>>>    /*
>>>>     * Amlogic Meson Nand Flash Controller Driver
>>>>     *
>>>> - * Copyright (c) 2018 Amlogic, inc.
>>>> + * Copyright (c) 2018-2021 Amlogic, inc.
>>>>     * Author: Liang Yang <liang.yang@amlogic.com>
>>>>     */
>>>>    @@ -10,6 +10,7 @@
>>>>    #include <linux/dma-mapping.h>
>>>>    #include <linux/interrupt.h>
>>>>    #include <linux/clk.h>
>>>> +#include <linux/clk-provider.h>
>>>>    #include <linux/mtd/rawnand.h>
>>>>    #include <linux/mtd/mtd.h>
>>>>    #include <linux/mfd/syscon.h>
>>>> @@ -55,6 +56,7 @@
>>>>    #define NFC_REG_VER        0x38
>>>>      #define NFC_RB_IRQ_EN        BIT(21)
>>>> +#define NFC_CMD_FIFO_RESET    BIT(31)
>>>>      #define CMDRWGEN(cmd_dir, ran, bch, short_mode, page_size, pages)    \
>>>>        (                                \
>>>> @@ -104,6 +106,9 @@
>>>>      #define PER_INFO_BYTE        8
>>>>    +#define CLK_DIV_SHIFT        0
>>>> +#define CLK_DIV_WIDTH        6
>>>> +
>>>>    struct meson_nfc_nand_chip {
>>>>        struct list_head node;
>>>>        struct nand_chip nand;
>>>> @@ -151,15 +156,15 @@ struct meson_nfc {
>>>>        struct nand_controller controller;
>>>>        struct clk *core_clk;
>>>>        struct clk *device_clk;
>>>> -    struct clk *phase_tx;
>>>> -    struct clk *phase_rx;
>>>
>>> I would have been nice to explain why these clock are no longer
>>> required, in the change description maybe ?
>>
>> i got the reply from our vlsi members that rx and tx doesn't make sense to meson NFC timing. so previous commit about this should be wrong.
>>>
>>>> +    struct clk *nand_clk;
>>>> +    struct clk_divider nand_divider;
>>>>          unsigned long clk_rate;
>>>>        u32 bus_timing;
>>>>          struct device *dev;
>>>>        void __iomem *reg_base;
>>>> -    struct regmap *reg_clk;
>>>> +    void __iomem *reg_clk;
>>>>        struct completion completion;
>>>>        struct list_head chips;
>>>>        const struct meson_nfc_data *data;
>>>> @@ -406,12 +411,14 @@ static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms)
>>>>        cmd = NFC_CMD_RB | NFC_CMD_RB_INT
>>>>            | nfc->param.chip_select | nfc->timing.tbers_max;
>>>>        writel(cmd, nfc->reg_base + NFC_REG_CMD);
>>>> -
>>>> +    meson_nfc_drain_cmd(nfc);
>>>
>>> is this clock related ?
>> ok, i will split it in another patch.
>>>
>>>>        ret = wait_for_completion_timeout(&nfc->completion,
>>>>                          msecs_to_jiffies(timeout_ms));
>>>>        if (ret == 0)
>>>>            ret = -1;
>>>>    +    /* reset command fifo to avoid lock */
>>>> +    writel(NFC_CMD_FIFO_RESET, nfc->reg_base + NFC_REG_CMD);
>>>
>>> Again, not seem to be clock related - does not belong in this patch
>> ok, i will split it in another patch.
>>>
>>>>        return ret;
>>>>    }
>>>>    @@ -988,8 +995,9 @@ static const struct mtd_ooblayout_ops meson_ooblayout_ops = {
>>>>    static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>>    {
>>>>        int ret;
>>>> +    struct clk_init_data init = {0};
>>>> +    const char *fix_div2_pll_name[1];
>>>>    -    /* request core clock */
>>>
>>> Why is the comment bothering you ?
>>>
>>>>        nfc->core_clk = devm_clk_get(nfc->dev, "core");
>>>>        if (IS_ERR(nfc->core_clk)) {
>>>>            dev_err(nfc->dev, "failed to get core clock\n");
>>>> @@ -1002,21 +1010,25 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>>            return PTR_ERR(nfc->device_clk);
>>>>        }
>>>>    -    nfc->phase_tx = devm_clk_get(nfc->dev, "tx");
>>>> -    if (IS_ERR(nfc->phase_tx)) {
>>>> -        dev_err(nfc->dev, "failed to get TX clk\n");
>>>> -        return PTR_ERR(nfc->phase_tx);
>>>> -    }
>>>> -
>>>> -    nfc->phase_rx = devm_clk_get(nfc->dev, "rx");
>>>> -    if (IS_ERR(nfc->phase_rx)) {
>>>> -        dev_err(nfc->dev, "failed to get RX clk\n");
>>>> -        return PTR_ERR(nfc->phase_rx);
>>>> -    }
>>>> +    init.name = devm_kstrdup(nfc->dev, "nfc#div", GFP_KERNEL);
>>>> +    init.ops = &clk_divider_ops;
>>>> +    fix_div2_pll_name[0] = __clk_get_name(nfc->device_clk);
>>>
>>> You should be using "fw_name" so CCF looks a DT directly, instead of this
>> ok
>>>
>>>> +    init.parent_names = fix_div2_pll_name;
>>>> +    init.num_parents = 1;
>>>> +    nfc->nand_divider.reg = nfc->reg_clk;
>>>> +    nfc->nand_divider.shift = CLK_DIV_SHIFT;
>>>> +    nfc->nand_divider.width = CLK_DIV_WIDTH;
>>>> +    nfc->nand_divider.hw.init = &init;
>>>> +    nfc->nand_divider.flags = CLK_DIVIDER_ONE_BASED |
>>>> +                  CLK_DIVIDER_ROUND_CLOSEST |
>>>> +                        CLK_DIVIDER_ALLOW_ZERO;
>>>> +
>>>> +    nfc->nand_clk = devm_clk_register(nfc->dev, &nfc->nand_divider.hw);
>>>> +    if (IS_ERR(nfc->nand_clk))
>>>> +        return PTR_ERR(nfc->nand_clk);
>>>>          /* init SD_EMMC_CLOCK to sane defaults w/min clock rate */
>>>> -    regmap_update_bits(nfc->reg_clk,
>>>> -               0, CLK_SELECT_NAND, CLK_SELECT_NAND);
>>>> +    writel(CLK_SELECT_NAND | readl(nfc->reg_clk), nfc->reg_clk);
>>>>          ret = clk_prepare_enable(nfc->core_clk);
>>>>        if (ret) {
>>>> @@ -1030,29 +1042,21 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>>            goto err_device_clk;
>>>>        }
>>>>    -    ret = clk_prepare_enable(nfc->phase_tx);
>>>> +    ret = clk_prepare_enable(nfc->nand_clk);
>>>>        if (ret) {
>>>> -        dev_err(nfc->dev, "failed to enable TX clock\n");
>>>> -        goto err_phase_tx;
>>>> -    }
>>>> -
>>>> -    ret = clk_prepare_enable(nfc->phase_rx);
>>>> -    if (ret) {
>>>> -        dev_err(nfc->dev, "failed to enable RX clock\n");
>>>> -        goto err_phase_rx;
>>>> +        dev_err(nfc->dev, "pre enable NFC divider fail\n");
>>>> +        goto err_nand_clk;
>>>>        }
>>>>          ret = clk_set_rate(nfc->device_clk, 24000000);
>>>>        if (ret)
>>>> -        goto err_disable_rx;
>>>> +        goto err_disable_clk;
>>>>          return 0;
>>>>    -err_disable_rx:
>>>> -    clk_disable_unprepare(nfc->phase_rx);
>>>> -err_phase_rx:
>>>> -    clk_disable_unprepare(nfc->phase_tx);
>>>> -err_phase_tx:
>>>> +err_disable_clk:
>>>> +    clk_disable_unprepare(nfc->nand_clk);
>>>> +err_nand_clk:
>>>>        clk_disable_unprepare(nfc->device_clk);
>>>>    err_device_clk:
>>>>        clk_disable_unprepare(nfc->core_clk);
>>>> @@ -1061,8 +1065,7 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>>      static void meson_nfc_disable_clk(struct meson_nfc *nfc)
>>>>    {
>>>> -    clk_disable_unprepare(nfc->phase_rx);
>>>> -    clk_disable_unprepare(nfc->phase_tx);
>>>> +    clk_disable_unprepare(nfc->nand_clk);
>>>>        clk_disable_unprepare(nfc->device_clk);
>>>>        clk_disable_unprepare(nfc->core_clk);
>>>>    }
>>>> @@ -1375,6 +1378,7 @@ static int meson_nfc_probe(struct platform_device *pdev)
>>>>        struct device *dev = &pdev->dev;
>>>>        struct meson_nfc *nfc;
>>>>        struct resource *res;
>>>> +    u32 ext_clk_reg;
>>>>        int ret, irq;
>>>>          nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL);
>>>> @@ -1396,9 +1400,15 @@ static int meson_nfc_probe(struct platform_device *pdev)
>>>>        if (IS_ERR(nfc->reg_base))
>>>>            return PTR_ERR(nfc->reg_base);
>>>>    -    nfc->reg_clk =
>>>> -        syscon_regmap_lookup_by_phandle(dev->of_node,
>>>> -                        "amlogic,mmc-syscon");
>>>> +    ret = of_property_read_u32(pdev->dev.of_node,
>>>> +                   "sd_emmc_c_clkc",
>>>> +                   &ext_clk_reg);
>>>> +    if (ret) {
>>>> +        dev_err(dev, "failed to get NAND external clock register\n");
>>>> +        return ret;
>>>> +    }
>>>> +
>>>> +    nfc->reg_clk = devm_ioremap(&pdev->dev, ext_clk_reg, sizeof(int));
>>>
>>> That's how you should get a register region.
>>> If you want an example of a device claiming several region on amlogic,
>>> have a look at the pinctrl driver.
>> ok
>>>
>>>>        if (IS_ERR(nfc->reg_clk)) {
>>>>            dev_err(dev, "Failed to lookup clock base\n");
>>>>            return PTR_ERR(nfc->reg_clk);
>>>
>>> .
> 
> .

_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic

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

* Re: [PATCH] mtd: rawnand: meson: fix the clock after discarding sd_emmc_c_clkc
@ 2022-01-10  3:28         ` Liang Yang
  0 siblings, 0 replies; 47+ messages in thread
From: Liang Yang @ 2022-01-10  3:28 UTC (permalink / raw)
  To: Neil Armstrong, Jerome Brunet, Miquel Raynal, linux-mtd
  Cc: Richard Weinberger, Martin Blumenstingl, Kevin Hilman,
	Jianxin Pan, Victor Wan, XianWei Zhao, Kelvin Zhang,
	BiChao Zheng, YongHui Yu, linux-arm-kernel, linux-amlogic,
	linux-kernel, devicetree

Hi,

On 2022/1/7 17:57, Neil Armstrong wrote:
> [ EXTERNAL EMAIL ]
> 
> Hi,
> 
> On 07/01/2022 05:04, Liang Yang wrote:
>> Hi Jerome,
>>
>> On 2022/1/6 16:16, Jerome Brunet wrote:
>>> [ EXTERNAL EMAIL ]
>>>
>>>
>>> On Thu 06 Jan 2022 at 11:25, Liang Yang <liang.yang@amlogic.com> wrote:
>>>
>>>> Because EMMC and NAND have the same control clock register, so we
>>>> implement a 'sd_emmc_c_clkc'. Previously DTS is defined as below:
>>>>
>>>>      sd_emmc_c_clkc: mmc@7000 {
>>>>          compatible = "amlogic,meson-axg-mmc-clkc", "syscon";
>>>>          reg = <0x0 0x7000 0x0 0x800>;
>>>>      };
>>>>
>>>>      nand-controller@7800 {
>>>>          ......
>>>>
>>>>          clocks = <&clkc CLKID_SD_EMMC_C>,
>>>>              <&sd_emmc_c_clkc CLKID_MMC_DIV>,
>>>>              <&sd_emmc_c_clkc CLKID_MMC_PHASE_RX>,
>>>>              <&sd_emmc_c_clkc CLKID_MMC_PHASE_TX>;
>>>>          clock-names = "core", "device", "rx", "tx";
>>>>          amlogic,mmc-syscon = <&sd_emmc_c_clkc>;
>>>>
>>>>          ......
>>>>      }
>>>>
>>>> but in fact, above implementation is rejected. so now registering
>>>> a nand_divider.
>>>
>>> Can you give a bit of context ? a link to the discussion rejecting this
>>>
>> Maybe I mistake the meaning of [jianxin.pan@amlogic.com], so i need him to clarify it.
>>> As far as remember, things were getting done for A1 and stopped before
>>> clock part was finished. I'm saying the change is wrong, just that a
>>> discussion is needed before a decision is made.
>>>
>> ok.
>> previous discussion in this link:
>> https://lore.kernel.org/all/86789d73-5a6c-7729-ecd1-dcd342b2fcde@amlogic.com/
>> it never go on since v6.
> 
> Looking at the serie I don't see any major blockers, if you're willing to take ownership
> of this patchset and send a v6 with all issues/comments addressed, it would be easier than
> restarting the whole design discussion
> 
> Neil


Hi Neil, thanks for your advice.
After talking with [jianxin.pan], form this link 
<https://lkml.org/lkml/2019/1/8/441>, it already moves futher and on v9, 
so we decide to continue to work hard on it.

> 
>>
>>>>
>>>> Change-Id: Ibeb4c7ff886f5886aac4d6c664d7bbd1b1bcb997
>>>> Signed-off-by: Liang Yang <liang.yang@amlogic.com>
>>>> ---
>>>>    drivers/mtd/nand/raw/meson_nand.c | 88 +++++++++++++++++--------------
>>>>    1 file changed, 49 insertions(+), 39 deletions(-)
>>>>
>>>> diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c
>>>> index ac3be92872d0..4472363059c2 100644
>>>> --- a/drivers/mtd/nand/raw/meson_nand.c
>>>> +++ b/drivers/mtd/nand/raw/meson_nand.c
>>>> @@ -2,7 +2,7 @@
>>>>    /*
>>>>     * Amlogic Meson Nand Flash Controller Driver
>>>>     *
>>>> - * Copyright (c) 2018 Amlogic, inc.
>>>> + * Copyright (c) 2018-2021 Amlogic, inc.
>>>>     * Author: Liang Yang <liang.yang@amlogic.com>
>>>>     */
>>>>    @@ -10,6 +10,7 @@
>>>>    #include <linux/dma-mapping.h>
>>>>    #include <linux/interrupt.h>
>>>>    #include <linux/clk.h>
>>>> +#include <linux/clk-provider.h>
>>>>    #include <linux/mtd/rawnand.h>
>>>>    #include <linux/mtd/mtd.h>
>>>>    #include <linux/mfd/syscon.h>
>>>> @@ -55,6 +56,7 @@
>>>>    #define NFC_REG_VER        0x38
>>>>      #define NFC_RB_IRQ_EN        BIT(21)
>>>> +#define NFC_CMD_FIFO_RESET    BIT(31)
>>>>      #define CMDRWGEN(cmd_dir, ran, bch, short_mode, page_size, pages)    \
>>>>        (                                \
>>>> @@ -104,6 +106,9 @@
>>>>      #define PER_INFO_BYTE        8
>>>>    +#define CLK_DIV_SHIFT        0
>>>> +#define CLK_DIV_WIDTH        6
>>>> +
>>>>    struct meson_nfc_nand_chip {
>>>>        struct list_head node;
>>>>        struct nand_chip nand;
>>>> @@ -151,15 +156,15 @@ struct meson_nfc {
>>>>        struct nand_controller controller;
>>>>        struct clk *core_clk;
>>>>        struct clk *device_clk;
>>>> -    struct clk *phase_tx;
>>>> -    struct clk *phase_rx;
>>>
>>> I would have been nice to explain why these clock are no longer
>>> required, in the change description maybe ?
>>
>> i got the reply from our vlsi members that rx and tx doesn't make sense to meson NFC timing. so previous commit about this should be wrong.
>>>
>>>> +    struct clk *nand_clk;
>>>> +    struct clk_divider nand_divider;
>>>>          unsigned long clk_rate;
>>>>        u32 bus_timing;
>>>>          struct device *dev;
>>>>        void __iomem *reg_base;
>>>> -    struct regmap *reg_clk;
>>>> +    void __iomem *reg_clk;
>>>>        struct completion completion;
>>>>        struct list_head chips;
>>>>        const struct meson_nfc_data *data;
>>>> @@ -406,12 +411,14 @@ static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms)
>>>>        cmd = NFC_CMD_RB | NFC_CMD_RB_INT
>>>>            | nfc->param.chip_select | nfc->timing.tbers_max;
>>>>        writel(cmd, nfc->reg_base + NFC_REG_CMD);
>>>> -
>>>> +    meson_nfc_drain_cmd(nfc);
>>>
>>> is this clock related ?
>> ok, i will split it in another patch.
>>>
>>>>        ret = wait_for_completion_timeout(&nfc->completion,
>>>>                          msecs_to_jiffies(timeout_ms));
>>>>        if (ret == 0)
>>>>            ret = -1;
>>>>    +    /* reset command fifo to avoid lock */
>>>> +    writel(NFC_CMD_FIFO_RESET, nfc->reg_base + NFC_REG_CMD);
>>>
>>> Again, not seem to be clock related - does not belong in this patch
>> ok, i will split it in another patch.
>>>
>>>>        return ret;
>>>>    }
>>>>    @@ -988,8 +995,9 @@ static const struct mtd_ooblayout_ops meson_ooblayout_ops = {
>>>>    static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>>    {
>>>>        int ret;
>>>> +    struct clk_init_data init = {0};
>>>> +    const char *fix_div2_pll_name[1];
>>>>    -    /* request core clock */
>>>
>>> Why is the comment bothering you ?
>>>
>>>>        nfc->core_clk = devm_clk_get(nfc->dev, "core");
>>>>        if (IS_ERR(nfc->core_clk)) {
>>>>            dev_err(nfc->dev, "failed to get core clock\n");
>>>> @@ -1002,21 +1010,25 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>>            return PTR_ERR(nfc->device_clk);
>>>>        }
>>>>    -    nfc->phase_tx = devm_clk_get(nfc->dev, "tx");
>>>> -    if (IS_ERR(nfc->phase_tx)) {
>>>> -        dev_err(nfc->dev, "failed to get TX clk\n");
>>>> -        return PTR_ERR(nfc->phase_tx);
>>>> -    }
>>>> -
>>>> -    nfc->phase_rx = devm_clk_get(nfc->dev, "rx");
>>>> -    if (IS_ERR(nfc->phase_rx)) {
>>>> -        dev_err(nfc->dev, "failed to get RX clk\n");
>>>> -        return PTR_ERR(nfc->phase_rx);
>>>> -    }
>>>> +    init.name = devm_kstrdup(nfc->dev, "nfc#div", GFP_KERNEL);
>>>> +    init.ops = &clk_divider_ops;
>>>> +    fix_div2_pll_name[0] = __clk_get_name(nfc->device_clk);
>>>
>>> You should be using "fw_name" so CCF looks a DT directly, instead of this
>> ok
>>>
>>>> +    init.parent_names = fix_div2_pll_name;
>>>> +    init.num_parents = 1;
>>>> +    nfc->nand_divider.reg = nfc->reg_clk;
>>>> +    nfc->nand_divider.shift = CLK_DIV_SHIFT;
>>>> +    nfc->nand_divider.width = CLK_DIV_WIDTH;
>>>> +    nfc->nand_divider.hw.init = &init;
>>>> +    nfc->nand_divider.flags = CLK_DIVIDER_ONE_BASED |
>>>> +                  CLK_DIVIDER_ROUND_CLOSEST |
>>>> +                        CLK_DIVIDER_ALLOW_ZERO;
>>>> +
>>>> +    nfc->nand_clk = devm_clk_register(nfc->dev, &nfc->nand_divider.hw);
>>>> +    if (IS_ERR(nfc->nand_clk))
>>>> +        return PTR_ERR(nfc->nand_clk);
>>>>          /* init SD_EMMC_CLOCK to sane defaults w/min clock rate */
>>>> -    regmap_update_bits(nfc->reg_clk,
>>>> -               0, CLK_SELECT_NAND, CLK_SELECT_NAND);
>>>> +    writel(CLK_SELECT_NAND | readl(nfc->reg_clk), nfc->reg_clk);
>>>>          ret = clk_prepare_enable(nfc->core_clk);
>>>>        if (ret) {
>>>> @@ -1030,29 +1042,21 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>>            goto err_device_clk;
>>>>        }
>>>>    -    ret = clk_prepare_enable(nfc->phase_tx);
>>>> +    ret = clk_prepare_enable(nfc->nand_clk);
>>>>        if (ret) {
>>>> -        dev_err(nfc->dev, "failed to enable TX clock\n");
>>>> -        goto err_phase_tx;
>>>> -    }
>>>> -
>>>> -    ret = clk_prepare_enable(nfc->phase_rx);
>>>> -    if (ret) {
>>>> -        dev_err(nfc->dev, "failed to enable RX clock\n");
>>>> -        goto err_phase_rx;
>>>> +        dev_err(nfc->dev, "pre enable NFC divider fail\n");
>>>> +        goto err_nand_clk;
>>>>        }
>>>>          ret = clk_set_rate(nfc->device_clk, 24000000);
>>>>        if (ret)
>>>> -        goto err_disable_rx;
>>>> +        goto err_disable_clk;
>>>>          return 0;
>>>>    -err_disable_rx:
>>>> -    clk_disable_unprepare(nfc->phase_rx);
>>>> -err_phase_rx:
>>>> -    clk_disable_unprepare(nfc->phase_tx);
>>>> -err_phase_tx:
>>>> +err_disable_clk:
>>>> +    clk_disable_unprepare(nfc->nand_clk);
>>>> +err_nand_clk:
>>>>        clk_disable_unprepare(nfc->device_clk);
>>>>    err_device_clk:
>>>>        clk_disable_unprepare(nfc->core_clk);
>>>> @@ -1061,8 +1065,7 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>>      static void meson_nfc_disable_clk(struct meson_nfc *nfc)
>>>>    {
>>>> -    clk_disable_unprepare(nfc->phase_rx);
>>>> -    clk_disable_unprepare(nfc->phase_tx);
>>>> +    clk_disable_unprepare(nfc->nand_clk);
>>>>        clk_disable_unprepare(nfc->device_clk);
>>>>        clk_disable_unprepare(nfc->core_clk);
>>>>    }
>>>> @@ -1375,6 +1378,7 @@ static int meson_nfc_probe(struct platform_device *pdev)
>>>>        struct device *dev = &pdev->dev;
>>>>        struct meson_nfc *nfc;
>>>>        struct resource *res;
>>>> +    u32 ext_clk_reg;
>>>>        int ret, irq;
>>>>          nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL);
>>>> @@ -1396,9 +1400,15 @@ static int meson_nfc_probe(struct platform_device *pdev)
>>>>        if (IS_ERR(nfc->reg_base))
>>>>            return PTR_ERR(nfc->reg_base);
>>>>    -    nfc->reg_clk =
>>>> -        syscon_regmap_lookup_by_phandle(dev->of_node,
>>>> -                        "amlogic,mmc-syscon");
>>>> +    ret = of_property_read_u32(pdev->dev.of_node,
>>>> +                   "sd_emmc_c_clkc",
>>>> +                   &ext_clk_reg);
>>>> +    if (ret) {
>>>> +        dev_err(dev, "failed to get NAND external clock register\n");
>>>> +        return ret;
>>>> +    }
>>>> +
>>>> +    nfc->reg_clk = devm_ioremap(&pdev->dev, ext_clk_reg, sizeof(int));
>>>
>>> That's how you should get a register region.
>>> If you want an example of a device claiming several region on amlogic,
>>> have a look at the pinctrl driver.
>> ok
>>>
>>>>        if (IS_ERR(nfc->reg_clk)) {
>>>>            dev_err(dev, "Failed to lookup clock base\n");
>>>>            return PTR_ERR(nfc->reg_clk);
>>>
>>> .
> 
> .

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH] mtd: rawnand: meson: fix the clock after discarding sd_emmc_c_clkc
@ 2022-01-10  3:28         ` Liang Yang
  0 siblings, 0 replies; 47+ messages in thread
From: Liang Yang @ 2022-01-10  3:28 UTC (permalink / raw)
  To: Neil Armstrong, Jerome Brunet, Miquel Raynal, linux-mtd
  Cc: Richard Weinberger, Martin Blumenstingl, Kevin Hilman,
	Jianxin Pan, Victor Wan, XianWei Zhao, Kelvin Zhang,
	BiChao Zheng, YongHui Yu, linux-arm-kernel, linux-amlogic,
	linux-kernel, devicetree

Hi,

On 2022/1/7 17:57, Neil Armstrong wrote:
> [ EXTERNAL EMAIL ]
> 
> Hi,
> 
> On 07/01/2022 05:04, Liang Yang wrote:
>> Hi Jerome,
>>
>> On 2022/1/6 16:16, Jerome Brunet wrote:
>>> [ EXTERNAL EMAIL ]
>>>
>>>
>>> On Thu 06 Jan 2022 at 11:25, Liang Yang <liang.yang@amlogic.com> wrote:
>>>
>>>> Because EMMC and NAND have the same control clock register, so we
>>>> implement a 'sd_emmc_c_clkc'. Previously DTS is defined as below:
>>>>
>>>>      sd_emmc_c_clkc: mmc@7000 {
>>>>          compatible = "amlogic,meson-axg-mmc-clkc", "syscon";
>>>>          reg = <0x0 0x7000 0x0 0x800>;
>>>>      };
>>>>
>>>>      nand-controller@7800 {
>>>>          ......
>>>>
>>>>          clocks = <&clkc CLKID_SD_EMMC_C>,
>>>>              <&sd_emmc_c_clkc CLKID_MMC_DIV>,
>>>>              <&sd_emmc_c_clkc CLKID_MMC_PHASE_RX>,
>>>>              <&sd_emmc_c_clkc CLKID_MMC_PHASE_TX>;
>>>>          clock-names = "core", "device", "rx", "tx";
>>>>          amlogic,mmc-syscon = <&sd_emmc_c_clkc>;
>>>>
>>>>          ......
>>>>      }
>>>>
>>>> but in fact, above implementation is rejected. so now registering
>>>> a nand_divider.
>>>
>>> Can you give a bit of context ? a link to the discussion rejecting this
>>>
>> Maybe I mistake the meaning of [jianxin.pan@amlogic.com], so i need him to clarify it.
>>> As far as remember, things were getting done for A1 and stopped before
>>> clock part was finished. I'm saying the change is wrong, just that a
>>> discussion is needed before a decision is made.
>>>
>> ok.
>> previous discussion in this link:
>> https://lore.kernel.org/all/86789d73-5a6c-7729-ecd1-dcd342b2fcde@amlogic.com/
>> it never go on since v6.
> 
> Looking at the serie I don't see any major blockers, if you're willing to take ownership
> of this patchset and send a v6 with all issues/comments addressed, it would be easier than
> restarting the whole design discussion
> 
> Neil


Hi Neil, thanks for your advice.
After talking with [jianxin.pan], form this link 
<https://lkml.org/lkml/2019/1/8/441>, it already moves futher and on v9, 
so we decide to continue to work hard on it.

> 
>>
>>>>
>>>> Change-Id: Ibeb4c7ff886f5886aac4d6c664d7bbd1b1bcb997
>>>> Signed-off-by: Liang Yang <liang.yang@amlogic.com>
>>>> ---
>>>>    drivers/mtd/nand/raw/meson_nand.c | 88 +++++++++++++++++--------------
>>>>    1 file changed, 49 insertions(+), 39 deletions(-)
>>>>
>>>> diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c
>>>> index ac3be92872d0..4472363059c2 100644
>>>> --- a/drivers/mtd/nand/raw/meson_nand.c
>>>> +++ b/drivers/mtd/nand/raw/meson_nand.c
>>>> @@ -2,7 +2,7 @@
>>>>    /*
>>>>     * Amlogic Meson Nand Flash Controller Driver
>>>>     *
>>>> - * Copyright (c) 2018 Amlogic, inc.
>>>> + * Copyright (c) 2018-2021 Amlogic, inc.
>>>>     * Author: Liang Yang <liang.yang@amlogic.com>
>>>>     */
>>>>    @@ -10,6 +10,7 @@
>>>>    #include <linux/dma-mapping.h>
>>>>    #include <linux/interrupt.h>
>>>>    #include <linux/clk.h>
>>>> +#include <linux/clk-provider.h>
>>>>    #include <linux/mtd/rawnand.h>
>>>>    #include <linux/mtd/mtd.h>
>>>>    #include <linux/mfd/syscon.h>
>>>> @@ -55,6 +56,7 @@
>>>>    #define NFC_REG_VER        0x38
>>>>      #define NFC_RB_IRQ_EN        BIT(21)
>>>> +#define NFC_CMD_FIFO_RESET    BIT(31)
>>>>      #define CMDRWGEN(cmd_dir, ran, bch, short_mode, page_size, pages)    \
>>>>        (                                \
>>>> @@ -104,6 +106,9 @@
>>>>      #define PER_INFO_BYTE        8
>>>>    +#define CLK_DIV_SHIFT        0
>>>> +#define CLK_DIV_WIDTH        6
>>>> +
>>>>    struct meson_nfc_nand_chip {
>>>>        struct list_head node;
>>>>        struct nand_chip nand;
>>>> @@ -151,15 +156,15 @@ struct meson_nfc {
>>>>        struct nand_controller controller;
>>>>        struct clk *core_clk;
>>>>        struct clk *device_clk;
>>>> -    struct clk *phase_tx;
>>>> -    struct clk *phase_rx;
>>>
>>> I would have been nice to explain why these clock are no longer
>>> required, in the change description maybe ?
>>
>> i got the reply from our vlsi members that rx and tx doesn't make sense to meson NFC timing. so previous commit about this should be wrong.
>>>
>>>> +    struct clk *nand_clk;
>>>> +    struct clk_divider nand_divider;
>>>>          unsigned long clk_rate;
>>>>        u32 bus_timing;
>>>>          struct device *dev;
>>>>        void __iomem *reg_base;
>>>> -    struct regmap *reg_clk;
>>>> +    void __iomem *reg_clk;
>>>>        struct completion completion;
>>>>        struct list_head chips;
>>>>        const struct meson_nfc_data *data;
>>>> @@ -406,12 +411,14 @@ static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms)
>>>>        cmd = NFC_CMD_RB | NFC_CMD_RB_INT
>>>>            | nfc->param.chip_select | nfc->timing.tbers_max;
>>>>        writel(cmd, nfc->reg_base + NFC_REG_CMD);
>>>> -
>>>> +    meson_nfc_drain_cmd(nfc);
>>>
>>> is this clock related ?
>> ok, i will split it in another patch.
>>>
>>>>        ret = wait_for_completion_timeout(&nfc->completion,
>>>>                          msecs_to_jiffies(timeout_ms));
>>>>        if (ret == 0)
>>>>            ret = -1;
>>>>    +    /* reset command fifo to avoid lock */
>>>> +    writel(NFC_CMD_FIFO_RESET, nfc->reg_base + NFC_REG_CMD);
>>>
>>> Again, not seem to be clock related - does not belong in this patch
>> ok, i will split it in another patch.
>>>
>>>>        return ret;
>>>>    }
>>>>    @@ -988,8 +995,9 @@ static const struct mtd_ooblayout_ops meson_ooblayout_ops = {
>>>>    static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>>    {
>>>>        int ret;
>>>> +    struct clk_init_data init = {0};
>>>> +    const char *fix_div2_pll_name[1];
>>>>    -    /* request core clock */
>>>
>>> Why is the comment bothering you ?
>>>
>>>>        nfc->core_clk = devm_clk_get(nfc->dev, "core");
>>>>        if (IS_ERR(nfc->core_clk)) {
>>>>            dev_err(nfc->dev, "failed to get core clock\n");
>>>> @@ -1002,21 +1010,25 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>>            return PTR_ERR(nfc->device_clk);
>>>>        }
>>>>    -    nfc->phase_tx = devm_clk_get(nfc->dev, "tx");
>>>> -    if (IS_ERR(nfc->phase_tx)) {
>>>> -        dev_err(nfc->dev, "failed to get TX clk\n");
>>>> -        return PTR_ERR(nfc->phase_tx);
>>>> -    }
>>>> -
>>>> -    nfc->phase_rx = devm_clk_get(nfc->dev, "rx");
>>>> -    if (IS_ERR(nfc->phase_rx)) {
>>>> -        dev_err(nfc->dev, "failed to get RX clk\n");
>>>> -        return PTR_ERR(nfc->phase_rx);
>>>> -    }
>>>> +    init.name = devm_kstrdup(nfc->dev, "nfc#div", GFP_KERNEL);
>>>> +    init.ops = &clk_divider_ops;
>>>> +    fix_div2_pll_name[0] = __clk_get_name(nfc->device_clk);
>>>
>>> You should be using "fw_name" so CCF looks a DT directly, instead of this
>> ok
>>>
>>>> +    init.parent_names = fix_div2_pll_name;
>>>> +    init.num_parents = 1;
>>>> +    nfc->nand_divider.reg = nfc->reg_clk;
>>>> +    nfc->nand_divider.shift = CLK_DIV_SHIFT;
>>>> +    nfc->nand_divider.width = CLK_DIV_WIDTH;
>>>> +    nfc->nand_divider.hw.init = &init;
>>>> +    nfc->nand_divider.flags = CLK_DIVIDER_ONE_BASED |
>>>> +                  CLK_DIVIDER_ROUND_CLOSEST |
>>>> +                        CLK_DIVIDER_ALLOW_ZERO;
>>>> +
>>>> +    nfc->nand_clk = devm_clk_register(nfc->dev, &nfc->nand_divider.hw);
>>>> +    if (IS_ERR(nfc->nand_clk))
>>>> +        return PTR_ERR(nfc->nand_clk);
>>>>          /* init SD_EMMC_CLOCK to sane defaults w/min clock rate */
>>>> -    regmap_update_bits(nfc->reg_clk,
>>>> -               0, CLK_SELECT_NAND, CLK_SELECT_NAND);
>>>> +    writel(CLK_SELECT_NAND | readl(nfc->reg_clk), nfc->reg_clk);
>>>>          ret = clk_prepare_enable(nfc->core_clk);
>>>>        if (ret) {
>>>> @@ -1030,29 +1042,21 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>>            goto err_device_clk;
>>>>        }
>>>>    -    ret = clk_prepare_enable(nfc->phase_tx);
>>>> +    ret = clk_prepare_enable(nfc->nand_clk);
>>>>        if (ret) {
>>>> -        dev_err(nfc->dev, "failed to enable TX clock\n");
>>>> -        goto err_phase_tx;
>>>> -    }
>>>> -
>>>> -    ret = clk_prepare_enable(nfc->phase_rx);
>>>> -    if (ret) {
>>>> -        dev_err(nfc->dev, "failed to enable RX clock\n");
>>>> -        goto err_phase_rx;
>>>> +        dev_err(nfc->dev, "pre enable NFC divider fail\n");
>>>> +        goto err_nand_clk;
>>>>        }
>>>>          ret = clk_set_rate(nfc->device_clk, 24000000);
>>>>        if (ret)
>>>> -        goto err_disable_rx;
>>>> +        goto err_disable_clk;
>>>>          return 0;
>>>>    -err_disable_rx:
>>>> -    clk_disable_unprepare(nfc->phase_rx);
>>>> -err_phase_rx:
>>>> -    clk_disable_unprepare(nfc->phase_tx);
>>>> -err_phase_tx:
>>>> +err_disable_clk:
>>>> +    clk_disable_unprepare(nfc->nand_clk);
>>>> +err_nand_clk:
>>>>        clk_disable_unprepare(nfc->device_clk);
>>>>    err_device_clk:
>>>>        clk_disable_unprepare(nfc->core_clk);
>>>> @@ -1061,8 +1065,7 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>>      static void meson_nfc_disable_clk(struct meson_nfc *nfc)
>>>>    {
>>>> -    clk_disable_unprepare(nfc->phase_rx);
>>>> -    clk_disable_unprepare(nfc->phase_tx);
>>>> +    clk_disable_unprepare(nfc->nand_clk);
>>>>        clk_disable_unprepare(nfc->device_clk);
>>>>        clk_disable_unprepare(nfc->core_clk);
>>>>    }
>>>> @@ -1375,6 +1378,7 @@ static int meson_nfc_probe(struct platform_device *pdev)
>>>>        struct device *dev = &pdev->dev;
>>>>        struct meson_nfc *nfc;
>>>>        struct resource *res;
>>>> +    u32 ext_clk_reg;
>>>>        int ret, irq;
>>>>          nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL);
>>>> @@ -1396,9 +1400,15 @@ static int meson_nfc_probe(struct platform_device *pdev)
>>>>        if (IS_ERR(nfc->reg_base))
>>>>            return PTR_ERR(nfc->reg_base);
>>>>    -    nfc->reg_clk =
>>>> -        syscon_regmap_lookup_by_phandle(dev->of_node,
>>>> -                        "amlogic,mmc-syscon");
>>>> +    ret = of_property_read_u32(pdev->dev.of_node,
>>>> +                   "sd_emmc_c_clkc",
>>>> +                   &ext_clk_reg);
>>>> +    if (ret) {
>>>> +        dev_err(dev, "failed to get NAND external clock register\n");
>>>> +        return ret;
>>>> +    }
>>>> +
>>>> +    nfc->reg_clk = devm_ioremap(&pdev->dev, ext_clk_reg, sizeof(int));
>>>
>>> That's how you should get a register region.
>>> If you want an example of a device claiming several region on amlogic,
>>> have a look at the pinctrl driver.
>> ok
>>>
>>>>        if (IS_ERR(nfc->reg_clk)) {
>>>>            dev_err(dev, "Failed to lookup clock base\n");
>>>>            return PTR_ERR(nfc->reg_clk);
>>>
>>> .
> 
> .

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH] mtd: rawnand: meson: fix the clock after discarding sd_emmc_c_clkc
  2022-01-07  7:54       ` Jerome Brunet
  (?)
  (?)
@ 2022-01-10  3:32         ` Liang Yang
  -1 siblings, 0 replies; 47+ messages in thread
From: Liang Yang @ 2022-01-10  3:32 UTC (permalink / raw)
  To: Jerome Brunet, Miquel Raynal
  Cc: linux-mtd, Richard Weinberger, Neil Armstrong,
	Martin Blumenstingl, Kevin Hilman, Jianxin Pan, Victor Wan,
	XianWei Zhao, Kelvin Zhang, BiChao Zheng, YongHui Yu,
	linux-arm-kernel, linux-amlogic, linux-kernel, devicetree

Hello Jerome,

On 2022/1/7 15:54, Jerome Brunet wrote:
> [ EXTERNAL EMAIL ]
> 
> 
> On Fri 07 Jan 2022 at 10:40, Liang Yang <liang.yang@amlogic.com> wrote:
> 
>> Hi Miquel,
>>
>> Meson NFC clock depends on the implementation of sd_emmc_c_clkc, but i
>> don't find the commit in
>> linux mainline. then the information i got from [jianxin.pan@amlogic.com]
>> is the rejection of
>> serial patches. I just look into the corresponding emails in link:
>>
>> https://lore.kernel.org/all/86789d73-5a6c-7729-ecd1-dcd342b2fcde@amlogic.com/
>> it seems the patch never go on since V6, so [jianxin.pan@amlogic.com],
>> could you help to clear it?
>> let us address the discussion in another email from
>> [jbrunet@baylibre.com].
> 
> That V6 was "rejected" because some comments from thre V5 were still not
> addressed.
> 
em, we decide to continue to work on sd_emmc_c_clkc and it already has a 
longer trip, see this link <https://lkml.org/lkml/2019/1/8/441>. thanks.

>>
>> On 2022/1/6 16:08, Miquel Raynal wrote:
>>> [ EXTERNAL EMAIL ]
>>> Hi Liang,
>>> liang.yang@amlogic.com wrote on Thu, 6 Jan 2022 11:25:04 +0800:
>>>
>>>> Because EMMC and NAND have the same control clock register, so we
>>>> implement a 'sd_emmc_c_clkc'. Previously DTS is defined as below:
>>>>
>>>> 	sd_emmc_c_clkc: mmc@7000 {
>>>> 		compatible = "amlogic,meson-axg-mmc-clkc", "syscon";
>>>> 		reg = <0x0 0x7000 0x0 0x800>;
>>>> 	};
>>>>
>>>> 	nand-controller@7800 {
>>>> 		......
>>>>
>>>> 		clocks = <&clkc CLKID_SD_EMMC_C>,
>>>> 			<&sd_emmc_c_clkc CLKID_MMC_DIV>,
>>>> 			<&sd_emmc_c_clkc CLKID_MMC_PHASE_RX>,
>>>> 			<&sd_emmc_c_clkc CLKID_MMC_PHASE_TX>;
>>>> 		clock-names = "core", "device", "rx", "tx";
>>>> 		amlogic,mmc-syscon = <&sd_emmc_c_clkc>;
>>>>
>>>> 		......
>>>> 	}
>>>>
>>>> but in fact, above implementation is rejected. so now registering
>>>> a nand_divider.
>>> What is rejected?
>>> Why is it rejected?
>>> What is nand_divider?
>> i simplify our clock framework below, so nand divider is SD_EMMC_CLOCK[5:0]
>> here.
>> 			   -----          -----		    -----
>> 	   the other------|	\        |     |	   |	 |
>>           		  | mux	| -----  |  N  | ----------| NFC/|
>> 	   FCLK_DIV2------|     |        |     |	   | EMMC|
>> 			   -----/         ----- 	    -----
>> 		    SD_EMMC_CLOCK[7:6] SD_EMMC_CLOCK[5:0]
>>>
>>>>
>>>> Change-Id: Ibeb4c7ff886f5886aac4d6c664d7bbd1b1bcb997
>>> Change Ids are not expected in the upstream kernel.
>>> But if you fix something you should have a Fixes:.
>>>
>>>> Signed-off-by: Liang Yang <liang.yang@amlogic.com>
>>>> ---
>>>>    drivers/mtd/nand/raw/meson_nand.c | 88 +++++++++++++++++--------------
>>>>    1 file changed, 49 insertions(+), 39 deletions(-)
>>>>
>>>> diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c
>>>> index ac3be92872d0..4472363059c2 100644
>>>> --- a/drivers/mtd/nand/raw/meson_nand.c
>>>> +++ b/drivers/mtd/nand/raw/meson_nand.c
>>>> @@ -2,7 +2,7 @@
>>>>    /*
>>>>     * Amlogic Meson Nand Flash Controller Driver
>>>>     *
>>>> - * Copyright (c) 2018 Amlogic, inc.
>>>> + * Copyright (c) 2018-2021 Amlogic, inc.
>>>>     * Author: Liang Yang <liang.yang@amlogic.com>
>>>>     */
>>>>    @@ -10,6 +10,7 @@
>>>>    #include <linux/dma-mapping.h>
>>>>    #include <linux/interrupt.h>
>>>>    #include <linux/clk.h>
>>>> +#include <linux/clk-provider.h>
>>>>    #include <linux/mtd/rawnand.h>
>>>>    #include <linux/mtd/mtd.h>
>>>>    #include <linux/mfd/syscon.h>
>>>> @@ -55,6 +56,7 @@
>>>>    #define NFC_REG_VER		0x38
>>>>      #define NFC_RB_IRQ_EN		BIT(21)
>>>> +#define NFC_CMD_FIFO_RESET	BIT(31)
>>>>      #define CMDRWGEN(cmd_dir, ran, bch, short_mode, page_size, pages)
>>>> \
>>>>    	(								\
>>>> @@ -104,6 +106,9 @@
>>>>      #define PER_INFO_BYTE		8
>>>>    +#define CLK_DIV_SHIFT		0
>>>> +#define CLK_DIV_WIDTH		6
>>>> +
>>>>    struct meson_nfc_nand_chip {
>>>>    	struct list_head node;
>>>>    	struct nand_chip nand;
>>>> @@ -151,15 +156,15 @@ struct meson_nfc {
>>>>    	struct nand_controller controller;
>>>>    	struct clk *core_clk;
>>>>    	struct clk *device_clk;
>>>> -	struct clk *phase_tx;
>>>> -	struct clk *phase_rx;
>>>> +	struct clk *nand_clk;
>>>> +	struct clk_divider nand_divider;
>>>>      	unsigned long clk_rate;
>>>>    	u32 bus_timing;
>>>>      	struct device *dev;
>>>>    	void __iomem *reg_base;
>>>> -	struct regmap *reg_clk;
>>>> +	void __iomem *reg_clk;
>>>>    	struct completion completion;
>>>>    	struct list_head chips;
>>>>    	const struct meson_nfc_data *data;
>>>> @@ -406,12 +411,14 @@ static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms)
>>>>    	cmd = NFC_CMD_RB | NFC_CMD_RB_INT
>>>>    		| nfc->param.chip_select | nfc->timing.tbers_max;
>>>>    	writel(cmd, nfc->reg_base + NFC_REG_CMD);
>>>> -
>>>> +	meson_nfc_drain_cmd(nfc);
>>>>    	ret = wait_for_completion_timeout(&nfc->completion,
>>>>    					  msecs_to_jiffies(timeout_ms));
>>>>    	if (ret == 0)
>>>>    		ret = -1;
>>>>    +	/* reset command fifo to avoid lock */
>>>> +	writel(NFC_CMD_FIFO_RESET, nfc->reg_base + NFC_REG_CMD);
>>>>    	return ret;
>>>>    }
>>>>    @@ -988,8 +995,9 @@ static const struct mtd_ooblayout_ops
>>>> meson_ooblayout_ops = {
>>>>    static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>>    {
>>>>    	int ret;
>>>> +	struct clk_init_data init = {0};
>>>> +	const char *fix_div2_pll_name[1];
>>>>    -	/* request core clock */
>>>>    	nfc->core_clk = devm_clk_get(nfc->dev, "core");
>>>>    	if (IS_ERR(nfc->core_clk)) {
>>>>    		dev_err(nfc->dev, "failed to get core clock\n");
>>>> @@ -1002,21 +1010,25 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>>    		return PTR_ERR(nfc->device_clk);
>>>>    	}
>>>>    -	nfc->phase_tx = devm_clk_get(nfc->dev, "tx");
>>>> -	if (IS_ERR(nfc->phase_tx)) {
>>>> -		dev_err(nfc->dev, "failed to get TX clk\n");
>>>> -		return PTR_ERR(nfc->phase_tx);
>>>> -	}
>>>> -
>>>> -	nfc->phase_rx = devm_clk_get(nfc->dev, "rx");
>>>> -	if (IS_ERR(nfc->phase_rx)) {
>>>> -		dev_err(nfc->dev, "failed to get RX clk\n");
>>>> -		return PTR_ERR(nfc->phase_rx);
>>>> -	}
>>>> +	init.name = devm_kstrdup(nfc->dev, "nfc#div", GFP_KERNEL);
>>>> +	init.ops = &clk_divider_ops;
>>>> +	fix_div2_pll_name[0] = __clk_get_name(nfc->device_clk);
>>>> +	init.parent_names = fix_div2_pll_name;
>>>> +	init.num_parents = 1;
>>>> +	nfc->nand_divider.reg = nfc->reg_clk;
>>>> +	nfc->nand_divider.shift = CLK_DIV_SHIFT;
>>>> +	nfc->nand_divider.width = CLK_DIV_WIDTH;
>>>> +	nfc->nand_divider.hw.init = &init;
>>>> +	nfc->nand_divider.flags = CLK_DIVIDER_ONE_BASED |
>>>> +				  CLK_DIVIDER_ROUND_CLOSEST |
>>>> +          			  CLK_DIVIDER_ALLOW_ZERO;
>>>> +
>>>> +	nfc->nand_clk = devm_clk_register(nfc->dev, &nfc->nand_divider.hw);
>>>> +	if (IS_ERR(nfc->nand_clk))
>>>> +		return PTR_ERR(nfc->nand_clk);
>>>>      	/* init SD_EMMC_CLOCK to sane defaults w/min clock rate */
>>>> -	regmap_update_bits(nfc->reg_clk,
>>>> -			   0, CLK_SELECT_NAND, CLK_SELECT_NAND);
>>>> +	writel(CLK_SELECT_NAND | readl(nfc->reg_clk), nfc->reg_clk);
>>>>      	ret = clk_prepare_enable(nfc->core_clk);
>>>>    	if (ret) {
>>>> @@ -1030,29 +1042,21 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>>    		goto err_device_clk;
>>>>    	}
>>>>    -	ret = clk_prepare_enable(nfc->phase_tx);
>>>> +	ret = clk_prepare_enable(nfc->nand_clk);
>>>>    	if (ret) {
>>>> -		dev_err(nfc->dev, "failed to enable TX clock\n");
>>>> -		goto err_phase_tx;
>>>> -	}
>>>> -
>>>> -	ret = clk_prepare_enable(nfc->phase_rx);
>>>> -	if (ret) {
>>>> -		dev_err(nfc->dev, "failed to enable RX clock\n");
>>>> -		goto err_phase_rx;
>>>> +		dev_err(nfc->dev, "pre enable NFC divider fail\n");
>>>> +		goto err_nand_clk;
>>>>    	}
>>>>      	ret = clk_set_rate(nfc->device_clk, 24000000);
>>>>    	if (ret)
>>>> -		goto err_disable_rx;
>>>> +		goto err_disable_clk;
>>>>      	return 0;
>>>>    -err_disable_rx:
>>>> -	clk_disable_unprepare(nfc->phase_rx);
>>>> -err_phase_rx:
>>>> -	clk_disable_unprepare(nfc->phase_tx);
>>>> -err_phase_tx:
>>>> +err_disable_clk:
>>>> +	clk_disable_unprepare(nfc->nand_clk);
>>>> +err_nand_clk:
>>>>    	clk_disable_unprepare(nfc->device_clk);
>>>>    err_device_clk:
>>>>    	clk_disable_unprepare(nfc->core_clk);
>>>> @@ -1061,8 +1065,7 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>>      static void meson_nfc_disable_clk(struct meson_nfc *nfc)
>>>>    {
>>>> -	clk_disable_unprepare(nfc->phase_rx);
>>>> -	clk_disable_unprepare(nfc->phase_tx);
>>>> +	clk_disable_unprepare(nfc->nand_clk);
>>>>    	clk_disable_unprepare(nfc->device_clk);
>>>>    	clk_disable_unprepare(nfc->core_clk);
>>>>    }
>>>> @@ -1375,6 +1378,7 @@ static int meson_nfc_probe(struct platform_device *pdev)
>>>>    	struct device *dev = &pdev->dev;
>>>>    	struct meson_nfc *nfc;
>>>>    	struct resource *res;
>>>> +	u32 ext_clk_reg;
>>>>    	int ret, irq;
>>>>      	nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL);
>>>> @@ -1396,9 +1400,15 @@ static int meson_nfc_probe(struct platform_device *pdev)
>>>>    	if (IS_ERR(nfc->reg_base))
>>>>    		return PTR_ERR(nfc->reg_base);
>>>>    -	nfc->reg_clk =
>>>> -		syscon_regmap_lookup_by_phandle(dev->of_node,
>>>> -						"amlogic,mmc-syscon");
>>>> +	ret = of_property_read_u32(pdev->dev.of_node,
>>>> +				   "sd_emmc_c_clkc",
>>>> +				   &ext_clk_reg);
>>>> +	if (ret) {
>>>> +		dev_err(dev, "failed to get NAND external clock register\n");
>>>> +		return ret;
>>>> +	}
>>>> +
>>>> +	nfc->reg_clk = devm_ioremap(&pdev->dev, ext_clk_reg, sizeof(int));
>>>>    	if (IS_ERR(nfc->reg_clk)) {
>>>>    		dev_err(dev, "Failed to lookup clock base\n");
>>>>    		return PTR_ERR(nfc->reg_clk);
>>>
>>> Thanks,
>>> Miquèl
>>> .
> 
> .

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

* Re: [PATCH] mtd: rawnand: meson: fix the clock after discarding sd_emmc_c_clkc
@ 2022-01-10  3:32         ` Liang Yang
  0 siblings, 0 replies; 47+ messages in thread
From: Liang Yang @ 2022-01-10  3:32 UTC (permalink / raw)
  To: Jerome Brunet, Miquel Raynal
  Cc: linux-mtd, Richard Weinberger, Neil Armstrong,
	Martin Blumenstingl, Kevin Hilman, Jianxin Pan, Victor Wan,
	XianWei Zhao, Kelvin Zhang, BiChao Zheng, YongHui Yu,
	linux-arm-kernel, linux-amlogic, linux-kernel, devicetree

Hello Jerome,

On 2022/1/7 15:54, Jerome Brunet wrote:
> [ EXTERNAL EMAIL ]
> 
> 
> On Fri 07 Jan 2022 at 10:40, Liang Yang <liang.yang@amlogic.com> wrote:
> 
>> Hi Miquel,
>>
>> Meson NFC clock depends on the implementation of sd_emmc_c_clkc, but i
>> don't find the commit in
>> linux mainline. then the information i got from [jianxin.pan@amlogic.com]
>> is the rejection of
>> serial patches. I just look into the corresponding emails in link:
>>
>> https://lore.kernel.org/all/86789d73-5a6c-7729-ecd1-dcd342b2fcde@amlogic.com/
>> it seems the patch never go on since V6, so [jianxin.pan@amlogic.com],
>> could you help to clear it?
>> let us address the discussion in another email from
>> [jbrunet@baylibre.com].
> 
> That V6 was "rejected" because some comments from thre V5 were still not
> addressed.
> 
em, we decide to continue to work on sd_emmc_c_clkc and it already has a 
longer trip, see this link <https://lkml.org/lkml/2019/1/8/441>. thanks.

>>
>> On 2022/1/6 16:08, Miquel Raynal wrote:
>>> [ EXTERNAL EMAIL ]
>>> Hi Liang,
>>> liang.yang@amlogic.com wrote on Thu, 6 Jan 2022 11:25:04 +0800:
>>>
>>>> Because EMMC and NAND have the same control clock register, so we
>>>> implement a 'sd_emmc_c_clkc'. Previously DTS is defined as below:
>>>>
>>>> 	sd_emmc_c_clkc: mmc@7000 {
>>>> 		compatible = "amlogic,meson-axg-mmc-clkc", "syscon";
>>>> 		reg = <0x0 0x7000 0x0 0x800>;
>>>> 	};
>>>>
>>>> 	nand-controller@7800 {
>>>> 		......
>>>>
>>>> 		clocks = <&clkc CLKID_SD_EMMC_C>,
>>>> 			<&sd_emmc_c_clkc CLKID_MMC_DIV>,
>>>> 			<&sd_emmc_c_clkc CLKID_MMC_PHASE_RX>,
>>>> 			<&sd_emmc_c_clkc CLKID_MMC_PHASE_TX>;
>>>> 		clock-names = "core", "device", "rx", "tx";
>>>> 		amlogic,mmc-syscon = <&sd_emmc_c_clkc>;
>>>>
>>>> 		......
>>>> 	}
>>>>
>>>> but in fact, above implementation is rejected. so now registering
>>>> a nand_divider.
>>> What is rejected?
>>> Why is it rejected?
>>> What is nand_divider?
>> i simplify our clock framework below, so nand divider is SD_EMMC_CLOCK[5:0]
>> here.
>> 			   -----          -----		    -----
>> 	   the other------|	\        |     |	   |	 |
>>           		  | mux	| -----  |  N  | ----------| NFC/|
>> 	   FCLK_DIV2------|     |        |     |	   | EMMC|
>> 			   -----/         ----- 	    -----
>> 		    SD_EMMC_CLOCK[7:6] SD_EMMC_CLOCK[5:0]
>>>
>>>>
>>>> Change-Id: Ibeb4c7ff886f5886aac4d6c664d7bbd1b1bcb997
>>> Change Ids are not expected in the upstream kernel.
>>> But if you fix something you should have a Fixes:.
>>>
>>>> Signed-off-by: Liang Yang <liang.yang@amlogic.com>
>>>> ---
>>>>    drivers/mtd/nand/raw/meson_nand.c | 88 +++++++++++++++++--------------
>>>>    1 file changed, 49 insertions(+), 39 deletions(-)
>>>>
>>>> diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c
>>>> index ac3be92872d0..4472363059c2 100644
>>>> --- a/drivers/mtd/nand/raw/meson_nand.c
>>>> +++ b/drivers/mtd/nand/raw/meson_nand.c
>>>> @@ -2,7 +2,7 @@
>>>>    /*
>>>>     * Amlogic Meson Nand Flash Controller Driver
>>>>     *
>>>> - * Copyright (c) 2018 Amlogic, inc.
>>>> + * Copyright (c) 2018-2021 Amlogic, inc.
>>>>     * Author: Liang Yang <liang.yang@amlogic.com>
>>>>     */
>>>>    @@ -10,6 +10,7 @@
>>>>    #include <linux/dma-mapping.h>
>>>>    #include <linux/interrupt.h>
>>>>    #include <linux/clk.h>
>>>> +#include <linux/clk-provider.h>
>>>>    #include <linux/mtd/rawnand.h>
>>>>    #include <linux/mtd/mtd.h>
>>>>    #include <linux/mfd/syscon.h>
>>>> @@ -55,6 +56,7 @@
>>>>    #define NFC_REG_VER		0x38
>>>>      #define NFC_RB_IRQ_EN		BIT(21)
>>>> +#define NFC_CMD_FIFO_RESET	BIT(31)
>>>>      #define CMDRWGEN(cmd_dir, ran, bch, short_mode, page_size, pages)
>>>> \
>>>>    	(								\
>>>> @@ -104,6 +106,9 @@
>>>>      #define PER_INFO_BYTE		8
>>>>    +#define CLK_DIV_SHIFT		0
>>>> +#define CLK_DIV_WIDTH		6
>>>> +
>>>>    struct meson_nfc_nand_chip {
>>>>    	struct list_head node;
>>>>    	struct nand_chip nand;
>>>> @@ -151,15 +156,15 @@ struct meson_nfc {
>>>>    	struct nand_controller controller;
>>>>    	struct clk *core_clk;
>>>>    	struct clk *device_clk;
>>>> -	struct clk *phase_tx;
>>>> -	struct clk *phase_rx;
>>>> +	struct clk *nand_clk;
>>>> +	struct clk_divider nand_divider;
>>>>      	unsigned long clk_rate;
>>>>    	u32 bus_timing;
>>>>      	struct device *dev;
>>>>    	void __iomem *reg_base;
>>>> -	struct regmap *reg_clk;
>>>> +	void __iomem *reg_clk;
>>>>    	struct completion completion;
>>>>    	struct list_head chips;
>>>>    	const struct meson_nfc_data *data;
>>>> @@ -406,12 +411,14 @@ static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms)
>>>>    	cmd = NFC_CMD_RB | NFC_CMD_RB_INT
>>>>    		| nfc->param.chip_select | nfc->timing.tbers_max;
>>>>    	writel(cmd, nfc->reg_base + NFC_REG_CMD);
>>>> -
>>>> +	meson_nfc_drain_cmd(nfc);
>>>>    	ret = wait_for_completion_timeout(&nfc->completion,
>>>>    					  msecs_to_jiffies(timeout_ms));
>>>>    	if (ret == 0)
>>>>    		ret = -1;
>>>>    +	/* reset command fifo to avoid lock */
>>>> +	writel(NFC_CMD_FIFO_RESET, nfc->reg_base + NFC_REG_CMD);
>>>>    	return ret;
>>>>    }
>>>>    @@ -988,8 +995,9 @@ static const struct mtd_ooblayout_ops
>>>> meson_ooblayout_ops = {
>>>>    static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>>    {
>>>>    	int ret;
>>>> +	struct clk_init_data init = {0};
>>>> +	const char *fix_div2_pll_name[1];
>>>>    -	/* request core clock */
>>>>    	nfc->core_clk = devm_clk_get(nfc->dev, "core");
>>>>    	if (IS_ERR(nfc->core_clk)) {
>>>>    		dev_err(nfc->dev, "failed to get core clock\n");
>>>> @@ -1002,21 +1010,25 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>>    		return PTR_ERR(nfc->device_clk);
>>>>    	}
>>>>    -	nfc->phase_tx = devm_clk_get(nfc->dev, "tx");
>>>> -	if (IS_ERR(nfc->phase_tx)) {
>>>> -		dev_err(nfc->dev, "failed to get TX clk\n");
>>>> -		return PTR_ERR(nfc->phase_tx);
>>>> -	}
>>>> -
>>>> -	nfc->phase_rx = devm_clk_get(nfc->dev, "rx");
>>>> -	if (IS_ERR(nfc->phase_rx)) {
>>>> -		dev_err(nfc->dev, "failed to get RX clk\n");
>>>> -		return PTR_ERR(nfc->phase_rx);
>>>> -	}
>>>> +	init.name = devm_kstrdup(nfc->dev, "nfc#div", GFP_KERNEL);
>>>> +	init.ops = &clk_divider_ops;
>>>> +	fix_div2_pll_name[0] = __clk_get_name(nfc->device_clk);
>>>> +	init.parent_names = fix_div2_pll_name;
>>>> +	init.num_parents = 1;
>>>> +	nfc->nand_divider.reg = nfc->reg_clk;
>>>> +	nfc->nand_divider.shift = CLK_DIV_SHIFT;
>>>> +	nfc->nand_divider.width = CLK_DIV_WIDTH;
>>>> +	nfc->nand_divider.hw.init = &init;
>>>> +	nfc->nand_divider.flags = CLK_DIVIDER_ONE_BASED |
>>>> +				  CLK_DIVIDER_ROUND_CLOSEST |
>>>> +          			  CLK_DIVIDER_ALLOW_ZERO;
>>>> +
>>>> +	nfc->nand_clk = devm_clk_register(nfc->dev, &nfc->nand_divider.hw);
>>>> +	if (IS_ERR(nfc->nand_clk))
>>>> +		return PTR_ERR(nfc->nand_clk);
>>>>      	/* init SD_EMMC_CLOCK to sane defaults w/min clock rate */
>>>> -	regmap_update_bits(nfc->reg_clk,
>>>> -			   0, CLK_SELECT_NAND, CLK_SELECT_NAND);
>>>> +	writel(CLK_SELECT_NAND | readl(nfc->reg_clk), nfc->reg_clk);
>>>>      	ret = clk_prepare_enable(nfc->core_clk);
>>>>    	if (ret) {
>>>> @@ -1030,29 +1042,21 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>>    		goto err_device_clk;
>>>>    	}
>>>>    -	ret = clk_prepare_enable(nfc->phase_tx);
>>>> +	ret = clk_prepare_enable(nfc->nand_clk);
>>>>    	if (ret) {
>>>> -		dev_err(nfc->dev, "failed to enable TX clock\n");
>>>> -		goto err_phase_tx;
>>>> -	}
>>>> -
>>>> -	ret = clk_prepare_enable(nfc->phase_rx);
>>>> -	if (ret) {
>>>> -		dev_err(nfc->dev, "failed to enable RX clock\n");
>>>> -		goto err_phase_rx;
>>>> +		dev_err(nfc->dev, "pre enable NFC divider fail\n");
>>>> +		goto err_nand_clk;
>>>>    	}
>>>>      	ret = clk_set_rate(nfc->device_clk, 24000000);
>>>>    	if (ret)
>>>> -		goto err_disable_rx;
>>>> +		goto err_disable_clk;
>>>>      	return 0;
>>>>    -err_disable_rx:
>>>> -	clk_disable_unprepare(nfc->phase_rx);
>>>> -err_phase_rx:
>>>> -	clk_disable_unprepare(nfc->phase_tx);
>>>> -err_phase_tx:
>>>> +err_disable_clk:
>>>> +	clk_disable_unprepare(nfc->nand_clk);
>>>> +err_nand_clk:
>>>>    	clk_disable_unprepare(nfc->device_clk);
>>>>    err_device_clk:
>>>>    	clk_disable_unprepare(nfc->core_clk);
>>>> @@ -1061,8 +1065,7 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>>      static void meson_nfc_disable_clk(struct meson_nfc *nfc)
>>>>    {
>>>> -	clk_disable_unprepare(nfc->phase_rx);
>>>> -	clk_disable_unprepare(nfc->phase_tx);
>>>> +	clk_disable_unprepare(nfc->nand_clk);
>>>>    	clk_disable_unprepare(nfc->device_clk);
>>>>    	clk_disable_unprepare(nfc->core_clk);
>>>>    }
>>>> @@ -1375,6 +1378,7 @@ static int meson_nfc_probe(struct platform_device *pdev)
>>>>    	struct device *dev = &pdev->dev;
>>>>    	struct meson_nfc *nfc;
>>>>    	struct resource *res;
>>>> +	u32 ext_clk_reg;
>>>>    	int ret, irq;
>>>>      	nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL);
>>>> @@ -1396,9 +1400,15 @@ static int meson_nfc_probe(struct platform_device *pdev)
>>>>    	if (IS_ERR(nfc->reg_base))
>>>>    		return PTR_ERR(nfc->reg_base);
>>>>    -	nfc->reg_clk =
>>>> -		syscon_regmap_lookup_by_phandle(dev->of_node,
>>>> -						"amlogic,mmc-syscon");
>>>> +	ret = of_property_read_u32(pdev->dev.of_node,
>>>> +				   "sd_emmc_c_clkc",
>>>> +				   &ext_clk_reg);
>>>> +	if (ret) {
>>>> +		dev_err(dev, "failed to get NAND external clock register\n");
>>>> +		return ret;
>>>> +	}
>>>> +
>>>> +	nfc->reg_clk = devm_ioremap(&pdev->dev, ext_clk_reg, sizeof(int));
>>>>    	if (IS_ERR(nfc->reg_clk)) {
>>>>    		dev_err(dev, "Failed to lookup clock base\n");
>>>>    		return PTR_ERR(nfc->reg_clk);
>>>
>>> Thanks,
>>> Miquèl
>>> .
> 
> .

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

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

* Re: [PATCH] mtd: rawnand: meson: fix the clock after discarding sd_emmc_c_clkc
@ 2022-01-10  3:32         ` Liang Yang
  0 siblings, 0 replies; 47+ messages in thread
From: Liang Yang @ 2022-01-10  3:32 UTC (permalink / raw)
  To: Jerome Brunet, Miquel Raynal
  Cc: linux-mtd, Richard Weinberger, Neil Armstrong,
	Martin Blumenstingl, Kevin Hilman, Jianxin Pan, Victor Wan,
	XianWei Zhao, Kelvin Zhang, BiChao Zheng, YongHui Yu,
	linux-arm-kernel, linux-amlogic, linux-kernel, devicetree

Hello Jerome,

On 2022/1/7 15:54, Jerome Brunet wrote:
> [ EXTERNAL EMAIL ]
> 
> 
> On Fri 07 Jan 2022 at 10:40, Liang Yang <liang.yang@amlogic.com> wrote:
> 
>> Hi Miquel,
>>
>> Meson NFC clock depends on the implementation of sd_emmc_c_clkc, but i
>> don't find the commit in
>> linux mainline. then the information i got from [jianxin.pan@amlogic.com]
>> is the rejection of
>> serial patches. I just look into the corresponding emails in link:
>>
>> https://lore.kernel.org/all/86789d73-5a6c-7729-ecd1-dcd342b2fcde@amlogic.com/
>> it seems the patch never go on since V6, so [jianxin.pan@amlogic.com],
>> could you help to clear it?
>> let us address the discussion in another email from
>> [jbrunet@baylibre.com].
> 
> That V6 was "rejected" because some comments from thre V5 were still not
> addressed.
> 
em, we decide to continue to work on sd_emmc_c_clkc and it already has a 
longer trip, see this link <https://lkml.org/lkml/2019/1/8/441>. thanks.

>>
>> On 2022/1/6 16:08, Miquel Raynal wrote:
>>> [ EXTERNAL EMAIL ]
>>> Hi Liang,
>>> liang.yang@amlogic.com wrote on Thu, 6 Jan 2022 11:25:04 +0800:
>>>
>>>> Because EMMC and NAND have the same control clock register, so we
>>>> implement a 'sd_emmc_c_clkc'. Previously DTS is defined as below:
>>>>
>>>> 	sd_emmc_c_clkc: mmc@7000 {
>>>> 		compatible = "amlogic,meson-axg-mmc-clkc", "syscon";
>>>> 		reg = <0x0 0x7000 0x0 0x800>;
>>>> 	};
>>>>
>>>> 	nand-controller@7800 {
>>>> 		......
>>>>
>>>> 		clocks = <&clkc CLKID_SD_EMMC_C>,
>>>> 			<&sd_emmc_c_clkc CLKID_MMC_DIV>,
>>>> 			<&sd_emmc_c_clkc CLKID_MMC_PHASE_RX>,
>>>> 			<&sd_emmc_c_clkc CLKID_MMC_PHASE_TX>;
>>>> 		clock-names = "core", "device", "rx", "tx";
>>>> 		amlogic,mmc-syscon = <&sd_emmc_c_clkc>;
>>>>
>>>> 		......
>>>> 	}
>>>>
>>>> but in fact, above implementation is rejected. so now registering
>>>> a nand_divider.
>>> What is rejected?
>>> Why is it rejected?
>>> What is nand_divider?
>> i simplify our clock framework below, so nand divider is SD_EMMC_CLOCK[5:0]
>> here.
>> 			   -----          -----		    -----
>> 	   the other------|	\        |     |	   |	 |
>>           		  | mux	| -----  |  N  | ----------| NFC/|
>> 	   FCLK_DIV2------|     |        |     |	   | EMMC|
>> 			   -----/         ----- 	    -----
>> 		    SD_EMMC_CLOCK[7:6] SD_EMMC_CLOCK[5:0]
>>>
>>>>
>>>> Change-Id: Ibeb4c7ff886f5886aac4d6c664d7bbd1b1bcb997
>>> Change Ids are not expected in the upstream kernel.
>>> But if you fix something you should have a Fixes:.
>>>
>>>> Signed-off-by: Liang Yang <liang.yang@amlogic.com>
>>>> ---
>>>>    drivers/mtd/nand/raw/meson_nand.c | 88 +++++++++++++++++--------------
>>>>    1 file changed, 49 insertions(+), 39 deletions(-)
>>>>
>>>> diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c
>>>> index ac3be92872d0..4472363059c2 100644
>>>> --- a/drivers/mtd/nand/raw/meson_nand.c
>>>> +++ b/drivers/mtd/nand/raw/meson_nand.c
>>>> @@ -2,7 +2,7 @@
>>>>    /*
>>>>     * Amlogic Meson Nand Flash Controller Driver
>>>>     *
>>>> - * Copyright (c) 2018 Amlogic, inc.
>>>> + * Copyright (c) 2018-2021 Amlogic, inc.
>>>>     * Author: Liang Yang <liang.yang@amlogic.com>
>>>>     */
>>>>    @@ -10,6 +10,7 @@
>>>>    #include <linux/dma-mapping.h>
>>>>    #include <linux/interrupt.h>
>>>>    #include <linux/clk.h>
>>>> +#include <linux/clk-provider.h>
>>>>    #include <linux/mtd/rawnand.h>
>>>>    #include <linux/mtd/mtd.h>
>>>>    #include <linux/mfd/syscon.h>
>>>> @@ -55,6 +56,7 @@
>>>>    #define NFC_REG_VER		0x38
>>>>      #define NFC_RB_IRQ_EN		BIT(21)
>>>> +#define NFC_CMD_FIFO_RESET	BIT(31)
>>>>      #define CMDRWGEN(cmd_dir, ran, bch, short_mode, page_size, pages)
>>>> \
>>>>    	(								\
>>>> @@ -104,6 +106,9 @@
>>>>      #define PER_INFO_BYTE		8
>>>>    +#define CLK_DIV_SHIFT		0
>>>> +#define CLK_DIV_WIDTH		6
>>>> +
>>>>    struct meson_nfc_nand_chip {
>>>>    	struct list_head node;
>>>>    	struct nand_chip nand;
>>>> @@ -151,15 +156,15 @@ struct meson_nfc {
>>>>    	struct nand_controller controller;
>>>>    	struct clk *core_clk;
>>>>    	struct clk *device_clk;
>>>> -	struct clk *phase_tx;
>>>> -	struct clk *phase_rx;
>>>> +	struct clk *nand_clk;
>>>> +	struct clk_divider nand_divider;
>>>>      	unsigned long clk_rate;
>>>>    	u32 bus_timing;
>>>>      	struct device *dev;
>>>>    	void __iomem *reg_base;
>>>> -	struct regmap *reg_clk;
>>>> +	void __iomem *reg_clk;
>>>>    	struct completion completion;
>>>>    	struct list_head chips;
>>>>    	const struct meson_nfc_data *data;
>>>> @@ -406,12 +411,14 @@ static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms)
>>>>    	cmd = NFC_CMD_RB | NFC_CMD_RB_INT
>>>>    		| nfc->param.chip_select | nfc->timing.tbers_max;
>>>>    	writel(cmd, nfc->reg_base + NFC_REG_CMD);
>>>> -
>>>> +	meson_nfc_drain_cmd(nfc);
>>>>    	ret = wait_for_completion_timeout(&nfc->completion,
>>>>    					  msecs_to_jiffies(timeout_ms));
>>>>    	if (ret == 0)
>>>>    		ret = -1;
>>>>    +	/* reset command fifo to avoid lock */
>>>> +	writel(NFC_CMD_FIFO_RESET, nfc->reg_base + NFC_REG_CMD);
>>>>    	return ret;
>>>>    }
>>>>    @@ -988,8 +995,9 @@ static const struct mtd_ooblayout_ops
>>>> meson_ooblayout_ops = {
>>>>    static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>>    {
>>>>    	int ret;
>>>> +	struct clk_init_data init = {0};
>>>> +	const char *fix_div2_pll_name[1];
>>>>    -	/* request core clock */
>>>>    	nfc->core_clk = devm_clk_get(nfc->dev, "core");
>>>>    	if (IS_ERR(nfc->core_clk)) {
>>>>    		dev_err(nfc->dev, "failed to get core clock\n");
>>>> @@ -1002,21 +1010,25 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>>    		return PTR_ERR(nfc->device_clk);
>>>>    	}
>>>>    -	nfc->phase_tx = devm_clk_get(nfc->dev, "tx");
>>>> -	if (IS_ERR(nfc->phase_tx)) {
>>>> -		dev_err(nfc->dev, "failed to get TX clk\n");
>>>> -		return PTR_ERR(nfc->phase_tx);
>>>> -	}
>>>> -
>>>> -	nfc->phase_rx = devm_clk_get(nfc->dev, "rx");
>>>> -	if (IS_ERR(nfc->phase_rx)) {
>>>> -		dev_err(nfc->dev, "failed to get RX clk\n");
>>>> -		return PTR_ERR(nfc->phase_rx);
>>>> -	}
>>>> +	init.name = devm_kstrdup(nfc->dev, "nfc#div", GFP_KERNEL);
>>>> +	init.ops = &clk_divider_ops;
>>>> +	fix_div2_pll_name[0] = __clk_get_name(nfc->device_clk);
>>>> +	init.parent_names = fix_div2_pll_name;
>>>> +	init.num_parents = 1;
>>>> +	nfc->nand_divider.reg = nfc->reg_clk;
>>>> +	nfc->nand_divider.shift = CLK_DIV_SHIFT;
>>>> +	nfc->nand_divider.width = CLK_DIV_WIDTH;
>>>> +	nfc->nand_divider.hw.init = &init;
>>>> +	nfc->nand_divider.flags = CLK_DIVIDER_ONE_BASED |
>>>> +				  CLK_DIVIDER_ROUND_CLOSEST |
>>>> +          			  CLK_DIVIDER_ALLOW_ZERO;
>>>> +
>>>> +	nfc->nand_clk = devm_clk_register(nfc->dev, &nfc->nand_divider.hw);
>>>> +	if (IS_ERR(nfc->nand_clk))
>>>> +		return PTR_ERR(nfc->nand_clk);
>>>>      	/* init SD_EMMC_CLOCK to sane defaults w/min clock rate */
>>>> -	regmap_update_bits(nfc->reg_clk,
>>>> -			   0, CLK_SELECT_NAND, CLK_SELECT_NAND);
>>>> +	writel(CLK_SELECT_NAND | readl(nfc->reg_clk), nfc->reg_clk);
>>>>      	ret = clk_prepare_enable(nfc->core_clk);
>>>>    	if (ret) {
>>>> @@ -1030,29 +1042,21 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>>    		goto err_device_clk;
>>>>    	}
>>>>    -	ret = clk_prepare_enable(nfc->phase_tx);
>>>> +	ret = clk_prepare_enable(nfc->nand_clk);
>>>>    	if (ret) {
>>>> -		dev_err(nfc->dev, "failed to enable TX clock\n");
>>>> -		goto err_phase_tx;
>>>> -	}
>>>> -
>>>> -	ret = clk_prepare_enable(nfc->phase_rx);
>>>> -	if (ret) {
>>>> -		dev_err(nfc->dev, "failed to enable RX clock\n");
>>>> -		goto err_phase_rx;
>>>> +		dev_err(nfc->dev, "pre enable NFC divider fail\n");
>>>> +		goto err_nand_clk;
>>>>    	}
>>>>      	ret = clk_set_rate(nfc->device_clk, 24000000);
>>>>    	if (ret)
>>>> -		goto err_disable_rx;
>>>> +		goto err_disable_clk;
>>>>      	return 0;
>>>>    -err_disable_rx:
>>>> -	clk_disable_unprepare(nfc->phase_rx);
>>>> -err_phase_rx:
>>>> -	clk_disable_unprepare(nfc->phase_tx);
>>>> -err_phase_tx:
>>>> +err_disable_clk:
>>>> +	clk_disable_unprepare(nfc->nand_clk);
>>>> +err_nand_clk:
>>>>    	clk_disable_unprepare(nfc->device_clk);
>>>>    err_device_clk:
>>>>    	clk_disable_unprepare(nfc->core_clk);
>>>> @@ -1061,8 +1065,7 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>>      static void meson_nfc_disable_clk(struct meson_nfc *nfc)
>>>>    {
>>>> -	clk_disable_unprepare(nfc->phase_rx);
>>>> -	clk_disable_unprepare(nfc->phase_tx);
>>>> +	clk_disable_unprepare(nfc->nand_clk);
>>>>    	clk_disable_unprepare(nfc->device_clk);
>>>>    	clk_disable_unprepare(nfc->core_clk);
>>>>    }
>>>> @@ -1375,6 +1378,7 @@ static int meson_nfc_probe(struct platform_device *pdev)
>>>>    	struct device *dev = &pdev->dev;
>>>>    	struct meson_nfc *nfc;
>>>>    	struct resource *res;
>>>> +	u32 ext_clk_reg;
>>>>    	int ret, irq;
>>>>      	nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL);
>>>> @@ -1396,9 +1400,15 @@ static int meson_nfc_probe(struct platform_device *pdev)
>>>>    	if (IS_ERR(nfc->reg_base))
>>>>    		return PTR_ERR(nfc->reg_base);
>>>>    -	nfc->reg_clk =
>>>> -		syscon_regmap_lookup_by_phandle(dev->of_node,
>>>> -						"amlogic,mmc-syscon");
>>>> +	ret = of_property_read_u32(pdev->dev.of_node,
>>>> +				   "sd_emmc_c_clkc",
>>>> +				   &ext_clk_reg);
>>>> +	if (ret) {
>>>> +		dev_err(dev, "failed to get NAND external clock register\n");
>>>> +		return ret;
>>>> +	}
>>>> +
>>>> +	nfc->reg_clk = devm_ioremap(&pdev->dev, ext_clk_reg, sizeof(int));
>>>>    	if (IS_ERR(nfc->reg_clk)) {
>>>>    		dev_err(dev, "Failed to lookup clock base\n");
>>>>    		return PTR_ERR(nfc->reg_clk);
>>>
>>> Thanks,
>>> Miquèl
>>> .
> 
> .

_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic

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

* Re: [PATCH] mtd: rawnand: meson: fix the clock after discarding sd_emmc_c_clkc
@ 2022-01-10  3:32         ` Liang Yang
  0 siblings, 0 replies; 47+ messages in thread
From: Liang Yang @ 2022-01-10  3:32 UTC (permalink / raw)
  To: Jerome Brunet, Miquel Raynal
  Cc: linux-mtd, Richard Weinberger, Neil Armstrong,
	Martin Blumenstingl, Kevin Hilman, Jianxin Pan, Victor Wan,
	XianWei Zhao, Kelvin Zhang, BiChao Zheng, YongHui Yu,
	linux-arm-kernel, linux-amlogic, linux-kernel, devicetree

Hello Jerome,

On 2022/1/7 15:54, Jerome Brunet wrote:
> [ EXTERNAL EMAIL ]
> 
> 
> On Fri 07 Jan 2022 at 10:40, Liang Yang <liang.yang@amlogic.com> wrote:
> 
>> Hi Miquel,
>>
>> Meson NFC clock depends on the implementation of sd_emmc_c_clkc, but i
>> don't find the commit in
>> linux mainline. then the information i got from [jianxin.pan@amlogic.com]
>> is the rejection of
>> serial patches. I just look into the corresponding emails in link:
>>
>> https://lore.kernel.org/all/86789d73-5a6c-7729-ecd1-dcd342b2fcde@amlogic.com/
>> it seems the patch never go on since V6, so [jianxin.pan@amlogic.com],
>> could you help to clear it?
>> let us address the discussion in another email from
>> [jbrunet@baylibre.com].
> 
> That V6 was "rejected" because some comments from thre V5 were still not
> addressed.
> 
em, we decide to continue to work on sd_emmc_c_clkc and it already has a 
longer trip, see this link <https://lkml.org/lkml/2019/1/8/441>. thanks.

>>
>> On 2022/1/6 16:08, Miquel Raynal wrote:
>>> [ EXTERNAL EMAIL ]
>>> Hi Liang,
>>> liang.yang@amlogic.com wrote on Thu, 6 Jan 2022 11:25:04 +0800:
>>>
>>>> Because EMMC and NAND have the same control clock register, so we
>>>> implement a 'sd_emmc_c_clkc'. Previously DTS is defined as below:
>>>>
>>>> 	sd_emmc_c_clkc: mmc@7000 {
>>>> 		compatible = "amlogic,meson-axg-mmc-clkc", "syscon";
>>>> 		reg = <0x0 0x7000 0x0 0x800>;
>>>> 	};
>>>>
>>>> 	nand-controller@7800 {
>>>> 		......
>>>>
>>>> 		clocks = <&clkc CLKID_SD_EMMC_C>,
>>>> 			<&sd_emmc_c_clkc CLKID_MMC_DIV>,
>>>> 			<&sd_emmc_c_clkc CLKID_MMC_PHASE_RX>,
>>>> 			<&sd_emmc_c_clkc CLKID_MMC_PHASE_TX>;
>>>> 		clock-names = "core", "device", "rx", "tx";
>>>> 		amlogic,mmc-syscon = <&sd_emmc_c_clkc>;
>>>>
>>>> 		......
>>>> 	}
>>>>
>>>> but in fact, above implementation is rejected. so now registering
>>>> a nand_divider.
>>> What is rejected?
>>> Why is it rejected?
>>> What is nand_divider?
>> i simplify our clock framework below, so nand divider is SD_EMMC_CLOCK[5:0]
>> here.
>> 			   -----          -----		    -----
>> 	   the other------|	\        |     |	   |	 |
>>           		  | mux	| -----  |  N  | ----------| NFC/|
>> 	   FCLK_DIV2------|     |        |     |	   | EMMC|
>> 			   -----/         ----- 	    -----
>> 		    SD_EMMC_CLOCK[7:6] SD_EMMC_CLOCK[5:0]
>>>
>>>>
>>>> Change-Id: Ibeb4c7ff886f5886aac4d6c664d7bbd1b1bcb997
>>> Change Ids are not expected in the upstream kernel.
>>> But if you fix something you should have a Fixes:.
>>>
>>>> Signed-off-by: Liang Yang <liang.yang@amlogic.com>
>>>> ---
>>>>    drivers/mtd/nand/raw/meson_nand.c | 88 +++++++++++++++++--------------
>>>>    1 file changed, 49 insertions(+), 39 deletions(-)
>>>>
>>>> diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c
>>>> index ac3be92872d0..4472363059c2 100644
>>>> --- a/drivers/mtd/nand/raw/meson_nand.c
>>>> +++ b/drivers/mtd/nand/raw/meson_nand.c
>>>> @@ -2,7 +2,7 @@
>>>>    /*
>>>>     * Amlogic Meson Nand Flash Controller Driver
>>>>     *
>>>> - * Copyright (c) 2018 Amlogic, inc.
>>>> + * Copyright (c) 2018-2021 Amlogic, inc.
>>>>     * Author: Liang Yang <liang.yang@amlogic.com>
>>>>     */
>>>>    @@ -10,6 +10,7 @@
>>>>    #include <linux/dma-mapping.h>
>>>>    #include <linux/interrupt.h>
>>>>    #include <linux/clk.h>
>>>> +#include <linux/clk-provider.h>
>>>>    #include <linux/mtd/rawnand.h>
>>>>    #include <linux/mtd/mtd.h>
>>>>    #include <linux/mfd/syscon.h>
>>>> @@ -55,6 +56,7 @@
>>>>    #define NFC_REG_VER		0x38
>>>>      #define NFC_RB_IRQ_EN		BIT(21)
>>>> +#define NFC_CMD_FIFO_RESET	BIT(31)
>>>>      #define CMDRWGEN(cmd_dir, ran, bch, short_mode, page_size, pages)
>>>> \
>>>>    	(								\
>>>> @@ -104,6 +106,9 @@
>>>>      #define PER_INFO_BYTE		8
>>>>    +#define CLK_DIV_SHIFT		0
>>>> +#define CLK_DIV_WIDTH		6
>>>> +
>>>>    struct meson_nfc_nand_chip {
>>>>    	struct list_head node;
>>>>    	struct nand_chip nand;
>>>> @@ -151,15 +156,15 @@ struct meson_nfc {
>>>>    	struct nand_controller controller;
>>>>    	struct clk *core_clk;
>>>>    	struct clk *device_clk;
>>>> -	struct clk *phase_tx;
>>>> -	struct clk *phase_rx;
>>>> +	struct clk *nand_clk;
>>>> +	struct clk_divider nand_divider;
>>>>      	unsigned long clk_rate;
>>>>    	u32 bus_timing;
>>>>      	struct device *dev;
>>>>    	void __iomem *reg_base;
>>>> -	struct regmap *reg_clk;
>>>> +	void __iomem *reg_clk;
>>>>    	struct completion completion;
>>>>    	struct list_head chips;
>>>>    	const struct meson_nfc_data *data;
>>>> @@ -406,12 +411,14 @@ static int meson_nfc_queue_rb(struct meson_nfc *nfc, int timeout_ms)
>>>>    	cmd = NFC_CMD_RB | NFC_CMD_RB_INT
>>>>    		| nfc->param.chip_select | nfc->timing.tbers_max;
>>>>    	writel(cmd, nfc->reg_base + NFC_REG_CMD);
>>>> -
>>>> +	meson_nfc_drain_cmd(nfc);
>>>>    	ret = wait_for_completion_timeout(&nfc->completion,
>>>>    					  msecs_to_jiffies(timeout_ms));
>>>>    	if (ret == 0)
>>>>    		ret = -1;
>>>>    +	/* reset command fifo to avoid lock */
>>>> +	writel(NFC_CMD_FIFO_RESET, nfc->reg_base + NFC_REG_CMD);
>>>>    	return ret;
>>>>    }
>>>>    @@ -988,8 +995,9 @@ static const struct mtd_ooblayout_ops
>>>> meson_ooblayout_ops = {
>>>>    static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>>    {
>>>>    	int ret;
>>>> +	struct clk_init_data init = {0};
>>>> +	const char *fix_div2_pll_name[1];
>>>>    -	/* request core clock */
>>>>    	nfc->core_clk = devm_clk_get(nfc->dev, "core");
>>>>    	if (IS_ERR(nfc->core_clk)) {
>>>>    		dev_err(nfc->dev, "failed to get core clock\n");
>>>> @@ -1002,21 +1010,25 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>>    		return PTR_ERR(nfc->device_clk);
>>>>    	}
>>>>    -	nfc->phase_tx = devm_clk_get(nfc->dev, "tx");
>>>> -	if (IS_ERR(nfc->phase_tx)) {
>>>> -		dev_err(nfc->dev, "failed to get TX clk\n");
>>>> -		return PTR_ERR(nfc->phase_tx);
>>>> -	}
>>>> -
>>>> -	nfc->phase_rx = devm_clk_get(nfc->dev, "rx");
>>>> -	if (IS_ERR(nfc->phase_rx)) {
>>>> -		dev_err(nfc->dev, "failed to get RX clk\n");
>>>> -		return PTR_ERR(nfc->phase_rx);
>>>> -	}
>>>> +	init.name = devm_kstrdup(nfc->dev, "nfc#div", GFP_KERNEL);
>>>> +	init.ops = &clk_divider_ops;
>>>> +	fix_div2_pll_name[0] = __clk_get_name(nfc->device_clk);
>>>> +	init.parent_names = fix_div2_pll_name;
>>>> +	init.num_parents = 1;
>>>> +	nfc->nand_divider.reg = nfc->reg_clk;
>>>> +	nfc->nand_divider.shift = CLK_DIV_SHIFT;
>>>> +	nfc->nand_divider.width = CLK_DIV_WIDTH;
>>>> +	nfc->nand_divider.hw.init = &init;
>>>> +	nfc->nand_divider.flags = CLK_DIVIDER_ONE_BASED |
>>>> +				  CLK_DIVIDER_ROUND_CLOSEST |
>>>> +          			  CLK_DIVIDER_ALLOW_ZERO;
>>>> +
>>>> +	nfc->nand_clk = devm_clk_register(nfc->dev, &nfc->nand_divider.hw);
>>>> +	if (IS_ERR(nfc->nand_clk))
>>>> +		return PTR_ERR(nfc->nand_clk);
>>>>      	/* init SD_EMMC_CLOCK to sane defaults w/min clock rate */
>>>> -	regmap_update_bits(nfc->reg_clk,
>>>> -			   0, CLK_SELECT_NAND, CLK_SELECT_NAND);
>>>> +	writel(CLK_SELECT_NAND | readl(nfc->reg_clk), nfc->reg_clk);
>>>>      	ret = clk_prepare_enable(nfc->core_clk);
>>>>    	if (ret) {
>>>> @@ -1030,29 +1042,21 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>>    		goto err_device_clk;
>>>>    	}
>>>>    -	ret = clk_prepare_enable(nfc->phase_tx);
>>>> +	ret = clk_prepare_enable(nfc->nand_clk);
>>>>    	if (ret) {
>>>> -		dev_err(nfc->dev, "failed to enable TX clock\n");
>>>> -		goto err_phase_tx;
>>>> -	}
>>>> -
>>>> -	ret = clk_prepare_enable(nfc->phase_rx);
>>>> -	if (ret) {
>>>> -		dev_err(nfc->dev, "failed to enable RX clock\n");
>>>> -		goto err_phase_rx;
>>>> +		dev_err(nfc->dev, "pre enable NFC divider fail\n");
>>>> +		goto err_nand_clk;
>>>>    	}
>>>>      	ret = clk_set_rate(nfc->device_clk, 24000000);
>>>>    	if (ret)
>>>> -		goto err_disable_rx;
>>>> +		goto err_disable_clk;
>>>>      	return 0;
>>>>    -err_disable_rx:
>>>> -	clk_disable_unprepare(nfc->phase_rx);
>>>> -err_phase_rx:
>>>> -	clk_disable_unprepare(nfc->phase_tx);
>>>> -err_phase_tx:
>>>> +err_disable_clk:
>>>> +	clk_disable_unprepare(nfc->nand_clk);
>>>> +err_nand_clk:
>>>>    	clk_disable_unprepare(nfc->device_clk);
>>>>    err_device_clk:
>>>>    	clk_disable_unprepare(nfc->core_clk);
>>>> @@ -1061,8 +1065,7 @@ static int meson_nfc_clk_init(struct meson_nfc *nfc)
>>>>      static void meson_nfc_disable_clk(struct meson_nfc *nfc)
>>>>    {
>>>> -	clk_disable_unprepare(nfc->phase_rx);
>>>> -	clk_disable_unprepare(nfc->phase_tx);
>>>> +	clk_disable_unprepare(nfc->nand_clk);
>>>>    	clk_disable_unprepare(nfc->device_clk);
>>>>    	clk_disable_unprepare(nfc->core_clk);
>>>>    }
>>>> @@ -1375,6 +1378,7 @@ static int meson_nfc_probe(struct platform_device *pdev)
>>>>    	struct device *dev = &pdev->dev;
>>>>    	struct meson_nfc *nfc;
>>>>    	struct resource *res;
>>>> +	u32 ext_clk_reg;
>>>>    	int ret, irq;
>>>>      	nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL);
>>>> @@ -1396,9 +1400,15 @@ static int meson_nfc_probe(struct platform_device *pdev)
>>>>    	if (IS_ERR(nfc->reg_base))
>>>>    		return PTR_ERR(nfc->reg_base);
>>>>    -	nfc->reg_clk =
>>>> -		syscon_regmap_lookup_by_phandle(dev->of_node,
>>>> -						"amlogic,mmc-syscon");
>>>> +	ret = of_property_read_u32(pdev->dev.of_node,
>>>> +				   "sd_emmc_c_clkc",
>>>> +				   &ext_clk_reg);
>>>> +	if (ret) {
>>>> +		dev_err(dev, "failed to get NAND external clock register\n");
>>>> +		return ret;
>>>> +	}
>>>> +
>>>> +	nfc->reg_clk = devm_ioremap(&pdev->dev, ext_clk_reg, sizeof(int));
>>>>    	if (IS_ERR(nfc->reg_clk)) {
>>>>    		dev_err(dev, "Failed to lookup clock base\n");
>>>>    		return PTR_ERR(nfc->reg_clk);
>>>
>>> Thanks,
>>> Miquèl
>>> .
> 
> .

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

end of thread, other threads:[~2022-01-10  3:34 UTC | newest]

Thread overview: 47+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-01-06  3:25 [PATCH] mtd: rawnand: meson: fix the clock after discarding sd_emmc_c_clkc Liang Yang
2022-01-06  3:25 ` Liang Yang
2022-01-06  3:25 ` Liang Yang
2022-01-06  3:25 ` Liang Yang
2022-01-06  8:08 ` Miquel Raynal
2022-01-06  8:08   ` Miquel Raynal
2022-01-06  8:08   ` Miquel Raynal
2022-01-06  8:08   ` Miquel Raynal
2022-01-07  2:40   ` Liang Yang
2022-01-07  2:40     ` Liang Yang
2022-01-07  2:40     ` Liang Yang
2022-01-07  2:40     ` Liang Yang
2022-01-07  4:08     ` Liang Yang
2022-01-07  4:08       ` Liang Yang
2022-01-07  4:08       ` Liang Yang
2022-01-07  4:08       ` Liang Yang
2022-01-07  7:54     ` Jerome Brunet
2022-01-07  7:54       ` Jerome Brunet
2022-01-07  7:54       ` Jerome Brunet
2022-01-07  7:54       ` Jerome Brunet
2022-01-10  3:32       ` Liang Yang
2022-01-10  3:32         ` Liang Yang
2022-01-10  3:32         ` Liang Yang
2022-01-10  3:32         ` Liang Yang
2022-01-06  8:16 ` Jerome Brunet
2022-01-06  8:16   ` Jerome Brunet
2022-01-06  8:16   ` Jerome Brunet
2022-01-06  8:16   ` Jerome Brunet
2022-01-07  4:04   ` Liang Yang
2022-01-07  4:04     ` Liang Yang
2022-01-07  4:04     ` Liang Yang
2022-01-07  4:04     ` Liang Yang
2022-01-07  9:57     ` Neil Armstrong
2022-01-07  9:57       ` Neil Armstrong
2022-01-07  9:57       ` Neil Armstrong
2022-01-07  9:57       ` Neil Armstrong
2022-01-10  3:28       ` Liang Yang
2022-01-10  3:28         ` Liang Yang
2022-01-10  3:28         ` Liang Yang
2022-01-10  3:28         ` Liang Yang
2022-01-06 14:03 ` kernel test robot
2022-01-06 14:03   ` kernel test robot
2022-01-06 20:40 ` kernel test robot
2022-01-06 20:40   ` kernel test robot
2022-01-06 20:40   ` kernel test robot
2022-01-06 21:21 ` kernel test robot
2022-01-06 21:21   ` kernel test robot

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.