1- #include <hardware.h>
21#include <stdio.h>
32#include <platform/bcm28xx/pll_read.h>
3+ #include <platform/bcm28xx.h>
4+ #include <lk/reg.h>
5+ #include <lk/console_cmd.h>
6+ #include <lk/debug.h>
47
58uint32_t xtal_freq ;
69
7- uint32_t get_vpu_per_freq () {
8- return clk_get_freq (& CM_VPUDIV , & CM_VPUCTL );
10+ static int cmd_pll_dump (int argc , const cmd_args * argv );
11+
12+ STATIC_COMMAND_START
13+ STATIC_COMMAND ("dump_pll_state" , "print all pll state" , & cmd_pll_dump )
14+ STATIC_COMMAND_END (pll );
15+
16+ uint32_t get_vpu_per_freq (void ) {
17+ return clk_get_freq (CM_VPUDIV , CM_VPUCTL );
918}
1019
1120uint32_t get_uart_base_freq () {
12- return clk_get_freq (& CM_UARTDIV , & CM_UARTCTL );
21+ return clk_get_freq (CM_UARTDIV , CM_UARTCTL );
1322}
1423
1524uint32_t compute_pll_freq (uint32_t ctrl , uint32_t frac ) {
16- uint32_t ndiv = A2W_PLLC_CTRL & A2W_PLLC_CTRL_NDIV_SET ;
17- uint32_t pdiv = (A2W_PLLC_CTRL & A2W_PLLC_CTRL_PDIV_SET ) >> A2W_PLLC_CTRL_PDIV_LSB ;
18- uint64_t mult1 = (ndiv << 20 ) | frac ;
25+ // FIXME, ignores the addr passed in
26+ uint32_t ndiv = * REG32 (ctrl ) & A2W_PLLC_CTRL_NDIV_SET ;
27+ uint32_t pdiv = (* REG32 (ctrl ) & A2W_PLLC_CTRL_PDIV_SET ) >> A2W_PLLC_CTRL_PDIV_LSB ;
28+ uint64_t mult1 = (ndiv << 20 ) | * REG32 (frac );
1929 mult1 *= pdiv ;
2030 // TODO, the optional /2 phase
2131 uint32_t freq = (xtal_freq * mult1 ) >> 20 ;
2232 return freq ;
2333}
2434
2535uint32_t plla () {
26- return compute_pll_freq (A2W_PLLA_CTRL , A2W_PLLA_FRAC & A2W_PLLA_FRAC_MASK );
36+ return compute_pll_freq (* REG32 ( A2W_PLLA_CTRL ), * REG32 ( A2W_PLLA_FRAC ) & A2W_PLLA_FRAC_MASK );
2737}
2838
2939uint32_t pllb () {
30- return compute_pll_freq (A2W_PLLB_CTRL , A2W_PLLB_FRAC & A2W_PLLB_FRAC_MASK );
40+ return compute_pll_freq (* REG32 ( A2W_PLLB_CTRL ), * REG32 ( A2W_PLLB_FRAC ) & A2W_PLLB_FRAC_MASK );
3141}
3242
3343uint32_t pllc () {
3444 //uint32_t ana1 = A2W_PLLC_ANA1;
35- uint32_t ctrl = A2W_PLLC_CTRL ;
36- uint32_t frac = A2W_PLLC_FRAC & A2W_PLLC_FRAC_MASK ;
45+ uint32_t ctrl = * REG32 ( A2W_PLLC_CTRL ) ;
46+ uint32_t frac = * REG32 ( A2W_PLLC_FRAC ) & A2W_PLLC_FRAC_MASK ;
3747 return compute_pll_freq (ctrl , frac );
3848}
3949
4050uint32_t plld () {
41- return compute_pll_freq (A2W_PLLD_CTRL , A2W_PLLD_FRAC & A2W_PLLD_FRAC_MASK );
51+ return compute_pll_freq (* REG32 ( A2W_PLLD_CTRL ), * REG32 ( A2W_PLLD_FRAC ) & A2W_PLLD_FRAC_MASK );
4252}
4353
4454uint32_t pllh () {
45- return compute_pll_freq (A2W_PLLH_CTRL , A2W_PLLH_FRAC & A2W_PLLH_FRAC_MASK );
55+ return compute_pll_freq (* REG32 ( A2W_PLLH_CTRL ), * REG32 ( A2W_PLLH_FRAC ) & A2W_PLLH_FRAC_MASK );
4656}
4757
48- uint32_t pllc_core0 () {
49- uint32_t ctrl = A2W_PLLC_CORE0 ;
58+ uint32_t pllc_core0 (void ) {
59+ uint32_t ctrl = * REG32 ( A2W_PLLC_CORE0 ) ;
5060 uint32_t div = ctrl & A2W_PLLC_CORE0_DIV_SET ;
5161 uint32_t pllc_freq = pllc ();
5262 return pllc_freq / div ;
5363}
5464
55- uint32_t clk_get_freq (volatile uint32_t * divreg , volatile uint32_t * ctlreg ) {
56- uint32_t div = * divreg ;
65+ uint32_t clk_get_freq (uint32_t divreg , uint32_t ctlreg ) {
66+ uint32_t div = * REG32 ( divreg ) ;
5767 if (div == 0 ) return 0 ;
5868 uint64_t input_freq = clk_get_input_freq (ctlreg );
59- return ((input_freq << 12 ) / * divreg );
69+ return ((input_freq << 12 ) / div );
6070}
6171
62- uint32_t clk_get_input_freq (volatile uint32_t * ctlreg ) {
63- uint32_t ctl = * ctlreg ;
72+ uint32_t clk_get_input_freq (uint32_t ctlreg ) {
73+ uint32_t ctl = * REG32 ( ctlreg ) ;
6474 switch (ctl & 0xf ) {
6575 case 0 : // GND clock source
6676 return 0 ;
@@ -85,3 +95,44 @@ uint32_t clk_get_input_freq(volatile uint32_t *ctlreg) {
8595 return 0 ;
8696 }
8797}
98+
99+ static uint32_t dump_pll_state (const char * prefix , uint32_t ctrl , uint32_t frac ) {
100+ uint32_t ctrl_val = * REG32 (ctrl );
101+ uint32_t frac_value = * REG32 (frac );
102+ dprintf (INFO , "A2W_%s_CTRL: 0x%x\n" , prefix , ctrl_val );
103+ dprintf (INFO , "A2W_%s_FRAC: 0x%x\n" , prefix , frac_value );
104+ uint32_t freq = compute_pll_freq (ctrl , frac );
105+ dprintf (INFO , "%s freq: %u\n" , prefix , freq );
106+ return freq ;
107+ }
108+
109+ static void dump_plldiv_state (const char * prefix , uint32_t ctrl , uint32_t input ) {
110+ uint32_t ctrl_val = * REG32 (ctrl );
111+ dprintf (INFO , "\tA2W_%s: 0x%x\n" , prefix , ctrl_val );
112+ uint8_t div = ctrl_val & 0xff ;
113+ if (div == 0 ) return ;
114+ uint32_t freq = input / div ;
115+ dprintf (INFO , "\t%s freq: %u\n" , prefix , freq );
116+ }
117+
118+ static void dump_plldiv2_state (const char * prefix , uint32_t ctrl , uint32_t div ) {
119+ uint32_t ctrl_val = * REG32 (ctrl );
120+ uint32_t div_val = * REG32 (div );
121+ dprintf (INFO , "CM_%sCTL: 0x%x\n" , prefix , ctrl_val );
122+ dprintf (INFO , "CM_%sDIV: 0x%x\n" , prefix , div_val );
123+ }
124+
125+ static int cmd_pll_dump (int argc , const cmd_args * argv ) {
126+ dump_pll_state ("PLLA" , A2W_PLLA_CTRL , A2W_PLLA_FRAC );
127+ dump_pll_state ("PLLB" , A2W_PLLB_CTRL , A2W_PLLB_FRAC );
128+ uint32_t pllc_freq = dump_pll_state ("PLLC" , A2W_PLLC_CTRL , A2W_PLLC_FRAC );
129+ if (pllc_freq > 0 ) {
130+ dump_plldiv_state ("PLLC_CORE0" , A2W_PLLC_CORE0 , pllc_freq );
131+ dump_plldiv_state ("PLLC_CORE1" , A2W_PLLC_CORE1 , pllc_freq );
132+ }
133+ dump_pll_state ("PLLD" , A2W_PLLD_CTRL , A2W_PLLD_FRAC );
134+ dump_pll_state ("PLLH" , A2W_PLLH_CTRL , A2W_PLLH_FRAC );
135+
136+ dump_plldiv2_state ("VPU" , CM_VPUCTL , CM_VPUDIV );
137+ return 0 ;
138+ }
0 commit comments