arm: bcm281xx: Add Ethernet Clock support
authorJiandong Zheng <jdzheng@broadcom.com>
Sat, 2 Aug 2014 03:37:15 +0000 (20:37 -0700)
committerTom Rini <trini@ti.com>
Sat, 30 Aug 2014 11:46:39 +0000 (07:46 -0400)
Enable Ethernet clock when Broadcom StarFighter2 Ethernet block
(CONFIG_BCM_SF2_ETH) is enabled.

Signed-off-by: Jiandong Zheng <jdzheng@broadcom.com>
Signed-off-by: Steve Rae <srae@broadcom.com>
arch/arm/cpu/armv7/bcm281xx/Makefile
arch/arm/cpu/armv7/bcm281xx/clk-bcm281xx.c
arch/arm/cpu/armv7/bcm281xx/clk-eth.c [new file with mode: 0644]
arch/arm/include/asm/arch-bcm281xx/sysmap.h

index 98f5aa59ca96cc0fe392167ea7d6a4dd2607ca5b..bd867a271802fa32ea00b0836b63949086b4ccd7 100644 (file)
@@ -9,3 +9,4 @@ obj-y   += clk-core.o
 obj-y  += clk-bcm281xx.o
 obj-y  += clk-sdio.o
 obj-y  += clk-bsc.o
+obj-$(CONFIG_BCM_SF2_ETH) += clk-eth.o
index bc8a170b407163b1a23c5b5107dcdc968d2798f8..d16b99fc23bc5ff36b9d291fe2e37813cedc4283 100644 (file)
@@ -118,6 +118,16 @@ unsigned long slave_apb_freq_tbl[8] = {
        78 * CLOCK_1M
 };
 
+unsigned long esub_freq_tbl[8] = {
+       78 * CLOCK_1M,
+       156 * CLOCK_1M,
+       156 * CLOCK_1M,
+       156 * CLOCK_1M,
+       208 * CLOCK_1M,
+       208 * CLOCK_1M,
+       208 * CLOCK_1M
+};
+
 static struct bus_clk_data bsc1_apb_data = {
        .gate = HW_SW_GATE_AUTO(0x0458, 16, 0, 1),
 };
@@ -295,6 +305,27 @@ static struct ccu_clock kps_ccu_clk = {
        .freq_tbl = slave_axi_freq_tbl,
 };
 
+#ifdef CONFIG_BCM_SF2_ETH
+static struct ccu_clock esub_ccu_clk = {
+       .clk = {
+               .name = "esub_ccu_clk",
+               .ops = &ccu_clk_ops,
+               .ccu_clk_mgr_base = ESUB_CLK_BASE_ADDR,
+       },
+       .num_policy_masks = 1,
+       .policy_freq_offset = 0x00000008,
+       .freq_bit_shift = 8,
+       .policy_ctl_offset = 0x0000000c,
+       .policy0_mask_offset = 0x00000010,
+       .policy1_mask_offset = 0x00000014,
+       .policy2_mask_offset = 0x00000018,
+       .policy3_mask_offset = 0x0000001c,
+       .lvm_en_offset = 0x00000034,
+       .freq_id = 2,
+       .freq_tbl = esub_freq_tbl,
+};
+#endif
+
 /*
  * Bus clocks
  */
@@ -517,6 +548,9 @@ struct clk_lookup arch_clk_tbl[] = {
        CLK_LK(bsc1_apb),
        CLK_LK(bsc2_apb),
        CLK_LK(bsc3_apb),
+#ifdef CONFIG_BCM_SF2_ETH
+       CLK_LK(esub_ccu),
+#endif
 };
 
 /* public array size */
