linux/arch/mips/pic32/pic32mzda/early_clk.c
<<
>>
Prefs
   1/*
   2 * Joshua Henderson <joshua.henderson@microchip.com>
   3 * Copyright (C) 2015 Microchip Technology Inc.  All rights reserved.
   4 *
   5 *  This program is free software; you can distribute it and/or modify it
   6 *  under the terms of the GNU General Public License (Version 2) as
   7 *  published by the Free Software Foundation.
   8 *
   9 *  This program is distributed in the hope it will be useful, but WITHOUT
  10 *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11 *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12 *  for more details.
  13 */
  14#include <asm/mach-pic32/pic32.h>
  15
  16#include "pic32mzda.h"
  17
  18/* Oscillators, PLL & clocks */
  19#define ICLK_MASK       0x00000080
  20#define PLLDIV_MASK     0x00000007
  21#define CUROSC_MASK     0x00000007
  22#define PLLMUL_MASK     0x0000007F
  23#define PB_MASK         0x00000007
  24#define FRC1            0
  25#define FRC2            7
  26#define SPLL            1
  27#define POSC            2
  28#define FRC_CLK         8000000
  29
  30#define PIC32_POSC_FREQ 24000000
  31
  32#define OSCCON          0x0000
  33#define SPLLCON         0x0020
  34#define PB1DIV          0x0140
  35
  36u32 pic32_get_sysclk(void)
  37{
  38        u32 osc_freq = 0;
  39        u32 pllclk;
  40        u32 frcdivn;
  41        u32 osccon;
  42        u32 spllcon;
  43        int curr_osc;
  44
  45        u32 plliclk;
  46        u32 pllidiv;
  47        u32 pllodiv;
  48        u32 pllmult;
  49        u32 frcdiv;
  50
  51        void __iomem *osc_base = ioremap(PIC32_BASE_OSC, 0x200);
  52
  53        osccon = __raw_readl(osc_base + OSCCON);
  54        spllcon = __raw_readl(osc_base + SPLLCON);
  55
  56        plliclk = (spllcon & ICLK_MASK);
  57        pllidiv = ((spllcon >> 8) & PLLDIV_MASK) + 1;
  58        pllodiv = ((spllcon >> 24) & PLLDIV_MASK);
  59        pllmult = ((spllcon >> 16) & PLLMUL_MASK) + 1;
  60        frcdiv = ((osccon >> 24) & PLLDIV_MASK);
  61
  62        pllclk = plliclk ? FRC_CLK : PIC32_POSC_FREQ;
  63        frcdivn = ((1 << frcdiv) + 1) + (128 * (frcdiv == 7));
  64
  65        if (pllodiv < 2)
  66                pllodiv = 2;
  67        else if (pllodiv < 5)
  68                pllodiv = (1 << pllodiv);
  69        else
  70                pllodiv = 32;
  71
  72        curr_osc = (int)((osccon >> 12) & CUROSC_MASK);
  73
  74        switch (curr_osc) {
  75        case FRC1:
  76        case FRC2:
  77                osc_freq = FRC_CLK / frcdivn;
  78                break;
  79        case SPLL:
  80                osc_freq = ((pllclk / pllidiv) * pllmult) / pllodiv;
  81                break;
  82        case POSC:
  83                osc_freq = PIC32_POSC_FREQ;
  84                break;
  85        default:
  86                break;
  87        }
  88
  89        iounmap(osc_base);
  90
  91        return osc_freq;
  92}
  93
  94u32 pic32_get_pbclk(int bus)
  95{
  96        u32 clk_freq;
  97        void __iomem *osc_base = ioremap(PIC32_BASE_OSC, 0x200);
  98        u32 pbxdiv = PB1DIV + ((bus - 1) * 0x10);
  99        u32 pbdiv = (__raw_readl(osc_base + pbxdiv) & PB_MASK) + 1;
 100
 101        iounmap(osc_base);
 102
 103        clk_freq = pic32_get_sysclk();
 104
 105        return clk_freq / pbdiv;
 106}
 107