net: zynq_gem: Calculate clock dividers dynamically
authorSoren Brinkmann <soren.brinkmann@xilinx.com>
Thu, 21 Nov 2013 21:39:01 +0000 (13:39 -0800)
committerMichal Simek <michal.simek@xilinx.com>
Wed, 19 Feb 2014 08:41:21 +0000 (09:41 +0100)
Remove hard coded clock divider setting and use the Zynq clock framework
to dynamically calculate appropriate dividers at run time.

Signed-off-by: Soren Brinkmann <soren.brinkmann@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
arch/arm/cpu/armv7/zynq/slcr.c
arch/arm/include/asm/arch-zynq/sys_proto.h
drivers/net/zynq_gem.c

index 6710d92c3441a651ab0f968f435628c745666c65..d7c18823322048f7c74764ab528a04a6c34b5c73 100644 (file)
@@ -8,6 +8,7 @@
 #include <asm/io.h>
 #include <malloc.h>
 #include <asm/arch/hardware.h>
+#include <asm/arch/clk.h>
 
 #define SLCR_LOCK_MAGIC                0x767B
 #define SLCR_UNLOCK_MAGIC      0xDF0D
@@ -50,8 +51,10 @@ void zynq_slcr_cpu_reset(void)
 }
 
 /* Setup clk for network */
-void zynq_slcr_gem_clk_setup(u32 gem_id, u32 clk)
+void zynq_slcr_gem_clk_setup(u32 gem_id, unsigned long clk_rate)
 {
+       int ret;
+
        zynq_slcr_unlock();
 
        if (gem_id > 1) {
@@ -59,14 +62,14 @@ void zynq_slcr_gem_clk_setup(u32 gem_id, u32 clk)
                goto out;
        }
 
+       ret = zynq_clk_set_rate(gem0_clk + gem_id, clk_rate);
+       if (ret)
+               goto out;
+
        if (gem_id) {
-               /* Set divisors for appropriate frequency in GEM_CLK_CTRL */
-               writel(clk, &slcr_base->gem1_clk_ctrl);
                /* Configure GEM_RCLK_CTRL */
                writel(1, &slcr_base->gem1_rclk_ctrl);
        } else {
-               /* Set divisors for appropriate frequency in GEM_CLK_CTRL */
-               writel(clk, &slcr_base->gem0_clk_ctrl);
                /* Configure GEM_RCLK_CTRL */
                writel(1, &slcr_base->gem0_rclk_ctrl);
        }
index a485d790a32795b2c834a2b8b7c668bbb30fba65..0a2ba058f26da77b8953ca63969d7c05eb5916c2 100644 (file)
@@ -10,7 +10,7 @@
 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, u32 clk);
+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);
index 2eb9e7d1ef39acdacff63e4a5778df37aa0f8819..6d4001b01736bd340f8059925fecd4410b53d445 100644 (file)
 #define ZYNQ_GEM_TXBUF_EXHAUSTED       0x08000000
 #define ZYNQ_GEM_TXBUF_UNDERRUN                0x10000000
 
+/* Clock frequencies for different speeds */
+#define ZYNQ_GEM_FREQUENCY_10  2500000UL
+#define ZYNQ_GEM_FREQUENCY_100 25000000UL
+#define ZYNQ_GEM_FREQUENCY_1000        125000000UL
+
 /* Device registers */
 struct zynq_gem_regs {
        u32 nwctrl; /* Network Control reg */
@@ -270,7 +275,8 @@ static int zynq_gem_setup_mac(struct eth_device *dev)
 
 static int zynq_gem_init(struct eth_device *dev, bd_t * bis)
 {
-       u32 i, clk = 0;
+       u32 i;
+       unsigned long clk_rate = 0;
        struct phy_device *phydev;
        const u32 stat_size = (sizeof(struct zynq_gem_regs) -
                                offsetof(struct zynq_gem_regs, stat)) / 4;
@@ -348,23 +354,22 @@ static int zynq_gem_init(struct eth_device *dev, bd_t * bis)
        case SPEED_1000:
                writel(ZYNQ_GEM_NWCFG_INIT | ZYNQ_GEM_NWCFG_SPEED1000,
                       &regs->nwcfg);
-               clk = (1 << 20) | (8 << 8) | (0 << 4) | (1 << 0);
+               clk_rate = ZYNQ_GEM_FREQUENCY_1000;
                break;
        case SPEED_100:
                clrsetbits_le32(&regs->nwcfg, ZYNQ_GEM_NWCFG_SPEED1000,
                                ZYNQ_GEM_NWCFG_INIT | ZYNQ_GEM_NWCFG_SPEED100);
-               clk = (5 << 20) | (8 << 8) | (0 << 4) | (1 << 0);
+               clk_rate = ZYNQ_GEM_FREQUENCY_100;
                break;
        case SPEED_10:
-               /* FIXME untested */
-               clk = (5 << 20) | (8 << 8) | (0 << 4) | (1 << 0);
+               clk_rate = ZYNQ_GEM_FREQUENCY_10;
                break;
        }
 
        /* Change the rclk and clk only not using EMIO interface */
        if (!priv->emio)
                zynq_slcr_gem_clk_setup(dev->iobase !=
-                                       ZYNQ_GEM_BASEADDR0, clk);
+                                       ZYNQ_GEM_BASEADDR0, clk_rate);
 
        setbits_le32(&regs->nwctrl, ZYNQ_GEM_NWCTRL_RXEN_MASK |
                                        ZYNQ_GEM_NWCTRL_TXEN_MASK);