uboot/arch/mips/mach-ath79/qca953x/clk.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2015-2016 Wills Wang <wills.wang@live.com>
   3 *
   4 * SPDX-License-Identifier: GPL-2.0+
   5 */
   6
   7#include <common.h>
   8#include <asm/io.h>
   9#include <asm/addrspace.h>
  10#include <asm/types.h>
  11#include <mach/ar71xx_regs.h>
  12#include <mach/ath79.h>
  13
  14DECLARE_GLOBAL_DATA_PTR;
  15
  16static u32 qca953x_get_xtal(void)
  17{
  18        u32 val;
  19
  20        val = ath79_get_bootstrap();
  21        if (val & QCA953X_BOOTSTRAP_REF_CLK_40)
  22                return 40000000;
  23        else
  24                return 25000000;
  25}
  26
  27int get_serial_clock(void)
  28{
  29        return qca953x_get_xtal();
  30}
  31
  32int get_clocks(void)
  33{
  34        void __iomem *regs;
  35        u32 val, ctrl, xtal, pll, div;
  36
  37        regs = map_physmem(AR71XX_PLL_BASE, AR71XX_PLL_SIZE,
  38                           MAP_NOCACHE);
  39
  40        xtal = qca953x_get_xtal();
  41        ctrl = readl(regs + QCA953X_PLL_CLK_CTRL_REG);
  42        val = readl(regs + QCA953X_PLL_CPU_CONFIG_REG);
  43
  44        /* VCOOUT = XTAL * DIV_INT */
  45        div = (val >> QCA953X_PLL_CPU_CONFIG_REFDIV_SHIFT)
  46                        & QCA953X_PLL_CPU_CONFIG_REFDIV_MASK;
  47        pll = xtal / div;
  48
  49        /* PLLOUT = VCOOUT * (1/2^OUTDIV) */
  50        div = (val >> QCA953X_PLL_CPU_CONFIG_NINT_SHIFT)
  51                        & QCA953X_PLL_CPU_CONFIG_NINT_MASK;
  52        pll *= div;
  53        div = (val >> QCA953X_PLL_CPU_CONFIG_OUTDIV_SHIFT)
  54                        & QCA953X_PLL_CPU_CONFIG_OUTDIV_MASK;
  55        if (!div)
  56                div = 1;
  57        pll >>= div;
  58
  59        /* CPU_CLK = PLLOUT / CPU_POST_DIV */
  60        div = ((ctrl >> QCA953X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT)
  61                        & QCA953X_PLL_CLK_CTRL_CPU_POST_DIV_MASK) + 1;
  62        gd->cpu_clk = pll / div;
  63
  64
  65        val = readl(regs + QCA953X_PLL_DDR_CONFIG_REG);
  66        /* VCOOUT = XTAL * DIV_INT */
  67        div = (val >> QCA953X_PLL_DDR_CONFIG_REFDIV_SHIFT)
  68                        & QCA953X_PLL_DDR_CONFIG_REFDIV_MASK;
  69        pll = xtal / div;
  70
  71        /* PLLOUT = VCOOUT * (1/2^OUTDIV) */
  72        div = (val >> QCA953X_PLL_DDR_CONFIG_NINT_SHIFT)
  73                        & QCA953X_PLL_DDR_CONFIG_NINT_MASK;
  74        pll *= div;
  75        div = (val >> QCA953X_PLL_DDR_CONFIG_OUTDIV_SHIFT)
  76                        & QCA953X_PLL_DDR_CONFIG_OUTDIV_MASK;
  77        if (!div)
  78                div = 1;
  79        pll >>= div;
  80
  81        /* DDR_CLK = PLLOUT / DDR_POST_DIV */
  82        div = ((ctrl >> QCA953X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT)
  83                        & QCA953X_PLL_CLK_CTRL_DDR_POST_DIV_MASK) + 1;
  84        gd->mem_clk = pll / div;
  85
  86        div = ((ctrl >> QCA953X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT)
  87                        & QCA953X_PLL_CLK_CTRL_AHB_POST_DIV_MASK) + 1;
  88        if (ctrl & QCA953X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL) {
  89                /* AHB_CLK = DDR_CLK / AHB_POST_DIV */
  90                gd->bus_clk = gd->mem_clk / (div + 1);
  91        } else {
  92                /* AHB_CLK = CPU_CLK / AHB_POST_DIV */
  93                gd->bus_clk = gd->cpu_clk / (div + 1);
  94        }
  95
  96        return 0;
  97}
  98
  99ulong get_bus_freq(ulong dummy)
 100{
 101        if (!gd->bus_clk)
 102                get_clocks();
 103        return gd->bus_clk;
 104}
 105
 106ulong get_ddr_freq(ulong dummy)
 107{
 108        if (!gd->mem_clk)
 109                get_clocks();
 110        return gd->mem_clk;
 111}
 112