Re: [PATCH v2 3/5] ARM: zynq: add clk support for zynq7000

2013-03-26 Thread Michal Simek
2013/3/26 Josh Cartwright :
> On Tue, Mar 26, 2013 at 08:20:15AM -0500, Josh Cartwright wrote:
>> On Tue, Mar 26, 2013 at 10:11:24AM +0100, Steffen Trumtrar wrote:
>> > This adds support for the clocktree on zynq7000 SoCs.
>> > The patch is based on clocks.c from the larger patch
>> > ARM: zynq: add suppport for Zynq 7000 SoC
>> > by Josh Cartwright.
>> >
>> > The driver in that patch is converted to a platform_driver and code to
>> > enable plls was added.
>> >
>> > Signed-off-by: Steffen Trumtrar 
>>
>> Reviewed-off-by: Josh Cartwright 
>
> Heh, clearly I meant Reviewed-by: .  I should stop reading my email
> before my morning coffee. :)

:-)

M



-- 
Michal Simek, Ing. (M.Eng)
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel - Microblaze cpu - http://www.monstr.eu/fdt/
Maintainer of Linux kernel - Xilinx Zynq ARM architecture
Microblaze U-BOOT custodian and responsible for u-boot arm zynq platform

___
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox


Re: [PATCH v2 3/5] ARM: zynq: add clk support for zynq7000

2013-03-26 Thread Josh Cartwright
On Tue, Mar 26, 2013 at 08:20:15AM -0500, Josh Cartwright wrote:
> On Tue, Mar 26, 2013 at 10:11:24AM +0100, Steffen Trumtrar wrote:
> > This adds support for the clocktree on zynq7000 SoCs.
> > The patch is based on clocks.c from the larger patch
> > ARM: zynq: add suppport for Zynq 7000 SoC
> > by Josh Cartwright.
> > 
> > The driver in that patch is converted to a platform_driver and code to
> > enable plls was added.
> > 
> > Signed-off-by: Steffen Trumtrar 
> 
> Reviewed-off-by: Josh Cartwright 

Heh, clearly I meant Reviewed-by: .  I should stop reading my email
before my morning coffee. :)

   Josh

___
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox


Re: [PATCH v2 3/5] ARM: zynq: add clk support for zynq7000

2013-03-26 Thread Josh Cartwright
On Tue, Mar 26, 2013 at 10:11:24AM +0100, Steffen Trumtrar wrote:
> This adds support for the clocktree on zynq7000 SoCs.
> The patch is based on clocks.c from the larger patch
>   ARM: zynq: add suppport for Zynq 7000 SoC
> by Josh Cartwright.
> 
> The driver in that patch is converted to a platform_driver and code to
> enable plls was added.
> 
> Signed-off-by: Steffen Trumtrar 

Reviewed-off-by: Josh Cartwright 

> ---
>  arch/arm/mach-zynq/clk-zynq7000.c| 417 
> +++
>  arch/arm/mach-zynq/include/mach/clkdev.h |   6 +
>  2 files changed, 423 insertions(+)
>  create mode 100644 arch/arm/mach-zynq/clk-zynq7000.c
>  create mode 100644 arch/arm/mach-zynq/include/mach/clkdev.h
> 
[..]
> diff --git a/arch/arm/mach-zynq/include/mach/clkdev.h 
> b/arch/arm/mach-zynq/include/mach/clkdev.h
> new file mode 100644
> index 000..31f7035
> --- /dev/null
> +++ b/arch/arm/mach-zynq/include/mach/clkdev.h
> @@ -0,0 +1,6 @@
> +#ifndef __ASM_MACH_CLKDEV_H
> +#define __ASM_MACH_CLKDEV_H
> +
> +#define __clk_get(clk) ({ 1; })
> +#define __clk_put(clk) do { } while (0)
> +#endif

I saw Sascha posted a patch removing these, so depending on when this
lands this may need cleaned up.

   Josh

___
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox


[PATCH v2 3/5] ARM: zynq: add clk support for zynq7000

2013-03-26 Thread Steffen Trumtrar
This adds support for the clocktree on zynq7000 SoCs.
The patch is based on clocks.c from the larger patch
ARM: zynq: add suppport for Zynq 7000 SoC
by Josh Cartwright.