diff --git a/arch/arm/cpu/armv7/bcm281xx/clk-eth.c b/arch/arm/cpu/armv7/bcm281xx/clk-eth.c
new file mode 100644 (file)
index 0000000..b0b92b9
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2014 Broadcom Corporation.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/errno.h>
+#include <asm/arch/sysmap.h>
+#include <asm/kona-common/clk.h>
+#include "clk-core.h"
+
+#define WR_ACCESS_ADDR                 ESUB_CLK_BASE_ADDR
+#define WR_ACCESS_PASSWORD                             0xA5A500
+
+#define PLLE_POST_RESETB_ADDR          (ESUB_CLK_BASE_ADDR + 0x00000C00)
+
+#define PLLE_RESETB_ADDR               (ESUB_CLK_BASE_ADDR + 0x00000C58)
+#define PLLE_RESETB_I_PLL_RESETB_PLLE_MASK             0x00010000
+#define PLLE_POST_RESETB_I_POST_RESETB_PLLE_MASK       0x00000001
+
+#define PLL_LOCK_ADDR                  (ESUB_CLK_BASE_ADDR + 0x00000C38)
+#define PLL_LOCK_PLL_LOCK_PLLE_MASK                    0x00000001
+
+#define ESW_SYS_DIV_ADDR               (ESUB_CLK_BASE_ADDR + 0x00000A04)
+#define ESW_SYS_DIV_PLL_SELECT_MASK                    0x00000300
+#define ESW_SYS_DIV_DIV_MASK                           0x0000001C
+#define ESW_SYS_DIV_PLL_VAR_208M_CLK_SELECT            0x00000100
+#define ESW_SYS_DIV_DIV_SELECT                         0x4
+#define ESW_SYS_DIV_TRIGGER_MASK                       0x00000001
+
+#define ESUB_AXI_DIV_DEBUG_ADDR                (ESUB_CLK_BASE_ADDR + 0x00000E04)
+#define ESUB_AXI_DIV_DEBUG_PLL_SELECT_MASK             0x0000001C
+#define ESUB_AXI_DIV_DEBUG_PLL_SELECT_OVERRIDE_MASK    0x00000040
+#define ESUB_AXI_DIV_DEBUG_PLL_VAR_208M_CLK_SELECT     0x0
+#define ESUB_AXI_DIV_DEBUG_TRIGGER_MASK                        0x00000001
+
+#define PLL_MAX_RETRY  100
+
+/* Enable appropriate clocks for Ethernet */
+int clk_eth_enable(void)
+{
+       int rc = -1;
+       int retry_count = 0;
+       rc = clk_get_and_enable("esub_ccu_clk");
+
+       /* Enable Access to CCU registers */
+       writel((1 | WR_ACCESS_PASSWORD), WR_ACCESS_ADDR);
+
+       writel(readl(PLLE_POST_RESETB_ADDR) &
+              ~PLLE_POST_RESETB_I_POST_RESETB_PLLE_MASK,
+              PLLE_POST_RESETB_ADDR);
+
+       /* Take PLL out of reset and put into normal mode */
+       writel(readl(PLLE_RESETB_ADDR) | PLLE_RESETB_I_PLL_RESETB_PLLE_MASK,
+              PLLE_RESETB_ADDR);
+
+       /* Wait for PLL lock */
+       rc = -1;
+       while (retry_count < PLL_MAX_RETRY) {
+               udelay(100);
+               if (readl(PLL_LOCK_ADDR) & PLL_LOCK_PLL_LOCK_PLLE_MASK) {
+                       rc = 0;
+                       break;
+               }
+               retry_count++;
+       }
+
+       if (rc == -1) {
+               printf("%s: ETH-PLL lock timeout, Ethernet is not enabled!\n",
+                      __func__);
+               return -1;
+       }
+
+       writel(readl(PLLE_POST_RESETB_ADDR) |
+              PLLE_POST_RESETB_I_POST_RESETB_PLLE_MASK,
+              PLLE_POST_RESETB_ADDR);
+
+       /* Switch esw_sys_clk to use 104MHz(208MHz/2) clock */
+       writel((readl(ESW_SYS_DIV_ADDR) &
+               ~(ESW_SYS_DIV_PLL_SELECT_MASK | ESW_SYS_DIV_DIV_MASK)) |
+              ESW_SYS_DIV_PLL_VAR_208M_CLK_SELECT | ESW_SYS_DIV_DIV_SELECT,
+              ESW_SYS_DIV_ADDR);
+
+       writel(readl(ESW_SYS_DIV_ADDR) | ESW_SYS_DIV_TRIGGER_MASK,
+              ESW_SYS_DIV_ADDR);
+
+       /* Wait for trigger complete */
+       rc = -1;
+       retry_count = 0;
+       while (retry_count < PLL_MAX_RETRY) {
+               udelay(100);
+               if (!(readl(ESW_SYS_DIV_ADDR) & ESW_SYS_DIV_TRIGGER_MASK)) {
+                       rc = 0;
+                       break;
+               }
+               retry_count++;
+       }
+
+       if (rc == -1) {
+               printf("%s: SYS CLK Trigger timeout, Ethernet is not enabled!\n",
+                      __func__);
+               return -1;
+       }
+
+       /* switch Esub AXI clock to 208MHz */
+       writel((readl(ESUB_AXI_DIV_DEBUG_ADDR) &
+               ~(ESUB_AXI_DIV_DEBUG_PLL_SELECT_MASK |
+                 ESUB_AXI_DIV_DEBUG_PLL_SELECT_OVERRIDE_MASK |
+                 ESUB_AXI_DIV_DEBUG_TRIGGER_MASK)) |
+              ESUB_AXI_DIV_DEBUG_PLL_VAR_208M_CLK_SELECT |
+              ESUB_AXI_DIV_DEBUG_PLL_SELECT_OVERRIDE_MASK,
+              ESUB_AXI_DIV_DEBUG_ADDR);
+
+       writel(readl(ESUB_AXI_DIV_DEBUG_ADDR) |
+              ESUB_AXI_DIV_DEBUG_TRIGGER_MASK,
+              ESUB_AXI_DIV_DEBUG_ADDR);
+
+       /* Wait for trigger complete */
+       rc = -1;
+       retry_count = 0;
+       while (retry_count < PLL_MAX_RETRY) {
+               udelay(100);
+               if (!(readl(ESUB_AXI_DIV_DEBUG_ADDR) &
+                     ESUB_AXI_DIV_DEBUG_TRIGGER_MASK)) {
+                       rc = 0;
+                       break;
+               }
+               retry_count++;
+       }
+
+       if (rc == -1) {
+               printf("%s: AXI CLK Trigger timeout, Ethernet is not enabled!\n",
+                      __func__);
+               return -1;
+       }
+
+       /* Disable Access to CCU registers */
+       writel(WR_ACCESS_PASSWORD, WR_ACCESS_ADDR);
+
+       return rc;
+}
index 880b4e090732f5c0456e9b80806e36943ecc31a9..350e7f6b723059644e1b559db76ab1a4f485a426 100644 (file)
@@ -9,6 +9,9 @@
 #define BSC1_BASE_ADDR         0x3e016000
 #define BSC2_BASE_ADDR         0x3e017000
 #define BSC3_BASE_ADDR         0x3e018000
+#define DWDMA_AHB_BASE_ADDR    0x38100000
+#define ESUB_CLK_BASE_ADDR     0x38000000
+#define ESW_CONTRL_BASE_ADDR   0x38200000
 #define GPIO2_BASE_ADDR                0x35003000
 #define KONA_MST_CLK_BASE_ADDR 0x3f001000
 #define KONA_SLV_CLK_BASE_ADDR 0x3e011000