linux/arch/mips/pic32/pic32mzda/early_clk.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Joshua Henderson <joshua.henderson@microchip.com>
   4 * Copyright (C) 2015 Microchip Technology Inc.  All rights reserved.
   5 */
   6#include <asm/mach-pic32/pic32.h>
   7
   8#include "pic32mzda.h"
   9
  10/* Oscillators, PLL & clocks */
  11#define ICLK_MASK       0x00000080
  12#define PLLDIV_MASK     0x00000007
  13#define CUROSC_MASK     0x00000007
  14#define PLLMUL_MASK     0x0000007F
  15#define PB_MASK         0x00000007
  16#define FRC1            0
  17#define FRC2            7
  18#define SPLL            1
  19#define POSC            2
  20#define FRC_CLK         8000000
  21
  22#define PIC32_POSC_FREQ 24000000
  23
  24#define OSCCON          0x0000
  25#define SPLLCON         0x0020
  26#define PB1DIV          0x0140
  27
  28u32 pic32_get_sysclk(void)
  29{
  30        u32 osc_freq = 0;
  31        u32 pllclk;
  32        u32 frcdivn;
  33        u32 osccon;
  34        u32 spllcon;
  35        int curr_osc;
  36
  37        u32 plliclk;
  38        u32 pllidiv;
  39        u32 pllodiv;
  40        u32 pllmult;
  41        u32 frcdiv;
  42
  43        void __iomem *osc_base = ioremap(PIC32_BASE_OSC, 0x200);
  44
  45        osccon = __raw_readl(osc_base + OSCCON);
  46        spllcon = __raw_readl(osc_base + SPLLCON);
  47
  48        plliclk = (spllcon & ICLK_MASK);
  49        pllidiv = ((spllcon >> 8) & PLLDIV_MASK) + 1;
  50        pllodiv = ((spllcon >> 24) & PLLDIV_MASK);
  51        pllmult = ((spllcon >> 16) & PLLMUL_MASK) + 1;
  52        frcdiv = ((osccon >> 24) & PLLDIV_MASK);
  53
  54        pllclk = plliclk ? FRC_CLK : PIC32_POSC_FREQ;
  55        frcdivn = ((1 << frcdiv) + 1) + (128 * (frcdiv == 7));
  56
  57        if (pllodiv < 2)
  58                pllodiv = 2;
  59        else if (pllodiv < 5)
  60                pllodiv = (1 << pllodiv);
  61        else
  62                pllodiv = 32;
  63
  64        curr_osc = (int)((osccon >> 12) & CUROSC_MASK);
  65
  66        switch (curr_osc) {
  67        case FRC1:
  68        case FRC2:
  69                osc_freq = FRC_CLK / frcdivn;
  70                break;
  71        case SPLL:
  72                osc_freq = ((pllclk / pllidiv) * pllmult) / pllodiv;
  73                break;
  74        case POSC:
  75                osc_freq = PIC32_POSC_FREQ;
  76                break;
  77        default:
  78                break;
  79        }
  80
  81        iounmap(osc_base);
  82
  83        return osc_freq;
  84}
  85
  86u32 pic32_get_pbclk(int bus)
  87{
  88        u32 clk_freq;
  89        void __iomem *osc_base = ioremap(PIC32_BASE_OSC, 0x200);
  90        u32 pbxdiv = PB1DIV + ((bus - 1) * 0x10);
  91        u32 pbdiv = (__raw_readl(osc_base + pbxdiv) & PB_MASK) + 1;
  92
  93        iounmap(osc_base);
  94
  95        clk_freq = pic32_get_sysclk();
  96
  97        return clk_freq / pbdiv;
  98}
  99