uboot/arch/arm/cpu/armv7/bcm281xx/clk-eth.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright 2014 Broadcom Corporation.
   4 */
   5
   6#include <common.h>
   7#include <asm/io.h>
   8#include <linux/delay.h>
   9#include <linux/errno.h>
  10#include <asm/arch/sysmap.h>
  11#include <asm/kona-common/clk.h>
  12#include "clk-core.h"
  13
  14#define WR_ACCESS_ADDR                  ESUB_CLK_BASE_ADDR
  15#define WR_ACCESS_PASSWORD                              0xA5A500
  16
  17#define PLLE_POST_RESETB_ADDR           (ESUB_CLK_BASE_ADDR + 0x00000C00)
  18
  19#define PLLE_RESETB_ADDR                (ESUB_CLK_BASE_ADDR + 0x00000C58)
  20#define PLLE_RESETB_I_PLL_RESETB_PLLE_MASK              0x00010000
  21#define PLLE_POST_RESETB_I_POST_RESETB_PLLE_MASK        0x00000001
  22
  23#define PLL_LOCK_ADDR                   (ESUB_CLK_BASE_ADDR + 0x00000C38)
  24#define PLL_LOCK_PLL_LOCK_PLLE_MASK                     0x00000001
  25
  26#define ESW_SYS_DIV_ADDR                (ESUB_CLK_BASE_ADDR + 0x00000A04)
  27#define ESW_SYS_DIV_PLL_SELECT_MASK                     0x00000300
  28#define ESW_SYS_DIV_DIV_MASK                            0x0000001C
  29#define ESW_SYS_DIV_PLL_VAR_208M_CLK_SELECT             0x00000100
  30#define ESW_SYS_DIV_DIV_SELECT                          0x4
  31#define ESW_SYS_DIV_TRIGGER_MASK                        0x00000001
  32
  33#define ESUB_AXI_DIV_DEBUG_ADDR         (ESUB_CLK_BASE_ADDR + 0x00000E04)
  34#define ESUB_AXI_DIV_DEBUG_PLL_SELECT_MASK              0x0000001C
  35#define ESUB_AXI_DIV_DEBUG_PLL_SELECT_OVERRIDE_MASK     0x00000040
  36#define ESUB_AXI_DIV_DEBUG_PLL_VAR_208M_CLK_SELECT      0x0
  37#define ESUB_AXI_DIV_DEBUG_TRIGGER_MASK                 0x00000001
  38
  39#define PLL_MAX_RETRY   100
  40
  41/* Enable appropriate clocks for Ethernet */
  42int clk_eth_enable(void)
  43{
  44        int rc = -1;
  45        int retry_count = 0;
  46        rc = clk_get_and_enable("esub_ccu_clk");
  47
  48        /* Enable Access to CCU registers */
  49        writel((1 | WR_ACCESS_PASSWORD), WR_ACCESS_ADDR);
  50
  51        writel(readl(PLLE_POST_RESETB_ADDR) &
  52               ~PLLE_POST_RESETB_I_POST_RESETB_PLLE_MASK,
  53               PLLE_POST_RESETB_ADDR);
  54
  55        /* Take PLL out of reset and put into normal mode */
  56        writel(readl(PLLE_RESETB_ADDR) | PLLE_RESETB_I_PLL_RESETB_PLLE_MASK,
  57               PLLE_RESETB_ADDR);
  58
  59        /* Wait for PLL lock */
  60        rc = -1;
  61        while (retry_count < PLL_MAX_RETRY) {
  62                udelay(100);
  63                if (readl(PLL_LOCK_ADDR) & PLL_LOCK_PLL_LOCK_PLLE_MASK) {
  64                        rc = 0;
  65                        break;
  66                }
  67                retry_count++;
  68        }
  69
  70        if (rc == -1) {
  71                printf("%s: ETH-PLL lock timeout, Ethernet is not enabled!\n",
  72                       __func__);
  73                return -1;
  74        }
  75
  76        writel(readl(PLLE_POST_RESETB_ADDR) |
  77               PLLE_POST_RESETB_I_POST_RESETB_PLLE_MASK,
  78               PLLE_POST_RESETB_ADDR);
  79
  80        /* Switch esw_sys_clk to use 104MHz(208MHz/2) clock */
  81        writel((readl(ESW_SYS_DIV_ADDR) &
  82                ~(ESW_SYS_DIV_PLL_SELECT_MASK | ESW_SYS_DIV_DIV_MASK)) |
  83               ESW_SYS_DIV_PLL_VAR_208M_CLK_SELECT | ESW_SYS_DIV_DIV_SELECT,
  84               ESW_SYS_DIV_ADDR);
  85
  86        writel(readl(ESW_SYS_DIV_ADDR) | ESW_SYS_DIV_TRIGGER_MASK,
  87               ESW_SYS_DIV_ADDR);
  88
  89        /* Wait for trigger complete */
  90        rc = -1;
  91        retry_count = 0;
  92        while (retry_count < PLL_MAX_RETRY) {
  93                udelay(100);
  94                if (!(readl(ESW_SYS_DIV_ADDR) & ESW_SYS_DIV_TRIGGER_MASK)) {
  95                        rc = 0;
  96                        break;
  97                }
  98                retry_count++;
  99        }
 100
 101        if (rc == -1) {
 102                printf("%s: SYS CLK Trigger timeout, Ethernet is not enabled!\n",
 103                       __func__);
 104                return -1;
 105        }
 106
 107        /* switch Esub AXI clock to 208MHz */
 108        writel((readl(ESUB_AXI_DIV_DEBUG_ADDR) &
 109                ~(ESUB_AXI_DIV_DEBUG_PLL_SELECT_MASK |
 110                  ESUB_AXI_DIV_DEBUG_PLL_SELECT_OVERRIDE_MASK |
 111                  ESUB_AXI_DIV_DEBUG_TRIGGER_MASK)) |
 112               ESUB_AXI_DIV_DEBUG_PLL_VAR_208M_CLK_SELECT |
 113               ESUB_AXI_DIV_DEBUG_PLL_SELECT_OVERRIDE_MASK,
 114               ESUB_AXI_DIV_DEBUG_ADDR);
 115
 116        writel(readl(ESUB_AXI_DIV_DEBUG_ADDR) |
 117               ESUB_AXI_DIV_DEBUG_TRIGGER_MASK,
 118               ESUB_AXI_DIV_DEBUG_ADDR);
 119
 120        /* Wait for trigger complete */
 121        rc = -1;
 122        retry_count = 0;
 123        while (retry_count < PLL_MAX_RETRY) {
 124                udelay(100);
 125                if (!(readl(ESUB_AXI_DIV_DEBUG_ADDR) &
 126                      ESUB_AXI_DIV_DEBUG_TRIGGER_MASK)) {
 127                        rc = 0;
 128                        break;
 129                }
 130                retry_count++;
 131        }
 132
 133        if (rc == -1) {
 134                printf("%s: AXI CLK Trigger timeout, Ethernet is not enabled!\n",
 135                       __func__);
 136                return -1;
 137        }
 138
 139        /* Disable Access to CCU registers */
 140        writel(WR_ACCESS_PASSWORD, WR_ACCESS_ADDR);
 141
 142        return rc;
 143}
 144