All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 0/8] zynq: clk: Move zynq platform to clock framework
@ 2017-01-04 12:27 stefan.herbrechtsmeier at weidmueller.com
  2017-01-04 12:27 ` [U-Boot] [PATCH 1/8] net: zynq: Don't overwrite gem_rclk_ctrl with default value stefan.herbrechtsmeier at weidmueller.com
                   ` (7 more replies)
  0 siblings, 8 replies; 29+ messages in thread
From: stefan.herbrechtsmeier at weidmueller.com @ 2017-01-04 12:27 UTC (permalink / raw)
  To: u-boot

From: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>


The old platform clock driver use a dynamic array which is filled at
every boot with static clock tree information and unused clock rates.
This needs much memory and complicates the strip down for the SPL.
The new clock framework driver contains the tree information in
functions and reads clock rates on demand.


Stefan Herbrechtsmeier (8):
  net: zynq: Don't overwrite gem_rclk_ctrl with default value
  net: zynq: Add clk framework support to zynq ethernet driver
  zynq: Add clk framework support to zynq timer
  zynq: Move static clock names into separate array
  zynq: Remove zynq_clk_get_name function
  clk: zynq: Add zynq clock framework driver
  zynq: Move zynq to clock framework
  clk: zynq: Add optional ethernet emio clock source support

 arch/arm/Kconfig                             |   2 +
 arch/arm/dts/zynq-7000.dtsi                  |   2 +
 arch/arm/include/asm/arch-zynqmp/sys_proto.h |   5 -
 arch/arm/mach-zynq/clk.c                     | 687 +++------------------------
 arch/arm/mach-zynq/cpu.c                     |   1 -
 arch/arm/mach-zynq/include/mach/clk.h        |   6 -
 arch/arm/mach-zynq/include/mach/sys_proto.h  |   1 -
 arch/arm/mach-zynq/slcr.c                    |  29 --
 arch/arm/mach-zynq/timer.c                   |  23 +
 drivers/clk/Kconfig                          |   7 +
 drivers/clk/Makefile                         |   1 +
 drivers/clk/clk_zynq.c                       | 499 +++++++++++++++++++
 drivers/net/zynq_gem.c                       |  27 +-
 drivers/serial/serial_zynq.c                 |   6 +-
 include/configs/topic_miami.h                |   2 -
 include/configs/zynq_zybo.h                  |   3 -
 scripts/config_whitelist.txt                 |   1 -
 17 files changed, 618 insertions(+), 684 deletions(-)
 create mode 100644 drivers/clk/clk_zynq.c

-- 
2.7.4



Kommanditgesellschaft - Sitz: Detmold - Amtsgericht Lemgo HRA 2790 - 
Komplement?rin: Weidm?ller Interface F?hrungsgesellschaft mbH - 
Sitz: Detmold - Amtsgericht Lemgo HRB 3924; 
Gesch?ftsf?hrer: Jos? Carlos ?lvarez Tobar, Elke Eckstein, Dr. Peter K?hler, J?rg Timmermann;
USt-ID-Nr. DE124599660

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

* [U-Boot] [PATCH 1/8] net: zynq: Don't overwrite gem_rclk_ctrl with default value
  2017-01-04 12:27 [U-Boot] [PATCH 0/8] zynq: clk: Move zynq platform to clock framework stefan.herbrechtsmeier at weidmueller.com
@ 2017-01-04 12:27 ` stefan.herbrechtsmeier at weidmueller.com
  2017-01-10 13:52   ` Michal Simek
  2017-01-04 12:27 ` [U-Boot] [PATCH 2/8] net: zynq: Add clk framework support to zynq ethernet driver stefan.herbrechtsmeier at weidmueller.com
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 29+ messages in thread
From: stefan.herbrechtsmeier at weidmueller.com @ 2017-01-04 12:27 UTC (permalink / raw)
  To: u-boot

From: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.de>

The gem[0-1]_rclk_ctrl registers control the source of the rx clock,
control and data signals and configure via ps7_init function. Don't
overwrite the register with the default value.

Signed-off-by: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
---

 arch/arm/mach-zynq/slcr.c | 7 -------
 drivers/net/zynq_gem.c    | 9 ++-------
 2 files changed, 2 insertions(+), 14 deletions(-)

diff --git a/arch/arm/mach-zynq/slcr.c b/arch/arm/mach-zynq/slcr.c
index 2d3bf2a..c1129cd 100644
--- a/arch/arm/mach-zynq/slcr.c
+++ b/arch/arm/mach-zynq/slcr.c
@@ -140,13 +140,6 @@ void zynq_slcr_gem_clk_setup(u32 gem_id, unsigned long clk_rate)
 	if (ret)
 		goto out;
 
-	if (gem_id) {
-		/* Configure GEM_RCLK_CTRL */
-		writel(1, &slcr_base->gem1_rclk_ctrl);
-	} else {
-		/* Configure GEM_RCLK_CTRL */
-		writel(1, &slcr_base->gem0_rclk_ctrl);
-	}
 	udelay(100000);
 out:
 	zynq_slcr_lock();
diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c
index d2e5e7c..9bfb89f 100644
--- a/drivers/net/zynq_gem.c
+++ b/drivers/net/zynq_gem.c
@@ -174,7 +174,6 @@ struct zynq_gem_priv {
 	u32 rxbd_current;
 	u32 rx_first_buf;
 	int phyaddr;
-	u32 emio;
 	int init;
 	struct zynq_gem_regs *iobase;
 	phy_interface_t interface;
@@ -467,10 +466,8 @@ static int zynq_gem_init(struct udevice *dev)
 		break;
 	}
 
-	/* Change the rclk and clk only not using EMIO interface */
-	if (!priv->emio)
-		zynq_slcr_gem_clk_setup((ulong)priv->iobase !=
-					ZYNQ_GEM_BASEADDR0, clk_rate);
+	zynq_slcr_gem_clk_setup((ulong)priv->iobase !=
+				ZYNQ_GEM_BASEADDR0, clk_rate);
 
 	setbits_le32(&regs->nwctrl, ZYNQ_GEM_NWCTRL_RXEN_MASK |
 					ZYNQ_GEM_NWCTRL_TXEN_MASK);
@@ -685,7 +682,6 @@ static int zynq_gem_ofdata_to_platdata(struct udevice *dev)
 	pdata->iobase = (phys_addr_t)dev_get_addr(dev);
 	priv->iobase = (struct zynq_gem_regs *)pdata->iobase;
 	/* Hardcode for now */
-	priv->emio = 0;
 	priv->phyaddr = -1;
 
 	priv->phy_of_handle = fdtdec_lookup_phandle(gd->fdt_blob,
@@ -703,7 +699,6 @@ static int zynq_gem_ofdata_to_platdata(struct udevice *dev)
 	}
 	priv->interface = pdata->phy_interface;
 
-	priv->emio = fdtdec_get_bool(gd->fdt_blob, dev->of_offset, "xlnx,emio");
 
 	printf("ZYNQ GEM: %lx, phyaddr %x, interface %s\n", (ulong)priv->iobase,
 	       priv->phyaddr, phy_string_for_interface(priv->interface));
-- 
2.7.4



Kommanditgesellschaft - Sitz: Detmold - Amtsgericht Lemgo HRA 2790 - 
Komplement?rin: Weidm?ller Interface F?hrungsgesellschaft mbH - 
Sitz: Detmold - Amtsgericht Lemgo HRB 3924; 
Gesch?ftsf?hrer: Jos? Carlos ?lvarez Tobar, Elke Eckstein, Dr. Peter K?hler, J?rg Timmermann;
USt-ID-Nr. DE124599660

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

* [U-Boot] [PATCH 2/8] net: zynq: Add clk framework support to zynq ethernet driver
  2017-01-04 12:27 [U-Boot] [PATCH 0/8] zynq: clk: Move zynq platform to clock framework stefan.herbrechtsmeier at weidmueller.com
  2017-01-04 12:27 ` [U-Boot] [PATCH 1/8] net: zynq: Don't overwrite gem_rclk_ctrl with default value stefan.herbrechtsmeier at weidmueller.com
@ 2017-01-04 12:27 ` stefan.herbrechtsmeier at weidmueller.com
  2017-01-10 13:58   ` Michal Simek
  2017-01-04 12:27 ` [U-Boot] [PATCH 3/8] zynq: Add clk framework support to zynq timer stefan.herbrechtsmeier at weidmueller.com
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 29+ messages in thread
From: stefan.herbrechtsmeier at weidmueller.com @ 2017-01-04 12:27 UTC (permalink / raw)
  To: u-boot

From: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.de>

If available use the clock framework to set the tx clock rate of the
zynq ethernet controller.

Signed-off-by: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
---

 arch/arm/include/asm/arch-zynqmp/sys_proto.h |  5 -----
 drivers/net/zynq_gem.c                       | 31 ++++++++++++++++++++++++++++
 2 files changed, 31 insertions(+), 5 deletions(-)

diff --git a/arch/arm/include/asm/arch-zynqmp/sys_proto.h b/arch/arm/include/asm/arch-zynqmp/sys_proto.h
index 1db2bd6..bd633a6 100644
--- a/arch/arm/include/asm/arch-zynqmp/sys_proto.h
+++ b/arch/arm/include/asm/arch-zynqmp/sys_proto.h
@@ -8,11 +8,6 @@
 #ifndef _ASM_ARCH_SYS_PROTO_H
 #define _ASM_ARCH_SYS_PROTO_H
 
-/* Setup clk for network */
-static inline void zynq_slcr_gem_clk_setup(u32 gem_id, unsigned long clk_rate)
-{
-}
-
 int zynq_slcr_get_mio_pin_status(const char *periph);
 
 unsigned int zynqmp_get_silicon_version(void);
diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c
index 9bfb89f..9118e49 100644
--- a/drivers/net/zynq_gem.c
+++ b/drivers/net/zynq_gem.c
@@ -9,6 +9,7 @@
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
+#include <clk.h>
 #include <common.h>
 #include <dm.h>
 #include <net.h>
@@ -180,6 +181,9 @@ struct zynq_gem_priv {
 	struct phy_device *phydev;
 	int phy_of_handle;
 	struct mii_dev *bus;
+#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
+	struct clk tx_clk;
+#endif
 };
 
 static inline int mdio_wait(struct zynq_gem_regs *regs)
@@ -364,6 +368,9 @@ static int zynq_gem_init(struct udevice *dev)
 	u32 i, nwconfig;
 	int ret;
 	unsigned long clk_rate = 0;
+#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
+	unsigned long clk_rate_rounded;
+#endif
 	struct zynq_gem_priv *priv = dev_get_priv(dev);
 	struct zynq_gem_regs *regs = priv->iobase;
 	struct emac_bd *dummy_tx_bd = &priv->tx_bd[TX_FREE_DESC];
@@ -466,8 +473,22 @@ static int zynq_gem_init(struct udevice *dev)
 		break;
 	}
 
+#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
+	clk_rate_rounded = clk_set_rate(&priv->tx_clk, clk_rate);
+	if (IS_ERR_VALUE(clk_rate_rounded)) {
+		dev_err(dev, "failed to set tx clock rate\n");
+		return clk_rate_rounded;
+	}
+
+	ret = clk_enable(&priv->tx_clk);
+	if (ret && ret != -ENOSYS) {
+		dev_err(dev, "failed to enable tx clock\n");
+		return ret;
+	}
+#else
 	zynq_slcr_gem_clk_setup((ulong)priv->iobase !=
 				ZYNQ_GEM_BASEADDR0, clk_rate);
+#endif
 
 	setbits_le32(&regs->nwctrl, ZYNQ_GEM_NWCTRL_RXEN_MASK |
 					ZYNQ_GEM_NWCTRL_TXEN_MASK);
@@ -678,6 +699,9 @@ static int zynq_gem_ofdata_to_platdata(struct udevice *dev)
 	struct eth_pdata *pdata = dev_get_platdata(dev);
 	struct zynq_gem_priv *priv = dev_get_priv(dev);
 	const char *phy_mode;
+#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
+	int ret;
+#endif
 
 	pdata->iobase = (phys_addr_t)dev_get_addr(dev);
 	priv->iobase = (struct zynq_gem_regs *)pdata->iobase;
@@ -699,6 +723,13 @@ static int zynq_gem_ofdata_to_platdata(struct udevice *dev)
 	}
 	priv->interface = pdata->phy_interface;
 
+#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
+	ret = clk_get_by_index(dev, 2, &priv->tx_clk);
+	if (ret < 0) {
+		dev_err(dev, "failed to get clock\n");
+		return ret;
+	}
+#endif
 
 	printf("ZYNQ GEM: %lx, phyaddr %x, interface %s\n", (ulong)priv->iobase,
 	       priv->phyaddr, phy_string_for_interface(priv->interface));
-- 
2.7.4



Kommanditgesellschaft - Sitz: Detmold - Amtsgericht Lemgo HRA 2790 - 
Komplement?rin: Weidm?ller Interface F?hrungsgesellschaft mbH - 
Sitz: Detmold - Amtsgericht Lemgo HRB 3924; 
Gesch?ftsf?hrer: Jos? Carlos ?lvarez Tobar, Elke Eckstein, Dr. Peter K?hler, J?rg Timmermann;
USt-ID-Nr. DE124599660

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

* [U-Boot] [PATCH 3/8] zynq: Add clk framework support to zynq timer
  2017-01-04 12:27 [U-Boot] [PATCH 0/8] zynq: clk: Move zynq platform to clock framework stefan.herbrechtsmeier at weidmueller.com
  2017-01-04 12:27 ` [U-Boot] [PATCH 1/8] net: zynq: Don't overwrite gem_rclk_ctrl with default value stefan.herbrechtsmeier at weidmueller.com
  2017-01-04 12:27 ` [U-Boot] [PATCH 2/8] net: zynq: Add clk framework support to zynq ethernet driver stefan.herbrechtsmeier at weidmueller.com
@ 2017-01-04 12:27 ` stefan.herbrechtsmeier at weidmueller.com
  2017-01-10 14:10   ` Michal Simek
  2017-01-04 12:27 ` [U-Boot] [PATCH 4/8] zynq: Move static clock names into separate array stefan.herbrechtsmeier at weidmueller.com
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 29+ messages in thread
From: stefan.herbrechtsmeier at weidmueller.com @ 2017-01-04 12:27 UTC (permalink / raw)
  To: u-boot

From: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>

If available use the clock framework to calculate the clock rate of the
zynq timer.

Signed-off-by: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
---

 arch/arm/mach-zynq/timer.c | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/arch/arm/mach-zynq/timer.c b/arch/arm/mach-zynq/timer.c
index 8ff82dc..0335cbe 100644
--- a/arch/arm/mach-zynq/timer.c
+++ b/arch/arm/mach-zynq/timer.c
@@ -1,4 +1,7 @@
 /*
+ * Copyright (C) 2017 Weidm?ller Interface GmbH & Co. KG
+ * Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
+ *
  * Copyright (C) 2012 Michal Simek <monstr@monstr.eu>
  * Copyright (C) 2011-2012 Xilinx, Inc. All rights reserved.
  *
@@ -25,8 +28,10 @@
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
+#include <clk.h>
 #include <common.h>
 #include <div64.h>
+#include <dm.h>
 #include <asm/io.h>
 #include <asm/arch/hardware.h>
 #include <asm/arch/clk.h>
@@ -56,6 +61,26 @@ int timer_init(void)
 			(TIMER_PRESCALE << SCUTIMER_CONTROL_PRESCALER_SHIFT) |
 			SCUTIMER_CONTROL_ENABLE_MASK;
 
+#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
+	struct udevice *dev;
+	struct clk clk;
+	int ret;
+
+	ret = uclass_get_device_by_driver(UCLASS_CLK,
+		DM_GET_DRIVER(zynq_clk), &dev);
+	if (ret)
+		return ret;
+
+	clk.id = cpu_6or4x_clk;
+	ret = clk_request(dev, &clk);
+	if (ret < 0)
+		return ret;
+
+	gd->cpu_clk = clk_get_rate(&clk);
+
+	clk_free(&clk);
+#endif
+
 	gd->arch.timer_rate_hz = (gd->cpu_clk / 2) / (TIMER_PRESCALE + 1);
 
 	/* Load the timer counter register */
-- 
2.7.4



Kommanditgesellschaft - Sitz: Detmold - Amtsgericht Lemgo HRA 2790 - 
Komplement?rin: Weidm?ller Interface F?hrungsgesellschaft mbH - 
Sitz: Detmold - Amtsgericht Lemgo HRB 3924; 
Gesch?ftsf?hrer: Jos? Carlos ?lvarez Tobar, Elke Eckstein, Dr. Peter K?hler, J?rg Timmermann;
USt-ID-Nr. DE124599660

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

* [U-Boot] [PATCH 4/8] zynq: Move static clock names into separate array
  2017-01-04 12:27 [U-Boot] [PATCH 0/8] zynq: clk: Move zynq platform to clock framework stefan.herbrechtsmeier at weidmueller.com
                   ` (2 preceding siblings ...)
  2017-01-04 12:27 ` [U-Boot] [PATCH 3/8] zynq: Add clk framework support to zynq timer stefan.herbrechtsmeier at weidmueller.com
@ 2017-01-04 12:27 ` stefan.herbrechtsmeier at weidmueller.com
  2017-01-10 14:15   ` Michal Simek
  2017-01-04 12:27 ` [U-Boot] [PATCH 5/8] zynq: Remove zynq_clk_get_name function stefan.herbrechtsmeier at weidmueller.com
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 29+ messages in thread
From: stefan.herbrechtsmeier at weidmueller.com @ 2017-01-04 12:27 UTC (permalink / raw)
  To: u-boot

From: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.de>

The clock names are static and correspond to the clock id. Separate
them from the dynamic filled clock array.

Signed-off-by: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
---

 arch/arm/mach-zynq/clk.c | 121 +++++++++++++++++++++++------------------------
 1 file changed, 60 insertions(+), 61 deletions(-)

diff --git a/arch/arm/mach-zynq/clk.c b/arch/arm/mach-zynq/clk.c
index 40383c1..7bff964 100644
--- a/arch/arm/mach-zynq/clk.c
+++ b/arch/arm/mach-zynq/clk.c
@@ -58,7 +58,6 @@ struct zynq_clk_ops {
 
 /**
  * struct clk:
- * @name:	Clock name
  * @frequency:	Currenct frequency
  * @parent:	Parent clock
  * @flags:	Clock flags
@@ -66,7 +65,6 @@ struct zynq_clk_ops {
  * @ops:	Clock operations
  */
 struct clk {
-	char		*name;
 	unsigned long	frequency;
 	enum zynq_clk	parent;
 	unsigned int	flags;
@@ -77,6 +75,20 @@ struct clk {
 
 static struct clk clks[clk_max];
 
+static const char * const clk_names[clk_max] = {
+	"armpll", "ddrpll", "iopll",
+	"cpu_6or4x", "cpu_3or2x", "cpu_2x", "cpu_1x",
+	"ddr2x", "ddr3x", "dci",
+	"lqspi", "smc", "pcap", "gem0", "gem1",
+	"fclk0", "fclk1", "fclk2", "fclk3", "can0", "can1",
+	"sdio0", "sdio1", "uart0", "uart1", "spi0", "spi1", "dma",
+	"usb0_aper", "usb1_aper", "gem0_aper", "gem1_aper",
+	"sdio0_aper", "sdio1_aper", "spi0_aper", "spi1_aper",
+	"can0_aper", "can1_aper", "i2c0_aper", "i2c1_aper",
+	"uart0_aper", "uart1_aper", "gpio_aper", "lqspi_aper",
+	"smc_aper", "swdt", "dbg_trc", "dbg_apb"
+};
+
 /**
  * __zynq_clk_cpu_get_parent() - Decode clock multiplexer
  * @srcsel:	Mux select value
@@ -140,14 +152,12 @@ static void init_ddr_clocks(void)
 	/* DDR2x */
 	clks[ddr2x_clk].reg = &slcr_base->ddr_clk_ctrl;
 	clks[ddr2x_clk].parent = ddrpll_clk;
-	clks[ddr2x_clk].name = "ddr_2x";
 	clks[ddr2x_clk].frequency = ddr2x_get_rate(&clks[ddr2x_clk]);
 	clks[ddr2x_clk].ops.get_rate = ddr2x_get_rate;
 
 	/* DDR3x */
 	clks[ddr3x_clk].reg = &slcr_base->ddr_clk_ctrl;
 	clks[ddr3x_clk].parent = ddrpll_clk;
-	clks[ddr3x_clk].name = "ddr_3x";
 	clks[ddr3x_clk].frequency = ddr3x_get_rate(&clks[ddr3x_clk]);
 	clks[ddr3x_clk].ops.get_rate = ddr3x_get_rate;
 
@@ -159,7 +169,6 @@ static void init_ddr_clocks(void)
 	clks[dci_clk].parent = ddrpll_clk;
 	clks[dci_clk].frequency = DIV_ROUND_CLOSEST(
 			DIV_ROUND_CLOSEST(prate, div0), div1);
-	clks[dci_clk].name = "dci";
 
 	gd->bd->bi_ddr_freq = clks[ddr3x_clk].frequency / 1000000;
 }
@@ -181,24 +190,20 @@ static void init_cpu_clocks(void)
 	clks[cpu_6or4x_clk].parent = parent;
 	clks[cpu_6or4x_clk].frequency = DIV_ROUND_CLOSEST(
 			zynq_clk_get_rate(parent), div);
-	clks[cpu_6or4x_clk].name = "cpu_6or4x";
 
 	clks[cpu_3or2x_clk].reg = &slcr_base->arm_clk_ctrl;
 	clks[cpu_3or2x_clk].parent = cpu_6or4x_clk;
 	clks[cpu_3or2x_clk].frequency = zynq_clk_get_rate(cpu_6or4x_clk) / 2;
-	clks[cpu_3or2x_clk].name = "cpu_3or2x";
 
 	clks[cpu_2x_clk].reg = &slcr_base->arm_clk_ctrl;
 	clks[cpu_2x_clk].parent = cpu_6or4x_clk;
 	clks[cpu_2x_clk].frequency = zynq_clk_get_rate(cpu_6or4x_clk) /
 			(2 + clk_621);
-	clks[cpu_2x_clk].name = "cpu_2x";
 
 	clks[cpu_1x_clk].reg = &slcr_base->arm_clk_ctrl;
 	clks[cpu_1x_clk].parent = cpu_6or4x_clk;
 	clks[cpu_1x_clk].frequency = zynq_clk_get_rate(cpu_6or4x_clk) /
 			(4 + 2 * clk_621);
-	clks[cpu_1x_clk].name = "cpu_1x";
 }
 
 /**
@@ -338,13 +343,11 @@ static enum zynq_clk zynq_clk_periph_get_parent(struct clk *clk)
  * zynq_clk_register_periph_clk() - Set up a peripheral clock with the framework
  * @clk:	Pointer to struct clk for the clock
  * @ctrl:	Clock control register
- * @name:	PLL name
  * @two_divs:	Indicates whether the clock features one or two dividers
  */
-static int zynq_clk_register_periph_clk(struct clk *clk, u32 *ctrl, char *name,
+static int zynq_clk_register_periph_clk(struct clk *clk, u32 *ctrl,
 		bool two_divs)
 {
-	clk->name = name;
 	clk->reg = ctrl;
 	if (two_divs)
 		clk->flags = ZYNQ_CLK_FLAGS_HAS_2_DIVS;
@@ -358,59 +361,57 @@ static int zynq_clk_register_periph_clk(struct clk *clk, u32 *ctrl, char *name,
 
 static void init_periph_clocks(void)
 {
-	zynq_clk_register_periph_clk(&clks[gem0_clk], &slcr_base->gem0_clk_ctrl,
-				     "gem0", 1);
-	zynq_clk_register_periph_clk(&clks[gem1_clk], &slcr_base->gem1_clk_ctrl,
-				     "gem1", 1);
+	zynq_clk_register_periph_clk(&clks[gem0_clk],
+				     &slcr_base->gem0_clk_ctrl, 1);
+	zynq_clk_register_periph_clk(&clks[gem1_clk],
+				     &slcr_base->gem1_clk_ctrl, 1);
 
-	zynq_clk_register_periph_clk(&clks[smc_clk], &slcr_base->smc_clk_ctrl,
-				     "smc", 0);
+	zynq_clk_register_periph_clk(&clks[smc_clk],
+				     &slcr_base->smc_clk_ctrl, 0);
 
 	zynq_clk_register_periph_clk(&clks[lqspi_clk],
-				     &slcr_base->lqspi_clk_ctrl, "lqspi", 0);
+				     &slcr_base->lqspi_clk_ctrl, 0);
 
 	zynq_clk_register_periph_clk(&clks[sdio0_clk],
-				     &slcr_base->sdio_clk_ctrl, "sdio0", 0);
+				     &slcr_base->sdio_clk_ctrl, 0);
 	zynq_clk_register_periph_clk(&clks[sdio1_clk],
-				     &slcr_base->sdio_clk_ctrl, "sdio1", 0);
+				     &slcr_base->sdio_clk_ctrl, 0);
 
-	zynq_clk_register_periph_clk(&clks[spi0_clk], &slcr_base->spi_clk_ctrl,
-				     "spi0", 0);
-	zynq_clk_register_periph_clk(&clks[spi1_clk], &slcr_base->spi_clk_ctrl,
-				     "spi1", 0);
+	zynq_clk_register_periph_clk(&clks[spi0_clk],
+				     &slcr_base->spi_clk_ctrl, 0);
+	zynq_clk_register_periph_clk(&clks[spi1_clk],
+				     &slcr_base->spi_clk_ctrl, 0);
 
 	zynq_clk_register_periph_clk(&clks[uart0_clk],
-				     &slcr_base->uart_clk_ctrl, "uart0", 0);
+				     &slcr_base->uart_clk_ctrl, 0);
 	zynq_clk_register_periph_clk(&clks[uart1_clk],
-				     &slcr_base->uart_clk_ctrl, "uart1", 0);
+				     &slcr_base->uart_clk_ctrl, 0);
 
 	zynq_clk_register_periph_clk(&clks[dbg_trc_clk],
-				     &slcr_base->dbg_clk_ctrl, "dbg_trc", 0);
+				     &slcr_base->dbg_clk_ctrl, 0);
 	zynq_clk_register_periph_clk(&clks[dbg_apb_clk],
-				     &slcr_base->dbg_clk_ctrl, "dbg_apb", 0);
+				     &slcr_base->dbg_clk_ctrl, 0);
 
 	zynq_clk_register_periph_clk(&clks[pcap_clk],
-				     &slcr_base->pcap_clk_ctrl, "pcap", 0);
+				     &slcr_base->pcap_clk_ctrl, 0);
 
 	zynq_clk_register_periph_clk(&clks[fclk0_clk],
-				     &slcr_base->fpga0_clk_ctrl, "fclk0", 1);
+				     &slcr_base->fpga0_clk_ctrl, 1);
 	zynq_clk_register_periph_clk(&clks[fclk1_clk],
-				     &slcr_base->fpga1_clk_ctrl, "fclk1", 1);
+				     &slcr_base->fpga1_clk_ctrl, 1);
 	zynq_clk_register_periph_clk(&clks[fclk2_clk],
-				     &slcr_base->fpga2_clk_ctrl, "fclk2", 1);
+				     &slcr_base->fpga2_clk_ctrl, 1);
 	zynq_clk_register_periph_clk(&clks[fclk3_clk],
-				     &slcr_base->fpga3_clk_ctrl, "fclk3", 1);
+				     &slcr_base->fpga3_clk_ctrl, 1);
 }
 
 /**
  * zynq_clk_register_aper_clk() - Set up a APER clock with the framework
  * @clk:	Pointer to struct clk for the clock
  * @ctrl:	Clock control register
- * @name:	PLL name
  */
-static void zynq_clk_register_aper_clk(struct clk *clk, u32 *ctrl, char *name)
+static void zynq_clk_register_aper_clk(struct clk *clk, u32 *ctrl)
 {
-	clk->name = name;
 	clk->reg = ctrl;
 	clk->parent = cpu_1x_clk;
 	clk->frequency = zynq_clk_get_rate(clk->parent);
@@ -419,48 +420,48 @@ static void zynq_clk_register_aper_clk(struct clk *clk, u32 *ctrl, char *name)
 static void init_aper_clocks(void)
 {
 	zynq_clk_register_aper_clk(&clks[usb0_aper_clk],
-				   &slcr_base->aper_clk_ctrl, "usb0_aper");
+				   &slcr_base->aper_clk_ctrl);
 	zynq_clk_register_aper_clk(&clks[usb1_aper_clk],
-				   &slcr_base->aper_clk_ctrl, "usb1_aper");
+				   &slcr_base->aper_clk_ctrl);
 
 	zynq_clk_register_aper_clk(&clks[gem0_aper_clk],
-				   &slcr_base->aper_clk_ctrl, "gem0_aper");
+				   &slcr_base->aper_clk_ctrl);
 	zynq_clk_register_aper_clk(&clks[gem1_aper_clk],
-				   &slcr_base->aper_clk_ctrl, "gem1_aper");
+				   &slcr_base->aper_clk_ctrl);
 
 	zynq_clk_register_aper_clk(&clks[sdio0_aper_clk],
-				   &slcr_base->aper_clk_ctrl, "sdio0_aper");
+				   &slcr_base->aper_clk_ctrl);
 	zynq_clk_register_aper_clk(&clks[sdio1_aper_clk],
-				   &slcr_base->aper_clk_ctrl, "sdio1_aper");
+				   &slcr_base->aper_clk_ctrl);
 
 	zynq_clk_register_aper_clk(&clks[spi0_aper_clk],
-				   &slcr_base->aper_clk_ctrl, "spi0_aper");
+				   &slcr_base->aper_clk_ctrl);
 	zynq_clk_register_aper_clk(&clks[spi1_aper_clk],
-				   &slcr_base->aper_clk_ctrl, "spi1_aper");
+				   &slcr_base->aper_clk_ctrl);
 
 	zynq_clk_register_aper_clk(&clks[can0_aper_clk],
-				   &slcr_base->aper_clk_ctrl, "can0_aper");
+				   &slcr_base->aper_clk_ctrl);
 	zynq_clk_register_aper_clk(&clks[can1_aper_clk],
-				   &slcr_base->aper_clk_ctrl, "can1_aper");
+				   &slcr_base->aper_clk_ctrl);
 
 	zynq_clk_register_aper_clk(&clks[i2c0_aper_clk],
-				   &slcr_base->aper_clk_ctrl, "i2c0_aper");
+				   &slcr_base->aper_clk_ctrl);
 	zynq_clk_register_aper_clk(&clks[i2c1_aper_clk],
-				   &slcr_base->aper_clk_ctrl, "i2c1_aper");
+				   &slcr_base->aper_clk_ctrl);
 
 	zynq_clk_register_aper_clk(&clks[uart0_aper_clk],
-				   &slcr_base->aper_clk_ctrl, "uart0_aper");
+				   &slcr_base->aper_clk_ctrl);
 	zynq_clk_register_aper_clk(&clks[uart1_aper_clk],
-				   &slcr_base->aper_clk_ctrl, "uart1_aper");
+				   &slcr_base->aper_clk_ctrl);
 
 	zynq_clk_register_aper_clk(&clks[gpio_aper_clk],
-				   &slcr_base->aper_clk_ctrl, "gpio_aper");
+				   &slcr_base->aper_clk_ctrl);
 
 	zynq_clk_register_aper_clk(&clks[lqspi_aper_clk],
-				   &slcr_base->aper_clk_ctrl, "lqspi_aper");
+				   &slcr_base->aper_clk_ctrl);
 
 	zynq_clk_register_aper_clk(&clks[smc_aper_clk],
-				   &slcr_base->aper_clk_ctrl, "smc_aper");
+				   &slcr_base->aper_clk_ctrl);
 }
 
 /**
@@ -496,13 +497,11 @@ static unsigned long zynq_clk_pll_get_rate(struct clk *pll)
  * zynq_clk_register_pll() - Set up a PLL with the framework
  * @clk:	Pointer to struct clk for the PLL
  * @ctrl:	PLL control register
- * @name:	PLL name
  * @prate:	PLL input clock rate
  */
-static void zynq_clk_register_pll(struct clk *clk, u32 *ctrl, char *name,
+static void zynq_clk_register_pll(struct clk *clk, u32 *ctrl,
 		unsigned long prate)
 {
-	clk->name = name;
 	clk->reg = ctrl;
 	clk->frequency = zynq_clk_pll_get_rate(clk);
 	clk->ops.get_rate = zynq_clk_pll_get_rate;
@@ -583,11 +582,11 @@ unsigned long get_uart_clk(int dev_index)
 int set_cpu_clk_info(void)
 {
 	zynq_clk_register_pll(&clks[armpll_clk], &slcr_base->arm_pll_ctrl,
-			      "armpll", CONFIG_ZYNQ_PS_CLK_FREQ);
+			      CONFIG_ZYNQ_PS_CLK_FREQ);
 	zynq_clk_register_pll(&clks[ddrpll_clk], &slcr_base->ddr_pll_ctrl,
-			      "ddrpll", CONFIG_ZYNQ_PS_CLK_FREQ);
+			      CONFIG_ZYNQ_PS_CLK_FREQ);
 	zynq_clk_register_pll(&clks[iopll_clk], &slcr_base->io_pll_ctrl,
-			      "iopll", CONFIG_ZYNQ_PS_CLK_FREQ);
+			      CONFIG_ZYNQ_PS_CLK_FREQ);
 
 	init_ddr_clocks();
 	init_cpu_clocks();
@@ -639,7 +638,7 @@ int zynq_clk_set_rate(enum zynq_clk clk, unsigned long rate)
  */
 const char *zynq_clk_get_name(enum zynq_clk clk)
 {
-	return clks[clk].name;
+	return clk_names[clk];
 }
 
 /**
-- 
2.7.4



Kommanditgesellschaft - Sitz: Detmold - Amtsgericht Lemgo HRA 2790 - 
Komplement?rin: Weidm?ller Interface F?hrungsgesellschaft mbH - 
Sitz: Detmold - Amtsgericht Lemgo HRB 3924; 
Gesch?ftsf?hrer: Jos? Carlos ?lvarez Tobar, Elke Eckstein, Dr. Peter K?hler, J?rg Timmermann;
USt-ID-Nr. DE124599660

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

* [U-Boot] [PATCH 5/8] zynq: Remove zynq_clk_get_name function
  2017-01-04 12:27 [U-Boot] [PATCH 0/8] zynq: clk: Move zynq platform to clock framework stefan.herbrechtsmeier at weidmueller.com
                   ` (3 preceding siblings ...)
  2017-01-04 12:27 ` [U-Boot] [PATCH 4/8] zynq: Move static clock names into separate array stefan.herbrechtsmeier at weidmueller.com
@ 2017-01-04 12:27 ` stefan.herbrechtsmeier at weidmueller.com
  2017-01-10 14:16   ` Michal Simek
  2017-01-04 12:27 ` [U-Boot] [PATCH 6/8] clk: zynq: Add zynq clock framework driver stefan.herbrechtsmeier at weidmueller.com
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 29+ messages in thread
From: stefan.herbrechtsmeier at weidmueller.com @ 2017-01-04 12:27 UTC (permalink / raw)
  To: u-boot

From: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>

The zynq_clk_get_name function is only used once inside the clock
driver. Replace the function call with the one-line code.

Signed-off-by: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
---

 arch/arm/mach-zynq/clk.c              | 12 +-----------
 arch/arm/mach-zynq/include/mach/clk.h |  1 -
 2 files changed, 1 insertion(+), 12 deletions(-)

diff --git a/arch/arm/mach-zynq/clk.c b/arch/arm/mach-zynq/clk.c
index 7bff964..570ebd7 100644
--- a/arch/arm/mach-zynq/clk.c
+++ b/arch/arm/mach-zynq/clk.c
@@ -632,16 +632,6 @@ int zynq_clk_set_rate(enum zynq_clk clk, unsigned long rate)
 }
 
 /**
- * zynq_clk_get_name() - Get clock name
- * @clk:	Clock identifier
- * Returns the name of @clk.
- */
-const char *zynq_clk_get_name(enum zynq_clk clk)
-{
-	return clk_names[clk];
-}
-
-/**
  * soc_clk_dump() - Print clock frequencies
  * Returns zero on success
  *
@@ -653,7 +643,7 @@ int soc_clk_dump(void)
 
 	printf("clk\t\tfrequency\n");
 	for (i = 0; i < clk_max; i++) {
-		const char *name = zynq_clk_get_name(i);
+		const char *name = clk_names[i];
 		if (name)
 			printf("%10s%20lu\n", name, zynq_clk_get_rate(i));
 	}
diff --git a/arch/arm/mach-zynq/include/mach/clk.h b/arch/arm/mach-zynq/include/mach/clk.h
index 250c5bc..5c2758a 100644
--- a/arch/arm/mach-zynq/include/mach/clk.h
+++ b/arch/arm/mach-zynq/include/mach/clk.h
@@ -23,7 +23,6 @@ enum zynq_clk {
 void zynq_clk_early_init(void);
 int zynq_clk_set_rate(enum zynq_clk clk, unsigned long rate);
 unsigned long zynq_clk_get_rate(enum zynq_clk clk);
-const char *zynq_clk_get_name(enum zynq_clk clk);
 unsigned long get_uart_clk(int dev_id);
 
 #endif
-- 
2.7.4



Kommanditgesellschaft - Sitz: Detmold - Amtsgericht Lemgo HRA 2790 - 
Komplement?rin: Weidm?ller Interface F?hrungsgesellschaft mbH - 
Sitz: Detmold - Amtsgericht Lemgo HRB 3924; 
Gesch?ftsf?hrer: Jos? Carlos ?lvarez Tobar, Elke Eckstein, Dr. Peter K?hler, J?rg Timmermann;
USt-ID-Nr. DE124599660

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

* [U-Boot] [PATCH 6/8] clk: zynq: Add zynq clock framework driver
  2017-01-04 12:27 [U-Boot] [PATCH 0/8] zynq: clk: Move zynq platform to clock framework stefan.herbrechtsmeier at weidmueller.com
                   ` (4 preceding siblings ...)
  2017-01-04 12:27 ` [U-Boot] [PATCH 5/8] zynq: Remove zynq_clk_get_name function stefan.herbrechtsmeier at weidmueller.com
@ 2017-01-04 12:27 ` stefan.herbrechtsmeier at weidmueller.com
  2017-01-10 14:57   ` Michal Simek
  2017-01-04 12:27 ` [U-Boot] [PATCH 7/8] zynq: Move zynq to clock framework stefan.herbrechtsmeier at weidmueller.com
  2017-01-04 12:27 ` [U-Boot] [PATCH 8/8] clk: zynq: Add optional ethernet emio clock source support stefan.herbrechtsmeier at weidmueller.com
  7 siblings, 1 reply; 29+ messages in thread
From: stefan.herbrechtsmeier at weidmueller.com @ 2017-01-04 12:27 UTC (permalink / raw)
  To: u-boot

From: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>

Add a clock framework driver for the zynq platform. The driver is based
on the platform zynq clock driver but reworked to use static functions
instead of run-time generated objects even for unused clocks.
Additionally the CONFIG_ZYNQ_PS_CLK_FREQ is replaced by the
ps-clk-frequency from the device tree.

Signed-off-by: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
---

 drivers/clk/Kconfig    |   7 +
 drivers/clk/Makefile   |   1 +
 drivers/clk/clk_zynq.c | 470 +++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 478 insertions(+)
 create mode 100644 drivers/clk/clk_zynq.c

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index c05ce2a..714ccca 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -28,6 +28,13 @@ config CLK_BOSTON
 	help
 	  Enable this to support the clocks
 
+config CLK_ZYNQ
+	bool "Zynq clock driver"
+	depends on CLK && ARCH_ZYNQ
+	default y
+	help
+	  Enable this to support the clocks
+
 source "drivers/clk/tegra/Kconfig"
 source "drivers/clk/uniphier/Kconfig"
 source "drivers/clk/exynos/Kconfig"
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 40a5e8c..5e5b6b1 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -16,3 +16,4 @@ obj-$(CONFIG_CLK_UNIPHIER) += uniphier/
 obj-$(CONFIG_CLK_EXYNOS) += exynos/
 obj-$(CONFIG_CLK_AT91) += at91/
 obj-$(CONFIG_CLK_BOSTON) += clk_boston.o
+obj-$(CONFIG_CLK_ZYNQ) += clk_zynq.o
diff --git a/drivers/clk/clk_zynq.c b/drivers/clk/clk_zynq.c
new file mode 100644
index 0000000..d276155
--- /dev/null
+++ b/drivers/clk/clk_zynq.c
@@ -0,0 +1,470 @@
+/*
+ * Copyright (C) 2017 Weidm?ller Interface GmbH & Co. KG
+ * Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
+ *
+ * Copyright (C) 2013 Soren Brinkmann <soren.brinkmann@xilinx.com>
+ * Copyright (C) 2013 Xilinx, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <dm/lists.h>
+#include <errno.h>
+#include <asm/io.h>
+#include <asm/arch/clk.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/sys_proto.h>
+
+/* Register bitfield defines */
+#define PLLCTRL_FBDIV_MASK	0x7f000
+#define PLLCTRL_FBDIV_SHIFT	12
+#define PLLCTRL_BPFORCE_MASK	(1 << 4)
+#define PLLCTRL_PWRDWN_MASK	2
+#define PLLCTRL_PWRDWN_SHIFT	1
+#define PLLCTRL_RESET_MASK	1
+#define PLLCTRL_RESET_SHIFT	0
+
+#define ZYNQ_CLK_MAXDIV		0x3f
+#define CLK_CTRL_DIV1_SHIFT	20
+#define CLK_CTRL_DIV1_MASK	(ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV1_SHIFT)
+#define CLK_CTRL_DIV0_SHIFT	8
+#define CLK_CTRL_DIV0_MASK	(ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV0_SHIFT)
+#define CLK_CTRL_SRCSEL_SHIFT	4
+#define CLK_CTRL_SRCSEL_MASK	(0x3 << CLK_CTRL_SRCSEL_SHIFT)
+
+#define CLK_CTRL_DIV2X_SHIFT	26
+#define CLK_CTRL_DIV2X_MASK	(ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV2X_SHIFT)
+#define CLK_CTRL_DIV3X_SHIFT	20
+#define CLK_CTRL_DIV3X_MASK	(ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV3X_SHIFT)
+
+#define ZYNQ_CLKMUX_SEL_0	0
+#define ZYNQ_CLKMUX_SEL_1	1
+#define ZYNQ_CLKMUX_SEL_2	2
+#define ZYNQ_CLKMUX_SEL_3	3
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifndef CONFIG_SPL_BUILD
+enum zynq_clk_rclk {mio_clk, emio_clk};
+#endif
+
+struct zynq_clk_priv {
+	ulong ps_clk_freq;
+};
+
+static void *zynq_clk_get_register(enum zynq_clk id)
+{
+	switch (id) {
+	case armpll_clk:
+		return &slcr_base->arm_pll_ctrl;
+	case ddrpll_clk:
+		return &slcr_base->ddr_pll_ctrl;
+	case iopll_clk:
+		return &slcr_base->io_pll_ctrl;
+#ifndef CONFIG_SPL_BUILD
+	case dci_clk:
+		return &slcr_base->dci_clk_ctrl;
+#endif
+	case lqspi_clk:
+		return &slcr_base->lqspi_clk_ctrl;
+	case smc_clk:
+		return &slcr_base->smc_clk_ctrl;
+	case pcap_clk:
+		return &slcr_base->pcap_clk_ctrl;
+#ifndef CONFIG_SPL_BUILD
+	case gem0_clk:
+		return &slcr_base->gem0_clk_ctrl;
+	case gem1_clk:
+		return &slcr_base->gem1_clk_ctrl;
+	case fclk0_clk:
+		return &slcr_base->fpga0_clk_ctrl;
+	case fclk1_clk:
+		return &slcr_base->fpga1_clk_ctrl;
+	case fclk2_clk:
+		return &slcr_base->fpga2_clk_ctrl;
+	case fclk3_clk:
+		return &slcr_base->fpga3_clk_ctrl;
+	case can0_clk ... can1_clk:
+		return &slcr_base->can_clk_ctrl;
+#endif
+	case sdio0_clk:
+	case sdio1_clk:
+		return &slcr_base->sdio_clk_ctrl;
+	case uart0_clk:
+	case uart1_clk:
+		return &slcr_base->uart_clk_ctrl;
+	case spi0_clk:
+	case spi1_clk:
+		return &slcr_base->spi_clk_ctrl;
+#ifndef CONFIG_SPL_BUILD
+	case dbg_trc_clk:
+	case dbg_apb_clk:
+		return &slcr_base->dbg_clk_ctrl;
+#endif
+	default:
+		return &slcr_base->dbg_clk_ctrl;
+	}
+}
+
+static enum zynq_clk zynq_clk_get_cpu_pll(u32 clk_ctrl)
+{
+	u32 srcsel = (clk_ctrl & CLK_CTRL_SRCSEL_MASK) >> CLK_CTRL_SRCSEL_SHIFT;
+
+	switch (srcsel) {
+	case ZYNQ_CLKMUX_SEL_0:
+	case ZYNQ_CLKMUX_SEL_1:
+		return armpll_clk;
+	case ZYNQ_CLKMUX_SEL_2:
+		return ddrpll_clk;
+	case ZYNQ_CLKMUX_SEL_3:
+		return iopll_clk;
+	default:
+		return armpll_clk;
+	}
+}
+
+static enum zynq_clk zynq_clk_get_peripheral_pll(u32 clk_ctrl)
+{
+	u32 srcsel = (clk_ctrl & CLK_CTRL_SRCSEL_MASK) >> CLK_CTRL_SRCSEL_SHIFT;
+
+	switch (srcsel) {
+	case ZYNQ_CLKMUX_SEL_0:
+	case ZYNQ_CLKMUX_SEL_1:
+		return iopll_clk;
+	case ZYNQ_CLKMUX_SEL_2:
+		return armpll_clk;
+	case ZYNQ_CLKMUX_SEL_3:
+		return ddrpll_clk;
+	default:
+		return iopll_clk;
+	}
+}
+
+static ulong zynq_clk_get_pll_rate(struct zynq_clk_priv *priv, enum zynq_clk id)
+{
+	u32 clk_ctrl, reset, pwrdwn, mul, bypass;
+
+	clk_ctrl = readl(zynq_clk_get_register(id));
+
+	reset = (clk_ctrl & PLLCTRL_RESET_MASK) >> PLLCTRL_RESET_SHIFT;
+	pwrdwn = (clk_ctrl & PLLCTRL_PWRDWN_MASK) >> PLLCTRL_PWRDWN_SHIFT;
+	if (reset || pwrdwn)
+		return 0;
+
+	bypass = clk_ctrl & PLLCTRL_BPFORCE_MASK;
+	if (bypass)
+		mul = 1;
+	else
+		mul = (clk_ctrl & PLLCTRL_FBDIV_MASK) >> PLLCTRL_FBDIV_SHIFT;
+
+	return priv->ps_clk_freq * mul;
+}
+
+#ifndef CONFIG_SPL_BUILD
+static enum zynq_clk_rclk zynq_clk_get_gem_rclk(enum zynq_clk id)
+{
+	u32 clk_ctrl, srcsel;
+
+	if (id == gem0_clk)
+		clk_ctrl = readl(&slcr_base->gem0_rclk_ctrl);
+	else
+		clk_ctrl = readl(&slcr_base->gem1_rclk_ctrl);
+
+	srcsel = (clk_ctrl & CLK_CTRL_SRCSEL_MASK) >> CLK_CTRL_SRCSEL_SHIFT;
+	if (srcsel)
+		return emio_clk;
+	else
+		return mio_clk;
+}
+#endif
+
+static ulong zynq_clk_get_cpu_rate(struct zynq_clk_priv *priv, enum zynq_clk id)
+{
+	u32 clk_621, clk_ctrl, div;
+	enum zynq_clk pll;
+
+	clk_ctrl = readl(&slcr_base->arm_clk_ctrl);
+
+	div = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
+
+	switch (id) {
+	case cpu_1x_clk:
+		div *= 2;
+		/* fall through */
+	case cpu_2x_clk:
+		clk_621 = readl(&slcr_base->clk_621_true) & 1;
+		div *= 2 + clk_621;
+		break;
+	case cpu_3or2x_clk:
+		div *= 2;
+		/* fall through */
+	case cpu_6or4x_clk:
+		break;
+	default:
+		return 0;
+	}
+
+	pll = zynq_clk_get_cpu_pll(clk_ctrl);
+
+	return DIV_ROUND_CLOSEST(zynq_clk_get_pll_rate(priv, pll), div);
+}
+
+#ifndef CONFIG_SPL_BUILD
+static ulong zynq_clk_get_ddr2x_rate(struct zynq_clk_priv *priv)
+{
+	u32 clk_ctrl, div;
+
+	clk_ctrl = readl(&slcr_base->ddr_clk_ctrl);
+
+	div = (clk_ctrl & CLK_CTRL_DIV2X_MASK) >> CLK_CTRL_DIV2X_SHIFT;
+
+	return DIV_ROUND_CLOSEST(zynq_clk_get_pll_rate(priv, ddrpll_clk), div);
+}
+#endif
+
+static ulong zynq_clk_get_ddr3x_rate(struct zynq_clk_priv *priv)
+{
+	u32 clk_ctrl, div;
+
+	clk_ctrl = readl(&slcr_base->ddr_clk_ctrl);
+
+	div = (clk_ctrl & CLK_CTRL_DIV3X_MASK) >> CLK_CTRL_DIV3X_SHIFT;
+
+	return DIV_ROUND_CLOSEST(zynq_clk_get_pll_rate(priv, ddrpll_clk), div);
+}
+
+#ifndef CONFIG_SPL_BUILD
+static ulong zynq_clk_get_dci_rate(struct zynq_clk_priv *priv)
+{
+	u32 clk_ctrl, div0, div1;
+
+	clk_ctrl = readl(&slcr_base->dci_clk_ctrl);
+
+	div0 = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
+	div1 = (clk_ctrl & CLK_CTRL_DIV1_MASK) >> CLK_CTRL_DIV1_SHIFT;
+
+	return DIV_ROUND_CLOSEST(DIV_ROUND_CLOSEST(
+		zynq_clk_get_pll_rate(priv, ddrpll_clk), div0), div1);
+}
+#endif
+
+static ulong zynq_clk_get_peripheral_rate(struct zynq_clk_priv *priv,
+					  enum zynq_clk id, bool two_divs)
+{
+	enum zynq_clk pll;
+	u32 clk_ctrl, div0;
+	u32 div1 = 1;
+
+	clk_ctrl = readl(zynq_clk_get_register(id));
+
+	div0 = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
+	if (!div0)
+		div0 = 1;
+
+#ifndef CONFIG_SPL_BUILD
+	if (two_divs) {
+		div1 = (clk_ctrl & CLK_CTRL_DIV1_MASK) >> CLK_CTRL_DIV1_SHIFT;
+		if (!div1)
+			div1 = 1;
+	}
+#endif
+
+	pll = zynq_clk_get_peripheral_pll(clk_ctrl);
+
+	return
+		DIV_ROUND_CLOSEST(
+			DIV_ROUND_CLOSEST(
+				zynq_clk_get_pll_rate(priv, pll), div0),
+			div1);
+}
+
+#ifndef CONFIG_SPL_BUILD
+static ulong zynq_clk_get_gem_rate(struct zynq_clk_priv *priv, enum zynq_clk id)
+{
+	if (zynq_clk_get_gem_rclk(id) == mio_clk)
+		return zynq_clk_get_peripheral_rate(priv, id, true);
+
+	return 0;
+}
+
+static unsigned long zynq_clk_calc_peripheral_two_divs(
+		ulong rate, ulong pll_rate, u32 *div0,
+		u32 *div1)
+{
+	long new_err, best_err = (long)(~0UL >> 1);
+	ulong new_rate, best_rate = 0;
+	u32 d0, d1;
+
+	for (d0 = 1; d0 <= ZYNQ_CLK_MAXDIV; d0++) {
+		for (d1 = 1; d1 <= ZYNQ_CLK_MAXDIV >> 1; d1++) {
+			new_rate = DIV_ROUND_CLOSEST(
+					DIV_ROUND_CLOSEST(pll_rate, d0), d1);
+			new_err = abs(new_rate - rate);
+
+			if (new_err < best_err) {
+				*div0 = d0;
+				*div1 = d1;
+				best_err = new_err;
+				best_rate = new_rate;
+			}
+		}
+	}
+
+	return best_rate;
+}
+
+static ulong zynq_clk_set_peripheral_rate(struct zynq_clk_priv *priv,
+					  enum zynq_clk id, ulong rate,
+					  bool two_divs)
+{
+	enum zynq_clk pll;
+	u32 clk_ctrl, div0 = 0, div1 = 0;
+	ulong pll_rate, new_rate;
+	u32 *reg;
+
+	reg = zynq_clk_get_register(id);
+	clk_ctrl = readl(reg);
+
+	pll = zynq_clk_get_peripheral_pll(clk_ctrl);
+	pll_rate = zynq_clk_get_pll_rate(priv, pll);
+	clk_ctrl &= ~CLK_CTRL_DIV0_MASK;
+	if (two_divs) {
+		clk_ctrl &= ~CLK_CTRL_DIV1_MASK;
+		new_rate = zynq_clk_calc_peripheral_two_divs(rate, pll_rate,
+				&div0, &div1);
+		clk_ctrl |= div1 << CLK_CTRL_DIV1_SHIFT;
+	} else {
+		div0 = DIV_ROUND_CLOSEST(pll_rate, rate);
+		if (div0 > ZYNQ_CLK_MAXDIV)
+			div0 = ZYNQ_CLK_MAXDIV;
+		new_rate = DIV_ROUND_CLOSEST(rate, div0);
+	}
+	clk_ctrl |= div0 << CLK_CTRL_DIV0_SHIFT;
+
+	zynq_slcr_unlock();
+	writel(clk_ctrl, reg);
+	zynq_slcr_lock();
+
+	return new_rate;
+}
+
+static ulong zynq_clk_set_gem_rate(struct zynq_clk_priv *priv, enum zynq_clk id,
+				   ulong rate)
+{
+	if (zynq_clk_get_gem_rclk(id) == mio_clk)
+		return zynq_clk_set_peripheral_rate(priv, id, rate, true);
+
+	return 0;
+}
+#endif
+
+#ifndef CONFIG_SPL_BUILD
+static ulong zynq_clk_get_rate(struct clk *clk)
+{
+	struct zynq_clk_priv *priv = dev_get_priv(clk->dev);
+	enum zynq_clk id = clk->id;
+	bool two_divs = false;
+
+	switch (id) {
+	case armpll_clk ... iopll_clk:
+		return zynq_clk_get_pll_rate(priv, id);
+	case cpu_6or4x_clk ... cpu_1x_clk:
+		return zynq_clk_get_cpu_rate(priv, id);
+	case ddr2x_clk:
+		return zynq_clk_get_ddr2x_rate(priv);
+	case ddr3x_clk:
+		return zynq_clk_get_ddr3x_rate(priv);
+	case dci_clk:
+		return zynq_clk_get_dci_rate(priv);
+	case gem0_clk ... gem1_clk:
+		return zynq_clk_get_gem_rate(priv, id);
+	case fclk0_clk ... can1_clk:
+		two_divs = true;
+		/* fall through */
+	case dbg_trc_clk ... dbg_apb_clk:
+	case lqspi_clk ... pcap_clk:
+	case sdio0_clk ... spi1_clk:
+		return zynq_clk_get_peripheral_rate(priv, id, two_divs);
+	case dma_clk:
+		return zynq_clk_get_cpu_rate(priv, cpu_2x_clk);
+	case usb0_aper_clk ... smc_aper_clk:
+		return zynq_clk_get_cpu_rate(priv, cpu_1x_clk);
+	default:
+		return -ENXIO;
+	}
+}
+
+static ulong zynq_clk_set_rate(struct clk *clk, ulong rate)
+{
+	struct zynq_clk_priv *priv = dev_get_priv(clk->dev);
+	enum zynq_clk id = clk->id;
+	bool two_divs = false;
+
+	switch (id) {
+	case gem0_clk ... gem1_clk:
+		return zynq_clk_set_gem_rate(priv, id, rate);
+	case fclk0_clk ... can1_clk:
+		two_divs = true;
+		/* fall through */
+	case lqspi_clk ... pcap_clk:
+	case sdio0_clk ... spi1_clk:
+	case dbg_trc_clk ... dbg_apb_clk:
+		return zynq_clk_set_peripheral_rate(priv, id, rate, two_divs);
+	default:
+		return -ENXIO;
+	}
+}
+#else
+static ulong zynq_clk_get_rate(struct clk *clk)
+{
+	struct zynq_clk_priv *priv = dev_get_priv(clk->dev);
+	enum zynq_clk id = clk->id;
+
+	switch (id) {
+	case cpu_6or4x_clk ... cpu_1x_clk:
+		return zynq_clk_get_cpu_rate(priv, id);
+	case ddr3x_clk:
+		return zynq_clk_get_ddr3x_rate(priv);
+	case lqspi_clk ... pcap_clk:
+	case sdio0_clk ... spi1_clk:
+		return zynq_clk_get_peripheral_rate(priv, id, 0);
+	default:
+		return -ENXIO;
+	}
+}
+#endif
+
+static struct clk_ops zynq_clk_ops = {
+	.get_rate = zynq_clk_get_rate,
+#ifndef CONFIG_SPL_BUILD
+	.set_rate = zynq_clk_set_rate,
+#endif
+};
+
+static int zynq_clk_probe(struct udevice *dev)
+{
+	struct zynq_clk_priv *priv = dev_get_priv(dev);
+
+	priv->ps_clk_freq = fdtdec_get_uint(gd->fdt_blob, dev->of_offset,
+					    "ps-clk-frequency", 33333333UL);
+
+	return 0;
+}
+
+static const struct udevice_id zynq_clk_ids[] = {
+	{ .compatible = "xlnx,ps7-clkc"},
+	{}
+};
+
+U_BOOT_DRIVER(zynq_clk) = {
+	.name		= "zynq_clk",
+	.id		= UCLASS_CLK,
+	.of_match	= zynq_clk_ids,
+	.flags		= DM_FLAG_PRE_RELOC,
+	.ops		= &zynq_clk_ops,
+	.priv_auto_alloc_size = sizeof(struct zynq_clk_priv),
+	.probe		= zynq_clk_probe,
+};
-- 
2.7.4



Kommanditgesellschaft - Sitz: Detmold - Amtsgericht Lemgo HRA 2790 - 
Komplement?rin: Weidm?ller Interface F?hrungsgesellschaft mbH - 
Sitz: Detmold - Amtsgericht Lemgo HRB 3924; 
Gesch?ftsf?hrer: Jos? Carlos ?lvarez Tobar, Elke Eckstein, Dr. Peter K?hler, J?rg Timmermann;
USt-ID-Nr. DE124599660

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

* [U-Boot] [PATCH 7/8] zynq: Move zynq to clock framework
  2017-01-04 12:27 [U-Boot] [PATCH 0/8] zynq: clk: Move zynq platform to clock framework stefan.herbrechtsmeier at weidmueller.com
                   ` (5 preceding siblings ...)
  2017-01-04 12:27 ` [U-Boot] [PATCH 6/8] clk: zynq: Add zynq clock framework driver stefan.herbrechtsmeier at weidmueller.com
@ 2017-01-04 12:27 ` stefan.herbrechtsmeier at weidmueller.com
  2017-01-10 15:04   ` Michal Simek
  2017-01-04 12:27 ` [U-Boot] [PATCH 8/8] clk: zynq: Add optional ethernet emio clock source support stefan.herbrechtsmeier at weidmueller.com
  7 siblings, 1 reply; 29+ messages in thread
From: stefan.herbrechtsmeier at weidmueller.com @ 2017-01-04 12:27 UTC (permalink / raw)
  To: u-boot

From: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.de>

Move the zynq to clock framework and remove unused functions as well as
the CONFIG_ZYNQ_PS_CLK_FREQ configuration.

Signed-off-by: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
---

 arch/arm/Kconfig                            |   2 +
 arch/arm/dts/zynq-7000.dtsi                 |   2 +
 arch/arm/mach-zynq/clk.c                    | 650 +++-------------------------
 arch/arm/mach-zynq/cpu.c                    |   1 -
 arch/arm/mach-zynq/include/mach/clk.h       |   5 -
 arch/arm/mach-zynq/include/mach/sys_proto.h |   1 -
 arch/arm/mach-zynq/slcr.c                   |  22 -
 arch/arm/mach-zynq/timer.c                  |   2 -
 drivers/net/zynq_gem.c                      |  13 -
 drivers/serial/serial_zynq.c                |   6 +-
 include/configs/topic_miami.h               |   2 -
 include/configs/zynq_zybo.h                 |   3 -
 scripts/config_whitelist.txt                |   1 -
 13 files changed, 55 insertions(+), 655 deletions(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 38080c0..f9daa99 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -631,6 +631,8 @@ config ARCH_ZYNQ
 	select SPL_SEPARATE_BSS if SPL
 	select DM_USB if USB
 	select BLK
+	select CLK
+	select SPL_CLK
 
 config ARCH_ZYNQMP
 	bool "Support Xilinx ZynqMP Platform"
diff --git a/arch/arm/dts/zynq-7000.dtsi b/arch/arm/dts/zynq-7000.dtsi
index 668f54e..2464830 100644
--- a/arch/arm/dts/zynq-7000.dtsi
+++ b/arch/arm/dts/zynq-7000.dtsi
@@ -250,12 +250,14 @@
 		};
 
 		slcr: slcr at f8000000 {
+			u-boot,dm-pre-reloc;
 			#address-cells = <1>;
 			#size-cells = <1>;
 			compatible = "xlnx,zynq-slcr", "syscon", "simple-mfd";
 			reg = <0xF8000000 0x1000>;
 			ranges;
 			clkc: clkc at 100 {
+				u-boot,dm-pre-reloc;
 				#clock-cells = <1>;
 				compatible = "xlnx,ps7-clkc";
 				fclk-enable = <0>;
diff --git a/arch/arm/mach-zynq/clk.c b/arch/arm/mach-zynq/clk.c
index 570ebd7..7283a94 100644
--- a/arch/arm/mach-zynq/clk.c
+++ b/arch/arm/mach-zynq/clk.c
@@ -4,77 +4,13 @@
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
+#include <clk.h>
 #include <common.h>
-#include <errno.h>
-#include <asm/io.h>
-#include <asm/arch/hardware.h>
+#include <dm.h>
 #include <asm/arch/clk.h>
 
-/* Board oscillator frequency */
-#ifndef CONFIG_ZYNQ_PS_CLK_FREQ
-# define CONFIG_ZYNQ_PS_CLK_FREQ	33333333UL
-#endif
-
-/* Register bitfield defines */
-#define PLLCTRL_FBDIV_MASK	0x7f000
-#define PLLCTRL_FBDIV_SHIFT	12
-#define PLLCTRL_BPFORCE_MASK	(1 << 4)
-#define PLLCTRL_PWRDWN_MASK	2
-#define PLLCTRL_PWRDWN_SHIFT	1
-#define PLLCTRL_RESET_MASK	1
-#define PLLCTRL_RESET_SHIFT	0
-
-#define ZYNQ_CLK_MAXDIV		0x3f
-#define CLK_CTRL_DIV1_SHIFT	20
-#define CLK_CTRL_DIV1_MASK	(ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV1_SHIFT)
-#define CLK_CTRL_DIV0_SHIFT	8
-#define CLK_CTRL_DIV0_MASK	(ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV0_SHIFT)
-#define CLK_CTRL_SRCSEL_SHIFT	4
-#define CLK_CTRL_SRCSEL_MASK	(0x3 << CLK_CTRL_SRCSEL_SHIFT)
-
-#define CLK_CTRL_DIV2X_SHIFT	26
-#define CLK_CTRL_DIV2X_MASK	(ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV2X_SHIFT)
-#define CLK_CTRL_DIV3X_SHIFT	20
-#define CLK_CTRL_DIV3X_MASK	(ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV3X_SHIFT)
-
-#define ZYNQ_CLKMUX_SEL_0	0
-#define ZYNQ_CLKMUX_SEL_1	1
-#define ZYNQ_CLKMUX_SEL_2	2
-#define ZYNQ_CLKMUX_SEL_3	3
-
 DECLARE_GLOBAL_DATA_PTR;
 
-struct clk;
-
-/**
- * struct zynq_clk_ops:
- * @set_rate:	Function pointer to set_rate() implementation
- * @get_rate:	Function pointer to get_rate() implementation
- */
-struct zynq_clk_ops {
-	int (*set_rate)(struct clk *clk, unsigned long rate);
-	unsigned long (*get_rate)(struct clk *clk);
-};
-
-/**
- * struct clk:
- * @frequency:	Currenct frequency
- * @parent:	Parent clock
- * @flags:	Clock flags
- * @reg:	Clock control register
- * @ops:	Clock operations
- */
-struct clk {
-	unsigned long	frequency;
-	enum zynq_clk	parent;
-	unsigned int	flags;
-	u32		*reg;
-	struct zynq_clk_ops	ops;
-};
-#define ZYNQ_CLK_FLAGS_HAS_2_DIVS	1
-
-static struct clk clks[clk_max];
-
 static const char * const clk_names[clk_max] = {
 	"armpll", "ddrpll", "iopll",
 	"cpu_6or4x", "cpu_3or2x", "cpu_2x", "cpu_1x",
@@ -90,548 +26,43 @@ static const char * const clk_names[clk_max] = {
 };
 
 /**
- * __zynq_clk_cpu_get_parent() - Decode clock multiplexer
- * @srcsel:	Mux select value
- * Returns the clock identifier associated with the selected mux input.
- */
-static int __zynq_clk_cpu_get_parent(unsigned int srcsel)
-{
-	unsigned int ret;
-
-	switch (srcsel) {
-	case ZYNQ_CLKMUX_SEL_0:
-	case ZYNQ_CLKMUX_SEL_1:
-		ret = armpll_clk;
-		break;
-	case ZYNQ_CLKMUX_SEL_2:
-		ret = ddrpll_clk;
-		break;
-	case ZYNQ_CLKMUX_SEL_3:
-		ret = iopll_clk;
-		break;
-	default:
-		ret = armpll_clk;
-		break;
-	}
-
-	return ret;
-}
-
-/**
- * ddr2x_get_rate() - Get clock rate of DDR2x clock
- * @clk:	Clock handle
- * Returns the current clock rate of @clk.
- */
-static unsigned long ddr2x_get_rate(struct clk *clk)
-{
-	u32 clk_ctrl = readl(clk->reg);
-	u32 div = (clk_ctrl & CLK_CTRL_DIV2X_MASK) >> CLK_CTRL_DIV2X_SHIFT;
-
-	return DIV_ROUND_CLOSEST(zynq_clk_get_rate(clk->parent), div);
-}
-
-/**
- * ddr3x_get_rate() - Get clock rate of DDR3x clock
- * @clk:	Clock handle
- * Returns the current clock rate of @clk.
- */
-static unsigned long ddr3x_get_rate(struct clk *clk)
-{
-	u32 clk_ctrl = readl(clk->reg);
-	u32 div = (clk_ctrl & CLK_CTRL_DIV3X_MASK) >> CLK_CTRL_DIV3X_SHIFT;
-
-	return DIV_ROUND_CLOSEST(zynq_clk_get_rate(clk->parent), div);
-}
-
-static void init_ddr_clocks(void)
-{
-	u32 div0, div1;
-	unsigned long prate = zynq_clk_get_rate(ddrpll_clk);
-	u32 clk_ctrl = readl(&slcr_base->ddr_clk_ctrl);
-
-	/* DDR2x */
-	clks[ddr2x_clk].reg = &slcr_base->ddr_clk_ctrl;
-	clks[ddr2x_clk].parent = ddrpll_clk;
-	clks[ddr2x_clk].frequency = ddr2x_get_rate(&clks[ddr2x_clk]);
-	clks[ddr2x_clk].ops.get_rate = ddr2x_get_rate;
-
-	/* DDR3x */
-	clks[ddr3x_clk].reg = &slcr_base->ddr_clk_ctrl;
-	clks[ddr3x_clk].parent = ddrpll_clk;
-	clks[ddr3x_clk].frequency = ddr3x_get_rate(&clks[ddr3x_clk]);
-	clks[ddr3x_clk].ops.get_rate = ddr3x_get_rate;
-
-	/* DCI */
-	clk_ctrl = readl(&slcr_base->dci_clk_ctrl);
-	div0 = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
-	div1 = (clk_ctrl & CLK_CTRL_DIV1_MASK) >> CLK_CTRL_DIV1_SHIFT;
-	clks[dci_clk].reg = &slcr_base->dci_clk_ctrl;
-	clks[dci_clk].parent = ddrpll_clk;
-	clks[dci_clk].frequency = DIV_ROUND_CLOSEST(
-			DIV_ROUND_CLOSEST(prate, div0), div1);
-
-	gd->bd->bi_ddr_freq = clks[ddr3x_clk].frequency / 1000000;
-}
-
-static void init_cpu_clocks(void)
-{
-	int clk_621;
-	u32 reg, div, srcsel;
-	enum zynq_clk parent;
-
-	reg = readl(&slcr_base->arm_clk_ctrl);
-	clk_621 = readl(&slcr_base->clk_621_true) & 1;
-	div = (reg & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
-	srcsel = (reg & CLK_CTRL_SRCSEL_MASK) >> CLK_CTRL_SRCSEL_SHIFT;
-	parent = __zynq_clk_cpu_get_parent(srcsel);
-
-	/* cpu clocks */
-	clks[cpu_6or4x_clk].reg = &slcr_base->arm_clk_ctrl;
-	clks[cpu_6or4x_clk].parent = parent;
-	clks[cpu_6or4x_clk].frequency = DIV_ROUND_CLOSEST(
-			zynq_clk_get_rate(parent), div);
-
-	clks[cpu_3or2x_clk].reg = &slcr_base->arm_clk_ctrl;
-	clks[cpu_3or2x_clk].parent = cpu_6or4x_clk;
-	clks[cpu_3or2x_clk].frequency = zynq_clk_get_rate(cpu_6or4x_clk) / 2;
-
-	clks[cpu_2x_clk].reg = &slcr_base->arm_clk_ctrl;
-	clks[cpu_2x_clk].parent = cpu_6or4x_clk;
-	clks[cpu_2x_clk].frequency = zynq_clk_get_rate(cpu_6or4x_clk) /
-			(2 + clk_621);
-
-	clks[cpu_1x_clk].reg = &slcr_base->arm_clk_ctrl;
-	clks[cpu_1x_clk].parent = cpu_6or4x_clk;
-	clks[cpu_1x_clk].frequency = zynq_clk_get_rate(cpu_6or4x_clk) /
-			(4 + 2 * clk_621);
-}
-
-/**
- * periph_calc_two_divs() - Calculate clock dividers
- * @cur_rate:	Current clock rate
- * @tgt_rate:	Target clock rate
- * @prate:	Parent clock rate
- * @div0:	First divider (output)
- * @div1:	Second divider (output)
- * Returns the actual clock rate possible.
- *
- * Calculates clock dividers for clocks with two 6-bit dividers.
- */
-static unsigned long periph_calc_two_divs(unsigned long cur_rate,
-		unsigned long tgt_rate, unsigned long prate, u32 *div0,
-		u32 *div1)
-{
-	long err, best_err = (long)(~0UL >> 1);
-	unsigned long rate, best_rate = 0;
-	u32 d0, d1;
-
-	for (d0 = 1; d0 <= ZYNQ_CLK_MAXDIV; d0++) {
-		for (d1 = 1; d1 <= ZYNQ_CLK_MAXDIV >> 1; d1++) {
-			rate = DIV_ROUND_CLOSEST(DIV_ROUND_CLOSEST(prate, d0),
-					d1);
-			err = abs(rate - tgt_rate);
-
-			if (err < best_err) {
-				*div0 = d0;
-				*div1 = d1;
-				best_err = err;
-				best_rate = rate;
-			}
-		}
-	}
-
-	return best_rate;
-}
-
-/**
- * zynq_clk_periph_set_rate() - Set clock rate
- * @clk:	Handle of the peripheral clock
- * @rate:	New clock rate
- * Sets the clock frequency of @clk to @rate. Returns zero on success.
- */
-static int zynq_clk_periph_set_rate(struct clk *clk,
-		unsigned long rate)
-{
-	u32 ctrl, div0 = 0, div1 = 0;
-	unsigned long prate, new_rate, cur_rate = clk->frequency;
-
-	ctrl = readl(clk->reg);
-	prate = zynq_clk_get_rate(clk->parent);
-	ctrl &= ~CLK_CTRL_DIV0_MASK;
-
-	if (clk->flags & ZYNQ_CLK_FLAGS_HAS_2_DIVS) {
-		ctrl &= ~CLK_CTRL_DIV1_MASK;
-		new_rate = periph_calc_two_divs(cur_rate, rate, prate, &div0,
-				&div1);
-		ctrl |= div1 << CLK_CTRL_DIV1_SHIFT;
-	} else {
-		div0 = DIV_ROUND_CLOSEST(prate, rate);
-		div0 &= ZYNQ_CLK_MAXDIV;
-		new_rate = DIV_ROUND_CLOSEST(rate, div0);
-	}
-
-	/* write new divs to hardware */
-	ctrl |= div0 << CLK_CTRL_DIV0_SHIFT;
-	writel(ctrl, clk->reg);
-
-	/* update frequency in clk framework */
-	clk->frequency = new_rate;
-
-	return 0;
-}
-
-/**
- * zynq_clk_periph_get_rate() - Get clock rate
- * @clk:	Handle of the peripheral clock
- * Returns the current clock rate of @clk.
- */
-static unsigned long zynq_clk_periph_get_rate(struct clk *clk)
-{
-	u32 clk_ctrl = readl(clk->reg);
-	u32 div0 = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
-	u32 div1 = 1;
-
-	if (clk->flags & ZYNQ_CLK_FLAGS_HAS_2_DIVS)
-		div1 = (clk_ctrl & CLK_CTRL_DIV1_MASK) >> CLK_CTRL_DIV1_SHIFT;
-
-	/* a register value of zero == division by 1 */
-	if (!div0)
-		div0 = 1;
-	if (!div1)
-		div1 = 1;
-
-	return
-		DIV_ROUND_CLOSEST(
-			DIV_ROUND_CLOSEST(zynq_clk_get_rate(clk->parent), div0),
-			div1);
-}
-
-/**
- * __zynq_clk_periph_get_parent() - Decode clock multiplexer
- * @srcsel:	Mux select value
- * Returns the clock identifier associated with the selected mux input.
- */
-static enum zynq_clk __zynq_clk_periph_get_parent(u32 srcsel)
-{
-	switch (srcsel) {
-	case ZYNQ_CLKMUX_SEL_0:
-	case ZYNQ_CLKMUX_SEL_1:
-		return iopll_clk;
-	case ZYNQ_CLKMUX_SEL_2:
-		return armpll_clk;
-	case ZYNQ_CLKMUX_SEL_3:
-		return ddrpll_clk;
-	default:
-		return 0;
-	}
-}
-
-/**
- * zynq_clk_periph_get_parent() - Decode clock multiplexer
- * @clk:	Clock handle
- * Returns the clock identifier associated with the selected mux input.
- */
-static enum zynq_clk zynq_clk_periph_get_parent(struct clk *clk)
-{
-	u32 clk_ctrl = readl(clk->reg);
-	u32 srcsel = (clk_ctrl & CLK_CTRL_SRCSEL_MASK) >> CLK_CTRL_SRCSEL_SHIFT;
-
-	return __zynq_clk_periph_get_parent(srcsel);
-}
-
-/**
- * zynq_clk_register_periph_clk() - Set up a peripheral clock with the framework
- * @clk:	Pointer to struct clk for the clock
- * @ctrl:	Clock control register
- * @two_divs:	Indicates whether the clock features one or two dividers
- */
-static int zynq_clk_register_periph_clk(struct clk *clk, u32 *ctrl,
-		bool two_divs)
-{
-	clk->reg = ctrl;
-	if (two_divs)
-		clk->flags = ZYNQ_CLK_FLAGS_HAS_2_DIVS;
-	clk->parent = zynq_clk_periph_get_parent(clk);
-	clk->frequency = zynq_clk_periph_get_rate(clk);
-	clk->ops.get_rate = zynq_clk_periph_get_rate;
-	clk->ops.set_rate = zynq_clk_periph_set_rate;
-
-	return 0;
-}
-
-static void init_periph_clocks(void)
-{
-	zynq_clk_register_periph_clk(&clks[gem0_clk],
-				     &slcr_base->gem0_clk_ctrl, 1);
-	zynq_clk_register_periph_clk(&clks[gem1_clk],
-				     &slcr_base->gem1_clk_ctrl, 1);
-
-	zynq_clk_register_periph_clk(&clks[smc_clk],
-				     &slcr_base->smc_clk_ctrl, 0);
-
-	zynq_clk_register_periph_clk(&clks[lqspi_clk],
-				     &slcr_base->lqspi_clk_ctrl, 0);
-
-	zynq_clk_register_periph_clk(&clks[sdio0_clk],
-				     &slcr_base->sdio_clk_ctrl, 0);
-	zynq_clk_register_periph_clk(&clks[sdio1_clk],
-				     &slcr_base->sdio_clk_ctrl, 0);
-
-	zynq_clk_register_periph_clk(&clks[spi0_clk],
-				     &slcr_base->spi_clk_ctrl, 0);
-	zynq_clk_register_periph_clk(&clks[spi1_clk],
-				     &slcr_base->spi_clk_ctrl, 0);
-
-	zynq_clk_register_periph_clk(&clks[uart0_clk],
-				     &slcr_base->uart_clk_ctrl, 0);
-	zynq_clk_register_periph_clk(&clks[uart1_clk],
-				     &slcr_base->uart_clk_ctrl, 0);
-
-	zynq_clk_register_periph_clk(&clks[dbg_trc_clk],
-				     &slcr_base->dbg_clk_ctrl, 0);
-	zynq_clk_register_periph_clk(&clks[dbg_apb_clk],
-				     &slcr_base->dbg_clk_ctrl, 0);
-
-	zynq_clk_register_periph_clk(&clks[pcap_clk],
-				     &slcr_base->pcap_clk_ctrl, 0);
-
-	zynq_clk_register_periph_clk(&clks[fclk0_clk],
-				     &slcr_base->fpga0_clk_ctrl, 1);
-	zynq_clk_register_periph_clk(&clks[fclk1_clk],
-				     &slcr_base->fpga1_clk_ctrl, 1);
-	zynq_clk_register_periph_clk(&clks[fclk2_clk],
-				     &slcr_base->fpga2_clk_ctrl, 1);
-	zynq_clk_register_periph_clk(&clks[fclk3_clk],
-				     &slcr_base->fpga3_clk_ctrl, 1);
-}
-
-/**
- * zynq_clk_register_aper_clk() - Set up a APER clock with the framework
- * @clk:	Pointer to struct clk for the clock
- * @ctrl:	Clock control register
- */
-static void zynq_clk_register_aper_clk(struct clk *clk, u32 *ctrl)
-{
-	clk->reg = ctrl;
-	clk->parent = cpu_1x_clk;
-	clk->frequency = zynq_clk_get_rate(clk->parent);
-}
-
-static void init_aper_clocks(void)
-{
-	zynq_clk_register_aper_clk(&clks[usb0_aper_clk],
-				   &slcr_base->aper_clk_ctrl);
-	zynq_clk_register_aper_clk(&clks[usb1_aper_clk],
-				   &slcr_base->aper_clk_ctrl);
-
-	zynq_clk_register_aper_clk(&clks[gem0_aper_clk],
-				   &slcr_base->aper_clk_ctrl);
-	zynq_clk_register_aper_clk(&clks[gem1_aper_clk],
-				   &slcr_base->aper_clk_ctrl);
-
-	zynq_clk_register_aper_clk(&clks[sdio0_aper_clk],
-				   &slcr_base->aper_clk_ctrl);
-	zynq_clk_register_aper_clk(&clks[sdio1_aper_clk],
-				   &slcr_base->aper_clk_ctrl);
-
-	zynq_clk_register_aper_clk(&clks[spi0_aper_clk],
-				   &slcr_base->aper_clk_ctrl);
-	zynq_clk_register_aper_clk(&clks[spi1_aper_clk],
-				   &slcr_base->aper_clk_ctrl);
-
-	zynq_clk_register_aper_clk(&clks[can0_aper_clk],
-				   &slcr_base->aper_clk_ctrl);
-	zynq_clk_register_aper_clk(&clks[can1_aper_clk],
-				   &slcr_base->aper_clk_ctrl);
-
-	zynq_clk_register_aper_clk(&clks[i2c0_aper_clk],
-				   &slcr_base->aper_clk_ctrl);
-	zynq_clk_register_aper_clk(&clks[i2c1_aper_clk],
-				   &slcr_base->aper_clk_ctrl);
-
-	zynq_clk_register_aper_clk(&clks[uart0_aper_clk],
-				   &slcr_base->aper_clk_ctrl);
-	zynq_clk_register_aper_clk(&clks[uart1_aper_clk],
-				   &slcr_base->aper_clk_ctrl);
-
-	zynq_clk_register_aper_clk(&clks[gpio_aper_clk],
-				   &slcr_base->aper_clk_ctrl);
-
-	zynq_clk_register_aper_clk(&clks[lqspi_aper_clk],
-				   &slcr_base->aper_clk_ctrl);
-
-	zynq_clk_register_aper_clk(&clks[smc_aper_clk],
-				   &slcr_base->aper_clk_ctrl);
-}
-
-/**
- * __zynq_clk_pll_get_rate() - Get PLL rate
- * @addr:	Address of the PLL's control register
- * Returns the current PLL output rate.
- */
-static unsigned long __zynq_clk_pll_get_rate(u32 *addr)
-{
-	u32 reg, mul, bypass;
-
-	reg = readl(addr);
-	bypass = reg & PLLCTRL_BPFORCE_MASK;
-	if (bypass)
-		mul = 1;
-	else
-		mul = (reg & PLLCTRL_FBDIV_MASK) >> PLLCTRL_FBDIV_SHIFT;
-
-	return CONFIG_ZYNQ_PS_CLK_FREQ * mul;
-}
-
-/**
- * zynq_clk_pll_get_rate() - Get PLL rate
- * @pll:	Handle of the PLL
- * Returns the current clock rate of @pll.
- */
-static unsigned long zynq_clk_pll_get_rate(struct clk *pll)
-{
-	return __zynq_clk_pll_get_rate(pll->reg);
-}
-
-/**
- * zynq_clk_register_pll() - Set up a PLL with the framework
- * @clk:	Pointer to struct clk for the PLL
- * @ctrl:	PLL control register
- * @prate:	PLL input clock rate
- */
-static void zynq_clk_register_pll(struct clk *clk, u32 *ctrl,
-		unsigned long prate)
-{
-	clk->reg = ctrl;
-	clk->frequency = zynq_clk_pll_get_rate(clk);
-	clk->ops.get_rate = zynq_clk_pll_get_rate;
-}
-
-/**
- * clkid_2_register() - Get clock control register
- * @id:	Clock identifier of one of the PLLs
- * Returns the address of the requested PLL's control register.
- */
-static u32 *clkid_2_register(enum zynq_clk id)
-{
-	switch (id) {
-	case armpll_clk:
-		return &slcr_base->arm_pll_ctrl;
-	case ddrpll_clk:
-		return &slcr_base->ddr_pll_ctrl;
-	case iopll_clk:
-		return &slcr_base->io_pll_ctrl;
-	default:
-		return &slcr_base->io_pll_ctrl;
-	}
-}
-
-/* API */
-/**
- * zynq_clk_early_init() - Early init for the clock framework
- *
- * This function is called from before relocation and sets up the CPU clock
- * frequency in the global data struct.
- */
-void zynq_clk_early_init(void)
-{
-	u32 reg = readl(&slcr_base->arm_clk_ctrl);
-	u32 div = (reg & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
-	u32 srcsel = (reg & CLK_CTRL_SRCSEL_MASK) >> CLK_CTRL_SRCSEL_SHIFT;
-	enum zynq_clk parent = __zynq_clk_cpu_get_parent(srcsel);
-	u32 *pllreg = clkid_2_register(parent);
-	unsigned long prate = __zynq_clk_pll_get_rate(pllreg);
-
-	if (!div)
-		div = 1;
-
-	gd->cpu_clk = DIV_ROUND_CLOSEST(prate, div);
-}
-
-/**
- * get_uart_clk() - Get UART input frequency
- * @dev_index:	UART ID
- * Returns UART input clock frequency in Hz.
- *
- * Compared to zynq_clk_get_rate() this function is designed to work before
- * relocation and can be called when the serial UART is set up.
- */
-unsigned long get_uart_clk(int dev_index)
-{
-	u32 reg = readl(&slcr_base->uart_clk_ctrl);
-	u32 div = (reg & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
-	u32 srcsel = (reg & CLK_CTRL_SRCSEL_MASK) >> CLK_CTRL_SRCSEL_SHIFT;
-	enum zynq_clk parent = __zynq_clk_periph_get_parent(srcsel);
-	u32 *pllreg = clkid_2_register(parent);
-	unsigned long prate = __zynq_clk_pll_get_rate(pllreg);
-
-	if (!div)
-		div = 1;
-
-	return DIV_ROUND_CLOSEST(prate, div);
-}
-
-/**
- * set_cpu_clk_info() - Initialize clock framework
- * Always returns zero.
+ * set_cpu_clk_info() - Setup clock information
  *
  * This function is called from common code after relocation and sets up the
- * clock framework. The framework must not be used before this function had been
- * called.
+ * clock information.
  */
 int set_cpu_clk_info(void)
 {
-	zynq_clk_register_pll(&clks[armpll_clk], &slcr_base->arm_pll_ctrl,
-			      CONFIG_ZYNQ_PS_CLK_FREQ);
-	zynq_clk_register_pll(&clks[ddrpll_clk], &slcr_base->ddr_pll_ctrl,
-			      CONFIG_ZYNQ_PS_CLK_FREQ);
-	zynq_clk_register_pll(&clks[iopll_clk], &slcr_base->io_pll_ctrl,
-			      CONFIG_ZYNQ_PS_CLK_FREQ);
-
-	init_ddr_clocks();
-	init_cpu_clocks();
-	init_periph_clocks();
-	init_aper_clocks();
-
-	gd->bd->bi_arm_freq = gd->cpu_clk / 1000000;
+	struct clk clk;
+	struct udevice *dev;
+	ulong rate;
+	int i, ret;
+
+	ret = uclass_get_device_by_driver(UCLASS_CLK,
+		DM_GET_DRIVER(zynq_clk), &dev);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < 2; i++) {
+		clk.id = i ? ddr3x_clk : cpu_6or4x_clk;
+		ret = clk_request(dev, &clk);
+		if (ret < 0)
+			return ret;
+
+		rate = clk_get_rate(&clk) / 1000000;
+		if (i)
+			gd->bd->bi_ddr_freq = rate;
+		else
+			gd->bd->bi_arm_freq = rate;
+
+		clk_free(&clk);
+	}
 	gd->bd->bi_dsp_freq = 0;
 
 	return 0;
 }
 
 /**
- * zynq_clk_get_rate() - Get clock rate
- * @clk:	Clock identifier
- * Returns the current clock rate of @clk on success or zero for an invalid
- * clock id.
- */
-unsigned long zynq_clk_get_rate(enum zynq_clk clk)
-{
-	if (clk < 0 || clk >= clk_max)
-		return 0;
-
-	return clks[clk].frequency;
-}
-
-/**
- * zynq_clk_set_rate() - Set clock rate
- * @clk:	Clock identifier
- * @rate:	Requested clock rate
- * Passes on the return value from the clock's set_rate() function or negative
- * errno.
- */
-int zynq_clk_set_rate(enum zynq_clk clk, unsigned long rate)
-{
-	if (clk < 0 || clk >= clk_max)
-		return -ENODEV;
-
-	if (clks[clk].ops.set_rate)
-		return clks[clk].ops.set_rate(&clks[clk], rate);
-
-	return -ENXIO;
-}
-
-/**
  * soc_clk_dump() - Print clock frequencies
  * Returns zero on success
  *
@@ -639,13 +70,32 @@ int zynq_clk_set_rate(enum zynq_clk clk, unsigned long rate)
  */
 int soc_clk_dump(void)
 {
-	int i;
+	struct udevice *dev;
+	int i, ret;
+
+	ret = uclass_get_device_by_driver(UCLASS_CLK,
+		DM_GET_DRIVER(zynq_clk), &dev);
+	if (ret)
+		return ret;
 
 	printf("clk\t\tfrequency\n");
 	for (i = 0; i < clk_max; i++) {
 		const char *name = clk_names[i];
-		if (name)
-			printf("%10s%20lu\n", name, zynq_clk_get_rate(i));
+		if (name) {
+			struct clk clk;
+			unsigned long rate;
+
+			clk.id = i;
+			ret = clk_request(dev, &clk);
+			if (ret < 0)
+				return ret;
+
+			rate = clk_get_rate(&clk);
+
+			clk_free(&clk);
+
+			printf("%10s%20lu\n", name, rate);
+		}
 	}
 
 	return 0;
diff --git a/arch/arm/mach-zynq/cpu.c b/arch/arm/mach-zynq/cpu.c
index ba9171e..ee1c1a9 100644
--- a/arch/arm/mach-zynq/cpu.c
+++ b/arch/arm/mach-zynq/cpu.c
@@ -35,7 +35,6 @@ int arch_cpu_init(void)
 	writel(0xC, &slcr_base->ddr_urgent);
 #endif
 #endif
-	zynq_clk_early_init();
 	zynq_slcr_lock();
 
 	return 0;
diff --git a/arch/arm/mach-zynq/include/mach/clk.h b/arch/arm/mach-zynq/include/mach/clk.h
index 5c2758a..8a039ae 100644
--- a/arch/arm/mach-zynq/include/mach/clk.h
+++ b/arch/arm/mach-zynq/include/mach/clk.h
@@ -20,9 +20,4 @@ enum zynq_clk {
 	uart0_aper_clk, uart1_aper_clk, gpio_aper_clk, lqspi_aper_clk,
 	smc_aper_clk, swdt_clk, dbg_trc_clk, dbg_apb_clk, clk_max};
 
-void zynq_clk_early_init(void);
-int zynq_clk_set_rate(enum zynq_clk clk, unsigned long rate);
-unsigned long zynq_clk_get_rate(enum zynq_clk clk);
-unsigned long get_uart_clk(int dev_id);
-
 #endif
diff --git a/arch/arm/mach-zynq/include/mach/sys_proto.h b/arch/arm/mach-zynq/include/mach/sys_proto.h
index 44c9b50..67238e7 100644
--- a/arch/arm/mach-zynq/include/mach/sys_proto.h
+++ b/arch/arm/mach-zynq/include/mach/sys_proto.h
@@ -10,7 +10,6 @@
 extern void zynq_slcr_lock(void);
 extern void zynq_slcr_unlock(void);
 extern void zynq_slcr_cpu_reset(void);
-extern void zynq_slcr_gem_clk_setup(u32 gem_id, unsigned long clk_rate);
 extern void zynq_slcr_devcfg_disable(void);
 extern void zynq_slcr_devcfg_enable(void);
 extern u32 zynq_slcr_get_boot_mode(void);
diff --git a/arch/arm/mach-zynq/slcr.c b/arch/arm/mach-zynq/slcr.c
index c1129cd..2a207ae 100644
--- a/arch/arm/mach-zynq/slcr.c
+++ b/arch/arm/mach-zynq/slcr.c
@@ -9,7 +9,6 @@
 #include <malloc.h>
 #include <asm/arch/hardware.h>
 #include <asm/arch/sys_proto.h>
-#include <asm/arch/clk.h>
 
 #define SLCR_LOCK_MAGIC		0x767B
 #define SLCR_UNLOCK_MAGIC	0xDF0D
@@ -124,27 +123,6 @@ void zynq_slcr_cpu_reset(void)
 	writel(1, &slcr_base->pss_rst_ctrl);
 }
 
-/* Setup clk for network */
-void zynq_slcr_gem_clk_setup(u32 gem_id, unsigned long clk_rate)
-{
-	int ret;
-
-	zynq_slcr_unlock();
-
-	if (gem_id > 1) {
-		printf("Non existing GEM id %d\n", gem_id);
-		goto out;
-	}
-
-	ret = zynq_clk_set_rate(gem0_clk + gem_id, clk_rate);
-	if (ret)
-		goto out;
-
-	udelay(100000);
-out:
-	zynq_slcr_lock();
-}
-
 void zynq_slcr_devcfg_disable(void)
 {
 	u32 reg_val;
diff --git a/arch/arm/mach-zynq/timer.c b/arch/arm/mach-zynq/timer.c
index 0335cbe..b1bb3b8 100644
--- a/arch/arm/mach-zynq/timer.c
+++ b/arch/arm/mach-zynq/timer.c
@@ -61,7 +61,6 @@ int timer_init(void)
 			(TIMER_PRESCALE << SCUTIMER_CONTROL_PRESCALER_SHIFT) |
 			SCUTIMER_CONTROL_ENABLE_MASK;
 
-#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
 	struct udevice *dev;
 	struct clk clk;
 	int ret;
@@ -79,7 +78,6 @@ int timer_init(void)
 	gd->cpu_clk = clk_get_rate(&clk);
 
 	clk_free(&clk);
-#endif
 
 	gd->arch.timer_rate_hz = (gd->cpu_clk / 2) / (TIMER_PRESCALE + 1);
 
diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c
index 9118e49..2c95188 100644
--- a/drivers/net/zynq_gem.c
+++ b/drivers/net/zynq_gem.c
@@ -181,9 +181,7 @@ struct zynq_gem_priv {
 	struct phy_device *phydev;
 	int phy_of_handle;
 	struct mii_dev *bus;
-#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
 	struct clk tx_clk;
-#endif
 };
 
 static inline int mdio_wait(struct zynq_gem_regs *regs)
@@ -368,9 +366,7 @@ static int zynq_gem_init(struct udevice *dev)
 	u32 i, nwconfig;
 	int ret;
 	unsigned long clk_rate = 0;
-#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
 	unsigned long clk_rate_rounded;
-#endif
 	struct zynq_gem_priv *priv = dev_get_priv(dev);
 	struct zynq_gem_regs *regs = priv->iobase;
 	struct emac_bd *dummy_tx_bd = &priv->tx_bd[TX_FREE_DESC];
@@ -473,7 +469,6 @@ static int zynq_gem_init(struct udevice *dev)
 		break;
 	}
 
-#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
 	clk_rate_rounded = clk_set_rate(&priv->tx_clk, clk_rate);
 	if (IS_ERR_VALUE(clk_rate_rounded)) {
 		dev_err(dev, "failed to set tx clock rate\n");
@@ -485,10 +480,6 @@ static int zynq_gem_init(struct udevice *dev)
 		dev_err(dev, "failed to enable tx clock\n");
 		return ret;
 	}
-#else
-	zynq_slcr_gem_clk_setup((ulong)priv->iobase !=
-				ZYNQ_GEM_BASEADDR0, clk_rate);
-#endif
 
 	setbits_le32(&regs->nwctrl, ZYNQ_GEM_NWCTRL_RXEN_MASK |
 					ZYNQ_GEM_NWCTRL_TXEN_MASK);
@@ -699,9 +690,7 @@ static int zynq_gem_ofdata_to_platdata(struct udevice *dev)
 	struct eth_pdata *pdata = dev_get_platdata(dev);
 	struct zynq_gem_priv *priv = dev_get_priv(dev);
 	const char *phy_mode;
-#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
 	int ret;
-#endif
 
 	pdata->iobase = (phys_addr_t)dev_get_addr(dev);
 	priv->iobase = (struct zynq_gem_regs *)pdata->iobase;
@@ -723,13 +712,11 @@ static int zynq_gem_ofdata_to_platdata(struct udevice *dev)
 	}
 	priv->interface = pdata->phy_interface;
 
-#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
 	ret = clk_get_by_index(dev, 2, &priv->tx_clk);
 	if (ret < 0) {
 		dev_err(dev, "failed to get clock\n");
 		return ret;
 	}
-#endif
 
 	printf("ZYNQ GEM: %lx, phyaddr %x, interface %s\n", (ulong)priv->iobase,
 	       priv->phyaddr, phy_string_for_interface(priv->interface));
diff --git a/drivers/serial/serial_zynq.c b/drivers/serial/serial_zynq.c
index 4f6e7e4..a2967c0 100644
--- a/drivers/serial/serial_zynq.c
+++ b/drivers/serial/serial_zynq.c
@@ -15,7 +15,6 @@
 #include <asm/io.h>
 #include <linux/compiler.h>
 #include <serial.h>
-#include <asm/arch/clk.h>
 #include <asm/arch/hardware.h>
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -111,7 +110,6 @@ int zynq_serial_setbrg(struct udevice *dev, int baudrate)
 	struct zynq_uart_priv *priv = dev_get_priv(dev);
 	unsigned long clock;
 
-#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
 	int ret;
 	struct clk clk;
 
@@ -133,9 +131,7 @@ int zynq_serial_setbrg(struct udevice *dev, int baudrate)
 		dev_err(dev, "failed to enable clock\n");
 		return ret;
 	}
-#else
-	clock = get_uart_clk(0);
-#endif
+
 	_uart_zynq_serial_setbrg(priv->regs, clock, baudrate);
 
 	return 0;
diff --git a/include/configs/topic_miami.h b/include/configs/topic_miami.h
index 3b0fa29..a1ccc42 100644
--- a/include/configs/topic_miami.h
+++ b/include/configs/topic_miami.h
@@ -10,8 +10,6 @@
 #ifndef __CONFIG_TOPIC_MIAMI_H
 #define __CONFIG_TOPIC_MIAMI_H
 
-#define CONFIG_ZYNQ_PS_CLK_FREQ		33333333UL
-
 #define CONFIG_ZYNQ_I2C0
 #define CONFIG_ZYNQ_I2C1
 
diff --git a/include/configs/zynq_zybo.h b/include/configs/zynq_zybo.h
index b9ff391..1488fd8 100644
--- a/include/configs/zynq_zybo.h
+++ b/include/configs/zynq_zybo.h
@@ -20,9 +20,6 @@
 #define CONFIG_DISPLAY
 #define CONFIG_I2C_EDID
 
-/* Define ZYBO PS Clock Frequency to 50MHz */
-#define CONFIG_ZYNQ_PS_CLK_FREQ	50000000UL
-
 #include <configs/zynq-common.h>
 
 #endif /* __CONFIG_ZYNQ_ZYBO_H */
diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt
index 6d614c6..375b9b8 100644
--- a/scripts/config_whitelist.txt
+++ b/scripts/config_whitelist.txt
@@ -8248,7 +8248,6 @@ CONFIG_ZYNQ_GEM_I2C_MAC_OFFSET
 CONFIG_ZYNQ_HISPD_BROKEN
 CONFIG_ZYNQ_I2C0
 CONFIG_ZYNQ_I2C1
-CONFIG_ZYNQ_PS_CLK_FREQ
 CONFIG_ZYNQ_SDHCI0
 CONFIG_ZYNQ_SDHCI1
 CONFIG_ZYNQ_SDHCI_MAX_FREQ
-- 
2.7.4



Kommanditgesellschaft - Sitz: Detmold - Amtsgericht Lemgo HRA 2790 - 
Komplement?rin: Weidm?ller Interface F?hrungsgesellschaft mbH - 
Sitz: Detmold - Amtsgericht Lemgo HRB 3924; 
Gesch?ftsf?hrer: Jos? Carlos ?lvarez Tobar, Elke Eckstein, Dr. Peter K?hler, J?rg Timmermann;
USt-ID-Nr. DE124599660

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

* [U-Boot] [PATCH 8/8] clk: zynq: Add optional ethernet emio clock source support
  2017-01-04 12:27 [U-Boot] [PATCH 0/8] zynq: clk: Move zynq platform to clock framework stefan.herbrechtsmeier at weidmueller.com
                   ` (6 preceding siblings ...)
  2017-01-04 12:27 ` [U-Boot] [PATCH 7/8] zynq: Move zynq to clock framework stefan.herbrechtsmeier at weidmueller.com
@ 2017-01-04 12:27 ` stefan.herbrechtsmeier at weidmueller.com
  2017-01-10 15:06   ` Michal Simek
  7 siblings, 1 reply; 29+ messages in thread
From: stefan.herbrechtsmeier at weidmueller.com @ 2017-01-04 12:27 UTC (permalink / raw)
  To: u-boot

From: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>

Add support for the optional ethernet emio clock source to the zynq
clock framework driver.

Signed-off-by: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>

---

 drivers/clk/clk_zynq.c | 33 +++++++++++++++++++++++++++++++--
 1 file changed, 31 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/clk_zynq.c b/drivers/clk/clk_zynq.c
index d276155..6f1448d 100644
--- a/drivers/clk/clk_zynq.c
+++ b/drivers/clk/clk_zynq.c
@@ -53,6 +53,9 @@ enum zynq_clk_rclk {mio_clk, emio_clk};
 
 struct zynq_clk_priv {
 	ulong ps_clk_freq;
+#ifndef CONFIG_SPL_BUILD
+	struct clk gem_emio_clk[2];
+#endif
 };
 
 static void *zynq_clk_get_register(enum zynq_clk id)
@@ -284,10 +287,16 @@ static ulong zynq_clk_get_peripheral_rate(struct zynq_clk_priv *priv,
 #ifndef CONFIG_SPL_BUILD
 static ulong zynq_clk_get_gem_rate(struct zynq_clk_priv *priv, enum zynq_clk id)
 {
+	struct clk *parent;
+
 	if (zynq_clk_get_gem_rclk(id) == mio_clk)
 		return zynq_clk_get_peripheral_rate(priv, id, true);
 
-	return 0;
+	parent = &priv->gem_emio_clk[id - gem0_clk];
+	if (parent)
+		return clk_get_rate(parent);
+
+	return -ENXIO;
 }
 
 static unsigned long zynq_clk_calc_peripheral_two_divs(
@@ -354,10 +363,16 @@ static ulong zynq_clk_set_peripheral_rate(struct zynq_clk_priv *priv,
 static ulong zynq_clk_set_gem_rate(struct zynq_clk_priv *priv, enum zynq_clk id,
 				   ulong rate)
 {
+	struct clk *parent;
+
 	if (zynq_clk_get_gem_rclk(id) == mio_clk)
 		return zynq_clk_set_peripheral_rate(priv, id, rate, true);
 
-	return 0;
+	parent = &priv->gem_emio_clk[id - gem0_clk];
+	if (parent)
+		return clk_set_rate(parent, rate);
+
+	return -ENXIO;
 }
 #endif
 
@@ -447,6 +462,20 @@ static struct clk_ops zynq_clk_ops = {
 static int zynq_clk_probe(struct udevice *dev)
 {
 	struct zynq_clk_priv *priv = dev_get_priv(dev);
+#ifndef CONFIG_SPL_BUILD
+	unsigned int i;
+	char name[16];
+	int ret;
+
+	for (i = 0; i < 2; i++) {
+		sprintf(name, "gem%d_emio_clk", i);
+		ret = clk_get_by_name(dev, name, &priv->gem_emio_clk[i]);
+		if (ret < 0 && ret != -FDT_ERR_NOTFOUND) {
+			dev_err(dev, "failed to get %s clock\n", name);
+			return ret;
+		}
+	}
+#endif
 
 	priv->ps_clk_freq = fdtdec_get_uint(gd->fdt_blob, dev->of_offset,
 					    "ps-clk-frequency", 33333333UL);
-- 
2.7.4



Kommanditgesellschaft - Sitz: Detmold - Amtsgericht Lemgo HRA 2790 - 
Komplement?rin: Weidm?ller Interface F?hrungsgesellschaft mbH - 
Sitz: Detmold - Amtsgericht Lemgo HRB 3924; 
Gesch?ftsf?hrer: Jos? Carlos ?lvarez Tobar, Elke Eckstein, Dr. Peter K?hler, J?rg Timmermann;
USt-ID-Nr. DE124599660

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

* [U-Boot] [PATCH 1/8] net: zynq: Don't overwrite gem_rclk_ctrl with default value
  2017-01-04 12:27 ` [U-Boot] [PATCH 1/8] net: zynq: Don't overwrite gem_rclk_ctrl with default value stefan.herbrechtsmeier at weidmueller.com
@ 2017-01-10 13:52   ` Michal Simek
  2017-01-10 14:28     ` Stefan.Herbrechtsmeier at weidmueller.com
  0 siblings, 1 reply; 29+ messages in thread
From: Michal Simek @ 2017-01-10 13:52 UTC (permalink / raw)
  To: u-boot

On 4.1.2017 13:27, stefan.herbrechtsmeier at weidmueller.com wrote:
> From: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.de>
> 
> The gem[0-1]_rclk_ctrl registers control the source of the rx clock,
> control and data signals and configure via ps7_init function. Don't
> overwrite the register with the default value.

TBH I don't think this is a win for us to relate on ps7_init
configuration. There are a lot of things there but I would like to
control this in this sw instead of psu_init.

Thanks,
Michal

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: OpenPGP digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170110/43417f00/attachment.sig>

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

* [U-Boot] [PATCH 2/8] net: zynq: Add clk framework support to zynq ethernet driver
  2017-01-04 12:27 ` [U-Boot] [PATCH 2/8] net: zynq: Add clk framework support to zynq ethernet driver stefan.herbrechtsmeier at weidmueller.com
@ 2017-01-10 13:58   ` Michal Simek
  2017-01-10 14:46     ` Stefan.Herbrechtsmeier at weidmueller.com
  0 siblings, 1 reply; 29+ messages in thread
From: Michal Simek @ 2017-01-10 13:58 UTC (permalink / raw)
  To: u-boot

On 4.1.2017 13:27, stefan.herbrechtsmeier at weidmueller.com wrote:
> From: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.de>
> 
> If available use the clock framework to set the tx clock rate of the
> zynq ethernet controller.
> 
> Signed-off-by: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
> ---
> 
>  arch/arm/include/asm/arch-zynqmp/sys_proto.h |  5 -----
>  drivers/net/zynq_gem.c                       | 31 ++++++++++++++++++++++++++++
>  2 files changed, 31 insertions(+), 5 deletions(-)
> 
> diff --git a/arch/arm/include/asm/arch-zynqmp/sys_proto.h b/arch/arm/include/asm/arch-zynqmp/sys_proto.h
> index 1db2bd6..bd633a6 100644
> --- a/arch/arm/include/asm/arch-zynqmp/sys_proto.h
> +++ b/arch/arm/include/asm/arch-zynqmp/sys_proto.h
> @@ -8,11 +8,6 @@
>  #ifndef _ASM_ARCH_SYS_PROTO_H
>  #define _ASM_ARCH_SYS_PROTO_H
>  
> -/* Setup clk for network */
> -static inline void zynq_slcr_gem_clk_setup(u32 gem_id, unsigned long clk_rate)
> -{
> -}
> -
>  int zynq_slcr_get_mio_pin_status(const char *periph);
>  
>  unsigned int zynqmp_get_silicon_version(void);
> diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c
> index 9bfb89f..9118e49 100644
> --- a/drivers/net/zynq_gem.c
> +++ b/drivers/net/zynq_gem.c
> @@ -9,6 +9,7 @@
>   * SPDX-License-Identifier:	GPL-2.0+
>   */
>  
> +#include <clk.h>
>  #include <common.h>
>  #include <dm.h>
>  #include <net.h>
> @@ -180,6 +181,9 @@ struct zynq_gem_priv {
>  	struct phy_device *phydev;
>  	int phy_of_handle;
>  	struct mii_dev *bus;
> +#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
> +	struct clk tx_clk;
> +#endif
>  };
>  
>  static inline int mdio_wait(struct zynq_gem_regs *regs)
> @@ -364,6 +368,9 @@ static int zynq_gem_init(struct udevice *dev)
>  	u32 i, nwconfig;
>  	int ret;
>  	unsigned long clk_rate = 0;
> +#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
> +	unsigned long clk_rate_rounded;
> +#endif
>  	struct zynq_gem_priv *priv = dev_get_priv(dev);
>  	struct zynq_gem_regs *regs = priv->iobase;
>  	struct emac_bd *dummy_tx_bd = &priv->tx_bd[TX_FREE_DESC];
> @@ -466,8 +473,22 @@ static int zynq_gem_init(struct udevice *dev)
>  		break;
>  	}
>  
> +#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
> +	clk_rate_rounded = clk_set_rate(&priv->tx_clk, clk_rate);
> +	if (IS_ERR_VALUE(clk_rate_rounded)) {
> +		dev_err(dev, "failed to set tx clock rate\n");
> +		return clk_rate_rounded;
> +	}
> +
> +	ret = clk_enable(&priv->tx_clk);
> +	if (ret && ret != -ENOSYS) {
> +		dev_err(dev, "failed to enable tx clock\n");
> +		return ret;
> +	}
> +#else
>  	zynq_slcr_gem_clk_setup((ulong)priv->iobase !=
>  				ZYNQ_GEM_BASEADDR0, clk_rate);
> +#endif
>  
>  	setbits_le32(&regs->nwctrl, ZYNQ_GEM_NWCTRL_RXEN_MASK |
>  					ZYNQ_GEM_NWCTRL_TXEN_MASK);
> @@ -678,6 +699,9 @@ static int zynq_gem_ofdata_to_platdata(struct udevice *dev)
>  	struct eth_pdata *pdata = dev_get_platdata(dev);
>  	struct zynq_gem_priv *priv = dev_get_priv(dev);
>  	const char *phy_mode;
> +#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
> +	int ret;
> +#endif
>  
>  	pdata->iobase = (phys_addr_t)dev_get_addr(dev);
>  	priv->iobase = (struct zynq_gem_regs *)pdata->iobase;
> @@ -699,6 +723,13 @@ static int zynq_gem_ofdata_to_platdata(struct udevice *dev)
>  	}
>  	priv->interface = pdata->phy_interface;
>  
> +#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
> +	ret = clk_get_by_index(dev, 2, &priv->tx_clk);
> +	if (ret < 0) {
> +		dev_err(dev, "failed to get clock\n");
> +		return ret;
> +	}
> +#endif
>  
>  	printf("ZYNQ GEM: %lx, phyaddr %x, interface %s\n", (ulong)priv->iobase,
>  	       priv->phyaddr, phy_string_for_interface(priv->interface));
> 

Can you please rebase it on the top of this?
https://patchwork.ozlabs.org/patch/706419/

The reason why this patch was written in this way is that we don't have
full zynqmp clk driver yet but we are using fixed clock where you can't
run set_rate which fails.

The patch above will be merged soon that's why please rebase it on the
top of it.
Here is branch with this patch.
http://git.denx.de/?p=u-boot/u-boot-microblaze.git;a=summary

Thanks,
Michal



-- 
Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel - Xilinx Microblaze
Maintainer of Linux kernel - Xilinx Zynq ARM and ZynqMP ARM64 SoCs
U-Boot custodian - Xilinx Microblaze/Zynq/ZynqMP SoCs


-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: OpenPGP digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170110/f664e931/attachment.sig>

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

* [U-Boot] [PATCH 3/8] zynq: Add clk framework support to zynq timer
  2017-01-04 12:27 ` [U-Boot] [PATCH 3/8] zynq: Add clk framework support to zynq timer stefan.herbrechtsmeier at weidmueller.com
@ 2017-01-10 14:10   ` Michal Simek
  2017-01-10 14:54     ` Stefan.Herbrechtsmeier at weidmueller.com
  0 siblings, 1 reply; 29+ messages in thread
From: Michal Simek @ 2017-01-10 14:10 UTC (permalink / raw)
  To: u-boot

On 4.1.2017 13:27, stefan.herbrechtsmeier at weidmueller.com wrote:
> From: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
> 
> If available use the clock framework to calculate the clock rate of the
> zynq timer.
> 
> Signed-off-by: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
> ---
> 
>  arch/arm/mach-zynq/timer.c | 25 +++++++++++++++++++++++++
>  1 file changed, 25 insertions(+)
> 
> diff --git a/arch/arm/mach-zynq/timer.c b/arch/arm/mach-zynq/timer.c
> index 8ff82dc..0335cbe 100644
> --- a/arch/arm/mach-zynq/timer.c
> +++ b/arch/arm/mach-zynq/timer.c
> @@ -1,4 +1,7 @@
>  /*
> + * Copyright (C) 2017 Weidm?ller Interface GmbH & Co. KG
> + * Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
> + *
>   * Copyright (C) 2012 Michal Simek <monstr@monstr.eu>
>   * Copyright (C) 2011-2012 Xilinx, Inc. All rights reserved.
>   *
> @@ -25,8 +28,10 @@
>   * SPDX-License-Identifier:	GPL-2.0+
>   */
>  
> +#include <clk.h>
>  #include <common.h>
>  #include <div64.h>
> +#include <dm.h>
>  #include <asm/io.h>
>  #include <asm/arch/hardware.h>
>  #include <asm/arch/clk.h>
> @@ -56,6 +61,26 @@ int timer_init(void)
>  			(TIMER_PRESCALE << SCUTIMER_CONTROL_PRESCALER_SHIFT) |
>  			SCUTIMER_CONTROL_ENABLE_MASK;
>  
> +#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
> +	struct udevice *dev;
> +	struct clk clk;
> +	int ret;
> +
> +	ret = uclass_get_device_by_driver(UCLASS_CLK,
> +		DM_GET_DRIVER(zynq_clk), &dev);
> +	if (ret)
> +		return ret;
> +
> +	clk.id = cpu_6or4x_clk;

This information is already present in DT file. What's the reason not to
take it from it?

> +	ret = clk_request(dev, &clk);
> +	if (ret < 0)
> +		return ret;
> +
> +	gd->cpu_clk = clk_get_rate(&clk);
> +
> +	clk_free(&clk);

Not clk expert but isn't there a way to handle it like it is handled for
other drivers? clk_get(), clk_get_rate()?

> +#endif
> +
>  	gd->arch.timer_rate_hz = (gd->cpu_clk / 2) / (TIMER_PRESCALE + 1);
>  
>  	/* Load the timer counter register */
> 

Thanks,
Michal


-- 
Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel - Xilinx Microblaze
Maintainer of Linux kernel - Xilinx Zynq ARM and ZynqMP ARM64 SoCs
U-Boot custodian - Xilinx Microblaze/Zynq/ZynqMP SoCs


-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: OpenPGP digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170110/69a56747/attachment.sig>

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

* [U-Boot] [PATCH 4/8] zynq: Move static clock names into separate array
  2017-01-04 12:27 ` [U-Boot] [PATCH 4/8] zynq: Move static clock names into separate array stefan.herbrechtsmeier at weidmueller.com
@ 2017-01-10 14:15   ` Michal Simek
  0 siblings, 0 replies; 29+ messages in thread
From: Michal Simek @ 2017-01-10 14:15 UTC (permalink / raw)
  To: u-boot

On 4.1.2017 13:27, stefan.herbrechtsmeier at weidmueller.com wrote:
> From: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.de>
> 
> The clock names are static and correspond to the clock id. Separate
> them from the dynamic filled clock array.
> 
> Signed-off-by: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
> ---
> 
>  arch/arm/mach-zynq/clk.c | 121 +++++++++++++++++++++++------------------------
>  1 file changed, 60 insertions(+), 61 deletions(-)
> 
> diff --git a/arch/arm/mach-zynq/clk.c b/arch/arm/mach-zynq/clk.c
> index 40383c1..7bff964 100644
> --- a/arch/arm/mach-zynq/clk.c
> +++ b/arch/arm/mach-zynq/clk.c
> @@ -58,7 +58,6 @@ struct zynq_clk_ops {
>  
>  /**
>   * struct clk:
> - * @name:	Clock name
>   * @frequency:	Currenct frequency
>   * @parent:	Parent clock
>   * @flags:	Clock flags
> @@ -66,7 +65,6 @@ struct zynq_clk_ops {
>   * @ops:	Clock operations
>   */
>  struct clk {
> -	char		*name;
>  	unsigned long	frequency;
>  	enum zynq_clk	parent;
>  	unsigned int	flags;
> @@ -77,6 +75,20 @@ struct clk {
>  
>  static struct clk clks[clk_max];
>  
> +static const char * const clk_names[clk_max] = {
> +	"armpll", "ddrpll", "iopll",
> +	"cpu_6or4x", "cpu_3or2x", "cpu_2x", "cpu_1x",
> +	"ddr2x", "ddr3x", "dci",
> +	"lqspi", "smc", "pcap", "gem0", "gem1",
> +	"fclk0", "fclk1", "fclk2", "fclk3", "can0", "can1",
> +	"sdio0", "sdio1", "uart0", "uart1", "spi0", "spi1", "dma",
> +	"usb0_aper", "usb1_aper", "gem0_aper", "gem1_aper",
> +	"sdio0_aper", "sdio1_aper", "spi0_aper", "spi1_aper",
> +	"can0_aper", "can1_aper", "i2c0_aper", "i2c1_aper",
> +	"uart0_aper", "uart1_aper", "gpio_aper", "lqspi_aper",
> +	"smc_aper", "swdt", "dbg_trc", "dbg_apb"
> +};
> +
>  /**
>   * __zynq_clk_cpu_get_parent() - Decode clock multiplexer
>   * @srcsel:	Mux select value
> @@ -140,14 +152,12 @@ static void init_ddr_clocks(void)
>  	/* DDR2x */
>  	clks[ddr2x_clk].reg = &slcr_base->ddr_clk_ctrl;
>  	clks[ddr2x_clk].parent = ddrpll_clk;
> -	clks[ddr2x_clk].name = "ddr_2x";
>  	clks[ddr2x_clk].frequency = ddr2x_get_rate(&clks[ddr2x_clk]);
>  	clks[ddr2x_clk].ops.get_rate = ddr2x_get_rate;
>  
>  	/* DDR3x */
>  	clks[ddr3x_clk].reg = &slcr_base->ddr_clk_ctrl;
>  	clks[ddr3x_clk].parent = ddrpll_clk;
> -	clks[ddr3x_clk].name = "ddr_3x";
>  	clks[ddr3x_clk].frequency = ddr3x_get_rate(&clks[ddr3x_clk]);
>  	clks[ddr3x_clk].ops.get_rate = ddr3x_get_rate;
>  
> @@ -159,7 +169,6 @@ static void init_ddr_clocks(void)
>  	clks[dci_clk].parent = ddrpll_clk;
>  	clks[dci_clk].frequency = DIV_ROUND_CLOSEST(
>  			DIV_ROUND_CLOSEST(prate, div0), div1);
> -	clks[dci_clk].name = "dci";
>  
>  	gd->bd->bi_ddr_freq = clks[ddr3x_clk].frequency / 1000000;
>  }
> @@ -181,24 +190,20 @@ static void init_cpu_clocks(void)
>  	clks[cpu_6or4x_clk].parent = parent;
>  	clks[cpu_6or4x_clk].frequency = DIV_ROUND_CLOSEST(
>  			zynq_clk_get_rate(parent), div);
> -	clks[cpu_6or4x_clk].name = "cpu_6or4x";
>  
>  	clks[cpu_3or2x_clk].reg = &slcr_base->arm_clk_ctrl;
>  	clks[cpu_3or2x_clk].parent = cpu_6or4x_clk;
>  	clks[cpu_3or2x_clk].frequency = zynq_clk_get_rate(cpu_6or4x_clk) / 2;
> -	clks[cpu_3or2x_clk].name = "cpu_3or2x";
>  
>  	clks[cpu_2x_clk].reg = &slcr_base->arm_clk_ctrl;
>  	clks[cpu_2x_clk].parent = cpu_6or4x_clk;
>  	clks[cpu_2x_clk].frequency = zynq_clk_get_rate(cpu_6or4x_clk) /
>  			(2 + clk_621);
> -	clks[cpu_2x_clk].name = "cpu_2x";
>  
>  	clks[cpu_1x_clk].reg = &slcr_base->arm_clk_ctrl;
>  	clks[cpu_1x_clk].parent = cpu_6or4x_clk;
>  	clks[cpu_1x_clk].frequency = zynq_clk_get_rate(cpu_6or4x_clk) /
>  			(4 + 2 * clk_621);
> -	clks[cpu_1x_clk].name = "cpu_1x";
>  }
>  
>  /**
> @@ -338,13 +343,11 @@ static enum zynq_clk zynq_clk_periph_get_parent(struct clk *clk)
>   * zynq_clk_register_periph_clk() - Set up a peripheral clock with the framework
>   * @clk:	Pointer to struct clk for the clock
>   * @ctrl:	Clock control register
> - * @name:	PLL name
>   * @two_divs:	Indicates whether the clock features one or two dividers
>   */
> -static int zynq_clk_register_periph_clk(struct clk *clk, u32 *ctrl, char *name,
> +static int zynq_clk_register_periph_clk(struct clk *clk, u32 *ctrl,
>  		bool two_divs)
>  {
> -	clk->name = name;
>  	clk->reg = ctrl;
>  	if (two_divs)
>  		clk->flags = ZYNQ_CLK_FLAGS_HAS_2_DIVS;
> @@ -358,59 +361,57 @@ static int zynq_clk_register_periph_clk(struct clk *clk, u32 *ctrl, char *name,
>  
>  static void init_periph_clocks(void)
>  {
> -	zynq_clk_register_periph_clk(&clks[gem0_clk], &slcr_base->gem0_clk_ctrl,
> -				     "gem0", 1);
> -	zynq_clk_register_periph_clk(&clks[gem1_clk], &slcr_base->gem1_clk_ctrl,
> -				     "gem1", 1);
> +	zynq_clk_register_periph_clk(&clks[gem0_clk],
> +				     &slcr_base->gem0_clk_ctrl, 1);
> +	zynq_clk_register_periph_clk(&clks[gem1_clk],
> +				     &slcr_base->gem1_clk_ctrl, 1);
>  

These position changes are a little bit confusing but I get it.

> -	zynq_clk_register_periph_clk(&clks[smc_clk], &slcr_base->smc_clk_ctrl,
> -				     "smc", 0);
> +	zynq_clk_register_periph_clk(&clks[smc_clk],
> +				     &slcr_base->smc_clk_ctrl, 0);
>  
>  	zynq_clk_register_periph_clk(&clks[lqspi_clk],
> -				     &slcr_base->lqspi_clk_ctrl, "lqspi", 0);
> +				     &slcr_base->lqspi_clk_ctrl, 0);
>  
>  	zynq_clk_register_periph_clk(&clks[sdio0_clk],
> -				     &slcr_base->sdio_clk_ctrl, "sdio0", 0);
> +				     &slcr_base->sdio_clk_ctrl, 0);
>  	zynq_clk_register_periph_clk(&clks[sdio1_clk],
> -				     &slcr_base->sdio_clk_ctrl, "sdio1", 0);
> +				     &slcr_base->sdio_clk_ctrl, 0);
>  
> -	zynq_clk_register_periph_clk(&clks[spi0_clk], &slcr_base->spi_clk_ctrl,
> -				     "spi0", 0);
> -	zynq_clk_register_periph_clk(&clks[spi1_clk], &slcr_base->spi_clk_ctrl,
> -				     "spi1", 0);
> +	zynq_clk_register_periph_clk(&clks[spi0_clk],
> +				     &slcr_base->spi_clk_ctrl, 0);
> +	zynq_clk_register_periph_clk(&clks[spi1_clk],
> +				     &slcr_base->spi_clk_ctrl, 0);
>  
>  	zynq_clk_register_periph_clk(&clks[uart0_clk],
> -				     &slcr_base->uart_clk_ctrl, "uart0", 0);
> +				     &slcr_base->uart_clk_ctrl, 0);
>  	zynq_clk_register_periph_clk(&clks[uart1_clk],
> -				     &slcr_base->uart_clk_ctrl, "uart1", 0);
> +				     &slcr_base->uart_clk_ctrl, 0);
>  
>  	zynq_clk_register_periph_clk(&clks[dbg_trc_clk],
> -				     &slcr_base->dbg_clk_ctrl, "dbg_trc", 0);
> +				     &slcr_base->dbg_clk_ctrl, 0);
>  	zynq_clk_register_periph_clk(&clks[dbg_apb_clk],
> -				     &slcr_base->dbg_clk_ctrl, "dbg_apb", 0);
> +				     &slcr_base->dbg_clk_ctrl, 0);
>  
>  	zynq_clk_register_periph_clk(&clks[pcap_clk],
> -				     &slcr_base->pcap_clk_ctrl, "pcap", 0);
> +				     &slcr_base->pcap_clk_ctrl, 0);
>  
>  	zynq_clk_register_periph_clk(&clks[fclk0_clk],
> -				     &slcr_base->fpga0_clk_ctrl, "fclk0", 1);
> +				     &slcr_base->fpga0_clk_ctrl, 1);
>  	zynq_clk_register_periph_clk(&clks[fclk1_clk],
> -				     &slcr_base->fpga1_clk_ctrl, "fclk1", 1);
> +				     &slcr_base->fpga1_clk_ctrl, 1);
>  	zynq_clk_register_periph_clk(&clks[fclk2_clk],
> -				     &slcr_base->fpga2_clk_ctrl, "fclk2", 1);
> +				     &slcr_base->fpga2_clk_ctrl, 1);
>  	zynq_clk_register_periph_clk(&clks[fclk3_clk],
> -				     &slcr_base->fpga3_clk_ctrl, "fclk3", 1);
> +				     &slcr_base->fpga3_clk_ctrl, 1);
>  }
>  
>  /**
>   * zynq_clk_register_aper_clk() - Set up a APER clock with the framework
>   * @clk:	Pointer to struct clk for the clock
>   * @ctrl:	Clock control register
> - * @name:	PLL name
>   */
> -static void zynq_clk_register_aper_clk(struct clk *clk, u32 *ctrl, char *name)
> +static void zynq_clk_register_aper_clk(struct clk *clk, u32 *ctrl)
>  {
> -	clk->name = name;
>  	clk->reg = ctrl;
>  	clk->parent = cpu_1x_clk;
>  	clk->frequency = zynq_clk_get_rate(clk->parent);
> @@ -419,48 +420,48 @@ static void zynq_clk_register_aper_clk(struct clk *clk, u32 *ctrl, char *name)
>  static void init_aper_clocks(void)
>  {
>  	zynq_clk_register_aper_clk(&clks[usb0_aper_clk],
> -				   &slcr_base->aper_clk_ctrl, "usb0_aper");
> +				   &slcr_base->aper_clk_ctrl);
>  	zynq_clk_register_aper_clk(&clks[usb1_aper_clk],
> -				   &slcr_base->aper_clk_ctrl, "usb1_aper");
> +				   &slcr_base->aper_clk_ctrl);
>  
>  	zynq_clk_register_aper_clk(&clks[gem0_aper_clk],
> -				   &slcr_base->aper_clk_ctrl, "gem0_aper");
> +				   &slcr_base->aper_clk_ctrl);
>  	zynq_clk_register_aper_clk(&clks[gem1_aper_clk],
> -				   &slcr_base->aper_clk_ctrl, "gem1_aper");
> +				   &slcr_base->aper_clk_ctrl);
>  
>  	zynq_clk_register_aper_clk(&clks[sdio0_aper_clk],
> -				   &slcr_base->aper_clk_ctrl, "sdio0_aper");
> +				   &slcr_base->aper_clk_ctrl);
>  	zynq_clk_register_aper_clk(&clks[sdio1_aper_clk],
> -				   &slcr_base->aper_clk_ctrl, "sdio1_aper");
> +				   &slcr_base->aper_clk_ctrl);
>  
>  	zynq_clk_register_aper_clk(&clks[spi0_aper_clk],
> -				   &slcr_base->aper_clk_ctrl, "spi0_aper");
> +				   &slcr_base->aper_clk_ctrl);
>  	zynq_clk_register_aper_clk(&clks[spi1_aper_clk],
> -				   &slcr_base->aper_clk_ctrl, "spi1_aper");
> +				   &slcr_base->aper_clk_ctrl);
>  
>  	zynq_clk_register_aper_clk(&clks[can0_aper_clk],
> -				   &slcr_base->aper_clk_ctrl, "can0_aper");
> +				   &slcr_base->aper_clk_ctrl);
>  	zynq_clk_register_aper_clk(&clks[can1_aper_clk],
> -				   &slcr_base->aper_clk_ctrl, "can1_aper");
> +				   &slcr_base->aper_clk_ctrl);
>  
>  	zynq_clk_register_aper_clk(&clks[i2c0_aper_clk],
> -				   &slcr_base->aper_clk_ctrl, "i2c0_aper");
> +				   &slcr_base->aper_clk_ctrl);
>  	zynq_clk_register_aper_clk(&clks[i2c1_aper_clk],
> -				   &slcr_base->aper_clk_ctrl, "i2c1_aper");
> +				   &slcr_base->aper_clk_ctrl);
>  
>  	zynq_clk_register_aper_clk(&clks[uart0_aper_clk],
> -				   &slcr_base->aper_clk_ctrl, "uart0_aper");
> +				   &slcr_base->aper_clk_ctrl);
>  	zynq_clk_register_aper_clk(&clks[uart1_aper_clk],
> -				   &slcr_base->aper_clk_ctrl, "uart1_aper");
> +				   &slcr_base->aper_clk_ctrl);
>  
>  	zynq_clk_register_aper_clk(&clks[gpio_aper_clk],
> -				   &slcr_base->aper_clk_ctrl, "gpio_aper");
> +				   &slcr_base->aper_clk_ctrl);
>  
>  	zynq_clk_register_aper_clk(&clks[lqspi_aper_clk],
> -				   &slcr_base->aper_clk_ctrl, "lqspi_aper");
> +				   &slcr_base->aper_clk_ctrl);
>  
>  	zynq_clk_register_aper_clk(&clks[smc_aper_clk],
> -				   &slcr_base->aper_clk_ctrl, "smc_aper");
> +				   &slcr_base->aper_clk_ctrl);
>  }
>  
>  /**
> @@ -496,13 +497,11 @@ static unsigned long zynq_clk_pll_get_rate(struct clk *pll)
>   * zynq_clk_register_pll() - Set up a PLL with the framework
>   * @clk:	Pointer to struct clk for the PLL
>   * @ctrl:	PLL control register
> - * @name:	PLL name
>   * @prate:	PLL input clock rate
>   */
> -static void zynq_clk_register_pll(struct clk *clk, u32 *ctrl, char *name,
> +static void zynq_clk_register_pll(struct clk *clk, u32 *ctrl,
>  		unsigned long prate)
>  {
> -	clk->name = name;
>  	clk->reg = ctrl;
>  	clk->frequency = zynq_clk_pll_get_rate(clk);
>  	clk->ops.get_rate = zynq_clk_pll_get_rate;
> @@ -583,11 +582,11 @@ unsigned long get_uart_clk(int dev_index)
>  int set_cpu_clk_info(void)
>  {
>  	zynq_clk_register_pll(&clks[armpll_clk], &slcr_base->arm_pll_ctrl,
> -			      "armpll", CONFIG_ZYNQ_PS_CLK_FREQ);
> +			      CONFIG_ZYNQ_PS_CLK_FREQ);
>  	zynq_clk_register_pll(&clks[ddrpll_clk], &slcr_base->ddr_pll_ctrl,
> -			      "ddrpll", CONFIG_ZYNQ_PS_CLK_FREQ);
> +			      CONFIG_ZYNQ_PS_CLK_FREQ);
>  	zynq_clk_register_pll(&clks[iopll_clk], &slcr_base->io_pll_ctrl,
> -			      "iopll", CONFIG_ZYNQ_PS_CLK_FREQ);
> +			      CONFIG_ZYNQ_PS_CLK_FREQ);
>  
>  	init_ddr_clocks();
>  	init_cpu_clocks();
> @@ -639,7 +638,7 @@ int zynq_clk_set_rate(enum zynq_clk clk, unsigned long rate)
>   */
>  const char *zynq_clk_get_name(enum zynq_clk clk)
>  {
> -	return clks[clk].name;
> +	return clk_names[clk];
>  }
>  
>  /**
> 

Patch is good.
Reviewed-by: Michal Simek <michal.simek@xilinx.com>

Thanks,
Michal


-- 
Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel - Xilinx Microblaze
Maintainer of Linux kernel - Xilinx Zynq ARM and ZynqMP ARM64 SoCs
U-Boot custodian - Xilinx Microblaze/Zynq/ZynqMP SoCs


-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: OpenPGP digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170110/1e4f5d03/attachment.sig>

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

* [U-Boot] [PATCH 5/8] zynq: Remove zynq_clk_get_name function
  2017-01-04 12:27 ` [U-Boot] [PATCH 5/8] zynq: Remove zynq_clk_get_name function stefan.herbrechtsmeier at weidmueller.com
@ 2017-01-10 14:16   ` Michal Simek
  0 siblings, 0 replies; 29+ messages in thread
From: Michal Simek @ 2017-01-10 14:16 UTC (permalink / raw)
  To: u-boot

On 4.1.2017 13:27, stefan.herbrechtsmeier at weidmueller.com wrote:
> From: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
> 
> The zynq_clk_get_name function is only used once inside the clock
> driver. Replace the function call with the one-line code.
> 
> Signed-off-by: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
> ---
> 
>  arch/arm/mach-zynq/clk.c              | 12 +-----------
>  arch/arm/mach-zynq/include/mach/clk.h |  1 -
>  2 files changed, 1 insertion(+), 12 deletions(-)
> 
> diff --git a/arch/arm/mach-zynq/clk.c b/arch/arm/mach-zynq/clk.c
> index 7bff964..570ebd7 100644
> --- a/arch/arm/mach-zynq/clk.c
> +++ b/arch/arm/mach-zynq/clk.c
> @@ -632,16 +632,6 @@ int zynq_clk_set_rate(enum zynq_clk clk, unsigned long rate)
>  }
>  
>  /**
> - * zynq_clk_get_name() - Get clock name
> - * @clk:	Clock identifier
> - * Returns the name of @clk.
> - */
> -const char *zynq_clk_get_name(enum zynq_clk clk)
> -{
> -	return clk_names[clk];
> -}
> -
> -/**
>   * soc_clk_dump() - Print clock frequencies
>   * Returns zero on success
>   *
> @@ -653,7 +643,7 @@ int soc_clk_dump(void)
>  
>  	printf("clk\t\tfrequency\n");
>  	for (i = 0; i < clk_max; i++) {
> -		const char *name = zynq_clk_get_name(i);
> +		const char *name = clk_names[i];
>  		if (name)
>  			printf("%10s%20lu\n", name, zynq_clk_get_rate(i));
>  	}
> diff --git a/arch/arm/mach-zynq/include/mach/clk.h b/arch/arm/mach-zynq/include/mach/clk.h
> index 250c5bc..5c2758a 100644
> --- a/arch/arm/mach-zynq/include/mach/clk.h
> +++ b/arch/arm/mach-zynq/include/mach/clk.h
> @@ -23,7 +23,6 @@ enum zynq_clk {
>  void zynq_clk_early_init(void);
>  int zynq_clk_set_rate(enum zynq_clk clk, unsigned long rate);
>  unsigned long zynq_clk_get_rate(enum zynq_clk clk);
> -const char *zynq_clk_get_name(enum zynq_clk clk);
>  unsigned long get_uart_clk(int dev_id);
>  
>  #endif
> 

Reviewed-by: Michal Simek <michal.simek@xilinx.com>

Thanks,
Michal


-- 
Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel - Xilinx Microblaze
Maintainer of Linux kernel - Xilinx Zynq ARM and ZynqMP ARM64 SoCs
U-Boot custodian - Xilinx Microblaze/Zynq/ZynqMP SoCs


-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: OpenPGP digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170110/bde46ef7/attachment.sig>

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

* [U-Boot] [PATCH 1/8] net: zynq: Don't overwrite gem_rclk_ctrl with default value
  2017-01-10 13:52   ` Michal Simek
@ 2017-01-10 14:28     ` Stefan.Herbrechtsmeier at weidmueller.com
  2017-01-10 15:26       ` Michal Simek
  0 siblings, 1 reply; 29+ messages in thread
From: Stefan.Herbrechtsmeier at weidmueller.com @ 2017-01-10 14:28 UTC (permalink / raw)
  To: u-boot

Hi Michal,

> -----Urspr?ngliche Nachricht-----
> Von: Michal Simek [mailto:monstr at monstr.eu]
> Gesendet: Dienstag, 10. Januar 2017 14:53
> An: Herbrechtsmeier, Stefan; u-boot at lists.denx.de
> Cc: Herbrechtsmeier, Stefan; Michal Simek; Jagan Teki; Albert Aribaud;
> Joe Hershberger; Mike Looijmans
> Betreff: Re: [PATCH 1/8] net: zynq: Don't overwrite gem_rclk_ctrl with
> default value
> 
> On 4.1.2017 13:27, stefan.herbrechtsmeier at weidmueller.com wrote:
> > From: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.de>
> >
> > The gem[0-1]_rclk_ctrl registers control the source of the rx clock,
> > control and data signals and configure via ps7_init function. Don't
> > overwrite the register with the default value.
> 
> TBH I don't think this is a win for us to relate on ps7_init
> configuration. There are a lot of things there but I would like to
> control this in this sw instead of psu_init.

At the moment the ps7_init only touch the register if the board doesn't use the default configuration. U-boot overwrite the register with the default value if 'xlnx,emio' isn't set in the device tree. It doesn't change the value to gem_rclk_ctrl if 'xlnx,emio' is set.

At the moment the clock configuration is managed by the ps7_init and only the gem_rclk_ctrl configuration is overwritten by u-boot. I don't think it is correct do overwrite some part of the clock tree configuration which is generated by Xilinx tools.

Regards,
  Stefan



Kommanditgesellschaft - Sitz: Detmold - Amtsgericht Lemgo HRA 2790 - 
Komplement?rin: Weidm?ller Interface F?hrungsgesellschaft mbH - 
Sitz: Detmold - Amtsgericht Lemgo HRB 3924; 
Gesch?ftsf?hrer: Jos? Carlos ?lvarez Tobar, Elke Eckstein, Dr. Peter K?hler, J?rg Timmermann;
USt-ID-Nr. DE124599660

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

* [U-Boot] [PATCH 2/8] net: zynq: Add clk framework support to zynq ethernet driver
  2017-01-10 13:58   ` Michal Simek
@ 2017-01-10 14:46     ` Stefan.Herbrechtsmeier at weidmueller.com
  2017-01-10 15:23       ` Michal Simek
  0 siblings, 1 reply; 29+ messages in thread
From: Stefan.Herbrechtsmeier at weidmueller.com @ 2017-01-10 14:46 UTC (permalink / raw)
  To: u-boot

> -----Urspr?ngliche Nachricht-----
> Von: Michal Simek [mailto:monstr at monstr.eu]
> Gesendet: Dienstag, 10. Januar 2017 14:59
> An: Herbrechtsmeier, Stefan; u-boot at lists.denx.de
> Cc: Herbrechtsmeier, Stefan; Albert Aribaud; Michal Simek; Joe
> Hershberger
> Betreff: Re: [PATCH 2/8] net: zynq: Add clk framework support to zynq
> ethernet driver
> 
> On 4.1.2017 13:27, stefan.herbrechtsmeier at weidmueller.com wrote:
> > From: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.de>
> >
> > If available use the clock framework to set the tx clock rate of the
> > zynq ethernet controller.
> >
> > Signed-off-by: Stefan Herbrechtsmeier
> > <stefan.herbrechtsmeier@weidmueller.com>
> > ---
> >
> >  arch/arm/include/asm/arch-zynqmp/sys_proto.h |  5 -----
> >  drivers/net/zynq_gem.c                       | 31
> ++++++++++++++++++++++++++++
> >  2 files changed, 31 insertions(+), 5 deletions(-)
> >
> > diff --git a/arch/arm/include/asm/arch-zynqmp/sys_proto.h
> > b/arch/arm/include/asm/arch-zynqmp/sys_proto.h
> > index 1db2bd6..bd633a6 100644
> > --- a/arch/arm/include/asm/arch-zynqmp/sys_proto.h
> > +++ b/arch/arm/include/asm/arch-zynqmp/sys_proto.h
> > @@ -8,11 +8,6 @@
> >  #ifndef _ASM_ARCH_SYS_PROTO_H
> >  #define _ASM_ARCH_SYS_PROTO_H
> >
> > -/* Setup clk for network */
> > -static inline void zynq_slcr_gem_clk_setup(u32 gem_id, unsigned long
> > clk_rate) -{ -}
> > -
> >  int zynq_slcr_get_mio_pin_status(const char *periph);
> >
> >  unsigned int zynqmp_get_silicon_version(void); diff --git
> > a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c index
> > 9bfb89f..9118e49 100644
> > --- a/drivers/net/zynq_gem.c
> > +++ b/drivers/net/zynq_gem.c
> > @@ -9,6 +9,7 @@
> >   * SPDX-License-Identifier:	GPL-2.0+
> >   */
> >
> > +#include <clk.h>
> >  #include <common.h>
> >  #include <dm.h>
> >  #include <net.h>
> > @@ -180,6 +181,9 @@ struct zynq_gem_priv {
> >  	struct phy_device *phydev;
> >  	int phy_of_handle;
> >  	struct mii_dev *bus;
> > +#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
> > +	struct clk tx_clk;
> > +#endif
> >  };
> >
> >  static inline int mdio_wait(struct zynq_gem_regs *regs) @@ -364,6
> > +368,9 @@ static int zynq_gem_init(struct udevice *dev)
> >  	u32 i, nwconfig;
> >  	int ret;
> >  	unsigned long clk_rate = 0;
> > +#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
> > +	unsigned long clk_rate_rounded;
> > +#endif
> >  	struct zynq_gem_priv *priv = dev_get_priv(dev);
> >  	struct zynq_gem_regs *regs = priv->iobase;
> >  	struct emac_bd *dummy_tx_bd = &priv->tx_bd[TX_FREE_DESC]; @@ -
> 466,8
> > +473,22 @@ static int zynq_gem_init(struct udevice *dev)
> >  		break;
> >  	}
> >
> > +#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
> > +	clk_rate_rounded = clk_set_rate(&priv->tx_clk, clk_rate);
> > +	if (IS_ERR_VALUE(clk_rate_rounded)) {
> > +		dev_err(dev, "failed to set tx clock rate\n");
> > +		return clk_rate_rounded;
> > +	}
> > +
> > +	ret = clk_enable(&priv->tx_clk);
> > +	if (ret && ret != -ENOSYS) {
> > +		dev_err(dev, "failed to enable tx clock\n");
> > +		return ret;
> > +	}
> > +#else
> >  	zynq_slcr_gem_clk_setup((ulong)priv->iobase !=
> >  				ZYNQ_GEM_BASEADDR0, clk_rate);
> > +#endif
> >
> >  	setbits_le32(&regs->nwctrl, ZYNQ_GEM_NWCTRL_RXEN_MASK |
> >  					ZYNQ_GEM_NWCTRL_TXEN_MASK);
> > @@ -678,6 +699,9 @@ static int zynq_gem_ofdata_to_platdata(struct
> udevice *dev)
> >  	struct eth_pdata *pdata = dev_get_platdata(dev);
> >  	struct zynq_gem_priv *priv = dev_get_priv(dev);
> >  	const char *phy_mode;
> > +#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
> > +	int ret;
> > +#endif
> >
> >  	pdata->iobase = (phys_addr_t)dev_get_addr(dev);
> >  	priv->iobase = (struct zynq_gem_regs *)pdata->iobase; @@ -699,6
> > +723,13 @@ static int zynq_gem_ofdata_to_platdata(struct udevice
> *dev)
> >  	}
> >  	priv->interface = pdata->phy_interface;
> >
> > +#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
> > +	ret = clk_get_by_index(dev, 2, &priv->tx_clk);
> > +	if (ret < 0) {
> > +		dev_err(dev, "failed to get clock\n");
> > +		return ret;
> > +	}
> > +#endif
> >
> >  	printf("ZYNQ GEM: %lx, phyaddr %x, interface %s\n", (ulong)priv-
> >iobase,
> >  	       priv->phyaddr, phy_string_for_interface(priv->interface));
> >
> 
> Can you please rebase it on the top of this?
> https://patchwork.ozlabs.org/patch/706419/
> 
> The reason why this patch was written in this way is that we don't have
> full zynqmp clk driver yet but we are using fixed clock where you can't
> run set_rate which fails.
> 
The patch assumes that the EMIO_ENET_TX_CLK is always fixed. Is this true?

Why don't you add a set_rate() function to the fixed clock?

Additionally the patch is missing an enable function call.

I don't think the emio configuration should be keep in the Ethernet driver as it is part of the clock configuration and doesn't influent the network interface.

Regards,
  Stefan



Kommanditgesellschaft - Sitz: Detmold - Amtsgericht Lemgo HRA 2790 - 
Komplement?rin: Weidm?ller Interface F?hrungsgesellschaft mbH - 
Sitz: Detmold - Amtsgericht Lemgo HRB 3924; 
Gesch?ftsf?hrer: Jos? Carlos ?lvarez Tobar, Elke Eckstein, Dr. Peter K?hler, J?rg Timmermann;
USt-ID-Nr. DE124599660

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

* [U-Boot] [PATCH 3/8] zynq: Add clk framework support to zynq timer
  2017-01-10 14:10   ` Michal Simek
@ 2017-01-10 14:54     ` Stefan.Herbrechtsmeier at weidmueller.com
  2017-01-10 15:08       ` Michal Simek
  0 siblings, 1 reply; 29+ messages in thread
From: Stefan.Herbrechtsmeier at weidmueller.com @ 2017-01-10 14:54 UTC (permalink / raw)
  To: u-boot

> -----Urspr?ngliche Nachricht-----
> Von: Michal Simek [mailto:monstr at monstr.eu]
> Gesendet: Dienstag, 10. Januar 2017 15:10
> An: Herbrechtsmeier, Stefan; u-boot at lists.denx.de
> Cc: Albert Aribaud; Herbrechtsmeier, Stefan
> Betreff: Re: [PATCH 3/8] zynq: Add clk framework support to zynq timer
> 
> On 4.1.2017 13:27, stefan.herbrechtsmeier at weidmueller.com wrote:
> > From: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
> >
> > If available use the clock framework to calculate the clock rate of
> > the zynq timer.
> >
> > Signed-off-by: Stefan Herbrechtsmeier
> > <stefan.herbrechtsmeier@weidmueller.com>
> > ---
> >
> >  arch/arm/mach-zynq/timer.c | 25 +++++++++++++++++++++++++
> >  1 file changed, 25 insertions(+)
> >
> > diff --git a/arch/arm/mach-zynq/timer.c b/arch/arm/mach-zynq/timer.c
> > index 8ff82dc..0335cbe 100644
> > --- a/arch/arm/mach-zynq/timer.c
> > +++ b/arch/arm/mach-zynq/timer.c
> > @@ -1,4 +1,7 @@
> >  /*
> > + * Copyright (C) 2017 Weidm?ller Interface GmbH & Co. KG
> > + * Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
> > + *
> >   * Copyright (C) 2012 Michal Simek <monstr@monstr.eu>
> >   * Copyright (C) 2011-2012 Xilinx, Inc. All rights reserved.
> >   *
> > @@ -25,8 +28,10 @@
> >   * SPDX-License-Identifier:	GPL-2.0+
> >   */
> >
> > +#include <clk.h>
> >  #include <common.h>
> >  #include <div64.h>
> > +#include <dm.h>
> >  #include <asm/io.h>
> >  #include <asm/arch/hardware.h>
> >  #include <asm/arch/clk.h>
> > @@ -56,6 +61,26 @@ int timer_init(void)
> >  			(TIMER_PRESCALE << SCUTIMER_CONTROL_PRESCALER_SHIFT)
> |
> >  			SCUTIMER_CONTROL_ENABLE_MASK;
> >
> > +#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
> > +	struct udevice *dev;
> > +	struct clk clk;
> > +	int ret;
> > +
> > +	ret = uclass_get_device_by_driver(UCLASS_CLK,
> > +		DM_GET_DRIVER(zynq_clk), &dev);
> > +	if (ret)
> > +		return ret;
> > +
> > +	clk.id = cpu_6or4x_clk;
> 
> This information is already present in DT file. What's the reason not
> to take it from it?
Because this is not a DM driver and I don't know the device node. This could be done if we move the driver to drivers/timer.

> 
> > +	ret = clk_request(dev, &clk);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	gd->cpu_clk = clk_get_rate(&clk);
> > +
> > +	clk_free(&clk);
> 
> Not clk expert but isn't there a way to handle it like it is handled
> for other drivers? clk_get(), clk_get_rate()?
This is the solution I found in other platform drivers. The clk_get function requires a DM device.

> 
> > +#endif
> > +
> >  	gd->arch.timer_rate_hz = (gd->cpu_clk / 2) / (TIMER_PRESCALE +
> 1);
> >
> >  	/* Load the timer counter register */
> >
> 

Regards,
  Stefan



Kommanditgesellschaft - Sitz: Detmold - Amtsgericht Lemgo HRA 2790 - 
Komplement?rin: Weidm?ller Interface F?hrungsgesellschaft mbH - 
Sitz: Detmold - Amtsgericht Lemgo HRB 3924; 
Gesch?ftsf?hrer: Jos? Carlos ?lvarez Tobar, Elke Eckstein, Dr. Peter K?hler, J?rg Timmermann;
USt-ID-Nr. DE124599660

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

* [U-Boot] [PATCH 6/8] clk: zynq: Add zynq clock framework driver
  2017-01-04 12:27 ` [U-Boot] [PATCH 6/8] clk: zynq: Add zynq clock framework driver stefan.herbrechtsmeier at weidmueller.com
@ 2017-01-10 14:57   ` Michal Simek
  2017-01-10 19:17     ` Sören Brinkmann
  2017-01-11  7:15     ` Stefan.Herbrechtsmeier at weidmueller.com
  0 siblings, 2 replies; 29+ messages in thread
From: Michal Simek @ 2017-01-10 14:57 UTC (permalink / raw)
  To: u-boot

+Soren

On 4.1.2017 13:27, stefan.herbrechtsmeier at weidmueller.com wrote:
> From: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
> 
> Add a clock framework driver for the zynq platform. The driver is based
> on the platform zynq clock driver but reworked to use static functions
> instead of run-time generated objects even for unused clocks.
> Additionally the CONFIG_ZYNQ_PS_CLK_FREQ is replaced by the
> ps-clk-frequency from the device tree.
> 
> Signed-off-by: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
> ---
> 
>  drivers/clk/Kconfig    |   7 +
>  drivers/clk/Makefile   |   1 +
>  drivers/clk/clk_zynq.c | 470 +++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 478 insertions(+)
>  create mode 100644 drivers/clk/clk_zynq.c
> 
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index c05ce2a..714ccca 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -28,6 +28,13 @@ config CLK_BOSTON
>  	help
>  	  Enable this to support the clocks
>  
> +config CLK_ZYNQ
> +	bool "Zynq clock driver"
> +	depends on CLK && ARCH_ZYNQ
> +	default y
> +	help
> +	  Enable this to support the clocks
> +
>  source "drivers/clk/tegra/Kconfig"
>  source "drivers/clk/uniphier/Kconfig"
>  source "drivers/clk/exynos/Kconfig"
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 40a5e8c..5e5b6b1 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -16,3 +16,4 @@ obj-$(CONFIG_CLK_UNIPHIER) += uniphier/
>  obj-$(CONFIG_CLK_EXYNOS) += exynos/
>  obj-$(CONFIG_CLK_AT91) += at91/
>  obj-$(CONFIG_CLK_BOSTON) += clk_boston.o
> +obj-$(CONFIG_CLK_ZYNQ) += clk_zynq.o
> diff --git a/drivers/clk/clk_zynq.c b/drivers/clk/clk_zynq.c
> new file mode 100644
> index 0000000..d276155
> --- /dev/null
> +++ b/drivers/clk/clk_zynq.c
> @@ -0,0 +1,470 @@
> +/*
> + * Copyright (C) 2017 Weidm?ller Interface GmbH & Co. KG
> + * Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
> + *
> + * Copyright (C) 2013 Soren Brinkmann <soren.brinkmann@xilinx.com>
> + * Copyright (C) 2013 Xilinx, Inc. All rights reserved.
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <clk-uclass.h>
> +#include <dm.h>
> +#include <dm/lists.h>
> +#include <errno.h>
> +#include <asm/io.h>
> +#include <asm/arch/clk.h>
> +#include <asm/arch/hardware.h>
> +#include <asm/arch/sys_proto.h>
> +
> +/* Register bitfield defines */
> +#define PLLCTRL_FBDIV_MASK	0x7f000
> +#define PLLCTRL_FBDIV_SHIFT	12
> +#define PLLCTRL_BPFORCE_MASK	(1 << 4)
> +#define PLLCTRL_PWRDWN_MASK	2
> +#define PLLCTRL_PWRDWN_SHIFT	1
> +#define PLLCTRL_RESET_MASK	1
> +#define PLLCTRL_RESET_SHIFT	0
> +
> +#define ZYNQ_CLK_MAXDIV		0x3f
> +#define CLK_CTRL_DIV1_SHIFT	20
> +#define CLK_CTRL_DIV1_MASK	(ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV1_SHIFT)
> +#define CLK_CTRL_DIV0_SHIFT	8
> +#define CLK_CTRL_DIV0_MASK	(ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV0_SHIFT)
> +#define CLK_CTRL_SRCSEL_SHIFT	4
> +#define CLK_CTRL_SRCSEL_MASK	(0x3 << CLK_CTRL_SRCSEL_SHIFT)
> +
> +#define CLK_CTRL_DIV2X_SHIFT	26
> +#define CLK_CTRL_DIV2X_MASK	(ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV2X_SHIFT)
> +#define CLK_CTRL_DIV3X_SHIFT	20
> +#define CLK_CTRL_DIV3X_MASK	(ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV3X_SHIFT)
> +
> +#define ZYNQ_CLKMUX_SEL_0	0
> +#define ZYNQ_CLKMUX_SEL_1	1
> +#define ZYNQ_CLKMUX_SEL_2	2
> +#define ZYNQ_CLKMUX_SEL_3	3
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +#ifndef CONFIG_SPL_BUILD
> +enum zynq_clk_rclk {mio_clk, emio_clk};
> +#endif
> +
> +struct zynq_clk_priv {
> +	ulong ps_clk_freq;
> +};
> +
> +static void *zynq_clk_get_register(enum zynq_clk id)
> +{
> +	switch (id) {
> +	case armpll_clk:
> +		return &slcr_base->arm_pll_ctrl;
> +	case ddrpll_clk:
> +		return &slcr_base->ddr_pll_ctrl;
> +	case iopll_clk:
> +		return &slcr_base->io_pll_ctrl;
> +#ifndef CONFIG_SPL_BUILD
> +	case dci_clk:
> +		return &slcr_base->dci_clk_ctrl;
> +#endif
> +	case lqspi_clk:
> +		return &slcr_base->lqspi_clk_ctrl;
> +	case smc_clk:
> +		return &slcr_base->smc_clk_ctrl;
> +	case pcap_clk:
> +		return &slcr_base->pcap_clk_ctrl;
> +#ifndef CONFIG_SPL_BUILD
> +	case gem0_clk:
> +		return &slcr_base->gem0_clk_ctrl;
> +	case gem1_clk:
> +		return &slcr_base->gem1_clk_ctrl;
> +	case fclk0_clk:
> +		return &slcr_base->fpga0_clk_ctrl;
> +	case fclk1_clk:
> +		return &slcr_base->fpga1_clk_ctrl;
> +	case fclk2_clk:
> +		return &slcr_base->fpga2_clk_ctrl;
> +	case fclk3_clk:
> +		return &slcr_base->fpga3_clk_ctrl;
> +	case can0_clk ... can1_clk:
> +		return &slcr_base->can_clk_ctrl;
> +#endif
> +	case sdio0_clk:
> +	case sdio1_clk:
> +		return &slcr_base->sdio_clk_ctrl;
> +	case uart0_clk:
> +	case uart1_clk:
> +		return &slcr_base->uart_clk_ctrl;
> +	case spi0_clk:
> +	case spi1_clk:
> +		return &slcr_base->spi_clk_ctrl;
> +#ifndef CONFIG_SPL_BUILD
> +	case dbg_trc_clk:
> +	case dbg_apb_clk:
> +		return &slcr_base->dbg_clk_ctrl;
> +#endif

Please put them together.

> +	default:
> +		return &slcr_base->dbg_clk_ctrl;
> +	}
> +}
> +
> +static enum zynq_clk zynq_clk_get_cpu_pll(u32 clk_ctrl)
> +{
> +	u32 srcsel = (clk_ctrl & CLK_CTRL_SRCSEL_MASK) >> CLK_CTRL_SRCSEL_SHIFT;
> +
> +	switch (srcsel) {
> +	case ZYNQ_CLKMUX_SEL_0:
> +	case ZYNQ_CLKMUX_SEL_1:
> +		return armpll_clk;
> +	case ZYNQ_CLKMUX_SEL_2:
> +		return ddrpll_clk;
> +	case ZYNQ_CLKMUX_SEL_3:
> +		return iopll_clk;
> +	default:
> +		return armpll_clk;


Default case shouldn't happen because of mask above.
But if you want to keep it maybe this is a little bit better.

	case ZYNQ_CLKMUX_SEL_2:
		return ddrpll_clk;
	case ZYNQ_CLKMUX_SEL_3:
		return iopll_clk;
	case ZYNQ_CLKMUX_SEL_0:
	case ZYNQ_CLKMUX_SEL_1:
	default:
		return armpll_clk;




> +	}
> +}
> +
> +static enum zynq_clk zynq_clk_get_peripheral_pll(u32 clk_ctrl)
> +{
> +	u32 srcsel = (clk_ctrl & CLK_CTRL_SRCSEL_MASK) >> CLK_CTRL_SRCSEL_SHIFT;
> +
> +	switch (srcsel) {
> +	case ZYNQ_CLKMUX_SEL_0:
> +	case ZYNQ_CLKMUX_SEL_1:
> +		return iopll_clk;
> +	case ZYNQ_CLKMUX_SEL_2:
> +		return armpll_clk;
> +	case ZYNQ_CLKMUX_SEL_3:
> +		return ddrpll_clk;
> +	default:
> +		return iopll_clk;

ditto.

> +	}
> +}
> +
> +static ulong zynq_clk_get_pll_rate(struct zynq_clk_priv *priv, enum zynq_clk id)
> +{
> +	u32 clk_ctrl, reset, pwrdwn, mul, bypass;
> +
> +	clk_ctrl = readl(zynq_clk_get_register(id));
> +
> +	reset = (clk_ctrl & PLLCTRL_RESET_MASK) >> PLLCTRL_RESET_SHIFT;
> +	pwrdwn = (clk_ctrl & PLLCTRL_PWRDWN_MASK) >> PLLCTRL_PWRDWN_SHIFT;
> +	if (reset || pwrdwn)
> +		return 0;
> +
> +	bypass = clk_ctrl & PLLCTRL_BPFORCE_MASK;
> +	if (bypass)
> +		mul = 1;
> +	else
> +		mul = (clk_ctrl & PLLCTRL_FBDIV_MASK) >> PLLCTRL_FBDIV_SHIFT;
> +
> +	return priv->ps_clk_freq * mul;
> +}
> +
> +#ifndef CONFIG_SPL_BUILD
> +static enum zynq_clk_rclk zynq_clk_get_gem_rclk(enum zynq_clk id)
> +{
> +	u32 clk_ctrl, srcsel;
> +
> +	if (id == gem0_clk)
> +		clk_ctrl = readl(&slcr_base->gem0_rclk_ctrl);
> +	else
> +		clk_ctrl = readl(&slcr_base->gem1_rclk_ctrl);
> +
> +	srcsel = (clk_ctrl & CLK_CTRL_SRCSEL_MASK) >> CLK_CTRL_SRCSEL_SHIFT;
> +	if (srcsel)
> +		return emio_clk;
> +	else
> +		return mio_clk;
> +}
> +#endif
> +
> +static ulong zynq_clk_get_cpu_rate(struct zynq_clk_priv *priv, enum zynq_clk id)
> +{
> +	u32 clk_621, clk_ctrl, div;
> +	enum zynq_clk pll;
> +
> +	clk_ctrl = readl(&slcr_base->arm_clk_ctrl);
> +
> +	div = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
> +
> +	switch (id) {
> +	case cpu_1x_clk:
> +		div *= 2;
> +		/* fall through */
> +	case cpu_2x_clk:
> +		clk_621 = readl(&slcr_base->clk_621_true) & 1;
> +		div *= 2 + clk_621;
> +		break;
> +	case cpu_3or2x_clk:
> +		div *= 2;
> +		/* fall through */
> +	case cpu_6or4x_clk:
> +		break;
> +	default:
> +		return 0;
> +	}
> +
> +	pll = zynq_clk_get_cpu_pll(clk_ctrl);
> +
> +	return DIV_ROUND_CLOSEST(zynq_clk_get_pll_rate(priv, pll), div);
> +}
> +
> +#ifndef CONFIG_SPL_BUILD
> +static ulong zynq_clk_get_ddr2x_rate(struct zynq_clk_priv *priv)
> +{
> +	u32 clk_ctrl, div;
> +
> +	clk_ctrl = readl(&slcr_base->ddr_clk_ctrl);
> +
> +	div = (clk_ctrl & CLK_CTRL_DIV2X_MASK) >> CLK_CTRL_DIV2X_SHIFT;
> +
> +	return DIV_ROUND_CLOSEST(zynq_clk_get_pll_rate(priv, ddrpll_clk), div);
> +}
> +#endif
> +
> +static ulong zynq_clk_get_ddr3x_rate(struct zynq_clk_priv *priv)
> +{
> +	u32 clk_ctrl, div;
> +
> +	clk_ctrl = readl(&slcr_base->ddr_clk_ctrl);
> +
> +	div = (clk_ctrl & CLK_CTRL_DIV3X_MASK) >> CLK_CTRL_DIV3X_SHIFT;
> +
> +	return DIV_ROUND_CLOSEST(zynq_clk_get_pll_rate(priv, ddrpll_clk), div);
> +}
> +
> +#ifndef CONFIG_SPL_BUILD
> +static ulong zynq_clk_get_dci_rate(struct zynq_clk_priv *priv)
> +{
> +	u32 clk_ctrl, div0, div1;
> +
> +	clk_ctrl = readl(&slcr_base->dci_clk_ctrl);
> +
> +	div0 = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
> +	div1 = (clk_ctrl & CLK_CTRL_DIV1_MASK) >> CLK_CTRL_DIV1_SHIFT;
> +
> +	return DIV_ROUND_CLOSEST(DIV_ROUND_CLOSEST(
> +		zynq_clk_get_pll_rate(priv, ddrpll_clk), div0), div1);
> +}
> +#endif
> +
> +static ulong zynq_clk_get_peripheral_rate(struct zynq_clk_priv *priv,
> +					  enum zynq_clk id, bool two_divs)
> +{
> +	enum zynq_clk pll;
> +	u32 clk_ctrl, div0;
> +	u32 div1 = 1;
> +
> +	clk_ctrl = readl(zynq_clk_get_register(id));
> +
> +	div0 = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
> +	if (!div0)
> +		div0 = 1;
> +
> +#ifndef CONFIG_SPL_BUILD
> +	if (two_divs) {
> +		div1 = (clk_ctrl & CLK_CTRL_DIV1_MASK) >> CLK_CTRL_DIV1_SHIFT;
> +		if (!div1)
> +			div1 = 1;
> +	}
> +#endif
> +
> +	pll = zynq_clk_get_peripheral_pll(clk_ctrl);
> +
> +	return
> +		DIV_ROUND_CLOSEST(
> +			DIV_ROUND_CLOSEST(
> +				zynq_clk_get_pll_rate(priv, pll), div0),
> +			div1);
> +}
> +
> +#ifndef CONFIG_SPL_BUILD
> +static ulong zynq_clk_get_gem_rate(struct zynq_clk_priv *priv, enum zynq_clk id)
> +{
> +	if (zynq_clk_get_gem_rclk(id) == mio_clk)
> +		return zynq_clk_get_peripheral_rate(priv, id, true);
> +

Not sure if my understanding is correct here but I would expect if input
is via emio that you will ask someone else to provide this value.
Returning 0 without message seems to me not enough.

> +	return 0;
> +}
> +
> +static unsigned long zynq_clk_calc_peripheral_two_divs(
incorrect parameter indetation


> +		ulong rate, ulong pll_rate, u32 *div0,
> +		u32 *div1)

> +{
> +	long new_err, best_err = (long)(~0UL >> 1);
> +	ulong new_rate, best_rate = 0;
> +	u32 d0, d1;
> +
> +	for (d0 = 1; d0 <= ZYNQ_CLK_MAXDIV; d0++) {
> +		for (d1 = 1; d1 <= ZYNQ_CLK_MAXDIV >> 1; d1++) {
> +			new_rate = DIV_ROUND_CLOSEST(
> +					DIV_ROUND_CLOSEST(pll_rate, d0), d1);
> +			new_err = abs(new_rate - rate);
> +
> +			if (new_err < best_err) {
> +				*div0 = d0;
> +				*div1 = d1;
> +				best_err = new_err;
> +				best_rate = new_rate;
> +			}
> +		}
> +	}
> +
> +	return best_rate;
> +}
> +
> +static ulong zynq_clk_set_peripheral_rate(struct zynq_clk_priv *priv,
> +					  enum zynq_clk id, ulong rate,
> +					  bool two_divs)
> +{
> +	enum zynq_clk pll;
> +	u32 clk_ctrl, div0 = 0, div1 = 0;
> +	ulong pll_rate, new_rate;
> +	u32 *reg;
> +
> +	reg = zynq_clk_get_register(id);
> +	clk_ctrl = readl(reg);
> +
> +	pll = zynq_clk_get_peripheral_pll(clk_ctrl);
> +	pll_rate = zynq_clk_get_pll_rate(priv, pll);
> +	clk_ctrl &= ~CLK_CTRL_DIV0_MASK;
> +	if (two_divs) {
> +		clk_ctrl &= ~CLK_CTRL_DIV1_MASK;
> +		new_rate = zynq_clk_calc_peripheral_two_divs(rate, pll_rate,
> +				&div0, &div1);
> +		clk_ctrl |= div1 << CLK_CTRL_DIV1_SHIFT;
> +	} else {
> +		div0 = DIV_ROUND_CLOSEST(pll_rate, rate);
> +		if (div0 > ZYNQ_CLK_MAXDIV)
> +			div0 = ZYNQ_CLK_MAXDIV;
> +		new_rate = DIV_ROUND_CLOSEST(rate, div0);
> +	}
> +	clk_ctrl |= div0 << CLK_CTRL_DIV0_SHIFT;
> +
> +	zynq_slcr_unlock();
> +	writel(clk_ctrl, reg);
> +	zynq_slcr_lock();
> +
> +	return new_rate;
> +}
> +
> +static ulong zynq_clk_set_gem_rate(struct zynq_clk_priv *priv, enum zynq_clk id,
> +				   ulong rate)
> +{
> +	if (zynq_clk_get_gem_rclk(id) == mio_clk)
> +		return zynq_clk_set_peripheral_rate(priv, id, rate, true);
> +
> +	return 0;
> +}
> +#endif
> +
> +#ifndef CONFIG_SPL_BUILD
> +static ulong zynq_clk_get_rate(struct clk *clk)
> +{
> +	struct zynq_clk_priv *priv = dev_get_priv(clk->dev);
> +	enum zynq_clk id = clk->id;
> +	bool two_divs = false;
> +
> +	switch (id) {
> +	case armpll_clk ... iopll_clk:
> +		return zynq_clk_get_pll_rate(priv, id);
> +	case cpu_6or4x_clk ... cpu_1x_clk:
> +		return zynq_clk_get_cpu_rate(priv, id);
> +	case ddr2x_clk:
> +		return zynq_clk_get_ddr2x_rate(priv);
> +	case ddr3x_clk:
> +		return zynq_clk_get_ddr3x_rate(priv);
> +	case dci_clk:
> +		return zynq_clk_get_dci_rate(priv);
> +	case gem0_clk ... gem1_clk:
> +		return zynq_clk_get_gem_rate(priv, id);
> +	case fclk0_clk ... can1_clk:
> +		two_divs = true;
> +		/* fall through */
> +	case dbg_trc_clk ... dbg_apb_clk:
> +	case lqspi_clk ... pcap_clk:
> +	case sdio0_clk ... spi1_clk:
> +		return zynq_clk_get_peripheral_rate(priv, id, two_divs);
> +	case dma_clk:
> +		return zynq_clk_get_cpu_rate(priv, cpu_2x_clk);
> +	case usb0_aper_clk ... smc_aper_clk:
> +		return zynq_clk_get_cpu_rate(priv, cpu_1x_clk);
> +	default:
> +		return -ENXIO;
> +	}
> +}
> +
> +static ulong zynq_clk_set_rate(struct clk *clk, ulong rate)
> +{
> +	struct zynq_clk_priv *priv = dev_get_priv(clk->dev);
> +	enum zynq_clk id = clk->id;
> +	bool two_divs = false;
> +
> +	switch (id) {
> +	case gem0_clk ... gem1_clk:
> +		return zynq_clk_set_gem_rate(priv, id, rate);
> +	case fclk0_clk ... can1_clk:
> +		two_divs = true;
> +		/* fall through */
> +	case lqspi_clk ... pcap_clk:
> +	case sdio0_clk ... spi1_clk:
> +	case dbg_trc_clk ... dbg_apb_clk:
> +		return zynq_clk_set_peripheral_rate(priv, id, rate, two_divs);
> +	default:
> +		return -ENXIO;
> +	}
> +}
> +#else
> +static ulong zynq_clk_get_rate(struct clk *clk)
> +{
> +	struct zynq_clk_priv *priv = dev_get_priv(clk->dev);
> +	enum zynq_clk id = clk->id;
> +
> +	switch (id) {
> +	case cpu_6or4x_clk ... cpu_1x_clk:
> +		return zynq_clk_get_cpu_rate(priv, id);
> +	case ddr3x_clk:
> +		return zynq_clk_get_ddr3x_rate(priv);
> +	case lqspi_clk ... pcap_clk:
> +	case sdio0_clk ... spi1_clk:
> +		return zynq_clk_get_peripheral_rate(priv, id, 0);
> +	default:
> +		return -ENXIO;
> +	}
> +}
> +#endif
> +
> +static struct clk_ops zynq_clk_ops = {
> +	.get_rate = zynq_clk_get_rate,
> +#ifndef CONFIG_SPL_BUILD
> +	.set_rate = zynq_clk_set_rate,
> +#endif
> +};
> +
> +static int zynq_clk_probe(struct udevice *dev)
> +{
> +	struct zynq_clk_priv *priv = dev_get_priv(dev);
> +
> +	priv->ps_clk_freq = fdtdec_get_uint(gd->fdt_blob, dev->of_offset,
> +					    "ps-clk-frequency", 33333333UL);
> +
> +	return 0;
> +}
> +
> +static const struct udevice_id zynq_clk_ids[] = {
> +	{ .compatible = "xlnx,ps7-clkc"},
> +	{}
> +};
> +
> +U_BOOT_DRIVER(zynq_clk) = {
> +	.name		= "zynq_clk",
> +	.id		= UCLASS_CLK,
> +	.of_match	= zynq_clk_ids,
> +	.flags		= DM_FLAG_PRE_RELOC,
> +	.ops		= &zynq_clk_ops,
> +	.priv_auto_alloc_size = sizeof(struct zynq_clk_priv),
> +	.probe		= zynq_clk_probe,
> +};
> 

The rest looks good.
Soren: Can you please look at it? IIRC you have written that origin driver.


Thanks,
Michal


-- 
Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel - Xilinx Microblaze
Maintainer of Linux kernel - Xilinx Zynq ARM and ZynqMP ARM64 SoCs
U-Boot custodian - Xilinx Microblaze/Zynq/ZynqMP SoCs


-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: OpenPGP digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170110/e02f8d87/attachment.sig>

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

* [U-Boot] [PATCH 7/8] zynq: Move zynq to clock framework
  2017-01-04 12:27 ` [U-Boot] [PATCH 7/8] zynq: Move zynq to clock framework stefan.herbrechtsmeier at weidmueller.com
@ 2017-01-10 15:04   ` Michal Simek
  0 siblings, 0 replies; 29+ messages in thread
From: Michal Simek @ 2017-01-10 15:04 UTC (permalink / raw)
  To: u-boot

On 4.1.2017 13:27, stefan.herbrechtsmeier at weidmueller.com wrote:
> From: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.de>
> 
> Move the zynq to clock framework and remove unused functions as well as
> the CONFIG_ZYNQ_PS_CLK_FREQ configuration.
> 
> Signed-off-by: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
> ---
> 
>  arch/arm/Kconfig                            |   2 +
>  arch/arm/dts/zynq-7000.dtsi                 |   2 +
>  arch/arm/mach-zynq/clk.c                    | 650 +++-------------------------
>  arch/arm/mach-zynq/cpu.c                    |   1 -
>  arch/arm/mach-zynq/include/mach/clk.h       |   5 -
>  arch/arm/mach-zynq/include/mach/sys_proto.h |   1 -
>  arch/arm/mach-zynq/slcr.c                   |  22 -
>  arch/arm/mach-zynq/timer.c                  |   2 -
>  drivers/net/zynq_gem.c                      |  13 -
>  drivers/serial/serial_zynq.c                |   6 +-
>  include/configs/topic_miami.h               |   2 -
>  include/configs/zynq_zybo.h                 |   3 -
>  scripts/config_whitelist.txt                |   1 -
>  13 files changed, 55 insertions(+), 655 deletions(-)
> 
> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> index 38080c0..f9daa99 100644
> --- a/arch/arm/Kconfig
> +++ b/arch/arm/Kconfig
> @@ -631,6 +631,8 @@ config ARCH_ZYNQ
>  	select SPL_SEPARATE_BSS if SPL
>  	select DM_USB if USB
>  	select BLK
> +	select CLK
> +	select SPL_CLK
>  
>  config ARCH_ZYNQMP
>  	bool "Support Xilinx ZynqMP Platform"
> diff --git a/arch/arm/dts/zynq-7000.dtsi b/arch/arm/dts/zynq-7000.dtsi
> index 668f54e..2464830 100644
> --- a/arch/arm/dts/zynq-7000.dtsi
> +++ b/arch/arm/dts/zynq-7000.dtsi
> @@ -250,12 +250,14 @@
>  		};
>  
>  		slcr: slcr at f8000000 {
> +			u-boot,dm-pre-reloc;
>  			#address-cells = <1>;
>  			#size-cells = <1>;
>  			compatible = "xlnx,zynq-slcr", "syscon", "simple-mfd";
>  			reg = <0xF8000000 0x1000>;
>  			ranges;
>  			clkc: clkc at 100 {
> +				u-boot,dm-pre-reloc;
>  				#clock-cells = <1>;
>  				compatible = "xlnx,ps7-clkc";
>  				fclk-enable = <0>;
> diff --git a/arch/arm/mach-zynq/clk.c b/arch/arm/mach-zynq/clk.c
> index 570ebd7..7283a94 100644
> --- a/arch/arm/mach-zynq/clk.c
> +++ b/arch/arm/mach-zynq/clk.c
> @@ -4,77 +4,13 @@
>   *
>   * SPDX-License-Identifier:	GPL-2.0+
>   */
> +#include <clk.h>
>  #include <common.h>
> -#include <errno.h>
> -#include <asm/io.h>
> -#include <asm/arch/hardware.h>
> +#include <dm.h>
>  #include <asm/arch/clk.h>
>  
> -/* Board oscillator frequency */
> -#ifndef CONFIG_ZYNQ_PS_CLK_FREQ
> -# define CONFIG_ZYNQ_PS_CLK_FREQ	33333333UL
> -#endif
> -
> -/* Register bitfield defines */
> -#define PLLCTRL_FBDIV_MASK	0x7f000
> -#define PLLCTRL_FBDIV_SHIFT	12
> -#define PLLCTRL_BPFORCE_MASK	(1 << 4)
> -#define PLLCTRL_PWRDWN_MASK	2
> -#define PLLCTRL_PWRDWN_SHIFT	1
> -#define PLLCTRL_RESET_MASK	1
> -#define PLLCTRL_RESET_SHIFT	0
> -
> -#define ZYNQ_CLK_MAXDIV		0x3f
> -#define CLK_CTRL_DIV1_SHIFT	20
> -#define CLK_CTRL_DIV1_MASK	(ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV1_SHIFT)
> -#define CLK_CTRL_DIV0_SHIFT	8
> -#define CLK_CTRL_DIV0_MASK	(ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV0_SHIFT)
> -#define CLK_CTRL_SRCSEL_SHIFT	4
> -#define CLK_CTRL_SRCSEL_MASK	(0x3 << CLK_CTRL_SRCSEL_SHIFT)
> -
> -#define CLK_CTRL_DIV2X_SHIFT	26
> -#define CLK_CTRL_DIV2X_MASK	(ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV2X_SHIFT)
> -#define CLK_CTRL_DIV3X_SHIFT	20
> -#define CLK_CTRL_DIV3X_MASK	(ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV3X_SHIFT)
> -
> -#define ZYNQ_CLKMUX_SEL_0	0
> -#define ZYNQ_CLKMUX_SEL_1	1
> -#define ZYNQ_CLKMUX_SEL_2	2
> -#define ZYNQ_CLKMUX_SEL_3	3
> -
>  DECLARE_GLOBAL_DATA_PTR;
>  
> -struct clk;
> -
> -/**
> - * struct zynq_clk_ops:
> - * @set_rate:	Function pointer to set_rate() implementation
> - * @get_rate:	Function pointer to get_rate() implementation
> - */
> -struct zynq_clk_ops {
> -	int (*set_rate)(struct clk *clk, unsigned long rate);
> -	unsigned long (*get_rate)(struct clk *clk);
> -};
> -
> -/**
> - * struct clk:
> - * @frequency:	Currenct frequency
> - * @parent:	Parent clock
> - * @flags:	Clock flags
> - * @reg:	Clock control register
> - * @ops:	Clock operations
> - */
> -struct clk {
> -	unsigned long	frequency;
> -	enum zynq_clk	parent;
> -	unsigned int	flags;
> -	u32		*reg;
> -	struct zynq_clk_ops	ops;
> -};
> -#define ZYNQ_CLK_FLAGS_HAS_2_DIVS	1
> -
> -static struct clk clks[clk_max];
> -
>  static const char * const clk_names[clk_max] = {
>  	"armpll", "ddrpll", "iopll",
>  	"cpu_6or4x", "cpu_3or2x", "cpu_2x", "cpu_1x",
> @@ -90,548 +26,43 @@ static const char * const clk_names[clk_max] = {
>  };
>  
>  /**
> - * __zynq_clk_cpu_get_parent() - Decode clock multiplexer
> - * @srcsel:	Mux select value
> - * Returns the clock identifier associated with the selected mux input.
> - */
> -static int __zynq_clk_cpu_get_parent(unsigned int srcsel)
> -{
> -	unsigned int ret;
> -
> -	switch (srcsel) {
> -	case ZYNQ_CLKMUX_SEL_0:
> -	case ZYNQ_CLKMUX_SEL_1:
> -		ret = armpll_clk;
> -		break;
> -	case ZYNQ_CLKMUX_SEL_2:
> -		ret = ddrpll_clk;
> -		break;
> -	case ZYNQ_CLKMUX_SEL_3:
> -		ret = iopll_clk;
> -		break;
> -	default:
> -		ret = armpll_clk;
> -		break;
> -	}
> -
> -	return ret;
> -}
> -
> -/**
> - * ddr2x_get_rate() - Get clock rate of DDR2x clock
> - * @clk:	Clock handle
> - * Returns the current clock rate of @clk.
> - */
> -static unsigned long ddr2x_get_rate(struct clk *clk)
> -{
> -	u32 clk_ctrl = readl(clk->reg);
> -	u32 div = (clk_ctrl & CLK_CTRL_DIV2X_MASK) >> CLK_CTRL_DIV2X_SHIFT;
> -
> -	return DIV_ROUND_CLOSEST(zynq_clk_get_rate(clk->parent), div);
> -}
> -
> -/**
> - * ddr3x_get_rate() - Get clock rate of DDR3x clock
> - * @clk:	Clock handle
> - * Returns the current clock rate of @clk.
> - */
> -static unsigned long ddr3x_get_rate(struct clk *clk)
> -{
> -	u32 clk_ctrl = readl(clk->reg);
> -	u32 div = (clk_ctrl & CLK_CTRL_DIV3X_MASK) >> CLK_CTRL_DIV3X_SHIFT;
> -
> -	return DIV_ROUND_CLOSEST(zynq_clk_get_rate(clk->parent), div);
> -}
> -
> -static void init_ddr_clocks(void)
> -{
> -	u32 div0, div1;
> -	unsigned long prate = zynq_clk_get_rate(ddrpll_clk);
> -	u32 clk_ctrl = readl(&slcr_base->ddr_clk_ctrl);
> -
> -	/* DDR2x */
> -	clks[ddr2x_clk].reg = &slcr_base->ddr_clk_ctrl;
> -	clks[ddr2x_clk].parent = ddrpll_clk;
> -	clks[ddr2x_clk].frequency = ddr2x_get_rate(&clks[ddr2x_clk]);
> -	clks[ddr2x_clk].ops.get_rate = ddr2x_get_rate;
> -
> -	/* DDR3x */
> -	clks[ddr3x_clk].reg = &slcr_base->ddr_clk_ctrl;
> -	clks[ddr3x_clk].parent = ddrpll_clk;
> -	clks[ddr3x_clk].frequency = ddr3x_get_rate(&clks[ddr3x_clk]);
> -	clks[ddr3x_clk].ops.get_rate = ddr3x_get_rate;
> -
> -	/* DCI */
> -	clk_ctrl = readl(&slcr_base->dci_clk_ctrl);
> -	div0 = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
> -	div1 = (clk_ctrl & CLK_CTRL_DIV1_MASK) >> CLK_CTRL_DIV1_SHIFT;
> -	clks[dci_clk].reg = &slcr_base->dci_clk_ctrl;
> -	clks[dci_clk].parent = ddrpll_clk;
> -	clks[dci_clk].frequency = DIV_ROUND_CLOSEST(
> -			DIV_ROUND_CLOSEST(prate, div0), div1);
> -
> -	gd->bd->bi_ddr_freq = clks[ddr3x_clk].frequency / 1000000;
> -}
> -
> -static void init_cpu_clocks(void)
> -{
> -	int clk_621;
> -	u32 reg, div, srcsel;
> -	enum zynq_clk parent;
> -
> -	reg = readl(&slcr_base->arm_clk_ctrl);
> -	clk_621 = readl(&slcr_base->clk_621_true) & 1;
> -	div = (reg & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
> -	srcsel = (reg & CLK_CTRL_SRCSEL_MASK) >> CLK_CTRL_SRCSEL_SHIFT;
> -	parent = __zynq_clk_cpu_get_parent(srcsel);
> -
> -	/* cpu clocks */
> -	clks[cpu_6or4x_clk].reg = &slcr_base->arm_clk_ctrl;
> -	clks[cpu_6or4x_clk].parent = parent;
> -	clks[cpu_6or4x_clk].frequency = DIV_ROUND_CLOSEST(
> -			zynq_clk_get_rate(parent), div);
> -
> -	clks[cpu_3or2x_clk].reg = &slcr_base->arm_clk_ctrl;
> -	clks[cpu_3or2x_clk].parent = cpu_6or4x_clk;
> -	clks[cpu_3or2x_clk].frequency = zynq_clk_get_rate(cpu_6or4x_clk) / 2;
> -
> -	clks[cpu_2x_clk].reg = &slcr_base->arm_clk_ctrl;
> -	clks[cpu_2x_clk].parent = cpu_6or4x_clk;
> -	clks[cpu_2x_clk].frequency = zynq_clk_get_rate(cpu_6or4x_clk) /
> -			(2 + clk_621);
> -
> -	clks[cpu_1x_clk].reg = &slcr_base->arm_clk_ctrl;
> -	clks[cpu_1x_clk].parent = cpu_6or4x_clk;
> -	clks[cpu_1x_clk].frequency = zynq_clk_get_rate(cpu_6or4x_clk) /
> -			(4 + 2 * clk_621);
> -}
> -
> -/**
> - * periph_calc_two_divs() - Calculate clock dividers
> - * @cur_rate:	Current clock rate
> - * @tgt_rate:	Target clock rate
> - * @prate:	Parent clock rate
> - * @div0:	First divider (output)
> - * @div1:	Second divider (output)
> - * Returns the actual clock rate possible.
> - *
> - * Calculates clock dividers for clocks with two 6-bit dividers.
> - */
> -static unsigned long periph_calc_two_divs(unsigned long cur_rate,
> -		unsigned long tgt_rate, unsigned long prate, u32 *div0,
> -		u32 *div1)
> -{
> -	long err, best_err = (long)(~0UL >> 1);
> -	unsigned long rate, best_rate = 0;
> -	u32 d0, d1;
> -
> -	for (d0 = 1; d0 <= ZYNQ_CLK_MAXDIV; d0++) {
> -		for (d1 = 1; d1 <= ZYNQ_CLK_MAXDIV >> 1; d1++) {
> -			rate = DIV_ROUND_CLOSEST(DIV_ROUND_CLOSEST(prate, d0),
> -					d1);
> -			err = abs(rate - tgt_rate);
> -
> -			if (err < best_err) {
> -				*div0 = d0;
> -				*div1 = d1;
> -				best_err = err;
> -				best_rate = rate;
> -			}
> -		}
> -	}
> -
> -	return best_rate;
> -}
> -
> -/**
> - * zynq_clk_periph_set_rate() - Set clock rate
> - * @clk:	Handle of the peripheral clock
> - * @rate:	New clock rate
> - * Sets the clock frequency of @clk to @rate. Returns zero on success.
> - */
> -static int zynq_clk_periph_set_rate(struct clk *clk,
> -		unsigned long rate)
> -{
> -	u32 ctrl, div0 = 0, div1 = 0;
> -	unsigned long prate, new_rate, cur_rate = clk->frequency;
> -
> -	ctrl = readl(clk->reg);
> -	prate = zynq_clk_get_rate(clk->parent);
> -	ctrl &= ~CLK_CTRL_DIV0_MASK;
> -
> -	if (clk->flags & ZYNQ_CLK_FLAGS_HAS_2_DIVS) {
> -		ctrl &= ~CLK_CTRL_DIV1_MASK;
> -		new_rate = periph_calc_two_divs(cur_rate, rate, prate, &div0,
> -				&div1);
> -		ctrl |= div1 << CLK_CTRL_DIV1_SHIFT;
> -	} else {
> -		div0 = DIV_ROUND_CLOSEST(prate, rate);
> -		div0 &= ZYNQ_CLK_MAXDIV;
> -		new_rate = DIV_ROUND_CLOSEST(rate, div0);
> -	}
> -
> -	/* write new divs to hardware */
> -	ctrl |= div0 << CLK_CTRL_DIV0_SHIFT;
> -	writel(ctrl, clk->reg);
> -
> -	/* update frequency in clk framework */
> -	clk->frequency = new_rate;
> -
> -	return 0;
> -}
> -
> -/**
> - * zynq_clk_periph_get_rate() - Get clock rate
> - * @clk:	Handle of the peripheral clock
> - * Returns the current clock rate of @clk.
> - */
> -static unsigned long zynq_clk_periph_get_rate(struct clk *clk)
> -{
> -	u32 clk_ctrl = readl(clk->reg);
> -	u32 div0 = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
> -	u32 div1 = 1;
> -
> -	if (clk->flags & ZYNQ_CLK_FLAGS_HAS_2_DIVS)
> -		div1 = (clk_ctrl & CLK_CTRL_DIV1_MASK) >> CLK_CTRL_DIV1_SHIFT;
> -
> -	/* a register value of zero == division by 1 */
> -	if (!div0)
> -		div0 = 1;
> -	if (!div1)
> -		div1 = 1;
> -
> -	return
> -		DIV_ROUND_CLOSEST(
> -			DIV_ROUND_CLOSEST(zynq_clk_get_rate(clk->parent), div0),
> -			div1);
> -}
> -
> -/**
> - * __zynq_clk_periph_get_parent() - Decode clock multiplexer
> - * @srcsel:	Mux select value
> - * Returns the clock identifier associated with the selected mux input.
> - */
> -static enum zynq_clk __zynq_clk_periph_get_parent(u32 srcsel)
> -{
> -	switch (srcsel) {
> -	case ZYNQ_CLKMUX_SEL_0:
> -	case ZYNQ_CLKMUX_SEL_1:
> -		return iopll_clk;
> -	case ZYNQ_CLKMUX_SEL_2:
> -		return armpll_clk;
> -	case ZYNQ_CLKMUX_SEL_3:
> -		return ddrpll_clk;
> -	default:
> -		return 0;
> -	}
> -}
> -
> -/**
> - * zynq_clk_periph_get_parent() - Decode clock multiplexer
> - * @clk:	Clock handle
> - * Returns the clock identifier associated with the selected mux input.
> - */
> -static enum zynq_clk zynq_clk_periph_get_parent(struct clk *clk)
> -{
> -	u32 clk_ctrl = readl(clk->reg);
> -	u32 srcsel = (clk_ctrl & CLK_CTRL_SRCSEL_MASK) >> CLK_CTRL_SRCSEL_SHIFT;
> -
> -	return __zynq_clk_periph_get_parent(srcsel);
> -}
> -
> -/**
> - * zynq_clk_register_periph_clk() - Set up a peripheral clock with the framework
> - * @clk:	Pointer to struct clk for the clock
> - * @ctrl:	Clock control register
> - * @two_divs:	Indicates whether the clock features one or two dividers
> - */
> -static int zynq_clk_register_periph_clk(struct clk *clk, u32 *ctrl,
> -		bool two_divs)
> -{
> -	clk->reg = ctrl;
> -	if (two_divs)
> -		clk->flags = ZYNQ_CLK_FLAGS_HAS_2_DIVS;
> -	clk->parent = zynq_clk_periph_get_parent(clk);
> -	clk->frequency = zynq_clk_periph_get_rate(clk);
> -	clk->ops.get_rate = zynq_clk_periph_get_rate;
> -	clk->ops.set_rate = zynq_clk_periph_set_rate;
> -
> -	return 0;
> -}
> -
> -static void init_periph_clocks(void)
> -{
> -	zynq_clk_register_periph_clk(&clks[gem0_clk],
> -				     &slcr_base->gem0_clk_ctrl, 1);
> -	zynq_clk_register_periph_clk(&clks[gem1_clk],
> -				     &slcr_base->gem1_clk_ctrl, 1);
> -
> -	zynq_clk_register_periph_clk(&clks[smc_clk],
> -				     &slcr_base->smc_clk_ctrl, 0);
> -
> -	zynq_clk_register_periph_clk(&clks[lqspi_clk],
> -				     &slcr_base->lqspi_clk_ctrl, 0);
> -
> -	zynq_clk_register_periph_clk(&clks[sdio0_clk],
> -				     &slcr_base->sdio_clk_ctrl, 0);
> -	zynq_clk_register_periph_clk(&clks[sdio1_clk],
> -				     &slcr_base->sdio_clk_ctrl, 0);
> -
> -	zynq_clk_register_periph_clk(&clks[spi0_clk],
> -				     &slcr_base->spi_clk_ctrl, 0);
> -	zynq_clk_register_periph_clk(&clks[spi1_clk],
> -				     &slcr_base->spi_clk_ctrl, 0);
> -
> -	zynq_clk_register_periph_clk(&clks[uart0_clk],
> -				     &slcr_base->uart_clk_ctrl, 0);
> -	zynq_clk_register_periph_clk(&clks[uart1_clk],
> -				     &slcr_base->uart_clk_ctrl, 0);
> -
> -	zynq_clk_register_periph_clk(&clks[dbg_trc_clk],
> -				     &slcr_base->dbg_clk_ctrl, 0);
> -	zynq_clk_register_periph_clk(&clks[dbg_apb_clk],
> -				     &slcr_base->dbg_clk_ctrl, 0);
> -
> -	zynq_clk_register_periph_clk(&clks[pcap_clk],
> -				     &slcr_base->pcap_clk_ctrl, 0);
> -
> -	zynq_clk_register_periph_clk(&clks[fclk0_clk],
> -				     &slcr_base->fpga0_clk_ctrl, 1);
> -	zynq_clk_register_periph_clk(&clks[fclk1_clk],
> -				     &slcr_base->fpga1_clk_ctrl, 1);
> -	zynq_clk_register_periph_clk(&clks[fclk2_clk],
> -				     &slcr_base->fpga2_clk_ctrl, 1);
> -	zynq_clk_register_periph_clk(&clks[fclk3_clk],
> -				     &slcr_base->fpga3_clk_ctrl, 1);
> -}
> -
> -/**
> - * zynq_clk_register_aper_clk() - Set up a APER clock with the framework
> - * @clk:	Pointer to struct clk for the clock
> - * @ctrl:	Clock control register
> - */
> -static void zynq_clk_register_aper_clk(struct clk *clk, u32 *ctrl)
> -{
> -	clk->reg = ctrl;
> -	clk->parent = cpu_1x_clk;
> -	clk->frequency = zynq_clk_get_rate(clk->parent);
> -}
> -
> -static void init_aper_clocks(void)
> -{
> -	zynq_clk_register_aper_clk(&clks[usb0_aper_clk],
> -				   &slcr_base->aper_clk_ctrl);
> -	zynq_clk_register_aper_clk(&clks[usb1_aper_clk],
> -				   &slcr_base->aper_clk_ctrl);
> -
> -	zynq_clk_register_aper_clk(&clks[gem0_aper_clk],
> -				   &slcr_base->aper_clk_ctrl);
> -	zynq_clk_register_aper_clk(&clks[gem1_aper_clk],
> -				   &slcr_base->aper_clk_ctrl);
> -
> -	zynq_clk_register_aper_clk(&clks[sdio0_aper_clk],
> -				   &slcr_base->aper_clk_ctrl);
> -	zynq_clk_register_aper_clk(&clks[sdio1_aper_clk],
> -				   &slcr_base->aper_clk_ctrl);
> -
> -	zynq_clk_register_aper_clk(&clks[spi0_aper_clk],
> -				   &slcr_base->aper_clk_ctrl);
> -	zynq_clk_register_aper_clk(&clks[spi1_aper_clk],
> -				   &slcr_base->aper_clk_ctrl);
> -
> -	zynq_clk_register_aper_clk(&clks[can0_aper_clk],
> -				   &slcr_base->aper_clk_ctrl);
> -	zynq_clk_register_aper_clk(&clks[can1_aper_clk],
> -				   &slcr_base->aper_clk_ctrl);
> -
> -	zynq_clk_register_aper_clk(&clks[i2c0_aper_clk],
> -				   &slcr_base->aper_clk_ctrl);
> -	zynq_clk_register_aper_clk(&clks[i2c1_aper_clk],
> -				   &slcr_base->aper_clk_ctrl);
> -
> -	zynq_clk_register_aper_clk(&clks[uart0_aper_clk],
> -				   &slcr_base->aper_clk_ctrl);
> -	zynq_clk_register_aper_clk(&clks[uart1_aper_clk],
> -				   &slcr_base->aper_clk_ctrl);
> -
> -	zynq_clk_register_aper_clk(&clks[gpio_aper_clk],
> -				   &slcr_base->aper_clk_ctrl);
> -
> -	zynq_clk_register_aper_clk(&clks[lqspi_aper_clk],
> -				   &slcr_base->aper_clk_ctrl);
> -
> -	zynq_clk_register_aper_clk(&clks[smc_aper_clk],
> -				   &slcr_base->aper_clk_ctrl);
> -}
> -
> -/**
> - * __zynq_clk_pll_get_rate() - Get PLL rate
> - * @addr:	Address of the PLL's control register
> - * Returns the current PLL output rate.
> - */
> -static unsigned long __zynq_clk_pll_get_rate(u32 *addr)
> -{
> -	u32 reg, mul, bypass;
> -
> -	reg = readl(addr);
> -	bypass = reg & PLLCTRL_BPFORCE_MASK;
> -	if (bypass)
> -		mul = 1;
> -	else
> -		mul = (reg & PLLCTRL_FBDIV_MASK) >> PLLCTRL_FBDIV_SHIFT;
> -
> -	return CONFIG_ZYNQ_PS_CLK_FREQ * mul;
> -}
> -
> -/**
> - * zynq_clk_pll_get_rate() - Get PLL rate
> - * @pll:	Handle of the PLL
> - * Returns the current clock rate of @pll.
> - */
> -static unsigned long zynq_clk_pll_get_rate(struct clk *pll)
> -{
> -	return __zynq_clk_pll_get_rate(pll->reg);
> -}
> -
> -/**
> - * zynq_clk_register_pll() - Set up a PLL with the framework
> - * @clk:	Pointer to struct clk for the PLL
> - * @ctrl:	PLL control register
> - * @prate:	PLL input clock rate
> - */
> -static void zynq_clk_register_pll(struct clk *clk, u32 *ctrl,
> -		unsigned long prate)
> -{
> -	clk->reg = ctrl;
> -	clk->frequency = zynq_clk_pll_get_rate(clk);
> -	clk->ops.get_rate = zynq_clk_pll_get_rate;
> -}
> -
> -/**
> - * clkid_2_register() - Get clock control register
> - * @id:	Clock identifier of one of the PLLs
> - * Returns the address of the requested PLL's control register.
> - */
> -static u32 *clkid_2_register(enum zynq_clk id)
> -{
> -	switch (id) {
> -	case armpll_clk:
> -		return &slcr_base->arm_pll_ctrl;
> -	case ddrpll_clk:
> -		return &slcr_base->ddr_pll_ctrl;
> -	case iopll_clk:
> -		return &slcr_base->io_pll_ctrl;
> -	default:
> -		return &slcr_base->io_pll_ctrl;
> -	}
> -}
> -
> -/* API */
> -/**
> - * zynq_clk_early_init() - Early init for the clock framework
> - *
> - * This function is called from before relocation and sets up the CPU clock
> - * frequency in the global data struct.
> - */
> -void zynq_clk_early_init(void)
> -{
> -	u32 reg = readl(&slcr_base->arm_clk_ctrl);
> -	u32 div = (reg & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
> -	u32 srcsel = (reg & CLK_CTRL_SRCSEL_MASK) >> CLK_CTRL_SRCSEL_SHIFT;
> -	enum zynq_clk parent = __zynq_clk_cpu_get_parent(srcsel);
> -	u32 *pllreg = clkid_2_register(parent);
> -	unsigned long prate = __zynq_clk_pll_get_rate(pllreg);
> -
> -	if (!div)
> -		div = 1;
> -
> -	gd->cpu_clk = DIV_ROUND_CLOSEST(prate, div);
> -}
> -
> -/**
> - * get_uart_clk() - Get UART input frequency
> - * @dev_index:	UART ID
> - * Returns UART input clock frequency in Hz.
> - *
> - * Compared to zynq_clk_get_rate() this function is designed to work before
> - * relocation and can be called when the serial UART is set up.
> - */
> -unsigned long get_uart_clk(int dev_index)
> -{
> -	u32 reg = readl(&slcr_base->uart_clk_ctrl);
> -	u32 div = (reg & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
> -	u32 srcsel = (reg & CLK_CTRL_SRCSEL_MASK) >> CLK_CTRL_SRCSEL_SHIFT;
> -	enum zynq_clk parent = __zynq_clk_periph_get_parent(srcsel);
> -	u32 *pllreg = clkid_2_register(parent);
> -	unsigned long prate = __zynq_clk_pll_get_rate(pllreg);
> -
> -	if (!div)
> -		div = 1;
> -
> -	return DIV_ROUND_CLOSEST(prate, div);
> -}
> -
> -/**
> - * set_cpu_clk_info() - Initialize clock framework
> - * Always returns zero.
> + * set_cpu_clk_info() - Setup clock information
>   *
>   * This function is called from common code after relocation and sets up the
> - * clock framework. The framework must not be used before this function had been
> - * called.
> + * clock information.
>   */
>  int set_cpu_clk_info(void)
>  {
> -	zynq_clk_register_pll(&clks[armpll_clk], &slcr_base->arm_pll_ctrl,
> -			      CONFIG_ZYNQ_PS_CLK_FREQ);
> -	zynq_clk_register_pll(&clks[ddrpll_clk], &slcr_base->ddr_pll_ctrl,
> -			      CONFIG_ZYNQ_PS_CLK_FREQ);
> -	zynq_clk_register_pll(&clks[iopll_clk], &slcr_base->io_pll_ctrl,
> -			      CONFIG_ZYNQ_PS_CLK_FREQ);
> -
> -	init_ddr_clocks();
> -	init_cpu_clocks();
> -	init_periph_clocks();
> -	init_aper_clocks();
> -
> -	gd->bd->bi_arm_freq = gd->cpu_clk / 1000000;
> +	struct clk clk;
> +	struct udevice *dev;
> +	ulong rate;
> +	int i, ret;
> +
> +	ret = uclass_get_device_by_driver(UCLASS_CLK,
> +		DM_GET_DRIVER(zynq_clk), &dev);
> +	if (ret)
> +		return ret;
> +
> +	for (i = 0; i < 2; i++) {
> +		clk.id = i ? ddr3x_clk : cpu_6or4x_clk;
> +		ret = clk_request(dev, &clk);
> +		if (ret < 0)
> +			return ret;
> +
> +		rate = clk_get_rate(&clk) / 1000000;
> +		if (i)
> +			gd->bd->bi_ddr_freq = rate;
> +		else
> +			gd->bd->bi_arm_freq = rate;
> +
> +		clk_free(&clk);
> +	}
>  	gd->bd->bi_dsp_freq = 0;
>  
>  	return 0;
>  }
>  
>  /**
> - * zynq_clk_get_rate() - Get clock rate
> - * @clk:	Clock identifier
> - * Returns the current clock rate of @clk on success or zero for an invalid
> - * clock id.
> - */
> -unsigned long zynq_clk_get_rate(enum zynq_clk clk)
> -{
> -	if (clk < 0 || clk >= clk_max)
> -		return 0;
> -
> -	return clks[clk].frequency;
> -}
> -
> -/**
> - * zynq_clk_set_rate() - Set clock rate
> - * @clk:	Clock identifier
> - * @rate:	Requested clock rate
> - * Passes on the return value from the clock's set_rate() function or negative
> - * errno.
> - */
> -int zynq_clk_set_rate(enum zynq_clk clk, unsigned long rate)
> -{
> -	if (clk < 0 || clk >= clk_max)
> -		return -ENODEV;
> -
> -	if (clks[clk].ops.set_rate)
> -		return clks[clk].ops.set_rate(&clks[clk], rate);
> -
> -	return -ENXIO;
> -}
> -
> -/**
>   * soc_clk_dump() - Print clock frequencies
>   * Returns zero on success
>   *
> @@ -639,13 +70,32 @@ int zynq_clk_set_rate(enum zynq_clk clk, unsigned long rate)
>   */
>  int soc_clk_dump(void)
>  {
> -	int i;
> +	struct udevice *dev;
> +	int i, ret;
> +
> +	ret = uclass_get_device_by_driver(UCLASS_CLK,
> +		DM_GET_DRIVER(zynq_clk), &dev);
> +	if (ret)
> +		return ret;
>  
>  	printf("clk\t\tfrequency\n");
>  	for (i = 0; i < clk_max; i++) {
>  		const char *name = clk_names[i];
> -		if (name)
> -			printf("%10s%20lu\n", name, zynq_clk_get_rate(i));
> +		if (name) {
> +			struct clk clk;
> +			unsigned long rate;
> +
> +			clk.id = i;
> +			ret = clk_request(dev, &clk);
> +			if (ret < 0)
> +				return ret;
> +
> +			rate = clk_get_rate(&clk);
> +
> +			clk_free(&clk);
> +
> +			printf("%10s%20lu\n", name, rate);
> +		}
>  	}
>  
>  	return 0;
> diff --git a/arch/arm/mach-zynq/cpu.c b/arch/arm/mach-zynq/cpu.c
> index ba9171e..ee1c1a9 100644
> --- a/arch/arm/mach-zynq/cpu.c
> +++ b/arch/arm/mach-zynq/cpu.c
> @@ -35,7 +35,6 @@ int arch_cpu_init(void)
>  	writel(0xC, &slcr_base->ddr_urgent);
>  #endif
>  #endif
> -	zynq_clk_early_init();
>  	zynq_slcr_lock();
>  
>  	return 0;
> diff --git a/arch/arm/mach-zynq/include/mach/clk.h b/arch/arm/mach-zynq/include/mach/clk.h
> index 5c2758a..8a039ae 100644
> --- a/arch/arm/mach-zynq/include/mach/clk.h
> +++ b/arch/arm/mach-zynq/include/mach/clk.h
> @@ -20,9 +20,4 @@ enum zynq_clk {
>  	uart0_aper_clk, uart1_aper_clk, gpio_aper_clk, lqspi_aper_clk,
>  	smc_aper_clk, swdt_clk, dbg_trc_clk, dbg_apb_clk, clk_max};
>  
> -void zynq_clk_early_init(void);
> -int zynq_clk_set_rate(enum zynq_clk clk, unsigned long rate);
> -unsigned long zynq_clk_get_rate(enum zynq_clk clk);
> -unsigned long get_uart_clk(int dev_id);
> -
>  #endif
> diff --git a/arch/arm/mach-zynq/include/mach/sys_proto.h b/arch/arm/mach-zynq/include/mach/sys_proto.h
> index 44c9b50..67238e7 100644
> --- a/arch/arm/mach-zynq/include/mach/sys_proto.h
> +++ b/arch/arm/mach-zynq/include/mach/sys_proto.h
> @@ -10,7 +10,6 @@
>  extern void zynq_slcr_lock(void);
>  extern void zynq_slcr_unlock(void);
>  extern void zynq_slcr_cpu_reset(void);
> -extern void zynq_slcr_gem_clk_setup(u32 gem_id, unsigned long clk_rate);
>  extern void zynq_slcr_devcfg_disable(void);
>  extern void zynq_slcr_devcfg_enable(void);
>  extern u32 zynq_slcr_get_boot_mode(void);
> diff --git a/arch/arm/mach-zynq/slcr.c b/arch/arm/mach-zynq/slcr.c
> index c1129cd..2a207ae 100644
> --- a/arch/arm/mach-zynq/slcr.c
> +++ b/arch/arm/mach-zynq/slcr.c
> @@ -9,7 +9,6 @@
>  #include <malloc.h>
>  #include <asm/arch/hardware.h>
>  #include <asm/arch/sys_proto.h>
> -#include <asm/arch/clk.h>
>  
>  #define SLCR_LOCK_MAGIC		0x767B
>  #define SLCR_UNLOCK_MAGIC	0xDF0D
> @@ -124,27 +123,6 @@ void zynq_slcr_cpu_reset(void)
>  	writel(1, &slcr_base->pss_rst_ctrl);
>  }
>  
> -/* Setup clk for network */
> -void zynq_slcr_gem_clk_setup(u32 gem_id, unsigned long clk_rate)
> -{
> -	int ret;
> -
> -	zynq_slcr_unlock();
> -
> -	if (gem_id > 1) {
> -		printf("Non existing GEM id %d\n", gem_id);
> -		goto out;
> -	}
> -
> -	ret = zynq_clk_set_rate(gem0_clk + gem_id, clk_rate);
> -	if (ret)
> -		goto out;
> -
> -	udelay(100000);
> -out:
> -	zynq_slcr_lock();
> -}
> -
>  void zynq_slcr_devcfg_disable(void)
>  {
>  	u32 reg_val;
> diff --git a/arch/arm/mach-zynq/timer.c b/arch/arm/mach-zynq/timer.c
> index 0335cbe..b1bb3b8 100644
> --- a/arch/arm/mach-zynq/timer.c
> +++ b/arch/arm/mach-zynq/timer.c
> @@ -61,7 +61,6 @@ int timer_init(void)
>  			(TIMER_PRESCALE << SCUTIMER_CONTROL_PRESCALER_SHIFT) |
>  			SCUTIMER_CONTROL_ENABLE_MASK;
>  
> -#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
>  	struct udevice *dev;
>  	struct clk clk;
>  	int ret;
> @@ -79,7 +78,6 @@ int timer_init(void)
>  	gd->cpu_clk = clk_get_rate(&clk);
>  
>  	clk_free(&clk);
> -#endif
>  
>  	gd->arch.timer_rate_hz = (gd->cpu_clk / 2) / (TIMER_PRESCALE + 1);
>  
> diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c
> index 9118e49..2c95188 100644
> --- a/drivers/net/zynq_gem.c
> +++ b/drivers/net/zynq_gem.c
> @@ -181,9 +181,7 @@ struct zynq_gem_priv {
>  	struct phy_device *phydev;
>  	int phy_of_handle;
>  	struct mii_dev *bus;
> -#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
>  	struct clk tx_clk;
> -#endif
>  };
>  
>  static inline int mdio_wait(struct zynq_gem_regs *regs)
> @@ -368,9 +366,7 @@ static int zynq_gem_init(struct udevice *dev)
>  	u32 i, nwconfig;
>  	int ret;
>  	unsigned long clk_rate = 0;
> -#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
>  	unsigned long clk_rate_rounded;
> -#endif
>  	struct zynq_gem_priv *priv = dev_get_priv(dev);
>  	struct zynq_gem_regs *regs = priv->iobase;
>  	struct emac_bd *dummy_tx_bd = &priv->tx_bd[TX_FREE_DESC];
> @@ -473,7 +469,6 @@ static int zynq_gem_init(struct udevice *dev)
>  		break;
>  	}
>  
> -#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
>  	clk_rate_rounded = clk_set_rate(&priv->tx_clk, clk_rate);
>  	if (IS_ERR_VALUE(clk_rate_rounded)) {
>  		dev_err(dev, "failed to set tx clock rate\n");
> @@ -485,10 +480,6 @@ static int zynq_gem_init(struct udevice *dev)
>  		dev_err(dev, "failed to enable tx clock\n");
>  		return ret;
>  	}
> -#else
> -	zynq_slcr_gem_clk_setup((ulong)priv->iobase !=
> -				ZYNQ_GEM_BASEADDR0, clk_rate);
> -#endif
>  
>  	setbits_le32(&regs->nwctrl, ZYNQ_GEM_NWCTRL_RXEN_MASK |
>  					ZYNQ_GEM_NWCTRL_TXEN_MASK);
> @@ -699,9 +690,7 @@ static int zynq_gem_ofdata_to_platdata(struct udevice *dev)
>  	struct eth_pdata *pdata = dev_get_platdata(dev);
>  	struct zynq_gem_priv *priv = dev_get_priv(dev);
>  	const char *phy_mode;
> -#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
>  	int ret;
> -#endif
>  
>  	pdata->iobase = (phys_addr_t)dev_get_addr(dev);
>  	priv->iobase = (struct zynq_gem_regs *)pdata->iobase;
> @@ -723,13 +712,11 @@ static int zynq_gem_ofdata_to_platdata(struct udevice *dev)
>  	}
>  	priv->interface = pdata->phy_interface;
>  
> -#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
>  	ret = clk_get_by_index(dev, 2, &priv->tx_clk);
>  	if (ret < 0) {
>  		dev_err(dev, "failed to get clock\n");
>  		return ret;
>  	}
> -#endif
>  
>  	printf("ZYNQ GEM: %lx, phyaddr %x, interface %s\n", (ulong)priv->iobase,
>  	       priv->phyaddr, phy_string_for_interface(priv->interface));
> diff --git a/drivers/serial/serial_zynq.c b/drivers/serial/serial_zynq.c
> index 4f6e7e4..a2967c0 100644
> --- a/drivers/serial/serial_zynq.c
> +++ b/drivers/serial/serial_zynq.c
> @@ -15,7 +15,6 @@
>  #include <asm/io.h>
>  #include <linux/compiler.h>
>  #include <serial.h>
> -#include <asm/arch/clk.h>
>  #include <asm/arch/hardware.h>
>  
>  DECLARE_GLOBAL_DATA_PTR;
> @@ -111,7 +110,6 @@ int zynq_serial_setbrg(struct udevice *dev, int baudrate)
>  	struct zynq_uart_priv *priv = dev_get_priv(dev);
>  	unsigned long clock;
>  
> -#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
>  	int ret;
>  	struct clk clk;
>  
> @@ -133,9 +131,7 @@ int zynq_serial_setbrg(struct udevice *dev, int baudrate)
>  		dev_err(dev, "failed to enable clock\n");
>  		return ret;
>  	}
> -#else
> -	clock = get_uart_clk(0);
> -#endif
> +
>  	_uart_zynq_serial_setbrg(priv->regs, clock, baudrate);
>  
>  	return 0;
> diff --git a/include/configs/topic_miami.h b/include/configs/topic_miami.h
> index 3b0fa29..a1ccc42 100644
> --- a/include/configs/topic_miami.h
> +++ b/include/configs/topic_miami.h
> @@ -10,8 +10,6 @@
>  #ifndef __CONFIG_TOPIC_MIAMI_H
>  #define __CONFIG_TOPIC_MIAMI_H
>  
> -#define CONFIG_ZYNQ_PS_CLK_FREQ		33333333UL
> -
>  #define CONFIG_ZYNQ_I2C0
>  #define CONFIG_ZYNQ_I2C1
>  
> diff --git a/include/configs/zynq_zybo.h b/include/configs/zynq_zybo.h
> index b9ff391..1488fd8 100644
> --- a/include/configs/zynq_zybo.h
> +++ b/include/configs/zynq_zybo.h
> @@ -20,9 +20,6 @@
>  #define CONFIG_DISPLAY
>  #define CONFIG_I2C_EDID
>  
> -/* Define ZYBO PS Clock Frequency to 50MHz */
> -#define CONFIG_ZYNQ_PS_CLK_FREQ	50000000UL
> -
>  #include <configs/zynq-common.h>
>  
>  #endif /* __CONFIG_ZYNQ_ZYBO_H */
> diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt
> index 6d614c6..375b9b8 100644
> --- a/scripts/config_whitelist.txt
> +++ b/scripts/config_whitelist.txt
> @@ -8248,7 +8248,6 @@ CONFIG_ZYNQ_GEM_I2C_MAC_OFFSET
>  CONFIG_ZYNQ_HISPD_BROKEN
>  CONFIG_ZYNQ_I2C0
>  CONFIG_ZYNQ_I2C1
> -CONFIG_ZYNQ_PS_CLK_FREQ
>  CONFIG_ZYNQ_SDHCI0
>  CONFIG_ZYNQ_SDHCI1
>  CONFIG_ZYNQ_SDHCI_MAX_FREQ
> 

Looks good.

Acked-by: Michal Simek <michal.simek@xilinx.com>

Thanks,
Michal

-- 
Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel - Xilinx Microblaze
Maintainer of Linux kernel - Xilinx Zynq ARM and ZynqMP ARM64 SoCs
U-Boot custodian - Xilinx Microblaze/Zynq/ZynqMP SoCs


-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: OpenPGP digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170110/a1c6414d/attachment.sig>

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

* [U-Boot] [PATCH 8/8] clk: zynq: Add optional ethernet emio clock source support
  2017-01-04 12:27 ` [U-Boot] [PATCH 8/8] clk: zynq: Add optional ethernet emio clock source support stefan.herbrechtsmeier at weidmueller.com
@ 2017-01-10 15:06   ` Michal Simek
  0 siblings, 0 replies; 29+ messages in thread
From: Michal Simek @ 2017-01-10 15:06 UTC (permalink / raw)
  To: u-boot

On 4.1.2017 13:27, stefan.herbrechtsmeier at weidmueller.com wrote:
> From: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
> 
> Add support for the optional ethernet emio clock source to the zynq
> clock framework driver.
> 
> Signed-off-by: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
> 
> ---
> 
>  drivers/clk/clk_zynq.c | 33 +++++++++++++++++++++++++++++++--
>  1 file changed, 31 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/clk/clk_zynq.c b/drivers/clk/clk_zynq.c
> index d276155..6f1448d 100644
> --- a/drivers/clk/clk_zynq.c
> +++ b/drivers/clk/clk_zynq.c
> @@ -53,6 +53,9 @@ enum zynq_clk_rclk {mio_clk, emio_clk};
>  
>  struct zynq_clk_priv {
>  	ulong ps_clk_freq;
> +#ifndef CONFIG_SPL_BUILD
> +	struct clk gem_emio_clk[2];
> +#endif
>  };
>  
>  static void *zynq_clk_get_register(enum zynq_clk id)
> @@ -284,10 +287,16 @@ static ulong zynq_clk_get_peripheral_rate(struct zynq_clk_priv *priv,
>  #ifndef CONFIG_SPL_BUILD
>  static ulong zynq_clk_get_gem_rate(struct zynq_clk_priv *priv, enum zynq_clk id)
>  {
> +	struct clk *parent;
> +
>  	if (zynq_clk_get_gem_rclk(id) == mio_clk)
>  		return zynq_clk_get_peripheral_rate(priv, id, true);
>  
> -	return 0;
> +	parent = &priv->gem_emio_clk[id - gem0_clk];
> +	if (parent)
> +		return clk_get_rate(parent);
> +
> +	return -ENXIO;
>  }
>  
>  static unsigned long zynq_clk_calc_peripheral_two_divs(
> @@ -354,10 +363,16 @@ static ulong zynq_clk_set_peripheral_rate(struct zynq_clk_priv *priv,
>  static ulong zynq_clk_set_gem_rate(struct zynq_clk_priv *priv, enum zynq_clk id,
>  				   ulong rate)
>  {
> +	struct clk *parent;
> +
>  	if (zynq_clk_get_gem_rclk(id) == mio_clk)
>  		return zynq_clk_set_peripheral_rate(priv, id, rate, true);
>  
> -	return 0;
> +	parent = &priv->gem_emio_clk[id - gem0_clk];
> +	if (parent)
> +		return clk_set_rate(parent, rate);
> +
> +	return -ENXIO;
>  }
>  #endif
>  
> @@ -447,6 +462,20 @@ static struct clk_ops zynq_clk_ops = {
>  static int zynq_clk_probe(struct udevice *dev)
>  {
>  	struct zynq_clk_priv *priv = dev_get_priv(dev);
> +#ifndef CONFIG_SPL_BUILD
> +	unsigned int i;
> +	char name[16];
> +	int ret;
> +
> +	for (i = 0; i < 2; i++) {
> +		sprintf(name, "gem%d_emio_clk", i);
> +		ret = clk_get_by_name(dev, name, &priv->gem_emio_clk[i]);
> +		if (ret < 0 && ret != -FDT_ERR_NOTFOUND) {
> +			dev_err(dev, "failed to get %s clock\n", name);
> +			return ret;
> +		}
> +	}
> +#endif
>  
>  	priv->ps_clk_freq = fdtdec_get_uint(gd->fdt_blob, dev->of_offset,
>  					    "ps-clk-frequency", 33333333UL);
> 

Ah ok. Here it is emio stuff for ethernet.

Thanks,
Michal

-- 
Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel - Xilinx Microblaze
Maintainer of Linux kernel - Xilinx Zynq ARM and ZynqMP ARM64 SoCs
U-Boot custodian - Xilinx Microblaze/Zynq/ZynqMP SoCs


-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: OpenPGP digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170110/0f4c3609/attachment.sig>

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

* [U-Boot] [PATCH 3/8] zynq: Add clk framework support to zynq timer
  2017-01-10 14:54     ` Stefan.Herbrechtsmeier at weidmueller.com
@ 2017-01-10 15:08       ` Michal Simek
  0 siblings, 0 replies; 29+ messages in thread
From: Michal Simek @ 2017-01-10 15:08 UTC (permalink / raw)
  To: u-boot

On 10.1.2017 15:54, Stefan.Herbrechtsmeier at weidmueller.com wrote:
>> -----Urspr?ngliche Nachricht-----
>> Von: Michal Simek [mailto:monstr at monstr.eu]
>> Gesendet: Dienstag, 10. Januar 2017 15:10
>> An: Herbrechtsmeier, Stefan; u-boot at lists.denx.de
>> Cc: Albert Aribaud; Herbrechtsmeier, Stefan
>> Betreff: Re: [PATCH 3/8] zynq: Add clk framework support to zynq timer
>>
>> On 4.1.2017 13:27, stefan.herbrechtsmeier at weidmueller.com wrote:
>>> From: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
>>>
>>> If available use the clock framework to calculate the clock rate of
>>> the zynq timer.
>>>
>>> Signed-off-by: Stefan Herbrechtsmeier
>>> <stefan.herbrechtsmeier@weidmueller.com>
>>> ---
>>>
>>>  arch/arm/mach-zynq/timer.c | 25 +++++++++++++++++++++++++
>>>  1 file changed, 25 insertions(+)
>>>
>>> diff --git a/arch/arm/mach-zynq/timer.c b/arch/arm/mach-zynq/timer.c
>>> index 8ff82dc..0335cbe 100644
>>> --- a/arch/arm/mach-zynq/timer.c
>>> +++ b/arch/arm/mach-zynq/timer.c
>>> @@ -1,4 +1,7 @@
>>>  /*
>>> + * Copyright (C) 2017 Weidm?ller Interface GmbH & Co. KG
>>> + * Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
>>> + *
>>>   * Copyright (C) 2012 Michal Simek <monstr@monstr.eu>
>>>   * Copyright (C) 2011-2012 Xilinx, Inc. All rights reserved.
>>>   *
>>> @@ -25,8 +28,10 @@
>>>   * SPDX-License-Identifier:	GPL-2.0+
>>>   */
>>>
>>> +#include <clk.h>
>>>  #include <common.h>
>>>  #include <div64.h>
>>> +#include <dm.h>
>>>  #include <asm/io.h>
>>>  #include <asm/arch/hardware.h>
>>>  #include <asm/arch/clk.h>
>>> @@ -56,6 +61,26 @@ int timer_init(void)
>>>  			(TIMER_PRESCALE << SCUTIMER_CONTROL_PRESCALER_SHIFT)
>> |
>>>  			SCUTIMER_CONTROL_ENABLE_MASK;
>>>
>>> +#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
>>> +	struct udevice *dev;
>>> +	struct clk clk;
>>> +	int ret;
>>> +
>>> +	ret = uclass_get_device_by_driver(UCLASS_CLK,
>>> +		DM_GET_DRIVER(zynq_clk), &dev);
>>> +	if (ret)
>>> +		return ret;
>>> +
>>> +	clk.id = cpu_6or4x_clk;
>>
>> This information is already present in DT file. What's the reason not
>> to take it from it?
> Because this is not a DM driver and I don't know the device node. This could be done if we move the driver to drivers/timer.
> 
>>
>>> +	ret = clk_request(dev, &clk);
>>> +	if (ret < 0)
>>> +		return ret;
>>> +
>>> +	gd->cpu_clk = clk_get_rate(&clk);
>>> +
>>> +	clk_free(&clk);
>>
>> Not clk expert but isn't there a way to handle it like it is handled
>> for other drivers? clk_get(), clk_get_rate()?
> This is the solution I found in other platform drivers. The clk_get function requires a DM device.

Ok fair enough. We can use it when driver is moved.

Thanks,
Michal

-- 
Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel - Xilinx Microblaze
Maintainer of Linux kernel - Xilinx Zynq ARM and ZynqMP ARM64 SoCs
U-Boot custodian - Xilinx Microblaze/Zynq/ZynqMP SoCs


-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: OpenPGP digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170110/6e93b62b/attachment.sig>

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

* [U-Boot] [PATCH 2/8] net: zynq: Add clk framework support to zynq ethernet driver
  2017-01-10 14:46     ` Stefan.Herbrechtsmeier at weidmueller.com
@ 2017-01-10 15:23       ` Michal Simek
  2017-01-11  7:30         ` Stefan.Herbrechtsmeier at weidmueller.com
  0 siblings, 1 reply; 29+ messages in thread
From: Michal Simek @ 2017-01-10 15:23 UTC (permalink / raw)
  To: u-boot

On 10.1.2017 15:46, Stefan.Herbrechtsmeier at weidmueller.com wrote:
>> -----Urspr?ngliche Nachricht-----
>> Von: Michal Simek [mailto:monstr at monstr.eu]
>> Gesendet: Dienstag, 10. Januar 2017 14:59
>> An: Herbrechtsmeier, Stefan; u-boot at lists.denx.de
>> Cc: Herbrechtsmeier, Stefan; Albert Aribaud; Michal Simek; Joe
>> Hershberger
>> Betreff: Re: [PATCH 2/8] net: zynq: Add clk framework support to zynq
>> ethernet driver
>>
>> On 4.1.2017 13:27, stefan.herbrechtsmeier at weidmueller.com wrote:
>>> From: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.de>
>>>
>>> If available use the clock framework to set the tx clock rate of the
>>> zynq ethernet controller.
>>>
>>> Signed-off-by: Stefan Herbrechtsmeier
>>> <stefan.herbrechtsmeier@weidmueller.com>
>>> ---
>>>
>>>  arch/arm/include/asm/arch-zynqmp/sys_proto.h |  5 -----
>>>  drivers/net/zynq_gem.c                       | 31
>> ++++++++++++++++++++++++++++
>>>  2 files changed, 31 insertions(+), 5 deletions(-)
>>>
>>> diff --git a/arch/arm/include/asm/arch-zynqmp/sys_proto.h
>>> b/arch/arm/include/asm/arch-zynqmp/sys_proto.h
>>> index 1db2bd6..bd633a6 100644
>>> --- a/arch/arm/include/asm/arch-zynqmp/sys_proto.h
>>> +++ b/arch/arm/include/asm/arch-zynqmp/sys_proto.h
>>> @@ -8,11 +8,6 @@
>>>  #ifndef _ASM_ARCH_SYS_PROTO_H
>>>  #define _ASM_ARCH_SYS_PROTO_H
>>>
>>> -/* Setup clk for network */
>>> -static inline void zynq_slcr_gem_clk_setup(u32 gem_id, unsigned long
>>> clk_rate) -{ -}
>>> -
>>>  int zynq_slcr_get_mio_pin_status(const char *periph);
>>>
>>>  unsigned int zynqmp_get_silicon_version(void); diff --git
>>> a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c index
>>> 9bfb89f..9118e49 100644
>>> --- a/drivers/net/zynq_gem.c
>>> +++ b/drivers/net/zynq_gem.c
>>> @@ -9,6 +9,7 @@
>>>   * SPDX-License-Identifier:	GPL-2.0+
>>>   */
>>>
>>> +#include <clk.h>
>>>  #include <common.h>
>>>  #include <dm.h>
>>>  #include <net.h>
>>> @@ -180,6 +181,9 @@ struct zynq_gem_priv {
>>>  	struct phy_device *phydev;
>>>  	int phy_of_handle;
>>>  	struct mii_dev *bus;
>>> +#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
>>> +	struct clk tx_clk;
>>> +#endif
>>>  };
>>>
>>>  static inline int mdio_wait(struct zynq_gem_regs *regs) @@ -364,6
>>> +368,9 @@ static int zynq_gem_init(struct udevice *dev)
>>>  	u32 i, nwconfig;
>>>  	int ret;
>>>  	unsigned long clk_rate = 0;
>>> +#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
>>> +	unsigned long clk_rate_rounded;
>>> +#endif
>>>  	struct zynq_gem_priv *priv = dev_get_priv(dev);
>>>  	struct zynq_gem_regs *regs = priv->iobase;
>>>  	struct emac_bd *dummy_tx_bd = &priv->tx_bd[TX_FREE_DESC]; @@ -
>> 466,8
>>> +473,22 @@ static int zynq_gem_init(struct udevice *dev)
>>>  		break;
>>>  	}
>>>
>>> +#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
>>> +	clk_rate_rounded = clk_set_rate(&priv->tx_clk, clk_rate);
>>> +	if (IS_ERR_VALUE(clk_rate_rounded)) {
>>> +		dev_err(dev, "failed to set tx clock rate\n");
>>> +		return clk_rate_rounded;
>>> +	}
>>> +
>>> +	ret = clk_enable(&priv->tx_clk);
>>> +	if (ret && ret != -ENOSYS) {
>>> +		dev_err(dev, "failed to enable tx clock\n");
>>> +		return ret;
>>> +	}
>>> +#else
>>>  	zynq_slcr_gem_clk_setup((ulong)priv->iobase !=
>>>  				ZYNQ_GEM_BASEADDR0, clk_rate);
>>> +#endif
>>>
>>>  	setbits_le32(&regs->nwctrl, ZYNQ_GEM_NWCTRL_RXEN_MASK |
>>>  					ZYNQ_GEM_NWCTRL_TXEN_MASK);
>>> @@ -678,6 +699,9 @@ static int zynq_gem_ofdata_to_platdata(struct
>> udevice *dev)
>>>  	struct eth_pdata *pdata = dev_get_platdata(dev);
>>>  	struct zynq_gem_priv *priv = dev_get_priv(dev);
>>>  	const char *phy_mode;
>>> +#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
>>> +	int ret;
>>> +#endif
>>>
>>>  	pdata->iobase = (phys_addr_t)dev_get_addr(dev);
>>>  	priv->iobase = (struct zynq_gem_regs *)pdata->iobase; @@ -699,6
>>> +723,13 @@ static int zynq_gem_ofdata_to_platdata(struct udevice
>> *dev)
>>>  	}
>>>  	priv->interface = pdata->phy_interface;
>>>
>>> +#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
>>> +	ret = clk_get_by_index(dev, 2, &priv->tx_clk);
>>> +	if (ret < 0) {
>>> +		dev_err(dev, "failed to get clock\n");
>>> +		return ret;
>>> +	}
>>> +#endif
>>>
>>>  	printf("ZYNQ GEM: %lx, phyaddr %x, interface %s\n", (ulong)priv-
>>> iobase,
>>>  	       priv->phyaddr, phy_string_for_interface(priv->interface));
>>>
>>
>> Can you please rebase it on the top of this?
>> https://patchwork.ozlabs.org/patch/706419/
>>
>> The reason why this patch was written in this way is that we don't have
>> full zynqmp clk driver yet but we are using fixed clock where you can't
>> run set_rate which fails.
>>
> The patch assumes that the EMIO_ENET_TX_CLK is always fixed. Is this true?
> 
> Why don't you add a set_rate() function to the fixed clock?

It would be a solution but I am not sure if fixed clock was designed for
this. I would expect that fixed clock only provided clock which you
can't change. It means we need to have something as transition when
u-boot has real clk driver for zynqmp.

> 
> Additionally the patch is missing an enable function call.

correct.

> 
> I don't think the emio configuration should be keep in the Ethernet driver as it is part of the clock configuration and doesn't influent the network interface.

Please correct me if I am wrong. Are you saying that with these patches
especially 8/8 clock for emio will handled automatically?

Thanks,
Michal


-- 
Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel - Xilinx Microblaze
Maintainer of Linux kernel - Xilinx Zynq ARM and ZynqMP ARM64 SoCs
U-Boot custodian - Xilinx Microblaze/Zynq/ZynqMP SoCs


-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: OpenPGP digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170110/574fafc1/attachment.sig>

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

* [U-Boot] [PATCH 1/8] net: zynq: Don't overwrite gem_rclk_ctrl with default value
  2017-01-10 14:28     ` Stefan.Herbrechtsmeier at weidmueller.com
@ 2017-01-10 15:26       ` Michal Simek
  0 siblings, 0 replies; 29+ messages in thread
From: Michal Simek @ 2017-01-10 15:26 UTC (permalink / raw)
  To: u-boot

+siva

On 10.1.2017 15:28, Stefan.Herbrechtsmeier at weidmueller.com wrote:
> Hi Michal,
> 
>> -----Urspr?ngliche Nachricht-----
>> Von: Michal Simek [mailto:monstr at monstr.eu]
>> Gesendet: Dienstag, 10. Januar 2017 14:53
>> An: Herbrechtsmeier, Stefan; u-boot at lists.denx.de
>> Cc: Herbrechtsmeier, Stefan; Michal Simek; Jagan Teki; Albert Aribaud;
>> Joe Hershberger; Mike Looijmans
>> Betreff: Re: [PATCH 1/8] net: zynq: Don't overwrite gem_rclk_ctrl with
>> default value
>>
>> On 4.1.2017 13:27, stefan.herbrechtsmeier at weidmueller.com wrote:
>>> From: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.de>
>>>
>>> The gem[0-1]_rclk_ctrl registers control the source of the rx clock,
>>> control and data signals and configure via ps7_init function. Don't
>>> overwrite the register with the default value.
>>
>> TBH I don't think this is a win for us to relate on ps7_init
>> configuration. There are a lot of things there but I would like to
>> control this in this sw instead of psu_init.
> 
> At the moment the ps7_init only touch the register if the board doesn't use the default configuration. U-boot overwrite the register with the default value if 'xlnx,emio' isn't set in the device tree. It doesn't change the value to gem_rclk_ctrl if 'xlnx,emio' is set.
> 
> At the moment the clock configuration is managed by the ps7_init and only the gem_rclk_ctrl configuration is overwritten by u-boot. I don't think it is correct do overwrite some part of the clock tree configuration which is generated by Xilinx tools.

ok.

Siva: I don't have testcase for emio or any hw design to test this.
Do you have something which we can check?

Thanks,
Michal

-- 
Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel - Xilinx Microblaze
Maintainer of Linux kernel - Xilinx Zynq ARM and ZynqMP ARM64 SoCs
U-Boot custodian - Xilinx Microblaze/Zynq/ZynqMP SoCs


-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: OpenPGP digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170110/2abb186b/attachment.sig>

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

* [U-Boot] [PATCH 6/8] clk: zynq: Add zynq clock framework driver
  2017-01-10 14:57   ` Michal Simek
@ 2017-01-10 19:17     ` Sören Brinkmann
  2017-01-11  7:15     ` Stefan.Herbrechtsmeier at weidmueller.com
  1 sibling, 0 replies; 29+ messages in thread
From: Sören Brinkmann @ 2017-01-10 19:17 UTC (permalink / raw)
  To: u-boot

On Tue, 2017-01-10 at 15:57:09 +0100, Michal Simek wrote:
> +Soren
> 
> On 4.1.2017 13:27, stefan.herbrechtsmeier at weidmueller.com wrote:
> > From: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
> > 
> > Add a clock framework driver for the zynq platform. The driver is based
> > on the platform zynq clock driver but reworked to use static functions
> > instead of run-time generated objects even for unused clocks.
> > Additionally the CONFIG_ZYNQ_PS_CLK_FREQ is replaced by the
> > ps-clk-frequency from the device tree.
> > 
> > Signed-off-by: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
> > ---
> > 
> >  drivers/clk/Kconfig    |   7 +
> >  drivers/clk/Makefile   |   1 +
> >  drivers/clk/clk_zynq.c | 470 +++++++++++++++++++++++++++++++++++++++++++++++++
> >  3 files changed, 478 insertions(+)
> >  create mode 100644 drivers/clk/clk_zynq.c
> > 
> > diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> > index c05ce2a..714ccca 100644
> > --- a/drivers/clk/Kconfig
> > +++ b/drivers/clk/Kconfig
> > @@ -28,6 +28,13 @@ config CLK_BOSTON
> >  	help
> >  	  Enable this to support the clocks
> >  
> > +config CLK_ZYNQ
> > +	bool "Zynq clock driver"
> > +	depends on CLK && ARCH_ZYNQ
> > +	default y
> > +	help
> > +	  Enable this to support the clocks
> > +
> >  source "drivers/clk/tegra/Kconfig"
> >  source "drivers/clk/uniphier/Kconfig"
> >  source "drivers/clk/exynos/Kconfig"
> > diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> > index 40a5e8c..5e5b6b1 100644
> > --- a/drivers/clk/Makefile
> > +++ b/drivers/clk/Makefile
> > @@ -16,3 +16,4 @@ obj-$(CONFIG_CLK_UNIPHIER) += uniphier/
> >  obj-$(CONFIG_CLK_EXYNOS) += exynos/
> >  obj-$(CONFIG_CLK_AT91) += at91/
> >  obj-$(CONFIG_CLK_BOSTON) += clk_boston.o
> > +obj-$(CONFIG_CLK_ZYNQ) += clk_zynq.o
> > diff --git a/drivers/clk/clk_zynq.c b/drivers/clk/clk_zynq.c
> > new file mode 100644
> > index 0000000..d276155
> > --- /dev/null
> > +++ b/drivers/clk/clk_zynq.c
> > @@ -0,0 +1,470 @@
> > +/*
> > + * Copyright (C) 2017 Weidm?ller Interface GmbH & Co. KG
> > + * Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
> > + *
> > + * Copyright (C) 2013 Soren Brinkmann <soren.brinkmann@xilinx.com>
> > + * Copyright (C) 2013 Xilinx, Inc. All rights reserved.
> > + *
> > + * SPDX-License-Identifier:	GPL-2.0+
> > + */
> > +
> > +#include <common.h>
> > +#include <clk-uclass.h>
> > +#include <dm.h>
> > +#include <dm/lists.h>
> > +#include <errno.h>
> > +#include <asm/io.h>
> > +#include <asm/arch/clk.h>
> > +#include <asm/arch/hardware.h>
> > +#include <asm/arch/sys_proto.h>
> > +
> > +/* Register bitfield defines */
> > +#define PLLCTRL_FBDIV_MASK	0x7f000
> > +#define PLLCTRL_FBDIV_SHIFT	12
> > +#define PLLCTRL_BPFORCE_MASK	(1 << 4)
> > +#define PLLCTRL_PWRDWN_MASK	2
> > +#define PLLCTRL_PWRDWN_SHIFT	1
> > +#define PLLCTRL_RESET_MASK	1
> > +#define PLLCTRL_RESET_SHIFT	0
> > +
> > +#define ZYNQ_CLK_MAXDIV		0x3f
> > +#define CLK_CTRL_DIV1_SHIFT	20
> > +#define CLK_CTRL_DIV1_MASK	(ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV1_SHIFT)
> > +#define CLK_CTRL_DIV0_SHIFT	8
> > +#define CLK_CTRL_DIV0_MASK	(ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV0_SHIFT)
> > +#define CLK_CTRL_SRCSEL_SHIFT	4
> > +#define CLK_CTRL_SRCSEL_MASK	(0x3 << CLK_CTRL_SRCSEL_SHIFT)
> > +
> > +#define CLK_CTRL_DIV2X_SHIFT	26
> > +#define CLK_CTRL_DIV2X_MASK	(ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV2X_SHIFT)
> > +#define CLK_CTRL_DIV3X_SHIFT	20
> > +#define CLK_CTRL_DIV3X_MASK	(ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV3X_SHIFT)
> > +
> > +#define ZYNQ_CLKMUX_SEL_0	0
> > +#define ZYNQ_CLKMUX_SEL_1	1
> > +#define ZYNQ_CLKMUX_SEL_2	2
> > +#define ZYNQ_CLKMUX_SEL_3	3
> > +
> > +DECLARE_GLOBAL_DATA_PTR;
> > +
> > +#ifndef CONFIG_SPL_BUILD
> > +enum zynq_clk_rclk {mio_clk, emio_clk};
> > +#endif
> > +
> > +struct zynq_clk_priv {
> > +	ulong ps_clk_freq;
> > +};
> > +
> > +static void *zynq_clk_get_register(enum zynq_clk id)
> > +{
> > +	switch (id) {
> > +	case armpll_clk:
> > +		return &slcr_base->arm_pll_ctrl;
> > +	case ddrpll_clk:
> > +		return &slcr_base->ddr_pll_ctrl;
> > +	case iopll_clk:
> > +		return &slcr_base->io_pll_ctrl;
> > +#ifndef CONFIG_SPL_BUILD
> > +	case dci_clk:
> > +		return &slcr_base->dci_clk_ctrl;
> > +#endif
> > +	case lqspi_clk:
> > +		return &slcr_base->lqspi_clk_ctrl;
> > +	case smc_clk:
> > +		return &slcr_base->smc_clk_ctrl;
> > +	case pcap_clk:
> > +		return &slcr_base->pcap_clk_ctrl;
> > +#ifndef CONFIG_SPL_BUILD
> > +	case gem0_clk:
> > +		return &slcr_base->gem0_clk_ctrl;
> > +	case gem1_clk:
> > +		return &slcr_base->gem1_clk_ctrl;
> > +	case fclk0_clk:
> > +		return &slcr_base->fpga0_clk_ctrl;
> > +	case fclk1_clk:
> > +		return &slcr_base->fpga1_clk_ctrl;
> > +	case fclk2_clk:
> > +		return &slcr_base->fpga2_clk_ctrl;
> > +	case fclk3_clk:
> > +		return &slcr_base->fpga3_clk_ctrl;
> > +	case can0_clk ... can1_clk:
> > +		return &slcr_base->can_clk_ctrl;
> > +#endif
> > +	case sdio0_clk:
> > +	case sdio1_clk:
> > +		return &slcr_base->sdio_clk_ctrl;
> > +	case uart0_clk:
> > +	case uart1_clk:
> > +		return &slcr_base->uart_clk_ctrl;
> > +	case spi0_clk:
> > +	case spi1_clk:
> > +		return &slcr_base->spi_clk_ctrl;
> > +#ifndef CONFIG_SPL_BUILD
> > +	case dbg_trc_clk:
> > +	case dbg_apb_clk:
> > +		return &slcr_base->dbg_clk_ctrl;
> > +#endif
> 
> Please put them together.
> 
> > +	default:
> > +		return &slcr_base->dbg_clk_ctrl;
> > +	}
> > +}
> > +
> > +static enum zynq_clk zynq_clk_get_cpu_pll(u32 clk_ctrl)
> > +{
> > +	u32 srcsel = (clk_ctrl & CLK_CTRL_SRCSEL_MASK) >> CLK_CTRL_SRCSEL_SHIFT;
> > +
> > +	switch (srcsel) {
> > +	case ZYNQ_CLKMUX_SEL_0:
> > +	case ZYNQ_CLKMUX_SEL_1:
> > +		return armpll_clk;
> > +	case ZYNQ_CLKMUX_SEL_2:
> > +		return ddrpll_clk;
> > +	case ZYNQ_CLKMUX_SEL_3:
> > +		return iopll_clk;
> > +	default:
> > +		return armpll_clk;
> 
> 
> Default case shouldn't happen because of mask above.
> But if you want to keep it maybe this is a little bit better.
> 
> 	case ZYNQ_CLKMUX_SEL_2:
> 		return ddrpll_clk;
> 	case ZYNQ_CLKMUX_SEL_3:
> 		return iopll_clk;
> 	case ZYNQ_CLKMUX_SEL_0:
> 	case ZYNQ_CLKMUX_SEL_1:
> 	default:
> 		return armpll_clk;
> 
> 
> 
> 
> > +	}
> > +}
> > +
> > +static enum zynq_clk zynq_clk_get_peripheral_pll(u32 clk_ctrl)
> > +{
> > +	u32 srcsel = (clk_ctrl & CLK_CTRL_SRCSEL_MASK) >> CLK_CTRL_SRCSEL_SHIFT;
> > +
> > +	switch (srcsel) {
> > +	case ZYNQ_CLKMUX_SEL_0:
> > +	case ZYNQ_CLKMUX_SEL_1:
> > +		return iopll_clk;
> > +	case ZYNQ_CLKMUX_SEL_2:
> > +		return armpll_clk;
> > +	case ZYNQ_CLKMUX_SEL_3:
> > +		return ddrpll_clk;
> > +	default:
> > +		return iopll_clk;
> 
> ditto.
> 
> > +	}
> > +}
> > +
> > +static ulong zynq_clk_get_pll_rate(struct zynq_clk_priv *priv, enum zynq_clk id)
> > +{
> > +	u32 clk_ctrl, reset, pwrdwn, mul, bypass;
> > +
> > +	clk_ctrl = readl(zynq_clk_get_register(id));
> > +
> > +	reset = (clk_ctrl & PLLCTRL_RESET_MASK) >> PLLCTRL_RESET_SHIFT;
> > +	pwrdwn = (clk_ctrl & PLLCTRL_PWRDWN_MASK) >> PLLCTRL_PWRDWN_SHIFT;
> > +	if (reset || pwrdwn)
> > +		return 0;
> > +
> > +	bypass = clk_ctrl & PLLCTRL_BPFORCE_MASK;
> > +	if (bypass)
> > +		mul = 1;
> > +	else
> > +		mul = (clk_ctrl & PLLCTRL_FBDIV_MASK) >> PLLCTRL_FBDIV_SHIFT;
> > +
> > +	return priv->ps_clk_freq * mul;
> > +}
> > +
> > +#ifndef CONFIG_SPL_BUILD
> > +static enum zynq_clk_rclk zynq_clk_get_gem_rclk(enum zynq_clk id)
> > +{
> > +	u32 clk_ctrl, srcsel;
> > +
> > +	if (id == gem0_clk)
> > +		clk_ctrl = readl(&slcr_base->gem0_rclk_ctrl);
> > +	else
> > +		clk_ctrl = readl(&slcr_base->gem1_rclk_ctrl);
> > +
> > +	srcsel = (clk_ctrl & CLK_CTRL_SRCSEL_MASK) >> CLK_CTRL_SRCSEL_SHIFT;
> > +	if (srcsel)
> > +		return emio_clk;
> > +	else
> > +		return mio_clk;
> > +}
> > +#endif
> > +
> > +static ulong zynq_clk_get_cpu_rate(struct zynq_clk_priv *priv, enum zynq_clk id)
> > +{
> > +	u32 clk_621, clk_ctrl, div;
> > +	enum zynq_clk pll;
> > +
> > +	clk_ctrl = readl(&slcr_base->arm_clk_ctrl);
> > +
> > +	div = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
> > +
> > +	switch (id) {
> > +	case cpu_1x_clk:
> > +		div *= 2;
> > +		/* fall through */
> > +	case cpu_2x_clk:
> > +		clk_621 = readl(&slcr_base->clk_621_true) & 1;
> > +		div *= 2 + clk_621;
> > +		break;
> > +	case cpu_3or2x_clk:
> > +		div *= 2;
> > +		/* fall through */
> > +	case cpu_6or4x_clk:
> > +		break;
> > +	default:
> > +		return 0;
> > +	}
> > +
> > +	pll = zynq_clk_get_cpu_pll(clk_ctrl);
> > +
> > +	return DIV_ROUND_CLOSEST(zynq_clk_get_pll_rate(priv, pll), div);
> > +}
> > +
> > +#ifndef CONFIG_SPL_BUILD
> > +static ulong zynq_clk_get_ddr2x_rate(struct zynq_clk_priv *priv)
> > +{
> > +	u32 clk_ctrl, div;
> > +
> > +	clk_ctrl = readl(&slcr_base->ddr_clk_ctrl);
> > +
> > +	div = (clk_ctrl & CLK_CTRL_DIV2X_MASK) >> CLK_CTRL_DIV2X_SHIFT;
> > +
> > +	return DIV_ROUND_CLOSEST(zynq_clk_get_pll_rate(priv, ddrpll_clk), div);
> > +}
> > +#endif
> > +
> > +static ulong zynq_clk_get_ddr3x_rate(struct zynq_clk_priv *priv)
> > +{
> > +	u32 clk_ctrl, div;
> > +
> > +	clk_ctrl = readl(&slcr_base->ddr_clk_ctrl);
> > +
> > +	div = (clk_ctrl & CLK_CTRL_DIV3X_MASK) >> CLK_CTRL_DIV3X_SHIFT;
> > +
> > +	return DIV_ROUND_CLOSEST(zynq_clk_get_pll_rate(priv, ddrpll_clk), div);
> > +}
> > +
> > +#ifndef CONFIG_SPL_BUILD
> > +static ulong zynq_clk_get_dci_rate(struct zynq_clk_priv *priv)
> > +{
> > +	u32 clk_ctrl, div0, div1;
> > +
> > +	clk_ctrl = readl(&slcr_base->dci_clk_ctrl);
> > +
> > +	div0 = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
> > +	div1 = (clk_ctrl & CLK_CTRL_DIV1_MASK) >> CLK_CTRL_DIV1_SHIFT;
> > +
> > +	return DIV_ROUND_CLOSEST(DIV_ROUND_CLOSEST(
> > +		zynq_clk_get_pll_rate(priv, ddrpll_clk), div0), div1);
> > +}
> > +#endif
> > +
> > +static ulong zynq_clk_get_peripheral_rate(struct zynq_clk_priv *priv,
> > +					  enum zynq_clk id, bool two_divs)
> > +{
> > +	enum zynq_clk pll;
> > +	u32 clk_ctrl, div0;
> > +	u32 div1 = 1;
> > +
> > +	clk_ctrl = readl(zynq_clk_get_register(id));
> > +
> > +	div0 = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
> > +	if (!div0)
> > +		div0 = 1;
> > +
> > +#ifndef CONFIG_SPL_BUILD
> > +	if (two_divs) {
> > +		div1 = (clk_ctrl & CLK_CTRL_DIV1_MASK) >> CLK_CTRL_DIV1_SHIFT;
> > +		if (!div1)
> > +			div1 = 1;
> > +	}
> > +#endif
> > +
> > +	pll = zynq_clk_get_peripheral_pll(clk_ctrl);
> > +
> > +	return
> > +		DIV_ROUND_CLOSEST(
> > +			DIV_ROUND_CLOSEST(
> > +				zynq_clk_get_pll_rate(priv, pll), div0),
> > +			div1);
> > +}
> > +
> > +#ifndef CONFIG_SPL_BUILD
> > +static ulong zynq_clk_get_gem_rate(struct zynq_clk_priv *priv, enum zynq_clk id)
> > +{
> > +	if (zynq_clk_get_gem_rclk(id) == mio_clk)
> > +		return zynq_clk_get_peripheral_rate(priv, id, true);
> > +
> 
> Not sure if my understanding is correct here but I would expect if input
> is via emio that you will ask someone else to provide this value.
> Returning 0 without message seems to me not enough.
> 
> > +	return 0;
> > +}
> > +
> > +static unsigned long zynq_clk_calc_peripheral_two_divs(
> incorrect parameter indetation
> 
> 
> > +		ulong rate, ulong pll_rate, u32 *div0,
> > +		u32 *div1)
> 
> > +{
> > +	long new_err, best_err = (long)(~0UL >> 1);
> > +	ulong new_rate, best_rate = 0;
> > +	u32 d0, d1;
> > +
> > +	for (d0 = 1; d0 <= ZYNQ_CLK_MAXDIV; d0++) {
> > +		for (d1 = 1; d1 <= ZYNQ_CLK_MAXDIV >> 1; d1++) {
> > +			new_rate = DIV_ROUND_CLOSEST(
> > +					DIV_ROUND_CLOSEST(pll_rate, d0), d1);
> > +			new_err = abs(new_rate - rate);
> > +
> > +			if (new_err < best_err) {
> > +				*div0 = d0;
> > +				*div1 = d1;
> > +				best_err = new_err;
> > +				best_rate = new_rate;
> > +			}
> > +		}
> > +	}
> > +
> > +	return best_rate;
> > +}
> > +
> > +static ulong zynq_clk_set_peripheral_rate(struct zynq_clk_priv *priv,
> > +					  enum zynq_clk id, ulong rate,
> > +					  bool two_divs)
> > +{
> > +	enum zynq_clk pll;
> > +	u32 clk_ctrl, div0 = 0, div1 = 0;
> > +	ulong pll_rate, new_rate;
> > +	u32 *reg;
> > +
> > +	reg = zynq_clk_get_register(id);
> > +	clk_ctrl = readl(reg);
> > +
> > +	pll = zynq_clk_get_peripheral_pll(clk_ctrl);
> > +	pll_rate = zynq_clk_get_pll_rate(priv, pll);
> > +	clk_ctrl &= ~CLK_CTRL_DIV0_MASK;
> > +	if (two_divs) {
> > +		clk_ctrl &= ~CLK_CTRL_DIV1_MASK;
> > +		new_rate = zynq_clk_calc_peripheral_two_divs(rate, pll_rate,
> > +				&div0, &div1);
> > +		clk_ctrl |= div1 << CLK_CTRL_DIV1_SHIFT;
> > +	} else {
> > +		div0 = DIV_ROUND_CLOSEST(pll_rate, rate);
> > +		if (div0 > ZYNQ_CLK_MAXDIV)
> > +			div0 = ZYNQ_CLK_MAXDIV;
> > +		new_rate = DIV_ROUND_CLOSEST(rate, div0);
> > +	}
> > +	clk_ctrl |= div0 << CLK_CTRL_DIV0_SHIFT;
> > +
> > +	zynq_slcr_unlock();
> > +	writel(clk_ctrl, reg);
> > +	zynq_slcr_lock();
> > +
> > +	return new_rate;
> > +}
> > +
> > +static ulong zynq_clk_set_gem_rate(struct zynq_clk_priv *priv, enum zynq_clk id,
> > +				   ulong rate)
> > +{
> > +	if (zynq_clk_get_gem_rclk(id) == mio_clk)
> > +		return zynq_clk_set_peripheral_rate(priv, id, rate, true);
> > +
> > +	return 0;
> > +}
> > +#endif
> > +
> > +#ifndef CONFIG_SPL_BUILD
> > +static ulong zynq_clk_get_rate(struct clk *clk)
> > +{
> > +	struct zynq_clk_priv *priv = dev_get_priv(clk->dev);
> > +	enum zynq_clk id = clk->id;
> > +	bool two_divs = false;
> > +
> > +	switch (id) {
> > +	case armpll_clk ... iopll_clk:
> > +		return zynq_clk_get_pll_rate(priv, id);
> > +	case cpu_6or4x_clk ... cpu_1x_clk:
> > +		return zynq_clk_get_cpu_rate(priv, id);
> > +	case ddr2x_clk:
> > +		return zynq_clk_get_ddr2x_rate(priv);
> > +	case ddr3x_clk:
> > +		return zynq_clk_get_ddr3x_rate(priv);
> > +	case dci_clk:
> > +		return zynq_clk_get_dci_rate(priv);
> > +	case gem0_clk ... gem1_clk:
> > +		return zynq_clk_get_gem_rate(priv, id);
> > +	case fclk0_clk ... can1_clk:
> > +		two_divs = true;
> > +		/* fall through */
> > +	case dbg_trc_clk ... dbg_apb_clk:
> > +	case lqspi_clk ... pcap_clk:
> > +	case sdio0_clk ... spi1_clk:
> > +		return zynq_clk_get_peripheral_rate(priv, id, two_divs);
> > +	case dma_clk:
> > +		return zynq_clk_get_cpu_rate(priv, cpu_2x_clk);
> > +	case usb0_aper_clk ... smc_aper_clk:
> > +		return zynq_clk_get_cpu_rate(priv, cpu_1x_clk);
> > +	default:
> > +		return -ENXIO;
> > +	}
> > +}
> > +
> > +static ulong zynq_clk_set_rate(struct clk *clk, ulong rate)
> > +{
> > +	struct zynq_clk_priv *priv = dev_get_priv(clk->dev);
> > +	enum zynq_clk id = clk->id;
> > +	bool two_divs = false;
> > +
> > +	switch (id) {
> > +	case gem0_clk ... gem1_clk:
> > +		return zynq_clk_set_gem_rate(priv, id, rate);
> > +	case fclk0_clk ... can1_clk:
> > +		two_divs = true;
> > +		/* fall through */
> > +	case lqspi_clk ... pcap_clk:
> > +	case sdio0_clk ... spi1_clk:
> > +	case dbg_trc_clk ... dbg_apb_clk:
> > +		return zynq_clk_set_peripheral_rate(priv, id, rate, two_divs);
> > +	default:
> > +		return -ENXIO;
> > +	}
> > +}
> > +#else
> > +static ulong zynq_clk_get_rate(struct clk *clk)
> > +{
> > +	struct zynq_clk_priv *priv = dev_get_priv(clk->dev);
> > +	enum zynq_clk id = clk->id;
> > +
> > +	switch (id) {
> > +	case cpu_6or4x_clk ... cpu_1x_clk:
> > +		return zynq_clk_get_cpu_rate(priv, id);
> > +	case ddr3x_clk:
> > +		return zynq_clk_get_ddr3x_rate(priv);
> > +	case lqspi_clk ... pcap_clk:
> > +	case sdio0_clk ... spi1_clk:
> > +		return zynq_clk_get_peripheral_rate(priv, id, 0);
> > +	default:
> > +		return -ENXIO;
> > +	}
> > +}
> > +#endif
> > +
> > +static struct clk_ops zynq_clk_ops = {
> > +	.get_rate = zynq_clk_get_rate,
> > +#ifndef CONFIG_SPL_BUILD
> > +	.set_rate = zynq_clk_set_rate,
> > +#endif
> > +};
> > +
> > +static int zynq_clk_probe(struct udevice *dev)
> > +{
> > +	struct zynq_clk_priv *priv = dev_get_priv(dev);
> > +
> > +	priv->ps_clk_freq = fdtdec_get_uint(gd->fdt_blob, dev->of_offset,
> > +					    "ps-clk-frequency", 33333333UL);
> > +
> > +	return 0;
> > +}
> > +
> > +static const struct udevice_id zynq_clk_ids[] = {
> > +	{ .compatible = "xlnx,ps7-clkc"},
> > +	{}
> > +};
> > +
> > +U_BOOT_DRIVER(zynq_clk) = {
> > +	.name		= "zynq_clk",
> > +	.id		= UCLASS_CLK,
> > +	.of_match	= zynq_clk_ids,
> > +	.flags		= DM_FLAG_PRE_RELOC,
> > +	.ops		= &zynq_clk_ops,
> > +	.priv_auto_alloc_size = sizeof(struct zynq_clk_priv),
> > +	.probe		= zynq_clk_probe,
> > +};
> > 
> 
> The rest looks good.
> Soren: Can you please look at it? IIRC you have written that origin driver.

Yeah, a long time ago. I'd say if everything works with this it should
be good (and given that my name is still mentioned in the sources means
this must be good, right? :) ).
Only questions I have: Is the clock support really optional? Usually there
are many dependencies on the clocks making this critical infrastructure.
Hence, the kconfig option making this selectable could probably go away
and the feature could just be enabled as part of the Zynq platform.

	S?ren

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

* [U-Boot] [PATCH 6/8] clk: zynq: Add zynq clock framework driver
  2017-01-10 14:57   ` Michal Simek
  2017-01-10 19:17     ` Sören Brinkmann
@ 2017-01-11  7:15     ` Stefan.Herbrechtsmeier at weidmueller.com
  1 sibling, 0 replies; 29+ messages in thread
From: Stefan.Herbrechtsmeier at weidmueller.com @ 2017-01-11  7:15 UTC (permalink / raw)
  To: u-boot

> -----Urspr?ngliche Nachricht-----
> Von: Michal Simek [mailto:monstr at monstr.eu]
> Gesendet: Dienstag, 10. Januar 2017 15:57
> 
> +Soren
> 
> On 4.1.2017 13:27, stefan.herbrechtsmeier at weidmueller.com wrote:
> > From: Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
> >
> > Add a clock framework driver for the zynq platform. The driver is
> > based on the platform zynq clock driver but reworked to use static
> > functions instead of run-time generated objects even for unused
> clocks.
> > Additionally the CONFIG_ZYNQ_PS_CLK_FREQ is replaced by the
> > ps-clk-frequency from the device tree.
> >
> > Signed-off-by: Stefan Herbrechtsmeier
> > <stefan.herbrechtsmeier@weidmueller.com>
> > ---
> >
> >  drivers/clk/Kconfig    |   7 +
> >  drivers/clk/Makefile   |   1 +
> >  drivers/clk/clk_zynq.c | 470
> > +++++++++++++++++++++++++++++++++++++++++++++++++
> >  3 files changed, 478 insertions(+)
> >  create mode 100644 drivers/clk/clk_zynq.c
> >
> > diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index
> > c05ce2a..714ccca 100644
> > --- a/drivers/clk/Kconfig
> > +++ b/drivers/clk/Kconfig
> > @@ -28,6 +28,13 @@ config CLK_BOSTON
> >  	help
> >  	  Enable this to support the clocks
> >
> > +config CLK_ZYNQ
> > +	bool "Zynq clock driver"
> > +	depends on CLK && ARCH_ZYNQ
> > +	default y
> > +	help
> > +	  Enable this to support the clocks
> > +
> >  source "drivers/clk/tegra/Kconfig"
> >  source "drivers/clk/uniphier/Kconfig"
> >  source "drivers/clk/exynos/Kconfig"
> > diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index
> > 40a5e8c..5e5b6b1 100644
> > --- a/drivers/clk/Makefile
> > +++ b/drivers/clk/Makefile
> > @@ -16,3 +16,4 @@ obj-$(CONFIG_CLK_UNIPHIER) += uniphier/
> >  obj-$(CONFIG_CLK_EXYNOS) += exynos/
> >  obj-$(CONFIG_CLK_AT91) += at91/
> >  obj-$(CONFIG_CLK_BOSTON) += clk_boston.o
> > +obj-$(CONFIG_CLK_ZYNQ) += clk_zynq.o
> > diff --git a/drivers/clk/clk_zynq.c b/drivers/clk/clk_zynq.c new file
> > mode 100644 index 0000000..d276155
> > --- /dev/null
> > +++ b/drivers/clk/clk_zynq.c
> > @@ -0,0 +1,470 @@
> > +/*
> > + * Copyright (C) 2017 Weidm?ller Interface GmbH & Co. KG
> > + * Stefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
> > + *
> > + * Copyright (C) 2013 Soren Brinkmann <soren.brinkmann@xilinx.com>
> > + * Copyright (C) 2013 Xilinx, Inc. All rights reserved.
> > + *
> > + * SPDX-License-Identifier:	GPL-2.0+
> > + */
> > +
> > +#include <common.h>
> > +#include <clk-uclass.h>
> > +#include <dm.h>
> > +#include <dm/lists.h>
> > +#include <errno.h>
> > +#include <asm/io.h>
> > +#include <asm/arch/clk.h>
> > +#include <asm/arch/hardware.h>
> > +#include <asm/arch/sys_proto.h>
> > +
> > +/* Register bitfield defines */
> > +#define PLLCTRL_FBDIV_MASK	0x7f000
> > +#define PLLCTRL_FBDIV_SHIFT	12
> > +#define PLLCTRL_BPFORCE_MASK	(1 << 4)
> > +#define PLLCTRL_PWRDWN_MASK	2
> > +#define PLLCTRL_PWRDWN_SHIFT	1
> > +#define PLLCTRL_RESET_MASK	1
> > +#define PLLCTRL_RESET_SHIFT	0
> > +
> > +#define ZYNQ_CLK_MAXDIV		0x3f
> > +#define CLK_CTRL_DIV1_SHIFT	20
> > +#define CLK_CTRL_DIV1_MASK	(ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV1_SHIFT)
> > +#define CLK_CTRL_DIV0_SHIFT	8
> > +#define CLK_CTRL_DIV0_MASK	(ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV0_SHIFT)
> > +#define CLK_CTRL_SRCSEL_SHIFT	4
> > +#define CLK_CTRL_SRCSEL_MASK	(0x3 << CLK_CTRL_SRCSEL_SHIFT)
> > +
> > +#define CLK_CTRL_DIV2X_SHIFT	26
> > +#define CLK_CTRL_DIV2X_MASK	(ZYNQ_CLK_MAXDIV <<
> CLK_CTRL_DIV2X_SHIFT)
> > +#define CLK_CTRL_DIV3X_SHIFT	20
> > +#define CLK_CTRL_DIV3X_MASK	(ZYNQ_CLK_MAXDIV <<
> CLK_CTRL_DIV3X_SHIFT)
> > +
> > +#define ZYNQ_CLKMUX_SEL_0	0
> > +#define ZYNQ_CLKMUX_SEL_1	1
> > +#define ZYNQ_CLKMUX_SEL_2	2
> > +#define ZYNQ_CLKMUX_SEL_3	3
> > +
> > +DECLARE_GLOBAL_DATA_PTR;
> > +
> > +#ifndef CONFIG_SPL_BUILD
> > +enum zynq_clk_rclk {mio_clk, emio_clk}; #endif
> > +
> > +struct zynq_clk_priv {
> > +	ulong ps_clk_freq;
> > +};
> > +
> > +static void *zynq_clk_get_register(enum zynq_clk id) {
> > +	switch (id) {
> > +	case armpll_clk:
> > +		return &slcr_base->arm_pll_ctrl;
> > +	case ddrpll_clk:
> > +		return &slcr_base->ddr_pll_ctrl;
> > +	case iopll_clk:
> > +		return &slcr_base->io_pll_ctrl;
> > +#ifndef CONFIG_SPL_BUILD
> > +	case dci_clk:
> > +		return &slcr_base->dci_clk_ctrl;
> > +#endif
> > +	case lqspi_clk:
> > +		return &slcr_base->lqspi_clk_ctrl;
> > +	case smc_clk:
> > +		return &slcr_base->smc_clk_ctrl;
> > +	case pcap_clk:
> > +		return &slcr_base->pcap_clk_ctrl;
> > +#ifndef CONFIG_SPL_BUILD
> > +	case gem0_clk:
> > +		return &slcr_base->gem0_clk_ctrl;
> > +	case gem1_clk:
> > +		return &slcr_base->gem1_clk_ctrl;
> > +	case fclk0_clk:
> > +		return &slcr_base->fpga0_clk_ctrl;
> > +	case fclk1_clk:
> > +		return &slcr_base->fpga1_clk_ctrl;
> > +	case fclk2_clk:
> > +		return &slcr_base->fpga2_clk_ctrl;
> > +	case fclk3_clk:
> > +		return &slcr_base->fpga3_clk_ctrl;
> > +	case can0_clk ... can1_clk:
> > +		return &slcr_base->can_clk_ctrl;
> > +#endif
> > +	case sdio0_clk:
> > +	case sdio1_clk:
> > +		return &slcr_base->sdio_clk_ctrl;
> > +	case uart0_clk:
> > +	case uart1_clk:
> > +		return &slcr_base->uart_clk_ctrl;
> > +	case spi0_clk:
> > +	case spi1_clk:
> > +		return &slcr_base->spi_clk_ctrl;
> > +#ifndef CONFIG_SPL_BUILD
> > +	case dbg_trc_clk:
> > +	case dbg_apb_clk:
> > +		return &slcr_base->dbg_clk_ctrl;
> > +#endif
> 
> Please put them together.

Do you mean the ifndef or the default?

> > +	default:
> > +		return &slcr_base->dbg_clk_ctrl;
> > +	}
> > +}
> > +
> > +static enum zynq_clk zynq_clk_get_cpu_pll(u32 clk_ctrl) {
> > +	u32 srcsel = (clk_ctrl & CLK_CTRL_SRCSEL_MASK) >>
> > +CLK_CTRL_SRCSEL_SHIFT;
> > +
> > +	switch (srcsel) {
> > +	case ZYNQ_CLKMUX_SEL_0:
> > +	case ZYNQ_CLKMUX_SEL_1:
> > +		return armpll_clk;
> > +	case ZYNQ_CLKMUX_SEL_2:
> > +		return ddrpll_clk;
> > +	case ZYNQ_CLKMUX_SEL_3:
> > +		return iopll_clk;
> > +	default:
> > +		return armpll_clk;
> 
> 
> Default case shouldn't happen because of mask above.
> But if you want to keep it maybe this is a little bit better.
> 
> 	case ZYNQ_CLKMUX_SEL_2:
> 		return ddrpll_clk;
> 	case ZYNQ_CLKMUX_SEL_3:
> 		return iopll_clk;
> 	case ZYNQ_CLKMUX_SEL_0:
> 	case ZYNQ_CLKMUX_SEL_1:
> 	default:
> 		return armpll_clk;

Okay. Is it okay if I replace the defines with the plain numbers?

> > +	}
> > +}
> > +
> > +static enum zynq_clk zynq_clk_get_peripheral_pll(u32 clk_ctrl) {
> > +	u32 srcsel = (clk_ctrl & CLK_CTRL_SRCSEL_MASK) >>
> > +CLK_CTRL_SRCSEL_SHIFT;
> > +
> > +	switch (srcsel) {
> > +	case ZYNQ_CLKMUX_SEL_0:
> > +	case ZYNQ_CLKMUX_SEL_1:
> > +		return iopll_clk;
> > +	case ZYNQ_CLKMUX_SEL_2:
> > +		return armpll_clk;
> > +	case ZYNQ_CLKMUX_SEL_3:
> > +		return ddrpll_clk;
> > +	default:
> > +		return iopll_clk;
> 
> ditto.

Okay

> > +	}
> > +}
> > +
> > +static ulong zynq_clk_get_pll_rate(struct zynq_clk_priv *priv, enum
> > +zynq_clk id) {
> > +	u32 clk_ctrl, reset, pwrdwn, mul, bypass;
> > +
> > +	clk_ctrl = readl(zynq_clk_get_register(id));
> > +
> > +	reset = (clk_ctrl & PLLCTRL_RESET_MASK) >> PLLCTRL_RESET_SHIFT;
> > +	pwrdwn = (clk_ctrl & PLLCTRL_PWRDWN_MASK) >>
> PLLCTRL_PWRDWN_SHIFT;
> > +	if (reset || pwrdwn)
> > +		return 0;
> > +
> > +	bypass = clk_ctrl & PLLCTRL_BPFORCE_MASK;
> > +	if (bypass)
> > +		mul = 1;
> > +	else
> > +		mul = (clk_ctrl & PLLCTRL_FBDIV_MASK) >>
> PLLCTRL_FBDIV_SHIFT;
> > +
> > +	return priv->ps_clk_freq * mul;
> > +}
> > +
> > +#ifndef CONFIG_SPL_BUILD
> > +static enum zynq_clk_rclk zynq_clk_get_gem_rclk(enum zynq_clk id) {
> > +	u32 clk_ctrl, srcsel;
> > +
> > +	if (id == gem0_clk)
> > +		clk_ctrl = readl(&slcr_base->gem0_rclk_ctrl);
> > +	else
> > +		clk_ctrl = readl(&slcr_base->gem1_rclk_ctrl);
> > +
> > +	srcsel = (clk_ctrl & CLK_CTRL_SRCSEL_MASK) >>
> CLK_CTRL_SRCSEL_SHIFT;
> > +	if (srcsel)
> > +		return emio_clk;
> > +	else
> > +		return mio_clk;
> > +}
> > +#endif
> > +
> > +static ulong zynq_clk_get_cpu_rate(struct zynq_clk_priv *priv, enum
> > +zynq_clk id) {
> > +	u32 clk_621, clk_ctrl, div;
> > +	enum zynq_clk pll;
> > +
> > +	clk_ctrl = readl(&slcr_base->arm_clk_ctrl);
> > +
> > +	div = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
> > +
> > +	switch (id) {
> > +	case cpu_1x_clk:
> > +		div *= 2;
> > +		/* fall through */
> > +	case cpu_2x_clk:
> > +		clk_621 = readl(&slcr_base->clk_621_true) & 1;
> > +		div *= 2 + clk_621;
> > +		break;
> > +	case cpu_3or2x_clk:
> > +		div *= 2;
> > +		/* fall through */
> > +	case cpu_6or4x_clk:
> > +		break;
> > +	default:
> > +		return 0;
> > +	}
> > +
> > +	pll = zynq_clk_get_cpu_pll(clk_ctrl);
> > +
> > +	return DIV_ROUND_CLOSEST(zynq_clk_get_pll_rate(priv, pll), div);
> }
> > +
> > +#ifndef CONFIG_SPL_BUILD
> > +static ulong zynq_clk_get_ddr2x_rate(struct zynq_clk_priv *priv) {
> > +	u32 clk_ctrl, div;
> > +
> > +	clk_ctrl = readl(&slcr_base->ddr_clk_ctrl);
> > +
> > +	div = (clk_ctrl & CLK_CTRL_DIV2X_MASK) >> CLK_CTRL_DIV2X_SHIFT;
> > +
> > +	return DIV_ROUND_CLOSEST(zynq_clk_get_pll_rate(priv, ddrpll_clk),
> > +div); } #endif
> > +
> > +static ulong zynq_clk_get_ddr3x_rate(struct zynq_clk_priv *priv) {
> > +	u32 clk_ctrl, div;
> > +
> > +	clk_ctrl = readl(&slcr_base->ddr_clk_ctrl);
> > +
> > +	div = (clk_ctrl & CLK_CTRL_DIV3X_MASK) >> CLK_CTRL_DIV3X_SHIFT;
> > +
> > +	return DIV_ROUND_CLOSEST(zynq_clk_get_pll_rate(priv, ddrpll_clk),
> > +div); }
> > +
> > +#ifndef CONFIG_SPL_BUILD
> > +static ulong zynq_clk_get_dci_rate(struct zynq_clk_priv *priv) {
> > +	u32 clk_ctrl, div0, div1;
> > +
> > +	clk_ctrl = readl(&slcr_base->dci_clk_ctrl);
> > +
> > +	div0 = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
> > +	div1 = (clk_ctrl & CLK_CTRL_DIV1_MASK) >> CLK_CTRL_DIV1_SHIFT;
> > +
> > +	return DIV_ROUND_CLOSEST(DIV_ROUND_CLOSEST(
> > +		zynq_clk_get_pll_rate(priv, ddrpll_clk), div0), div1); }
> #endif
> > +
> > +static ulong zynq_clk_get_peripheral_rate(struct zynq_clk_priv
> *priv,
> > +					  enum zynq_clk id, bool two_divs) {
> > +	enum zynq_clk pll;
> > +	u32 clk_ctrl, div0;
> > +	u32 div1 = 1;
> > +
> > +	clk_ctrl = readl(zynq_clk_get_register(id));
> > +
> > +	div0 = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
> > +	if (!div0)
> > +		div0 = 1;
> > +
> > +#ifndef CONFIG_SPL_BUILD
> > +	if (two_divs) {
> > +		div1 = (clk_ctrl & CLK_CTRL_DIV1_MASK) >>
> CLK_CTRL_DIV1_SHIFT;
> > +		if (!div1)
> > +			div1 = 1;
> > +	}
> > +#endif
> > +
> > +	pll = zynq_clk_get_peripheral_pll(clk_ctrl);
> > +
> > +	return
> > +		DIV_ROUND_CLOSEST(
> > +			DIV_ROUND_CLOSEST(
> > +				zynq_clk_get_pll_rate(priv, pll), div0),
> > +			div1);
> > +}
> > +
> > +#ifndef CONFIG_SPL_BUILD
> > +static ulong zynq_clk_get_gem_rate(struct zynq_clk_priv *priv, enum
> > +zynq_clk id) {
> > +	if (zynq_clk_get_gem_rclk(id) == mio_clk)
> > +		return zynq_clk_get_peripheral_rate(priv, id, true);
> > +
> 
> Not sure if my understanding is correct here but I would expect if
> input is via emio that you will ask someone else to provide this value.

As you realised I add this function in a later patch. Should I merge the patches?

> Returning 0 without message seems to me not enough.

I will add a message. Should I also return a error code like ENODEV?

> > +	return 0;
> > +}
> > +
> > +static unsigned long zynq_clk_calc_peripheral_two_divs(
> incorrect parameter indetation
> 
> 
> > +		ulong rate, ulong pll_rate, u32 *div0,
> > +		u32 *div1)
> 
> > +{
> > +	long new_err, best_err = (long)(~0UL >> 1);
> > +	ulong new_rate, best_rate = 0;
> > +	u32 d0, d1;
> > +
> > +	for (d0 = 1; d0 <= ZYNQ_CLK_MAXDIV; d0++) {
> > +		for (d1 = 1; d1 <= ZYNQ_CLK_MAXDIV >> 1; d1++) {
> > +			new_rate = DIV_ROUND_CLOSEST(
> > +					DIV_ROUND_CLOSEST(pll_rate, d0), d1);
> > +			new_err = abs(new_rate - rate);
> > +
> > +			if (new_err < best_err) {
> > +				*div0 = d0;
> > +				*div1 = d1;
> > +				best_err = new_err;
> > +				best_rate = new_rate;
> > +			}
> > +		}
> > +	}
> > +
> > +	return best_rate;
> > +}
> > +
> > +static ulong zynq_clk_set_peripheral_rate(struct zynq_clk_priv
> *priv,
> > +					  enum zynq_clk id, ulong rate,
> > +					  bool two_divs)
> > +{
> > +	enum zynq_clk pll;
> > +	u32 clk_ctrl, div0 = 0, div1 = 0;
> > +	ulong pll_rate, new_rate;
> > +	u32 *reg;
> > +
> > +	reg = zynq_clk_get_register(id);
> > +	clk_ctrl = readl(reg);
> > +
> > +	pll = zynq_clk_get_peripheral_pll(clk_ctrl);
> > +	pll_rate = zynq_clk_get_pll_rate(priv, pll);
> > +	clk_ctrl &= ~CLK_CTRL_DIV0_MASK;
> > +	if (two_divs) {
> > +		clk_ctrl &= ~CLK_CTRL_DIV1_MASK;
> > +		new_rate = zynq_clk_calc_peripheral_two_divs(rate,
> pll_rate,
> > +				&div0, &div1);
> > +		clk_ctrl |= div1 << CLK_CTRL_DIV1_SHIFT;
> > +	} else {
> > +		div0 = DIV_ROUND_CLOSEST(pll_rate, rate);
> > +		if (div0 > ZYNQ_CLK_MAXDIV)
> > +			div0 = ZYNQ_CLK_MAXDIV;
> > +		new_rate = DIV_ROUND_CLOSEST(rate, div0);
> > +	}
> > +	clk_ctrl |= div0 << CLK_CTRL_DIV0_SHIFT;
> > +
> > +	zynq_slcr_unlock();
> > +	writel(clk_ctrl, reg);
> > +	zynq_slcr_lock();
> > +
> > +	return new_rate;
> > +}
> > +
> > +static ulong zynq_clk_set_gem_rate(struct zynq_clk_priv *priv, enum
> zynq_clk id,
> > +				   ulong rate)
> > +{
> > +	if (zynq_clk_get_gem_rclk(id) == mio_clk)
> > +		return zynq_clk_set_peripheral_rate(priv, id, rate, true);
> > +
> > +	return 0;
> > +}
> > +#endif
> > +
> > +#ifndef CONFIG_SPL_BUILD
> > +static ulong zynq_clk_get_rate(struct clk *clk) {
> > +	struct zynq_clk_priv *priv = dev_get_priv(clk->dev);
> > +	enum zynq_clk id = clk->id;
> > +	bool two_divs = false;
> > +
> > +	switch (id) {
> > +	case armpll_clk ... iopll_clk:
> > +		return zynq_clk_get_pll_rate(priv, id);
> > +	case cpu_6or4x_clk ... cpu_1x_clk:
> > +		return zynq_clk_get_cpu_rate(priv, id);
> > +	case ddr2x_clk:
> > +		return zynq_clk_get_ddr2x_rate(priv);
> > +	case ddr3x_clk:
> > +		return zynq_clk_get_ddr3x_rate(priv);
> > +	case dci_clk:
> > +		return zynq_clk_get_dci_rate(priv);
> > +	case gem0_clk ... gem1_clk:
> > +		return zynq_clk_get_gem_rate(priv, id);
> > +	case fclk0_clk ... can1_clk:
> > +		two_divs = true;
> > +		/* fall through */
> > +	case dbg_trc_clk ... dbg_apb_clk:
> > +	case lqspi_clk ... pcap_clk:
> > +	case sdio0_clk ... spi1_clk:
> > +		return zynq_clk_get_peripheral_rate(priv, id, two_divs);
> > +	case dma_clk:
> > +		return zynq_clk_get_cpu_rate(priv, cpu_2x_clk);
> > +	case usb0_aper_clk ... smc_aper_clk:
> > +		return zynq_clk_get_cpu_rate(priv, cpu_1x_clk);
> > +	default:
> > +		return -ENXIO;
> > +	}
> > +}
> > +
> > +static ulong zynq_clk_set_rate(struct clk *clk, ulong rate) {
> > +	struct zynq_clk_priv *priv = dev_get_priv(clk->dev);
> > +	enum zynq_clk id = clk->id;
> > +	bool two_divs = false;
> > +
> > +	switch (id) {
> > +	case gem0_clk ... gem1_clk:
> > +		return zynq_clk_set_gem_rate(priv, id, rate);
> > +	case fclk0_clk ... can1_clk:
> > +		two_divs = true;
> > +		/* fall through */
> > +	case lqspi_clk ... pcap_clk:
> > +	case sdio0_clk ... spi1_clk:
> > +	case dbg_trc_clk ... dbg_apb_clk:
> > +		return zynq_clk_set_peripheral_rate(priv, id, rate,
> two_divs);
> > +	default:
> > +		return -ENXIO;
> > +	}
> > +}
> > +#else
> > +static ulong zynq_clk_get_rate(struct clk *clk) {
> > +	struct zynq_clk_priv *priv = dev_get_priv(clk->dev);
> > +	enum zynq_clk id = clk->id;
> > +
> > +	switch (id) {
> > +	case cpu_6or4x_clk ... cpu_1x_clk:
> > +		return zynq_clk_get_cpu_rate(priv, id);
> > +	case ddr3x_clk:
> > +		return zynq_clk_get_ddr3x_rate(priv);
> > +	case lqspi_clk ... pcap_clk:
> > +	case sdio0_clk ... spi1_clk:
> > +		return zynq_clk_get_peripheral_rate(priv, id, 0);
> > +	default:
> > +		return -ENXIO;
> > +	}
> > +}
> > +#endif
> > +
> > +static struct clk_ops zynq_clk_ops = {
> > +	.get_rate = zynq_clk_get_rate,
> > +#ifndef CONFIG_SPL_BUILD
> > +	.set_rate = zynq_clk_set_rate,
> > +#endif
> > +};
> > +
> > +static int zynq_clk_probe(struct udevice *dev) {
> > +	struct zynq_clk_priv *priv = dev_get_priv(dev);
> > +
> > +	priv->ps_clk_freq = fdtdec_get_uint(gd->fdt_blob, dev->of_offset,
> > +					    "ps-clk-frequency", 33333333UL);
> > +
> > +	return 0;
> > +}
> > +
> > +static const struct udevice_id zynq_clk_ids[] = {
> > +	{ .compatible = "xlnx,ps7-clkc"},
> > +	{}
> > +};
> > +
> > +U_BOOT_DRIVER(zynq_clk) = {
> > +	.name		= "zynq_clk",
> > +	.id		= UCLASS_CLK,
> > +	.of_match	= zynq_clk_ids,
> > +	.flags		= DM_FLAG_PRE_RELOC,
> > +	.ops		= &zynq_clk_ops,
> > +	.priv_auto_alloc_size = sizeof(struct zynq_clk_priv),
> > +	.probe		= zynq_clk_probe,
> > +};
> >
> 
> The rest looks good.
> Soren: Can you please look at it? IIRC you have written that origin
> driver.

Regards,
  Stefan



Kommanditgesellschaft - Sitz: Detmold - Amtsgericht Lemgo HRA 2790 - 
Komplement?rin: Weidm?ller Interface F?hrungsgesellschaft mbH - 
Sitz: Detmold - Amtsgericht Lemgo HRB 3924; 
Gesch?ftsf?hrer: Jos? Carlos ?lvarez Tobar, Elke Eckstein, Dr. Peter K?hler, J?rg Timmermann;
USt-ID-Nr. DE124599660

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

* [U-Boot] [PATCH 2/8] net: zynq: Add clk framework support to zynq ethernet driver
  2017-01-10 15:23       ` Michal Simek
@ 2017-01-11  7:30         ` Stefan.Herbrechtsmeier at weidmueller.com
  2017-01-11  8:21           ` Michal Simek
  0 siblings, 1 reply; 29+ messages in thread
From: Stefan.Herbrechtsmeier at weidmueller.com @ 2017-01-11  7:30 UTC (permalink / raw)
  To: u-boot

> -----Urspr?ngliche Nachricht-----
> Von: Michal Simek [mailto:monstr at monstr.eu]
> Gesendet: Dienstag, 10. Januar 2017 16:23
> 
> On 10.1.2017 15:46, Stefan.Herbrechtsmeier at weidmueller.com wrote:
> >> -----Urspr?ngliche Nachricht-----
> >> Von: Michal Simek [mailto:monstr at monstr.eu]
> >> Gesendet: Dienstag, 10. Januar 2017 14:59
> >> An: Herbrechtsmeier, Stefan; u-boot at lists.denx.de
> >> Cc: Herbrechtsmeier, Stefan; Albert Aribaud; Michal Simek; Joe
> >> Hershberger
> >> Betreff: Re: [PATCH 2/8] net: zynq: Add clk framework support to
> zynq
> >> ethernet driver
> >>
> >> On 4.1.2017 13:27, stefan.herbrechtsmeier at weidmueller.com wrote:
> >>> From: Stefan Herbrechtsmeier
> <stefan.herbrechtsmeier@weidmueller.de>
> >>>
> >>> If available use the clock framework to set the tx clock rate of
> the
> >>> zynq ethernet controller.
> >>>
> >>> Signed-off-by: Stefan Herbrechtsmeier
> >>> <stefan.herbrechtsmeier@weidmueller.com>
> >>> ---
> >>>
> >>>  arch/arm/include/asm/arch-zynqmp/sys_proto.h |  5 -----
> >>>  drivers/net/zynq_gem.c                       | 31
> >> ++++++++++++++++++++++++++++
> >>>  2 files changed, 31 insertions(+), 5 deletions(-)
> >>>
> >>> diff --git a/arch/arm/include/asm/arch-zynqmp/sys_proto.h
> >>> b/arch/arm/include/asm/arch-zynqmp/sys_proto.h
> >>> index 1db2bd6..bd633a6 100644
> >>> --- a/arch/arm/include/asm/arch-zynqmp/sys_proto.h
> >>> +++ b/arch/arm/include/asm/arch-zynqmp/sys_proto.h
> >>> @@ -8,11 +8,6 @@
> >>>  #ifndef _ASM_ARCH_SYS_PROTO_H
> >>>  #define _ASM_ARCH_SYS_PROTO_H
> >>>
> >>> -/* Setup clk for network */
> >>> -static inline void zynq_slcr_gem_clk_setup(u32 gem_id, unsigned
> >>> long
> >>> clk_rate) -{ -}
> >>> -
> >>>  int zynq_slcr_get_mio_pin_status(const char *periph);
> >>>
> >>>  unsigned int zynqmp_get_silicon_version(void); diff --git
> >>> a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c index
> >>> 9bfb89f..9118e49 100644
> >>> --- a/drivers/net/zynq_gem.c
> >>> +++ b/drivers/net/zynq_gem.c
> >>> @@ -9,6 +9,7 @@
> >>>   * SPDX-License-Identifier:	GPL-2.0+
> >>>   */
> >>>
> >>> +#include <clk.h>
> >>>  #include <common.h>
> >>>  #include <dm.h>
> >>>  #include <net.h>
> >>> @@ -180,6 +181,9 @@ struct zynq_gem_priv {
> >>>  	struct phy_device *phydev;
> >>>  	int phy_of_handle;
> >>>  	struct mii_dev *bus;
> >>> +#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
> >>> +	struct clk tx_clk;
> >>> +#endif
> >>>  };
> >>>
> >>>  static inline int mdio_wait(struct zynq_gem_regs *regs) @@ -364,6
> >>> +368,9 @@ static int zynq_gem_init(struct udevice *dev)
> >>>  	u32 i, nwconfig;
> >>>  	int ret;
> >>>  	unsigned long clk_rate = 0;
> >>> +#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
> >>> +	unsigned long clk_rate_rounded;
> >>> +#endif
> >>>  	struct zynq_gem_priv *priv = dev_get_priv(dev);
> >>>  	struct zynq_gem_regs *regs = priv->iobase;
> >>>  	struct emac_bd *dummy_tx_bd = &priv->tx_bd[TX_FREE_DESC]; @@ -
> >> 466,8
> >>> +473,22 @@ static int zynq_gem_init(struct udevice *dev)
> >>>  		break;
> >>>  	}
> >>>
> >>> +#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
> >>> +	clk_rate_rounded = clk_set_rate(&priv->tx_clk, clk_rate);
> >>> +	if (IS_ERR_VALUE(clk_rate_rounded)) {
> >>> +		dev_err(dev, "failed to set tx clock rate\n");
> >>> +		return clk_rate_rounded;
> >>> +	}
> >>> +
> >>> +	ret = clk_enable(&priv->tx_clk);
> >>> +	if (ret && ret != -ENOSYS) {
> >>> +		dev_err(dev, "failed to enable tx clock\n");
> >>> +		return ret;
> >>> +	}
> >>> +#else
> >>>  	zynq_slcr_gem_clk_setup((ulong)priv->iobase !=
> >>>  				ZYNQ_GEM_BASEADDR0, clk_rate);
> >>> +#endif
> >>>
> >>>  	setbits_le32(&regs->nwctrl, ZYNQ_GEM_NWCTRL_RXEN_MASK |
> >>>  					ZYNQ_GEM_NWCTRL_TXEN_MASK);
> >>> @@ -678,6 +699,9 @@ static int zynq_gem_ofdata_to_platdata(struct
> >> udevice *dev)
> >>>  	struct eth_pdata *pdata = dev_get_platdata(dev);
> >>>  	struct zynq_gem_priv *priv = dev_get_priv(dev);
> >>>  	const char *phy_mode;
> >>> +#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
> >>> +	int ret;
> >>> +#endif
> >>>
> >>>  	pdata->iobase = (phys_addr_t)dev_get_addr(dev);
> >>>  	priv->iobase = (struct zynq_gem_regs *)pdata->iobase; @@ -699,6
> >>> +723,13 @@ static int zynq_gem_ofdata_to_platdata(struct udevice
> >> *dev)
> >>>  	}
> >>>  	priv->interface = pdata->phy_interface;
> >>>
> >>> +#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
> >>> +	ret = clk_get_by_index(dev, 2, &priv->tx_clk);
> >>> +	if (ret < 0) {
> >>> +		dev_err(dev, "failed to get clock\n");
> >>> +		return ret;
> >>> +	}
> >>> +#endif
> >>>
> >>>  	printf("ZYNQ GEM: %lx, phyaddr %x, interface %s\n", (ulong)priv-
> >>> iobase,
> >>>  	       priv->phyaddr, phy_string_for_interface(priv->interface));
> >>>
> >>
> >> Can you please rebase it on the top of this?
> >> https://patchwork.ozlabs.org/patch/706419/
> >>
> >> The reason why this patch was written in this way is that we don't
> >> have full zynqmp clk driver yet but we are using fixed clock where
> >> you can't run set_rate which fails.
> >>
> > The patch assumes that the EMIO_ENET_TX_CLK is always fixed. Is this
> true?
> >
> > Why don't you add a set_rate() function to the fixed clock?
> 
> It would be a solution but I am not sure if fixed clock was designed
> for this. I would expect that fixed clock only provided clock which you
> can't change.

I think the current clock framework is not optimal as it doesn't abstract the clock framework from the drivers. I don't know why a not clock driver want to know that an internal clock ops isn't implemented.

I would expect that the driver should not care what clock provides the rate. The clk_set_rate() function should always return the nearest possible clock rate and the clk_enable() shouldn't failed with a missing ops function. Otherwise this functions should be mandatory.

> It means we need to have something as transition when u-
> boot has real clk driver for zynqmp.

We could use the same fall back for the clk_set_rate() as we use for the clk_enable() and ignore the -ENOSYS error.

> >
> > Additionally the patch is missing an enable function call.
> 
> correct.
> 
> >
> > I don't think the emio configuration should be keep in the Ethernet
> driver as it is part of the clock configuration and doesn't influent
> the network interface.
> 
> Please correct me if I am wrong. Are you saying that with these patches
> especially 8/8 clock for emio will handled automatically?

What do you mean by 8/8 clock?

The Ethernet driver should not care how the clock is connected and only set the required clock rate. The clock driver should route the function calls to the correct clock.

Regards,
  Stefan



Kommanditgesellschaft - Sitz: Detmold - Amtsgericht Lemgo HRA 2790 - 
Komplement?rin: Weidm?ller Interface F?hrungsgesellschaft mbH - 
Sitz: Detmold - Amtsgericht Lemgo HRB 3924; 
Gesch?ftsf?hrer: Jos? Carlos ?lvarez Tobar, Elke Eckstein, Dr. Peter K?hler, J?rg Timmermann;
USt-ID-Nr. DE124599660

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

* [U-Boot] [PATCH 2/8] net: zynq: Add clk framework support to zynq ethernet driver
  2017-01-11  7:30         ` Stefan.Herbrechtsmeier at weidmueller.com
@ 2017-01-11  8:21           ` Michal Simek
  2017-01-11  9:55             ` Stefan.Herbrechtsmeier at weidmueller.com
  0 siblings, 1 reply; 29+ messages in thread
From: Michal Simek @ 2017-01-11  8:21 UTC (permalink / raw)
  To: u-boot

On 11.1.2017 08:30, Stefan.Herbrechtsmeier at weidmueller.com wrote:
>> -----Urspr?ngliche Nachricht-----
>> Von: Michal Simek [mailto:monstr at monstr.eu]
>> Gesendet: Dienstag, 10. Januar 2017 16:23
>>
>> On 10.1.2017 15:46, Stefan.Herbrechtsmeier at weidmueller.com wrote:
>>>> -----Urspr?ngliche Nachricht-----
>>>> Von: Michal Simek [mailto:monstr at monstr.eu]
>>>> Gesendet: Dienstag, 10. Januar 2017 14:59
>>>> An: Herbrechtsmeier, Stefan; u-boot at lists.denx.de
>>>> Cc: Herbrechtsmeier, Stefan; Albert Aribaud; Michal Simek; Joe
>>>> Hershberger
>>>> Betreff: Re: [PATCH 2/8] net: zynq: Add clk framework support to
>> zynq
>>>> ethernet driver
>>>>
>>>> On 4.1.2017 13:27, stefan.herbrechtsmeier at weidmueller.com wrote:
>>>>> From: Stefan Herbrechtsmeier
>> <stefan.herbrechtsmeier@weidmueller.de>
>>>>>
>>>>> If available use the clock framework to set the tx clock rate of
>> the
>>>>> zynq ethernet controller.
>>>>>
>>>>> Signed-off-by: Stefan Herbrechtsmeier
>>>>> <stefan.herbrechtsmeier@weidmueller.com>
>>>>> ---
>>>>>
>>>>>  arch/arm/include/asm/arch-zynqmp/sys_proto.h |  5 -----
>>>>>  drivers/net/zynq_gem.c                       | 31
>>>> ++++++++++++++++++++++++++++
>>>>>  2 files changed, 31 insertions(+), 5 deletions(-)
>>>>>
>>>>> diff --git a/arch/arm/include/asm/arch-zynqmp/sys_proto.h
>>>>> b/arch/arm/include/asm/arch-zynqmp/sys_proto.h
>>>>> index 1db2bd6..bd633a6 100644
>>>>> --- a/arch/arm/include/asm/arch-zynqmp/sys_proto.h
>>>>> +++ b/arch/arm/include/asm/arch-zynqmp/sys_proto.h
>>>>> @@ -8,11 +8,6 @@
>>>>>  #ifndef _ASM_ARCH_SYS_PROTO_H
>>>>>  #define _ASM_ARCH_SYS_PROTO_H
>>>>>
>>>>> -/* Setup clk for network */
>>>>> -static inline void zynq_slcr_gem_clk_setup(u32 gem_id, unsigned
>>>>> long
>>>>> clk_rate) -{ -}
>>>>> -
>>>>>  int zynq_slcr_get_mio_pin_status(const char *periph);
>>>>>
>>>>>  unsigned int zynqmp_get_silicon_version(void); diff --git
>>>>> a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c index
>>>>> 9bfb89f..9118e49 100644
>>>>> --- a/drivers/net/zynq_gem.c
>>>>> +++ b/drivers/net/zynq_gem.c
>>>>> @@ -9,6 +9,7 @@
>>>>>   * SPDX-License-Identifier:	GPL-2.0+
>>>>>   */
>>>>>
>>>>> +#include <clk.h>
>>>>>  #include <common.h>
>>>>>  #include <dm.h>
>>>>>  #include <net.h>
>>>>> @@ -180,6 +181,9 @@ struct zynq_gem_priv {
>>>>>  	struct phy_device *phydev;
>>>>>  	int phy_of_handle;
>>>>>  	struct mii_dev *bus;
>>>>> +#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
>>>>> +	struct clk tx_clk;
>>>>> +#endif
>>>>>  };
>>>>>
>>>>>  static inline int mdio_wait(struct zynq_gem_regs *regs) @@ -364,6
>>>>> +368,9 @@ static int zynq_gem_init(struct udevice *dev)
>>>>>  	u32 i, nwconfig;
>>>>>  	int ret;
>>>>>  	unsigned long clk_rate = 0;
>>>>> +#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
>>>>> +	unsigned long clk_rate_rounded;
>>>>> +#endif
>>>>>  	struct zynq_gem_priv *priv = dev_get_priv(dev);
>>>>>  	struct zynq_gem_regs *regs = priv->iobase;
>>>>>  	struct emac_bd *dummy_tx_bd = &priv->tx_bd[TX_FREE_DESC]; @@ -
>>>> 466,8
>>>>> +473,22 @@ static int zynq_gem_init(struct udevice *dev)
>>>>>  		break;
>>>>>  	}
>>>>>
>>>>> +#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
>>>>> +	clk_rate_rounded = clk_set_rate(&priv->tx_clk, clk_rate);
>>>>> +	if (IS_ERR_VALUE(clk_rate_rounded)) {
>>>>> +		dev_err(dev, "failed to set tx clock rate\n");
>>>>> +		return clk_rate_rounded;
>>>>> +	}
>>>>> +
>>>>> +	ret = clk_enable(&priv->tx_clk);
>>>>> +	if (ret && ret != -ENOSYS) {
>>>>> +		dev_err(dev, "failed to enable tx clock\n");
>>>>> +		return ret;
>>>>> +	}
>>>>> +#else
>>>>>  	zynq_slcr_gem_clk_setup((ulong)priv->iobase !=
>>>>>  				ZYNQ_GEM_BASEADDR0, clk_rate);
>>>>> +#endif
>>>>>
>>>>>  	setbits_le32(&regs->nwctrl, ZYNQ_GEM_NWCTRL_RXEN_MASK |
>>>>>  					ZYNQ_GEM_NWCTRL_TXEN_MASK);
>>>>> @@ -678,6 +699,9 @@ static int zynq_gem_ofdata_to_platdata(struct
>>>> udevice *dev)
>>>>>  	struct eth_pdata *pdata = dev_get_platdata(dev);
>>>>>  	struct zynq_gem_priv *priv = dev_get_priv(dev);
>>>>>  	const char *phy_mode;
>>>>> +#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
>>>>> +	int ret;
>>>>> +#endif
>>>>>
>>>>>  	pdata->iobase = (phys_addr_t)dev_get_addr(dev);
>>>>>  	priv->iobase = (struct zynq_gem_regs *)pdata->iobase; @@ -699,6
>>>>> +723,13 @@ static int zynq_gem_ofdata_to_platdata(struct udevice
>>>> *dev)
>>>>>  	}
>>>>>  	priv->interface = pdata->phy_interface;
>>>>>
>>>>> +#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
>>>>> +	ret = clk_get_by_index(dev, 2, &priv->tx_clk);
>>>>> +	if (ret < 0) {
>>>>> +		dev_err(dev, "failed to get clock\n");
>>>>> +		return ret;
>>>>> +	}
>>>>> +#endif
>>>>>
>>>>>  	printf("ZYNQ GEM: %lx, phyaddr %x, interface %s\n", (ulong)priv-
>>>>> iobase,
>>>>>  	       priv->phyaddr, phy_string_for_interface(priv->interface));
>>>>>
>>>>
>>>> Can you please rebase it on the top of this?
>>>> https://patchwork.ozlabs.org/patch/706419/
>>>>
>>>> The reason why this patch was written in this way is that we don't
>>>> have full zynqmp clk driver yet but we are using fixed clock where
>>>> you can't run set_rate which fails.
>>>>
>>> The patch assumes that the EMIO_ENET_TX_CLK is always fixed. Is this
>> true?
>>>
>>> Why don't you add a set_rate() function to the fixed clock?
>>
>> It would be a solution but I am not sure if fixed clock was designed
>> for this. I would expect that fixed clock only provided clock which you
>> can't change.
> 
> I think the current clock framework is not optimal as it doesn't abstract the clock framework from the drivers. I don't know why a not clock driver want to know that an internal clock ops isn't implemented.
> 
> I would expect that the driver should not care what clock provides the rate. The clk_set_rate() function should always return the nearest possible clock rate and the clk_enable() shouldn't failed with a missing ops function.
 Otherwise this functions should be mandatory.

I can't see an issue if clk_set_rate simply failed for clocks which
can't change. It is up to driver to handle this if this is fine or not.
In ZynqMP some clocks can be locked because they are used for something
more important than non secure sw.

> 
>> It means we need to have something as transition when u-
>> boot has real clk driver for zynqmp.
> 
> We could use the same fall back for the clk_set_rate() as we use for the clk_enable() and ignore the -ENOSYS error.

Not a problem with using -ENOSYS which is just a signal that clk driver
doesn't care about it.

> 
>>>
>>> Additionally the patch is missing an enable function call.
>>
>> correct.
>>
>>>
>>> I don't think the emio configuration should be keep in the Ethernet
>> driver as it is part of the clock configuration and doesn't influent
>> the network interface.
>>
>> Please correct me if I am wrong. Are you saying that with these patches
>> especially 8/8 clock for emio will handled automatically?
> 
> What do you mean by 8/8 clock?

I meant patch 8/8 in this series.

> 
> The Ethernet driver should not care how the clock is connected and only set the required clock rate. The clock driver should route the function calls to the correct clock.

ok. I will try to get testcases for emio to make sure that they are
still working correctly.

Thanks,
Michal

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

* [U-Boot] [PATCH 2/8] net: zynq: Add clk framework support to zynq ethernet driver
  2017-01-11  8:21           ` Michal Simek
@ 2017-01-11  9:55             ` Stefan.Herbrechtsmeier at weidmueller.com
  2017-01-11 10:14               ` Michal Simek
  0 siblings, 1 reply; 29+ messages in thread
From: Stefan.Herbrechtsmeier at weidmueller.com @ 2017-01-11  9:55 UTC (permalink / raw)
  To: u-boot

> -----Urspr?ngliche Nachricht-----
> Von: Michal Simek [mailto:michal.simek at xilinx.com]
> Gesendet: Mittwoch, 11. Januar 2017 09:22
> 
> On 11.1.2017 08:30, Stefan.Herbrechtsmeier at weidmueller.com wrote:
> >> -----Urspr?ngliche Nachricht-----
> >> Von: Michal Simek [mailto:monstr at monstr.eu]
> >> Gesendet: Dienstag, 10. Januar 2017 16:23
> >>
> >> On 10.1.2017 15:46, Stefan.Herbrechtsmeier at weidmueller.com wrote:
> >>>> -----Urspr?ngliche Nachricht-----
> >>>> Von: Michal Simek [mailto:monstr at monstr.eu]
> >>>> Gesendet: Dienstag, 10. Januar 2017 14:59
> >>>> An: Herbrechtsmeier, Stefan; u-boot at lists.denx.de
> >>>> Cc: Herbrechtsmeier, Stefan; Albert Aribaud; Michal Simek; Joe
> >>>> Hershberger
> >>>> Betreff: Re: [PATCH 2/8] net: zynq: Add clk framework support to
> >> zynq
> >>>> ethernet driver
> >>>>
> >>>> On 4.1.2017 13:27, stefan.herbrechtsmeier at weidmueller.com wrote:
> >>>>> From: Stefan Herbrechtsmeier
> >> <stefan.herbrechtsmeier@weidmueller.de>
> >>>>>
> >>>>> If available use the clock framework to set the tx clock rate of
> >> the
> >>>>> zynq ethernet controller.
> >>>>>
> >>>>> Signed-off-by: Stefan Herbrechtsmeier
> >>>>> <stefan.herbrechtsmeier@weidmueller.com>
> >>>>> ---
> >>>>>
> >>>>>  arch/arm/include/asm/arch-zynqmp/sys_proto.h |  5 -----
> >>>>>  drivers/net/zynq_gem.c                       | 31
> >>>> ++++++++++++++++++++++++++++
> >>>>>  2 files changed, 31 insertions(+), 5 deletions(-)
> >>>>>
> >>>>> diff --git a/arch/arm/include/asm/arch-zynqmp/sys_proto.h
> >>>>> b/arch/arm/include/asm/arch-zynqmp/sys_proto.h
> >>>>> index 1db2bd6..bd633a6 100644
> >>>>> --- a/arch/arm/include/asm/arch-zynqmp/sys_proto.h
> >>>>> +++ b/arch/arm/include/asm/arch-zynqmp/sys_proto.h
> >>>>> @@ -8,11 +8,6 @@
> >>>>>  #ifndef _ASM_ARCH_SYS_PROTO_H
> >>>>>  #define _ASM_ARCH_SYS_PROTO_H
> >>>>>
> >>>>> -/* Setup clk for network */
> >>>>> -static inline void zynq_slcr_gem_clk_setup(u32 gem_id, unsigned
> >>>>> long
> >>>>> clk_rate) -{ -}
> >>>>> -
> >>>>>  int zynq_slcr_get_mio_pin_status(const char *periph);
> >>>>>
> >>>>>  unsigned int zynqmp_get_silicon_version(void); diff --git
> >>>>> a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c index
> >>>>> 9bfb89f..9118e49 100644
> >>>>> --- a/drivers/net/zynq_gem.c
> >>>>> +++ b/drivers/net/zynq_gem.c
> >>>>> @@ -9,6 +9,7 @@
> >>>>>   * SPDX-License-Identifier:	GPL-2.0+
> >>>>>   */
> >>>>>
> >>>>> +#include <clk.h>
> >>>>>  #include <common.h>
> >>>>>  #include <dm.h>
> >>>>>  #include <net.h>
> >>>>> @@ -180,6 +181,9 @@ struct zynq_gem_priv {
> >>>>>  	struct phy_device *phydev;
> >>>>>  	int phy_of_handle;
> >>>>>  	struct mii_dev *bus;
> >>>>> +#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
> >>>>> +	struct clk tx_clk;
> >>>>> +#endif
> >>>>>  };
> >>>>>
> >>>>>  static inline int mdio_wait(struct zynq_gem_regs *regs) @@ -
> 364,6
> >>>>> +368,9 @@ static int zynq_gem_init(struct udevice *dev)
> >>>>>  	u32 i, nwconfig;
> >>>>>  	int ret;
> >>>>>  	unsigned long clk_rate = 0;
> >>>>> +#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
> >>>>> +	unsigned long clk_rate_rounded;
> >>>>> +#endif
> >>>>>  	struct zynq_gem_priv *priv = dev_get_priv(dev);
> >>>>>  	struct zynq_gem_regs *regs = priv->iobase;
> >>>>>  	struct emac_bd *dummy_tx_bd = &priv->tx_bd[TX_FREE_DESC];
> @@ -
> >>>> 466,8
> >>>>> +473,22 @@ static int zynq_gem_init(struct udevice *dev)
> >>>>>  		break;
> >>>>>  	}
> >>>>>
> >>>>> +#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
> >>>>> +	clk_rate_rounded = clk_set_rate(&priv->tx_clk, clk_rate);
> >>>>> +	if (IS_ERR_VALUE(clk_rate_rounded)) {
> >>>>> +		dev_err(dev, "failed to set tx clock rate\n");
> >>>>> +		return clk_rate_rounded;
> >>>>> +	}
> >>>>> +
> >>>>> +	ret = clk_enable(&priv->tx_clk);
> >>>>> +	if (ret && ret != -ENOSYS) {
> >>>>> +		dev_err(dev, "failed to enable tx clock\n");
> >>>>> +		return ret;
> >>>>> +	}
> >>>>> +#else
> >>>>>  	zynq_slcr_gem_clk_setup((ulong)priv->iobase !=
> >>>>>  				ZYNQ_GEM_BASEADDR0, clk_rate);
> >>>>> +#endif
> >>>>>
> >>>>>  	setbits_le32(&regs->nwctrl, ZYNQ_GEM_NWCTRL_RXEN_MASK |
> >>>>>  					ZYNQ_GEM_NWCTRL_TXEN_MASK);
> >>>>> @@ -678,6 +699,9 @@ static int zynq_gem_ofdata_to_platdata(struct
> >>>> udevice *dev)
> >>>>>  	struct eth_pdata *pdata = dev_get_platdata(dev);
> >>>>>  	struct zynq_gem_priv *priv = dev_get_priv(dev);
> >>>>>  	const char *phy_mode;
> >>>>> +#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
> >>>>> +	int ret;
> >>>>> +#endif
> >>>>>
> >>>>>  	pdata->iobase = (phys_addr_t)dev_get_addr(dev);
> >>>>>  	priv->iobase = (struct zynq_gem_regs *)pdata->iobase; @@ -
> 699,6
> >>>>> +723,13 @@ static int zynq_gem_ofdata_to_platdata(struct udevice
> >>>> *dev)
> >>>>>  	}
> >>>>>  	priv->interface = pdata->phy_interface;
> >>>>>
> >>>>> +#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
> >>>>> +	ret = clk_get_by_index(dev, 2, &priv->tx_clk);
> >>>>> +	if (ret < 0) {
> >>>>> +		dev_err(dev, "failed to get clock\n");
> >>>>> +		return ret;
> >>>>> +	}
> >>>>> +#endif
> >>>>>
> >>>>>  	printf("ZYNQ GEM: %lx, phyaddr %x, interface %s\n",
> (ulong)priv-
> >>>>> iobase,
> >>>>>  	       priv->phyaddr,
> >>>>> phy_string_for_interface(priv->interface));
> >>>>>
> >>>>
> >>>> Can you please rebase it on the top of this?
> >>>> https://patchwork.ozlabs.org/patch/706419/
> >>>>
> >>>> The reason why this patch was written in this way is that we don't
> >>>> have full zynqmp clk driver yet but we are using fixed clock where
> >>>> you can't run set_rate which fails.
> >>>>
> >>> The patch assumes that the EMIO_ENET_TX_CLK is always fixed. Is
> this
> >> true?
> >>>
> >>> Why don't you add a set_rate() function to the fixed clock?
> >>
> >> It would be a solution but I am not sure if fixed clock was designed
> >> for this. I would expect that fixed clock only provided clock which
> >> you can't change.
> >
> > I think the current clock framework is not optimal as it doesn't
> abstract the clock framework from the drivers. I don't know why a not
> clock driver want to know that an internal clock ops isn't implemented.
> >
> > I would expect that the driver should not care what clock provides
> > the rate. The clk_set_rate() function should always return the nearest
> > possible clock rate and the clk_enable() shouldn't failed with a
> > missing ops function.
> > Otherwise this functions should be mandatory.
> 
> I can't see an issue if clk_set_rate simply failed for clocks which
> can't change. It is up to driver to handle this if this is fine or not.
> In ZynqMP some clocks can be locked because they are used for something
> more important than non secure sw.

In this case the clock should return the current rate and the not clock driver could decide if it could work with this clock rate or not.

> >
> >> It means we need to have something as transition when u- boot has
> >> real clk driver for zynqmp.
> >
> > We could use the same fall back for the clk_set_rate() as we use for
> > the clk_enable() and ignore the -ENOSYS error.
> 
> Not a problem with using -ENOSYS which is just a signal that clk driver
> doesn't care about it.

Okay. Will you update your patch? 

> >>>
> >>> Additionally the patch is missing an enable function call.
> >>
> >> correct.
> >>
> >>>
> >>> I don't think the emio configuration should be keep in the Ethernet
> >> driver as it is part of the clock configuration and doesn't influent
> >> the network interface.
> >>
> >> Please correct me if I am wrong. Are you saying that with these
> >> patches especially 8/8 clock for emio will handled automatically?
> >
> > What do you mean by 8/8 clock?
> 
> I meant patch 8/8 in this series.

Okay. After patch 8/8 the emio clock should be handled automatically like in Linux kernel.

> >
> > The Ethernet driver should not care how the clock is connected and
> only set the required clock rate. The clock driver should route the
> function calls to the correct clock.
> 
> ok. I will try to get testcases for emio to make sure that they are
> still working correctly.

Thanks.

Regards,
  Stefan



Kommanditgesellschaft - Sitz: Detmold - Amtsgericht Lemgo HRA 2790 - 
Komplement?rin: Weidm?ller Interface F?hrungsgesellschaft mbH - 
Sitz: Detmold - Amtsgericht Lemgo HRB 3924; 
Gesch?ftsf?hrer: Jos? Carlos ?lvarez Tobar, Elke Eckstein, Dr. Peter K?hler, J?rg Timmermann;
USt-ID-Nr. DE124599660

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

* [U-Boot] [PATCH 2/8] net: zynq: Add clk framework support to zynq ethernet driver
  2017-01-11  9:55             ` Stefan.Herbrechtsmeier at weidmueller.com
@ 2017-01-11 10:14               ` Michal Simek
  0 siblings, 0 replies; 29+ messages in thread
From: Michal Simek @ 2017-01-11 10:14 UTC (permalink / raw)
  To: u-boot

On 11.1.2017 10:55, Stefan.Herbrechtsmeier at weidmueller.com wrote:
>> -----Urspr?ngliche Nachricht-----
>> Von: Michal Simek [mailto:michal.simek at xilinx.com]
>> Gesendet: Mittwoch, 11. Januar 2017 09:22
>>
>> On 11.1.2017 08:30, Stefan.Herbrechtsmeier at weidmueller.com wrote:
>>>> -----Urspr?ngliche Nachricht-----
>>>> Von: Michal Simek [mailto:monstr at monstr.eu]
>>>> Gesendet: Dienstag, 10. Januar 2017 16:23
>>>>
>>>> On 10.1.2017 15:46, Stefan.Herbrechtsmeier at weidmueller.com wrote:
>>>>>> -----Urspr?ngliche Nachricht-----
>>>>>> Von: Michal Simek [mailto:monstr at monstr.eu]
>>>>>> Gesendet: Dienstag, 10. Januar 2017 14:59
>>>>>> An: Herbrechtsmeier, Stefan; u-boot at lists.denx.de
>>>>>> Cc: Herbrechtsmeier, Stefan; Albert Aribaud; Michal Simek; Joe
>>>>>> Hershberger
>>>>>> Betreff: Re: [PATCH 2/8] net: zynq: Add clk framework support to
>>>> zynq
>>>>>> ethernet driver
>>>>>>
>>>>>> On 4.1.2017 13:27, stefan.herbrechtsmeier at weidmueller.com wrote:
>>>>>>> From: Stefan Herbrechtsmeier
>>>> <stefan.herbrechtsmeier@weidmueller.de>
>>>>>>>
>>>>>>> If available use the clock framework to set the tx clock rate of
>>>> the
>>>>>>> zynq ethernet controller.
>>>>>>>
>>>>>>> Signed-off-by: Stefan Herbrechtsmeier
>>>>>>> <stefan.herbrechtsmeier@weidmueller.com>
>>>>>>> ---
>>>>>>>
>>>>>>>  arch/arm/include/asm/arch-zynqmp/sys_proto.h |  5 -----
>>>>>>>  drivers/net/zynq_gem.c                       | 31
>>>>>> ++++++++++++++++++++++++++++
>>>>>>>  2 files changed, 31 insertions(+), 5 deletions(-)
>>>>>>>
>>>>>>> diff --git a/arch/arm/include/asm/arch-zynqmp/sys_proto.h
>>>>>>> b/arch/arm/include/asm/arch-zynqmp/sys_proto.h
>>>>>>> index 1db2bd6..bd633a6 100644
>>>>>>> --- a/arch/arm/include/asm/arch-zynqmp/sys_proto.h
>>>>>>> +++ b/arch/arm/include/asm/arch-zynqmp/sys_proto.h
>>>>>>> @@ -8,11 +8,6 @@
>>>>>>>  #ifndef _ASM_ARCH_SYS_PROTO_H
>>>>>>>  #define _ASM_ARCH_SYS_PROTO_H
>>>>>>>
>>>>>>> -/* Setup clk for network */
>>>>>>> -static inline void zynq_slcr_gem_clk_setup(u32 gem_id, unsigned
>>>>>>> long
>>>>>>> clk_rate) -{ -}
>>>>>>> -
>>>>>>>  int zynq_slcr_get_mio_pin_status(const char *periph);
>>>>>>>
>>>>>>>  unsigned int zynqmp_get_silicon_version(void); diff --git
>>>>>>> a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c index
>>>>>>> 9bfb89f..9118e49 100644
>>>>>>> --- a/drivers/net/zynq_gem.c
>>>>>>> +++ b/drivers/net/zynq_gem.c
>>>>>>> @@ -9,6 +9,7 @@
>>>>>>>   * SPDX-License-Identifier:	GPL-2.0+
>>>>>>>   */
>>>>>>>
>>>>>>> +#include <clk.h>
>>>>>>>  #include <common.h>
>>>>>>>  #include <dm.h>
>>>>>>>  #include <net.h>
>>>>>>> @@ -180,6 +181,9 @@ struct zynq_gem_priv {
>>>>>>>  	struct phy_device *phydev;
>>>>>>>  	int phy_of_handle;
>>>>>>>  	struct mii_dev *bus;
>>>>>>> +#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
>>>>>>> +	struct clk tx_clk;
>>>>>>> +#endif
>>>>>>>  };
>>>>>>>
>>>>>>>  static inline int mdio_wait(struct zynq_gem_regs *regs) @@ -
>> 364,6
>>>>>>> +368,9 @@ static int zynq_gem_init(struct udevice *dev)
>>>>>>>  	u32 i, nwconfig;
>>>>>>>  	int ret;
>>>>>>>  	unsigned long clk_rate = 0;
>>>>>>> +#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
>>>>>>> +	unsigned long clk_rate_rounded;
>>>>>>> +#endif
>>>>>>>  	struct zynq_gem_priv *priv = dev_get_priv(dev);
>>>>>>>  	struct zynq_gem_regs *regs = priv->iobase;
>>>>>>>  	struct emac_bd *dummy_tx_bd = &priv->tx_bd[TX_FREE_DESC];
>> @@ -
>>>>>> 466,8
>>>>>>> +473,22 @@ static int zynq_gem_init(struct udevice *dev)
>>>>>>>  		break;
>>>>>>>  	}
>>>>>>>
>>>>>>> +#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
>>>>>>> +	clk_rate_rounded = clk_set_rate(&priv->tx_clk, clk_rate);
>>>>>>> +	if (IS_ERR_VALUE(clk_rate_rounded)) {
>>>>>>> +		dev_err(dev, "failed to set tx clock rate\n");
>>>>>>> +		return clk_rate_rounded;
>>>>>>> +	}
>>>>>>> +
>>>>>>> +	ret = clk_enable(&priv->tx_clk);
>>>>>>> +	if (ret && ret != -ENOSYS) {
>>>>>>> +		dev_err(dev, "failed to enable tx clock\n");
>>>>>>> +		return ret;
>>>>>>> +	}
>>>>>>> +#else
>>>>>>>  	zynq_slcr_gem_clk_setup((ulong)priv->iobase !=
>>>>>>>  				ZYNQ_GEM_BASEADDR0, clk_rate);
>>>>>>> +#endif
>>>>>>>
>>>>>>>  	setbits_le32(&regs->nwctrl, ZYNQ_GEM_NWCTRL_RXEN_MASK |
>>>>>>>  					ZYNQ_GEM_NWCTRL_TXEN_MASK);
>>>>>>> @@ -678,6 +699,9 @@ static int zynq_gem_ofdata_to_platdata(struct
>>>>>> udevice *dev)
>>>>>>>  	struct eth_pdata *pdata = dev_get_platdata(dev);
>>>>>>>  	struct zynq_gem_priv *priv = dev_get_priv(dev);
>>>>>>>  	const char *phy_mode;
>>>>>>> +#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
>>>>>>> +	int ret;
>>>>>>> +#endif
>>>>>>>
>>>>>>>  	pdata->iobase = (phys_addr_t)dev_get_addr(dev);
>>>>>>>  	priv->iobase = (struct zynq_gem_regs *)pdata->iobase; @@ -
>> 699,6
>>>>>>> +723,13 @@ static int zynq_gem_ofdata_to_platdata(struct udevice
>>>>>> *dev)
>>>>>>>  	}
>>>>>>>  	priv->interface = pdata->phy_interface;
>>>>>>>
>>>>>>> +#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK)
>>>>>>> +	ret = clk_get_by_index(dev, 2, &priv->tx_clk);
>>>>>>> +	if (ret < 0) {
>>>>>>> +		dev_err(dev, "failed to get clock\n");
>>>>>>> +		return ret;
>>>>>>> +	}
>>>>>>> +#endif
>>>>>>>
>>>>>>>  	printf("ZYNQ GEM: %lx, phyaddr %x, interface %s\n",
>> (ulong)priv-
>>>>>>> iobase,
>>>>>>>  	       priv->phyaddr,
>>>>>>> phy_string_for_interface(priv->interface));
>>>>>>>
>>>>>>
>>>>>> Can you please rebase it on the top of this?
>>>>>> https://patchwork.ozlabs.org/patch/706419/
>>>>>>
>>>>>> The reason why this patch was written in this way is that we don't
>>>>>> have full zynqmp clk driver yet but we are using fixed clock where
>>>>>> you can't run set_rate which fails.
>>>>>>
>>>>> The patch assumes that the EMIO_ENET_TX_CLK is always fixed. Is
>> this
>>>> true?
>>>>>
>>>>> Why don't you add a set_rate() function to the fixed clock?
>>>>
>>>> It would be a solution but I am not sure if fixed clock was designed
>>>> for this. I would expect that fixed clock only provided clock which
>>>> you can't change.
>>>
>>> I think the current clock framework is not optimal as it doesn't
>> abstract the clock framework from the drivers. I don't know why a not
>> clock driver want to know that an internal clock ops isn't implemented.
>>>
>>> I would expect that the driver should not care what clock provides
>>> the rate. The clk_set_rate() function should always return the nearest
>>> possible clock rate and the clk_enable() shouldn't failed with a
>>> missing ops function.
>>> Otherwise this functions should be mandatory.
>>
>> I can't see an issue if clk_set_rate simply failed for clocks which
>> can't change. It is up to driver to handle this if this is fine or not.
>> In ZynqMP some clocks can be locked because they are used for something
>> more important than non secure sw.
> 
> In this case the clock should return the current rate and the not clock driver could decide if it could work with this clock rate or not.

I would discuss this with clk guys.
I was checking existing code and a lot of drivers are only checking
error value not rate which is return.
But based on clk.h driver should check if clk rate is sufficient for
that particular case.


>>>
>>>> It means we need to have something as transition when u- boot has
>>>> real clk driver for zynqmp.
>>>
>>> We could use the same fall back for the clk_set_rate() as we use for
>>> the clk_enable() and ignore the -ENOSYS error.
>>
>> Not a problem with using -ENOSYS which is just a signal that clk driver
>> doesn't care about it.
> 
> Okay. Will you update your patch? 

I have sent PR to Tom some hours ago. It is not big deal to patch it.
If you can do it as the part of your rebase that will be great.
If you want me to do I can send another patch just for this one.

>>>>>
>>>>> Additionally the patch is missing an enable function call.
>>>>
>>>> correct.
>>>>
>>>>>
>>>>> I don't think the emio configuration should be keep in the Ethernet
>>>> driver as it is part of the clock configuration and doesn't influent
>>>> the network interface.
>>>>
>>>> Please correct me if I am wrong. Are you saying that with these
>>>> patches especially 8/8 clock for emio will handled automatically?
>>>
>>> What do you mean by 8/8 clock?
>>
>> I meant patch 8/8 in this series.
> 
> Okay. After patch 8/8 the emio clock should be handled automatically like in Linux kernel.

good.

Thanks,
Michal

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

end of thread, other threads:[~2017-01-11 10:14 UTC | newest]

Thread overview: 29+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-01-04 12:27 [U-Boot] [PATCH 0/8] zynq: clk: Move zynq platform to clock framework stefan.herbrechtsmeier at weidmueller.com
2017-01-04 12:27 ` [U-Boot] [PATCH 1/8] net: zynq: Don't overwrite gem_rclk_ctrl with default value stefan.herbrechtsmeier at weidmueller.com
2017-01-10 13:52   ` Michal Simek
2017-01-10 14:28     ` Stefan.Herbrechtsmeier at weidmueller.com
2017-01-10 15:26       ` Michal Simek
2017-01-04 12:27 ` [U-Boot] [PATCH 2/8] net: zynq: Add clk framework support to zynq ethernet driver stefan.herbrechtsmeier at weidmueller.com
2017-01-10 13:58   ` Michal Simek
2017-01-10 14:46     ` Stefan.Herbrechtsmeier at weidmueller.com
2017-01-10 15:23       ` Michal Simek
2017-01-11  7:30         ` Stefan.Herbrechtsmeier at weidmueller.com
2017-01-11  8:21           ` Michal Simek
2017-01-11  9:55             ` Stefan.Herbrechtsmeier at weidmueller.com
2017-01-11 10:14               ` Michal Simek
2017-01-04 12:27 ` [U-Boot] [PATCH 3/8] zynq: Add clk framework support to zynq timer stefan.herbrechtsmeier at weidmueller.com
2017-01-10 14:10   ` Michal Simek
2017-01-10 14:54     ` Stefan.Herbrechtsmeier at weidmueller.com
2017-01-10 15:08       ` Michal Simek
2017-01-04 12:27 ` [U-Boot] [PATCH 4/8] zynq: Move static clock names into separate array stefan.herbrechtsmeier at weidmueller.com
2017-01-10 14:15   ` Michal Simek
2017-01-04 12:27 ` [U-Boot] [PATCH 5/8] zynq: Remove zynq_clk_get_name function stefan.herbrechtsmeier at weidmueller.com
2017-01-10 14:16   ` Michal Simek
2017-01-04 12:27 ` [U-Boot] [PATCH 6/8] clk: zynq: Add zynq clock framework driver stefan.herbrechtsmeier at weidmueller.com
2017-01-10 14:57   ` Michal Simek
2017-01-10 19:17     ` Sören Brinkmann
2017-01-11  7:15     ` Stefan.Herbrechtsmeier at weidmueller.com
2017-01-04 12:27 ` [U-Boot] [PATCH 7/8] zynq: Move zynq to clock framework stefan.herbrechtsmeier at weidmueller.com
2017-01-10 15:04   ` Michal Simek
2017-01-04 12:27 ` [U-Boot] [PATCH 8/8] clk: zynq: Add optional ethernet emio clock source support stefan.herbrechtsmeier at weidmueller.com
2017-01-10 15:06   ` Michal Simek

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.