github.com/usbarmory/tamago@v0.0.0-20240508072735-8612bbe1e454/soc/sifive/fu540/clock.go (about)

     1  // SiFive FU540 clock control
     2  // https://github.com/usbarmory/tamago
     3  //
     4  // Copyright (c) WithSecure Corporation
     5  // https://foundry.withsecure.com
     6  //
     7  // Use of this source code is governed by the license
     8  // that can be found in the LICENSE file.
     9  
    10  package fu540
    11  
    12  import (
    13  	"github.com/usbarmory/tamago/bits"
    14  	"github.com/usbarmory/tamago/internal/reg"
    15  )
    16  
    17  // Clock registers
    18  const (
    19  	PRCI_BASE = 0x10000000
    20  
    21  	PRCI_COREPLLCFG = PRCI_BASE + 0x4
    22  	COREPLL_DIVR    = 0
    23  	COREPLL_DIVF    = 6
    24  	COREPLL_DIVQ    = 15
    25  
    26  	PRCI_CORECLKSEL = PRCI_BASE + 0x24
    27  )
    28  
    29  // Oscillator frequencies
    30  const (
    31  	// p43, 7.1 Clocking, FU540C00RM
    32  	RTCCLK  = 1000000
    33  	COREPLL = 33330000
    34  )
    35  
    36  func init() {
    37  	c := reg.Read(PRCI_COREPLLCFG)
    38  
    39  	// set COREPLL for 1 GHz operation
    40  	bits.Clear(&c, COREPLL_DIVR)
    41  	bits.SetN(&c, COREPLL_DIVF, 0x1ff, 59)
    42  	bits.SetN(&c, COREPLL_DIVQ, 0b111, 2)
    43  
    44  	reg.Write(PRCI_COREPLLCFG, c)
    45  	reg.Clear(PRCI_CORECLKSEL, 0)
    46  }
    47  
    48  // Freq returns the RISC-V core frequency.
    49  func Freq() (hz uint32) {
    50  	if reg.Get(PRCI_CORECLKSEL, 0, 1) == 1 {
    51  		return COREPLL
    52  	}
    53  
    54  	// p47, 7.4.2 Setting coreclk frequency, FU540C00RM
    55  
    56  	c := reg.Read(PRCI_COREPLLCFG)
    57  
    58  	divr := bits.Get(&c, COREPLL_DIVR, 0x3f)
    59  	divf := bits.Get(&c, COREPLL_DIVF, 0x1ff)
    60  	divq := bits.Get(&c, COREPLL_DIVQ, 0b111)
    61  
    62  	return (COREPLL * 2 * (divf + 1)) / ((divr + 1) * 1 << divq)
    63  }