The driver in that patch is converted to a platform_driver and code to
enable plls was added.

Signed-off-by: Steffen Trumtrar 
---
 arch/arm/mach-zynq/clk-zynq7000.c| 417 +++
 arch/arm/mach-zynq/include/mach/clkdev.h |   6 +
 2 files changed, 423 insertions(+)
 create mode 100644 arch/arm/mach-zynq/clk-zynq7000.c
 create mode 100644 arch/arm/mach-zynq/include/mach/clkdev.h

diff --git a/arch/arm/mach-zynq/clk-zynq7000.c 
b/arch/arm/mach-zynq/clk-zynq7000.c
new file mode 100644
index 000..1e03514
--- /dev/null
+++ b/arch/arm/mach-zynq/clk-zynq7000.c
@@ -0,0 +1,417 @@
+/*
+ * Copyright (c) 2013 Josh Cartwright 
+ * Copyright (c) 2013 Steffen Trumtrar 
+ *
+ * Based on drivers/clk-zynq.c from Linux.
+ *
+ * Copyright (c) 2012 National Instruments
+ *
+ * Josh Cartwright 
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see .
+ */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+enum zynq_clks {
+   dummy, ps_clk, arm_pll, ddr_pll, io_pll, uart_clk, uart0, uart1,
+   cpu_clk, cpu_6x4x, cpu_3x2x, cpu_2x, cpu_1x, clks_max
+};
+
+enum zynq_pll_type {
+   ZYNQ_PLL_ARM,
+   ZYNQ_PLL_DDR,
+   ZYNQ_PLL_IO,
+};
+
+#define PLL_STATUS_ARM_PLL_LOCK(1 << 0)
+#define PLL_STATUS_DDR_PLL_LOCK(1 << 1)
+#define PLL_STATUS_IO_PLL_LOCK (1 << 2)
+#define PLL_STATUS_ARM_PLL_STABLE  (1 << 0)
+#define PLL_STATUS_DDR_PLL_STABLE  (1 << 1)
+#define PLL_STATUS_IO_PLL_STABLE   (1 << 2)
+#define PLL_CTRL_BYPASS_FORCE  (1 << 4)
+
+static struct clk *clks[clks_max];
+
+struct zynq_pll_clk {
+   struct clk  clk;
+   u32 pll_lock;
+   void __iomem*pll_ctrl;
+};
+
+#define to_zynq_pll_clk(c) container_of(c, struct zynq_pll_clk, clk)
+
+#define PLL_CTRL_FDIV(x)   (((x) >> 12) & 0x7F)
+
+static unsigned long zynq_pll_recalc_rate(struct clk *clk,
+ unsigned long parent_rate)
+{
+   struct zynq_pll_clk *pll = to_zynq_pll_clk(clk);
+   return parent_rate * PLL_CTRL_FDIV(readl(pll->pll_ctrl));
+}
+
+static int zynq_pll_enable(struct clk *clk)
+{
+   struct zynq_pll_clk *pll = to_zynq_pll_clk(clk);
+   u32 val;
+   int timeout = 1;
+
+   val = readl(pll->pll_ctrl);
+   val &= ~PLL_CTRL_BYPASS_FORCE;
+   writel(val, pll->pll_ctrl);
+
+   while (timeout--) {
+   if (readl(ZYNQ_CLOCK_CTRL_BASE + ZYNQ_PLL_STATUS) & 
pll->pll_lock)
+   break;
+   }
+
+   if (!timeout)
+   return -ETIMEDOUT;
+
+   return 0;
+}
+
+static struct clk_ops zynq_pll_clk_ops = {
+   .recalc_rate = zynq_pll_recalc_rate,
+   .enable = zynq_pll_enable,
+};
+
+static inline struct clk *zynq_pll_clk(enum zynq_pll_type type,
+  const char *name,
+  void __iomem *pll_ctrl)
+{
+   static const char *pll_parent = "ps_clk";
+   struct zynq_pll_clk *pll;
+   int ret;
+
+   pll = xzalloc(sizeof(*pll));
+   pll->pll_ctrl   = pll_ctrl;
+   pll->clk.ops= &zynq_pll_clk_ops;
+   pll->clk.name   = name;
+   pll->clk.parent_names   = &pll_parent;
+   pll->clk.num_parents= 1;
+
+   switch(type) {
+   case ZYNQ_PLL_ARM:
+   pll->pll_lock = PLL_STATUS_ARM_PLL_LOCK;
+   break;
+   case ZYNQ_PLL_DDR:
+   pll->pll_lock = PLL_STATUS_DDR_PLL_LOCK;
+   break;
+   case ZYNQ_PLL_IO:
+   pll->pll_lock = PLL_STATUS_IO_PLL_LOCK;
+   break;
+   }
+
+   ret = clk_register(&pll->clk);
+   if (ret) {
+   free(pll);
+   return ERR_PTR(ret);
+   }
+
+   return &pll->clk;
+}
+
+struct zynq_periph_clk {
+   struct clk  clk;
+   void __iomem*clk_ctrl;
+};
+
+#define to_zynq_periph_clk(c)  container_of(c, struct zynq_periph_clk, c)
+
+static const u8 periph_clk_parent_map[] = {
+   0, 0, 1, 2
+};
+#define PERIPH_CLK_CTRL_SRC(x) (periph_clk_parent_map[((x) & 0x30) >> 4])
+#define PERIPH_CLK_CTRL_DIV(x) (((x) & 0x3F00) >> 8)
+
+static unsigned long zynq_periph_recalc_rate(struct c

[PATCH v2 3/5] ARM: zynq: add clk support for zynq7000

2013-03-25 Thread Steffen Trumtrar
This adds support for the clocktree on zynq7000 SoCs.
The patch is based on clocks.c from the larger patch
ARM: zynq: add suppport for Zynq 7000 SoC
by Josh Cartwright.

The driver in that patch is converted to a platform_driver and code to
enable plls was added.

Signed-off-by: Steffen Trumtrar 
---
 arch/arm/mach-zynq/clk-zynq7000.c| 417 +++
 arch/arm/mach-zynq/include/mach/clkdev.h |   6 +
 2 files changed, 423 insertions(+)
 create mode 100644 arch/arm/mach-zynq/clk-zynq7000.c
 create mode 100644 arch/arm/mach-zynq/include/mach/clkdev.h

diff --git a/arch/arm/mach-zynq/clk-zynq7000.c 
b/arch/arm/mach-zynq/clk-zynq7000.c
new file mode 100644
index 000..1e03514
--- /dev/null
+++ b/arch/arm/mach-zynq/clk-zynq7000.c
@@ -0,0 +1,417 @@
+/*
+ * Copyright (c) 2013 Josh Cartwright 
+ * Copyright (c) 2013 Steffen Trumtrar 
+ *
+ * Based on drivers/clk-zynq.c from Linux.
+ *
+ * Copyright (c) 2012 National Instruments
+ *
+ * Josh Cartwright 
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see .
+ */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+enum zynq_clks {
+   dummy, ps_clk, arm_pll, ddr_pll, io_pll, uart_clk, uart0, uart1,
+   cpu_clk, cpu_6x4x, cpu_3x2x, cpu_2x, cpu_1x, clks_max
+};
+
+enum zynq_pll_type {
+   ZYNQ_PLL_ARM,
+   ZYNQ_PLL_DDR,
+   ZYNQ_PLL_IO,
+};
+
+#define PLL_STATUS_ARM_PLL_LOCK(1 << 0)
+#define PLL_STATUS_DDR_PLL_LOCK(1 << 1)
+#define PLL_STATUS_IO_PLL_LOCK (1 << 2)
+#define PLL_STATUS_ARM_PLL_STABLE  (1 << 0)
+#define PLL_STATUS_DDR_PLL_STABLE  (1 << 1)
+#define PLL_STATUS_IO_PLL_STABLE   (1 << 2)
+#define PLL_CTRL_BYPASS_FORCE  (1 << 4)
+
+static struct clk *clks[clks_max];
+
+struct zynq_pll_clk {
+   struct clk  clk;
+   u32 pll_lock;
+   void __iomem*pll_ctrl;
+};
+
+#define to_zynq_pll_clk(c) container_of(c, struct zynq_pll_clk, clk)
+
+#define PLL_CTRL_FDIV(x)   (((x) >> 12) & 0x7F)
+
+static unsigned long zynq_pll_recalc_rate(struct clk *clk,
+ unsigned long parent_rate)
+{
+   struct zynq_pll_clk *pll = to_zynq_pll_clk(clk);
+   return parent_rate * PLL_CTRL_FDIV(readl(pll->pll_ctrl));
+}
+
+static int zynq_pll_enable(struct clk *clk)
+{
+   struct zynq_pll_clk *pll = to_zynq_pll_clk(clk);
+   u32 val;
+   int timeout = 1;
+
+   val = readl(pll->pll_ctrl);
+   val &= ~PLL_CTRL_BYPASS_FORCE;
+   writel(val, pll->pll_ctrl);
+
+   while (timeout--) {
+   if (readl(ZYNQ_CLOCK_CTRL_BASE + ZYNQ_PLL_STATUS) & 
pll->pll_lock)
+   break;
+   }
+
+   if (!timeout)
+   return -ETIMEDOUT;
+
+   return 0;
+}
+
+static struct clk_ops zynq_pll_clk_ops = {
+   .recalc_rate = zynq_pll_recalc_rate,
+   .enable = zynq_pll_enable,
+};
+
+static inline struct clk *zynq_pll_clk(enum zynq_pll_type type,
+  const char *name,
+  void __iomem *pll_ctrl)
+{
+   static const char *pll_parent = "ps_clk";
+   struct zynq_pll_clk *pll;
+   int ret;
+
+   pll = xzalloc(sizeof(*pll));
+   pll->pll_ctrl   = pll_ctrl;
+   pll->clk.ops= &zynq_pll_clk_ops;
+   pll->clk.name   = name;
+   pll->clk.parent_names   = &pll_parent;
+   pll->clk.num_parents= 1;
+
+   switch(type) {
+   case ZYNQ_PLL_ARM:
+   pll->pll_lock = PLL_STATUS_ARM_PLL_LOCK;
+   break;
+   case ZYNQ_PLL_DDR:
+   pll->pll_lock = PLL_STATUS_DDR_PLL_LOCK;
+   break;
+   case ZYNQ_PLL_IO:
+   pll->pll_lock = PLL_STATUS_IO_PLL_LOCK;
+   break;
+   }
+
+   ret = clk_register(&pll->clk);
+   if (ret) {
+   free(pll);
+   return ERR_PTR(ret);
+   }
+
+   return &pll->clk;
+}
+
+struct zynq_periph_clk {
+   struct clk  clk;
+   void __iomem*clk_ctrl;
+};
+
+#define to_zynq_periph_clk(c)  container_of(c, struct zynq_periph_clk, c)
+
+static const u8 periph_clk_parent_map[] = {
+   0, 0, 1, 2
+};
+#define PERIPH_CLK_CTRL_SRC(x) (periph_clk_parent_map[((x) & 0x30) >> 4])
+#define PERIPH_CLK_CTRL_DIV(x) (((x) & 0x3F00) >> 8)
+
+static unsigned long zynq_periph_recalc_rate(struct c

Re: [PATCH v2 3/5] ARM: zynq: add clk support for zynq7000

2013-03-19 Thread Josh Cartwright
On Tue, Mar 19, 2013 at 02:35:33PM +0100, Steffen Trumtrar wrote:
> On Tue, Mar 19, 2013 at 08:29:54AM -0500, Josh Cartwright wrote:
> > On Tue, Mar 19, 2013 at 10:21:58AM +0100, Steffen Trumtrar wrote:
> > > This adds support for the clocktree on zynq7000 SoCs.
> > > The patch is based on clocks.c from the larger patch
> > >   ARM: zynq: add suppport for Zynq 7000 SoC
> > > by Josh Cartwright.
> > > 
> > > The driver in that patch is converted to a platform_driver and code to
> > > enable plls was added.
> > > 
> > > Signed-off-by: Steffen Trumtrar 
> > > ---
> > [..]
> > > +
> > > +static int zynq_clock_probe(struct device_d *dev)
> > > +{
> > > + void __iomem *slcr_base;
> > > + unsigned long ps_clk_rate = 3330;
> > 
> > My version of the patchset had this ^ configurable, since it's possible
> > a different osc could be used on the board.  Any reason why you've
> > hardcoded this instead?
> > 
> 
> Hm, not really any good reason. But the plan is to get this from the
> devicetree instead. I didn't get around to actually doing that.
> Do your boards have another osc or would a hardcoded value suffice for
> the moment?

I agree that we should be leveraging the device tree here, so maybe it's
worth dropping until we get sorted out.  I'm fine with a hardcoded value
for now.

   Josh

___
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox


Re: [PATCH v2 3/5] ARM: zynq: add clk support for zynq7000

2013-03-19 Thread Steffen Trumtrar
On Tue, Mar 19, 2013 at 08:29:54AM -0500, Josh Cartwright wrote:
> On Tue, Mar 19, 2013 at 10:21:58AM +0100, Steffen Trumtrar wrote:
> > This adds support for the clocktree on zynq7000 SoCs.
> > The patch is based on clocks.c from the larger patch
> > ARM: zynq: add suppport for Zynq 7000 SoC
> > by Josh Cartwright.
> > 
> > The driver in that patch is converted to a platform_driver and code to
> > enable plls was added.
> > 
> > Signed-off-by: Steffen Trumtrar 
> > ---
> [..]
> > +
> > +static int zynq_clock_probe(struct device_d *dev)
> > +{
> > +   void __iomem *slcr_base;
> > +   unsigned long ps_clk_rate = 3330;
> 
> My version of the patchset had this ^ configurable, since it's possible
> a different osc could be used on the board.  Any reason why you've
> hardcoded this instead?
> 

Hm, not really any good reason. But the plan is to get this from the
devicetree instead. I didn't get around to actually doing that.
Do your boards have another osc or would a hardcoded value suffice for
the moment?

str

-- 
Pengutronix e.K.   | |
Industrial Linux Solutions | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0|
Amtsgericht Hildesheim, HRA 2686   | Fax:   +49-5121-206917- |

___
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox


Re: [PATCH v2 3/5] ARM: zynq: add clk support for zynq7000

2013-03-19 Thread Josh Cartwright
On Tue, Mar 19, 2013 at 10:21:58AM +0100, Steffen Trumtrar wrote:
> This adds support for the clocktree on zynq7000 SoCs.
> The patch is based on clocks.c from the larger patch
>   ARM: zynq: add suppport for Zynq 7000 SoC
> by Josh Cartwright.
> 
> The driver in that patch is converted to a platform_driver and code to
> enable plls was added.
> 
> Signed-off-by: Steffen Trumtrar 
> ---
[..]
> +
> +static int zynq_clock_probe(struct device_d *dev)
> +{
> + void __iomem *slcr_base;
> + unsigned long ps_clk_rate = 3330;

My version of the patchset had this ^ configurable, since it's possible
a different osc could be used on the board.  Any reason why you've
hardcoded this instead?

   Josh

___
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox


[PATCH v2 3/5] ARM: zynq: add clk support for zynq7000

2013-03-19 Thread Steffen Trumtrar
This adds support for the clocktree on zynq7000 SoCs.
The patch is based on clocks.c from the larger patch
ARM: zynq: add suppport for Zynq 7000 SoC
by Josh Cartwright.

The driver in that patch is converted to a platform_driver and code to
enable plls was added.

Signed-off-by: Steffen Trumtrar 
---
 arch/arm/mach-zynq/clk-zynq7000.c| 417 +++
 arch/arm/mach-zynq/include/mach/clkdev.h |   6 +
 2 files changed, 423 insertions(+)
 create mode 100644 arch/arm/mach-zynq/clk-zynq7000.c
 create mode 100644 arch/arm/mach-zynq/include/mach/clkdev.h

diff --git a/arch/arm/mach-zynq/clk-zynq7000.c 
b/arch/arm/mach-zynq/clk-zynq7000.c
new file mode 100644
index 000..1e03514
--- /dev/null
+++ b/arch/arm/mach-zynq/clk-zynq7000.c
@@ -0,0 +1,417 @@
+/*
+ * Copyright (c) 2013 Josh Cartwright 
+ * Copyright (c) 2013 Steffen Trumtrar 
+ *
+ * Based on drivers/clk-zynq.c from Linux.
+ *
+ * Copyright (c) 2012 National Instruments
+ *
+ * Josh Cartwright 
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see .
+ */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+enum zynq_clks {
+   dummy, ps_clk, arm_pll, ddr_pll, io_pll, uart_clk, uart0, uart1,
+   cpu_clk, cpu_6x4x, cpu_3x2x, cpu_2x, cpu_1x, clks_max
+};
+
+enum zynq_pll_type {
+   ZYNQ_PLL_ARM,
+   ZYNQ_PLL_DDR,
+   ZYNQ_PLL_IO,
+};
+
+#define PLL_STATUS_ARM_PLL_LOCK(1 << 0)
+#define PLL_STATUS_DDR_PLL_LOCK(1 << 1)
+#define PLL_STATUS_IO_PLL_LOCK (1 << 2)
+#define PLL_STATUS_ARM_PLL_STABLE  (1 << 0)
+#define PLL_STATUS_DDR_PLL_STABLE  (1 << 1)
+#define PLL_STATUS_IO_PLL_STABLE   (1 << 2)
+#define PLL_CTRL_BYPASS_FORCE  (1 << 4)
+
+static struct clk *clks[clks_max];
+
+struct zynq_pll_clk {
+   struct clk  clk;
+   u32 pll_lock;
+   void __iomem*pll_ctrl;
+};
+
+#define to_zynq_pll_clk(c) container_of(c, struct zynq_pll_clk, clk)
+
+#define PLL_CTRL_FDIV(x)   (((x) >> 12) & 0x7F)
+
+static unsigned long zynq_pll_recalc_rate(struct clk *clk,
+ unsigned long parent_rate)
+{
+   struct zynq_pll_clk *pll = to_zynq_pll_clk(clk);
+   return parent_rate * PLL_CTRL_FDIV(readl(pll->pll_ctrl));
+}
+
+static int zynq_pll_enable(struct clk *clk)
+{
+   struct zynq_pll_clk *pll = to_zynq_pll_clk(clk);
+   u32 val;
+   int timeout = 1;
+
+   val = readl(pll->pll_ctrl);
+   val &= ~PLL_CTRL_BYPASS_FORCE;
+   writel(val, pll->pll_ctrl);
+
+   while (timeout--) {
+   if (readl(ZYNQ_CLOCK_CTRL_BASE + ZYNQ_PLL_STATUS) & 
pll->pll_lock)
+   break;
+   }
+
+   if (!timeout)
+   return -ETIMEDOUT;
+
+   return 0;
+}
+
+static struct clk_ops zynq_pll_clk_ops = {
+   .recalc_rate = zynq_pll_recalc_rate,
+   .enable = zynq_pll_enable,
+};
+
+static inline struct clk *zynq_pll_clk(enum zynq_pll_type type,
+  const char *name,
+  void __iomem *pll_ctrl)
+{
+   static const char *pll_parent = "ps_clk";
+   struct zynq_pll_clk *pll;
+   int ret;
+
+   pll = xzalloc(sizeof(*pll));
+   pll->pll_ctrl   = pll_ctrl;
+   pll->clk.ops= &zynq_pll_clk_ops;
+   pll->clk.name   = name;
+   pll->clk.parent_names   = &pll_parent;
+   pll->clk.num_parents= 1;
+
+   switch(type) {
+   case ZYNQ_PLL_ARM:
+   pll->pll_lock = PLL_STATUS_ARM_PLL_LOCK;
+   break;
+   case ZYNQ_PLL_DDR:
+   pll->pll_lock = PLL_STATUS_DDR_PLL_LOCK;
+   break;
+   case ZYNQ_PLL_IO:
+   pll->pll_lock = PLL_STATUS_IO_PLL_LOCK;
+   break;
+   }
+
+   ret = clk_register(&pll->clk);
+   if (ret) {
+   free(pll);
+   return ERR_PTR(ret);
+   }
+
+   return &pll->clk;
+}
+
+struct zynq_periph_clk {
+   struct clk  clk;
+   void __iomem*clk_ctrl;
+};
+
+#define to_zynq_periph_clk(c)  container_of(c, struct zynq_periph_clk, c)
+
+static const u8 periph_clk_parent_map[] = {
+   0, 0, 1, 2
+};
+#define PERIPH_CLK_CTRL_SRC(x) (periph_clk_parent_map[((x) & 0x30) >> 4])
+#define PERIPH_CLK_CTRL_DIV(x) (((x) & 0x3F00) >> 8)
+
+static unsigned long zynq_periph_recalc_rate(struct c