[U-Boot] [PATCH v2 00/10] zynq: clk: Move zynq platform to clock framework

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.
This series depends on patch 'mmc: sdhci: Distinguish between base clock and maximum peripheral frequency'
Changes in v2: - Rebase - Group ifndef CONFIG_SPL_BUILD inside switch case of zynq_clk_get_register() - Put same switch case code together in zynq_clk_get_*_pll() - Replace ZYNQ_CLKMUX_SEL_* by there numbers - Return error code and add debug message for unknown gem eimo rx clock source - Correct zynq_clk_calc_peripheral_two_divs() parameter indetation - Add support for unknown clock rate to soc_clk_dump() - Return a error and print a debug message if a gem emio rx clock source is unknown - Correct the checks for valid clock objects - Add patch to determine base clock frequency of zynq mmc driver via clock framework - Add patch to add fdt max-frequency support to zynq mmc driver
Stefan Herbrechtsmeier (10): 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 mmc: zynq: Determine base clock frequency via clock framework mmc: zynq: Add fdt max-frequency support
arch/arm/Kconfig | 3 + arch/arm/dts/zynq-7000.dtsi | 2 + arch/arm/include/asm/arch-zynqmp/sys_proto.h | 7 - arch/arm/mach-zynq/clk.c | 690 +++------------------------ 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 | 8 + drivers/clk/Makefile | 1 + drivers/clk/clk_zynq.c | 488 +++++++++++++++++++ drivers/mmc/zynq_sdhci.c | 33 +- drivers/net/zynq_gem.c | 28 +- drivers/serial/serial_zynq.c | 6 +- include/configs/topic_miami.h | 2 - include/configs/zynq_zybo.h | 3 - scripts/config_whitelist.txt | 1 - 18 files changed, 634 insertions(+), 698 deletions(-) create mode 100644 drivers/clk/clk_zynq.c

From: Stefan Herbrechtsmeier stefan.herbrechtsmeier@weidmueller.com
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 ---
Changes in v2: None
arch/arm/mach-zynq/slcr.c | 7 ------- drivers/net/zynq_gem.c | 15 +++++---------- 2 files changed, 5 insertions(+), 17 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 6dd87cf..872e4f8 100644 --- a/drivers/net/zynq_gem.c +++ b/drivers/net/zynq_gem.c @@ -175,7 +175,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; @@ -457,15 +456,13 @@ static int zynq_gem_init(struct udevice *dev) break; }
- /* Change the rclk and clk only not using EMIO interface */ - if (!priv->emio) #ifndef CONFIG_CLK_ZYNQMP - 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); #else - ret = clk_set_rate(&priv->clk, clk_rate); - if (IS_ERR_VALUE(ret)) - return -1; + ret = clk_set_rate(&priv->clk, clk_rate); + if (IS_ERR_VALUE(ret)) + return -1; #endif
setbits_le32(®s->nwctrl, ZYNQ_GEM_NWCTRL_RXEN_MASK | @@ -689,7 +686,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, @@ -707,7 +703,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));

On Tue, Jan 17, 2017 at 9:27 AM, stefan.herbrechtsmeier@weidmueller.com wrote:
From: Stefan Herbrechtsmeier stefan.herbrechtsmeier@weidmueller.com
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
Reviewed-by: Joe Hershberger joe.hershberger@ni.com

From: Stefan Herbrechtsmeier stefan.herbrechtsmeier@weidmueller.com
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 ---
Changes in v2: - Rebase
arch/arm/include/asm/arch-zynqmp/sys_proto.h | 7 ------- drivers/net/zynq_gem.c | 22 +++++++++++++++------- 2 files changed, 15 insertions(+), 14 deletions(-)
diff --git a/arch/arm/include/asm/arch-zynqmp/sys_proto.h b/arch/arm/include/asm/arch-zynqmp/sys_proto.h index 8c54fce..7b11895 100644 --- a/arch/arm/include/asm/arch-zynqmp/sys_proto.h +++ b/arch/arm/include/asm/arch-zynqmp/sys_proto.h @@ -8,13 +8,6 @@ #ifndef _ASM_ARCH_SYS_PROTO_H #define _ASM_ARCH_SYS_PROTO_H
-#ifndef CONFIG_CLK_ZYNQMP -/* Setup clk for network */ -static inline void zynq_slcr_gem_clk_setup(u32 gem_id, unsigned long clk_rate) -{ -} -#endif - 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 872e4f8..8c5c55a 100644 --- a/drivers/net/zynq_gem.c +++ b/drivers/net/zynq_gem.c @@ -181,7 +181,7 @@ struct zynq_gem_priv { struct phy_device *phydev; int phy_of_handle; struct mii_dev *bus; -#ifdef CONFIG_CLK_ZYNQMP +#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK) struct clk clk; #endif }; @@ -456,13 +456,21 @@ static int zynq_gem_init(struct udevice *dev) break; }
-#ifndef CONFIG_CLK_ZYNQMP +#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK) + ret = clk_set_rate(&priv->clk, clk_rate); + if (IS_ERR_VALUE(ret) && ret != (unsigned long)-ENOSYS) { + dev_err(dev, "failed to set tx clock rate\n"); + return ret; + } + + ret = clk_enable(&priv->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); -#else - ret = clk_set_rate(&priv->clk, clk_rate); - if (IS_ERR_VALUE(ret)) - return -1; #endif
setbits_le32(®s->nwctrl, ZYNQ_GEM_NWCTRL_RXEN_MASK | @@ -636,7 +644,7 @@ static int zynq_gem_probe(struct udevice *dev) priv->tx_bd = (struct emac_bd *)bd_space; priv->rx_bd = (struct emac_bd *)((ulong)bd_space + BD_SEPRN_SPACE);
-#ifdef CONFIG_CLK_ZYNQMP +#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK) ret = clk_get_by_name(dev, "tx_clk", &priv->clk); if (ret < 0) { dev_err(dev, "failed to get clock\n");

On Tue, Jan 17, 2017 at 9:27 AM, stefan.herbrechtsmeier@weidmueller.com wrote:
From: Stefan Herbrechtsmeier stefan.herbrechtsmeier@weidmueller.com
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
Reviewed-by: Joe Hershberger joe.hershberger@ni.com

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 ---
Changes in v2: None
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 */

From: Stefan Herbrechtsmeier stefan.herbrechtsmeier@weidmueller.com
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 Reviewed-by: Michal Simek michal.simek@xilinx.com ---
Changes in v2: None
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]; }
/**

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 Reviewed-by: Michal Simek michal.simek@xilinx.com ---
Changes in v2: None
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

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
---
Changes in v2: - Group ifndef CONFIG_SPL_BUILD inside switch case of zynq_clk_get_register() - Put same switch case code together in zynq_clk_get_*_pll() - Replace ZYNQ_CLKMUX_SEL_* by there numbers - Return error code and add debug message for unknown gem eimo rx clock source - Correct zynq_clk_calc_peripheral_two_divs() parameter indetation
drivers/clk/Kconfig | 8 + drivers/clk/Makefile | 1 + drivers/clk/clk_zynq.c | 459 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 468 insertions(+) create mode 100644 drivers/clk/clk_zynq.c
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 335ef9e..5ca958c 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -28,6 +28,14 @@ config CLK_BOSTON help Enable this to support the clocks
+config CLK_ZYNQ + bool "Enable clock driver support for Zynq" + depends on CLK && ARCH_ZYNQ + default y + help + This clock driver adds support for clock realted settings for + Zynq platform. + config CLK_ZYNQMP bool "Enable clock driver support for ZynqMP" depends on ARCH_ZYNQMP diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index f55348e..ce9df25 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -17,3 +17,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..a070f01 --- /dev/null +++ b/drivers/clk/clk_zynq.c @@ -0,0 +1,459 @@ +/* + * 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) + +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; + 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; + case sdio0_clk ... sdio1_clk: + return &slcr_base->sdio_clk_ctrl; + case uart0_clk ... uart1_clk: + return &slcr_base->uart_clk_ctrl; + case spi0_clk ... spi1_clk: + return &slcr_base->spi_clk_ctrl; +#ifndef CONFIG_SPL_BUILD + case dci_clk: + return &slcr_base->dci_clk_ctrl; + 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; + case dbg_trc_clk ... dbg_apb_clk: + /* fall through */ +#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 2: + return ddrpll_clk; + case 3: + return iopll_clk; + case 0 ... 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 2: + return armpll_clk; + case 3: + return ddrpll_clk; + case 0 ... 1: + 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); + + debug("%s: gem%d emio rx clock source unknown\n", __func__, + id - gem0_clk); + + return -ENOSYS; +} + +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); + + debug("%s: gem%d emio rx clock source unknown\n", __func__, + id - gem0_clk); + + return -ENOSYS; +} +#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, +};

From: Stefan Herbrechtsmeier stefan.herbrechtsmeier@weidmueller.com
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
---
Changes in v2: - Add support for unknown clock rate to soc_clk_dump()
arch/arm/Kconfig | 3 + arch/arm/dts/zynq-7000.dtsi | 2 + arch/arm/mach-zynq/clk.c | 653 +++------------------------- 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 | 9 - 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, 59 insertions(+), 651 deletions(-)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 0ed36cd..449f4af 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -647,6 +647,9 @@ config ARCH_ZYNQ select SPL_SEPARATE_BSS if SPL select DM_USB if USB select BLK + select CLK + select SPL_CLK + select CLK_ZYNQ
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 fa9ee27..34fc6e5 100644 --- a/arch/arm/dts/zynq-7000.dtsi +++ b/arch/arm/dts/zynq-7000.dtsi @@ -248,12 +248,14 @@ };
slcr: slcr@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@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..1369cd0 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,35 @@ 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); + + if (rate == (unsigned long)-ENOSYS) + printf("%10s%20s\n", name, "unknown"); + else + 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 8c5c55a..38fb5a4 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 clk; -#endif };
static u32 phy_setup_op(struct zynq_gem_priv *priv, u32 phy_addr, u32 regnum, @@ -456,7 +454,6 @@ static int zynq_gem_init(struct udevice *dev) break; }
-#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK) ret = clk_set_rate(&priv->clk, clk_rate); if (IS_ERR_VALUE(ret) && ret != (unsigned long)-ENOSYS) { dev_err(dev, "failed to set tx clock rate\n"); @@ -468,10 +465,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(®s->nwctrl, ZYNQ_GEM_NWCTRL_RXEN_MASK | ZYNQ_GEM_NWCTRL_TXEN_MASK); @@ -644,13 +637,11 @@ static int zynq_gem_probe(struct udevice *dev) priv->tx_bd = (struct emac_bd *)bd_space; priv->rx_bd = (struct emac_bd *)((ulong)bd_space + BD_SEPRN_SPACE);
-#if defined(CONFIG_CLK) || defined(CONFIG_SPL_CLK) ret = clk_get_by_name(dev, "tx_clk", &priv->clk); if (ret < 0) { dev_err(dev, "failed to get clock\n"); return -EINVAL; } -#endif
priv->bus = mdio_alloc(); priv->bus->read = zynq_gem_miiphy_read; 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 4935b91..99a1de5 100644 --- a/scripts/config_whitelist.txt +++ b/scripts/config_whitelist.txt @@ -6955,7 +6955,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

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
---
Changes in v2: - Return a error and print a debug message if a gem emio rx clock source is unknown - Correct the checks for valid clock objects
drivers/clk/clk_zynq.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+)
diff --git a/drivers/clk/clk_zynq.c b/drivers/clk/clk_zynq.c index a070f01..6edc4dc 100644 --- a/drivers/clk/clk_zynq.c +++ b/drivers/clk/clk_zynq.c @@ -48,6 +48,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) @@ -267,9 +270,15 @@ 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);
+ parent = &priv->gem_emio_clk[id - gem0_clk]; + if (parent->dev) + return clk_get_rate(parent); + debug("%s: gem%d emio rx clock source unknown\n", __func__, id - gem0_clk);
@@ -340,9 +349,15 @@ 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);
+ parent = &priv->gem_emio_clk[id - gem0_clk]; + if (parent->dev) + return clk_set_rate(parent, rate); + debug("%s: gem%d emio rx clock source unknown\n", __func__, id - gem0_clk);
@@ -436,6 +451,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);

From: Stefan Herbrechtsmeier stefan.herbrechtsmeier@weidmueller.com
The zynq_sdhci controller driver use CONFIG_ZYNQ_SDHCI_MAX_FREQ as base clock frequency but this clock is not fixed and depends on the hardware configuration. Additionally the value of CONFIG_ZYNQ_SDHCI_MAX_FREQ doesn't match the real base clock frequency of SDIO_FREQ. Use the clock framework to determine the frequency at run time.
Signed-off-by: Stefan Herbrechtsmeier stefan.herbrechtsmeier@weidmueller.com
---
Changes in v2: - Add patch to determine base clock frequency of zynq mmc driver via clock framework
drivers/mmc/zynq_sdhci.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-)
diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c index 69efa38..c73a4d3 100644 --- a/drivers/mmc/zynq_sdhci.c +++ b/drivers/mmc/zynq_sdhci.c @@ -6,6 +6,7 @@ * SPDX-License-Identifier: GPL-2.0+ */
+#include <clk.h> #include <common.h> #include <dm.h> #include <fdtdec.h> @@ -27,8 +28,29 @@ static int arasan_sdhci_probe(struct udevice *dev) struct arasan_sdhci_plat *plat = dev_get_platdata(dev); struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); struct sdhci_host *host = dev_get_priv(dev); + struct clk clk; + unsigned long clock; int ret;
+ ret = clk_get_by_index(dev, 0, &clk); + if (ret < 0) { + dev_err(dev, "failed to get clock\n"); + return ret; + } + + clock = clk_get_rate(&clk); + if (IS_ERR_VALUE(clock)) { + dev_err(dev, "failed to get rate\n"); + return clock; + } + debug("%s: CLK %ld\n", __func__, clock); + + ret = clk_enable(&clk); + if (ret && ret != -ENOSYS) { + dev_err(dev, "failed to enable clock\n"); + return ret; + } + host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_BROKEN_R1B;
@@ -36,9 +58,9 @@ static int arasan_sdhci_probe(struct udevice *dev) host->quirks |= SDHCI_QUIRK_NO_HISPD_BIT; #endif
- host->max_clk = CONFIG_ZYNQ_SDHCI_MAX_FREQ; + host->max_clk = clock;
- ret = sdhci_setup_cfg(&plat->cfg, host, 0, + ret = sdhci_setup_cfg(&plat->cfg, host, CONFIG_ZYNQ_SDHCI_MAX_FREQ, CONFIG_ZYNQ_SDHCI_MIN_FREQ); host->mmc = &plat->mmc; if (ret)

On 01/18/2017 12:27 AM, stefan.herbrechtsmeier@weidmueller.com wrote:
From: Stefan Herbrechtsmeier stefan.herbrechtsmeier@weidmueller.com
The zynq_sdhci controller driver use CONFIG_ZYNQ_SDHCI_MAX_FREQ as base clock frequency but this clock is not fixed and depends on the hardware configuration. Additionally the value of CONFIG_ZYNQ_SDHCI_MAX_FREQ doesn't match the real base clock frequency of SDIO_FREQ. Use the clock framework to determine the frequency at run time.
Signed-off-by: Stefan Herbrechtsmeier stefan.herbrechtsmeier@weidmueller.com
Reviewed-by: Jaehoon Chung jh80.chung@samsung.com
Best Regards, Jaehoon Chung
Changes in v2:
- Add patch to determine base clock frequency of zynq mmc driver via clock framework
drivers/mmc/zynq_sdhci.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-)
diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c index 69efa38..c73a4d3 100644 --- a/drivers/mmc/zynq_sdhci.c +++ b/drivers/mmc/zynq_sdhci.c @@ -6,6 +6,7 @@
- SPDX-License-Identifier: GPL-2.0+
*/
+#include <clk.h> #include <common.h> #include <dm.h> #include <fdtdec.h> @@ -27,8 +28,29 @@ static int arasan_sdhci_probe(struct udevice *dev) struct arasan_sdhci_plat *plat = dev_get_platdata(dev); struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); struct sdhci_host *host = dev_get_priv(dev);
struct clk clk;
unsigned long clock; int ret;
ret = clk_get_by_index(dev, 0, &clk);
if (ret < 0) {
dev_err(dev, "failed to get clock\n");
return ret;
}
clock = clk_get_rate(&clk);
if (IS_ERR_VALUE(clock)) {
dev_err(dev, "failed to get rate\n");
return clock;
}
debug("%s: CLK %ld\n", __func__, clock);
ret = clk_enable(&clk);
if (ret && ret != -ENOSYS) {
dev_err(dev, "failed to enable clock\n");
return ret;
}
host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_BROKEN_R1B;
@@ -36,9 +58,9 @@ static int arasan_sdhci_probe(struct udevice *dev) host->quirks |= SDHCI_QUIRK_NO_HISPD_BIT; #endif
- host->max_clk = CONFIG_ZYNQ_SDHCI_MAX_FREQ;
- host->max_clk = clock;
- ret = sdhci_setup_cfg(&plat->cfg, host, 0,
- ret = sdhci_setup_cfg(&plat->cfg, host, CONFIG_ZYNQ_SDHCI_MAX_FREQ, CONFIG_ZYNQ_SDHCI_MIN_FREQ); host->mmc = &plat->mmc; if (ret)

From: Stefan Herbrechtsmeier stefan.herbrechtsmeier@weidmueller.com
The maximum supported peripheral clock frequency of the zynq depends on the IO routing. The MIO and EMIO support a maximum frequency of 50 MHz respectively 25 MHz. Use the max-frequency value of the device tree to determine the maximal supported peripheral clock frequency.
Signed-off-by: Stefan Herbrechtsmeier stefan.herbrechtsmeier@weidmueller.com Acked-by: Michal Simek michal.simek@xilinx.com
---
Changes in v2: - Add patch to add fdt max-frequency support to zynq mmc driver
drivers/mmc/zynq_sdhci.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c index c73a4d3..28cedf0 100644 --- a/drivers/mmc/zynq_sdhci.c +++ b/drivers/mmc/zynq_sdhci.c @@ -14,6 +14,8 @@ #include <malloc.h> #include <sdhci.h>
+DECLARE_GLOBAL_DATA_PTR; + #ifndef CONFIG_ZYNQ_SDHCI_MIN_FREQ # define CONFIG_ZYNQ_SDHCI_MIN_FREQ 0 #endif @@ -21,6 +23,7 @@ struct arasan_sdhci_plat { struct mmc_config cfg; struct mmc mmc; + unsigned int f_max; };
static int arasan_sdhci_probe(struct udevice *dev) @@ -60,7 +63,7 @@ static int arasan_sdhci_probe(struct udevice *dev)
host->max_clk = clock;
- ret = sdhci_setup_cfg(&plat->cfg, host, CONFIG_ZYNQ_SDHCI_MAX_FREQ, + ret = sdhci_setup_cfg(&plat->cfg, host, plat->f_max, CONFIG_ZYNQ_SDHCI_MIN_FREQ); host->mmc = &plat->mmc; if (ret) @@ -74,11 +77,15 @@ static int arasan_sdhci_probe(struct udevice *dev)
static int arasan_sdhci_ofdata_to_platdata(struct udevice *dev) { + struct arasan_sdhci_plat *plat = dev_get_platdata(dev); struct sdhci_host *host = dev_get_priv(dev);
host->name = dev->name; host->ioaddr = (void *)dev_get_addr(dev);
+ plat->f_max = fdtdec_get_int(gd->fdt_blob, dev->of_offset, + "max-frequency", CONFIG_ZYNQ_SDHCI_MAX_FREQ); + return 0; }

On 01/18/2017 12:27 AM, stefan.herbrechtsmeier@weidmueller.com wrote:
From: Stefan Herbrechtsmeier stefan.herbrechtsmeier@weidmueller.com
The maximum supported peripheral clock frequency of the zynq depends on the IO routing. The MIO and EMIO support a maximum frequency of 50 MHz respectively 25 MHz. Use the max-frequency value of the device tree to determine the maximal supported peripheral clock frequency.
Signed-off-by: Stefan Herbrechtsmeier stefan.herbrechtsmeier@weidmueller.com Acked-by: Michal Simek michal.simek@xilinx.com
Reviewed-by: Jaehoon Chung jh80.chung@samsung.com
Best Regards, Jaehoon Chung
Changes in v2:
- Add patch to add fdt max-frequency support to zynq mmc driver
drivers/mmc/zynq_sdhci.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c index c73a4d3..28cedf0 100644 --- a/drivers/mmc/zynq_sdhci.c +++ b/drivers/mmc/zynq_sdhci.c @@ -14,6 +14,8 @@ #include <malloc.h> #include <sdhci.h>
+DECLARE_GLOBAL_DATA_PTR;
#ifndef CONFIG_ZYNQ_SDHCI_MIN_FREQ # define CONFIG_ZYNQ_SDHCI_MIN_FREQ 0 #endif @@ -21,6 +23,7 @@ struct arasan_sdhci_plat { struct mmc_config cfg; struct mmc mmc;
- unsigned int f_max;
};
static int arasan_sdhci_probe(struct udevice *dev) @@ -60,7 +63,7 @@ static int arasan_sdhci_probe(struct udevice *dev)
host->max_clk = clock;
- ret = sdhci_setup_cfg(&plat->cfg, host, CONFIG_ZYNQ_SDHCI_MAX_FREQ,
- ret = sdhci_setup_cfg(&plat->cfg, host, plat->f_max, CONFIG_ZYNQ_SDHCI_MIN_FREQ); host->mmc = &plat->mmc; if (ret)
@@ -74,11 +77,15 @@ static int arasan_sdhci_probe(struct udevice *dev)
static int arasan_sdhci_ofdata_to_platdata(struct udevice *dev) {
struct arasan_sdhci_plat *plat = dev_get_platdata(dev); struct sdhci_host *host = dev_get_priv(dev);
host->name = dev->name; host->ioaddr = (void *)dev_get_addr(dev);
plat->f_max = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
"max-frequency", CONFIG_ZYNQ_SDHCI_MAX_FREQ);
return 0;
}

Hi Michal,
-----Ursprüngliche Nachricht----- Von: 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.
Any comments on this patch series?
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

Hi Stefan,
On 6.2.2017 11:14, Stefan.Herbrechtsmeier@weidmueller.com wrote:
Hi Michal,
-----Ursprüngliche Nachricht----- Von: 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.
Any comments on this patch series?
I was sick the whole last week and catching emails. I have tried it on zc702 and it didn't work for me that's why I will have closer look hopefully this week. Definitely sorry for delay.
Thanks, Michal

Hi Michal,
-----Ursprüngliche Nachricht----- Von: Michal Simek [mailto:michal.simek@xilinx.com]
Hi Stefan,
On 6.2.2017 11:14, Stefan.Herbrechtsmeier@weidmueller.com wrote:
Hi Michal,
-----Ursprüngliche Nachricht----- Von: 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.
Any comments on this patch series?
I was sick the whole last week and catching emails. I have tried it on zc702 and it didn't work for me that's why I will have closer look hopefully this week. Definitely sorry for delay.
Could you describe the problem. Maybe I could help.
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

On 17.2.2017 08:33, Stefan.Herbrechtsmeier@weidmueller.com wrote:
Hi Michal,
-----Ursprüngliche Nachricht----- Von: Michal Simek [mailto:michal.simek@xilinx.com]
Hi Stefan,
On 6.2.2017 11:14, Stefan.Herbrechtsmeier@weidmueller.com wrote:
Hi Michal,
-----Ursprüngliche Nachricht----- Von: 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.
Any comments on this patch series?
I was sick the whole last week and catching emails. I have tried it on zc702 and it didn't work for me that's why I will have closer look hopefully this week. Definitely sorry for delay.
Could you describe the problem. Maybe I could help.
On zybo I am getting this.
failed to get clock failed to get clock No serial driver found
Thanks, Michal

On 17.2.2017 10:21, Michal Simek wrote:
On 17.2.2017 08:33, Stefan.Herbrechtsmeier@weidmueller.com wrote:
Hi Michal,
-----Ursprüngliche Nachricht----- Von: Michal Simek [mailto:michal.simek@xilinx.com]
Hi Stefan,
On 6.2.2017 11:14, Stefan.Herbrechtsmeier@weidmueller.com wrote:
Hi Michal,
-----Ursprüngliche Nachricht----- Von: 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.
Any comments on this patch series?
I was sick the whole last week and catching emails. I have tried it on zc702 and it didn't work for me that's why I will have closer look hopefully this week. Definitely sorry for delay.
Could you describe the problem. Maybe I could help.
On zybo I am getting this.
failed to get clock failed to get clock No serial driver found
Interesting. I have rebased trees and it started to work on zybo/zc702/zc706/microzed.
I will rebuild all targets and let you know.
Thanks, Michal

-----Ursprüngliche Nachricht----- Von: Michal Simek [mailto:michal.simek@xilinx.com]
On 17.2.2017 10:21, Michal Simek wrote:
On 17.2.2017 08:33, Stefan.Herbrechtsmeier@weidmueller.com wrote:
Hi Michal,
-----Ursprüngliche Nachricht----- Von: Michal Simek [mailto:michal.simek@xilinx.com]
Hi Stefan,
On 6.2.2017 11:14, Stefan.Herbrechtsmeier@weidmueller.com wrote:
Hi Michal,
-----Ursprüngliche Nachricht----- Von: 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.
Any comments on this patch series?
I was sick the whole last week and catching emails. I have tried it on zc702 and it didn't work for me that's why I
will
have closer look hopefully this week. Definitely sorry for delay.
Could you describe the problem. Maybe I could help.
On zybo I am getting this.
failed to get clock failed to get clock No serial driver found
Interesting. I have rebased trees and it started to work on zybo/zc702/zc706/microzed.
I assume a SPL malloc problem because of the additional "u-boot,dm-pre-reloc" entries inside the device tree.
Maybe we need to increase the CONFIG_SYS_SPL_MALLOC_SIZE.
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

On 17.2.2017 12:51, Stefan.Herbrechtsmeier@weidmueller.com wrote:
-----Ursprüngliche Nachricht----- Von: Michal Simek [mailto:michal.simek@xilinx.com]
On 17.2.2017 10:21, Michal Simek wrote:
On 17.2.2017 08:33, Stefan.Herbrechtsmeier@weidmueller.com wrote:
Hi Michal,
-----Ursprüngliche Nachricht----- Von: Michal Simek [mailto:michal.simek@xilinx.com]
Hi Stefan,
On 6.2.2017 11:14, Stefan.Herbrechtsmeier@weidmueller.com wrote:
Hi Michal,
> -----Ursprüngliche Nachricht----- > Von: 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. >
Any comments on this patch series?
I was sick the whole last week and catching emails. I have tried it on zc702 and it didn't work for me that's why I
will
have closer look hopefully this week. Definitely sorry for delay.
Could you describe the problem. Maybe I could help.
On zybo I am getting this.
failed to get clock failed to get clock No serial driver found
Interesting. I have rebased trees and it started to work on zybo/zc702/zc706/microzed.
I assume a SPL malloc problem because of the additional "u-boot,dm-pre-reloc" entries inside the device tree.
Maybe we need to increase the CONFIG_SYS_SPL_MALLOC_SIZE.
Will see - right now that major boards I have tested have no issue. I have merged the whole series to master branch in my repo and travis is building it again.
We have rc3 now and I will queue it to next release.
Thanks, Michal
participants (5)
-
Jaehoon Chung
-
Joe Hershberger
-
Michal Simek
-
Stefan.Herbrechtsmeier@weidmueller.com
-
stefan.herbrechtsmeier@weidmueller.com