1/* 2 * Copyright 2017, Data61 3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO) 4 * ABN 41 687 119 230. 5 * 6 * This software may be distributed and modified according to the terms of 7 * the BSD 2-Clause license. Note that NO WARRANTY is provided. 8 * See "LICENSE_BSD2.txt" for details. 9 * 10 * @TAG(DATA61_BSD) 11 */ 12 13#include "../../arch/arm/clock.h" 14#include "../../common.h" 15 16#define MXO_SRC_CLK_INV (1U << 12) 17#define MXO_SRC_BRANCH_ENA (1U << 11) 18#define PXO_SRC_CLK_INV (1U << 10) 19#define PXO_SRC_BRANCH_ENA (1U << 9) 20#define CLK_INV (1U << 5) 21#define CLK_BRANCH_ENA (1U << 4) 22#define SRC_SEL (1U << 0) 23#define SRC_SEL_PXO (0U << 0) 24#define SRC_SEL_MXO (1U << 0) 25#define PPSS_TIMER0_CLK_CTL 0x0090258C 26#define PPSS_TIMER1_CLK_CTL 0x00902590 27 28#define REG_READ(base, offset) *(uint32_t*)((uintptr_t)base + (offset)) 29#define REG_WRITE(base, offset, v) *(uint32_t*)((uintptr_t)base + (offset)) = v 30 31struct clock_sys_regs { 32 void* block0; 33 void* block1; 34 void* block2; 35 void* block3; 36}; 37 38struct clock_sys_regs clk_sys_regs; 39 40static inline uint32_t reg_read(uintptr_t addr) 41{ 42 uint32_t* reg; 43 switch (addr & 0x3000) { 44 case 0x0000: 45 reg = (uint32_t*)clk_sys_regs.block0; 46 break; 47 case 0x1000: 48 reg = (uint32_t*)clk_sys_regs.block1; 49 break; 50 case 0x2000: 51 reg = (uint32_t*)clk_sys_regs.block2; 52 break; 53 case 0x3000: 54 reg = (uint32_t*)clk_sys_regs.block3; 55 break; 56 default: 57 printf("Invalid memory access: 0x%x\n", (uint32_t)addr); 58 return 0; 59 } 60 61 if (addr & 0x3) { 62 printf("Unaligned memory access: 0x%x\n", (uint32_t)addr); 63 } 64 addr &= 0xfff; 65 addr /= 4; 66 return reg[addr]; 67} 68 69static inline void reg_write(uintptr_t addr, uint32_t v) 70{ 71 uint32_t* reg; 72 switch (addr & 0x3000) { 73 case 0x0000: 74 reg = (uint32_t*)clk_sys_regs.block0; 75 break; 76 case 0x1000: 77 reg = (uint32_t*)clk_sys_regs.block1; 78 break; 79 case 0x2000: 80 reg = (uint32_t*)clk_sys_regs.block2; 81 break; 82 case 0x3000: 83 reg = (uint32_t*)clk_sys_regs.block3; 84 break; 85 default: 86 printf("Invalid memory access: 0x%x\n", (uint32_t)addr); 87 return; 88 } 89 90 if (addr & 0x3) { 91 printf("Unaligned memory access: 0x%x\n", (uint32_t)addr); 92 } 93 addr &= 0xfff; 94 addr /= 4; 95 reg[addr] = v; 96} 97 98void test(void) 99{ 100 reg_write(PPSS_TIMER0_CLK_CTL, CLK_BRANCH_ENA); 101 reg_write(PPSS_TIMER1_CLK_CTL, CLK_BRANCH_ENA); 102} 103 104static struct clock master_clk = { CLK_OPS_DEFAULT(MASTER) }; 105static struct clock pxo_clk = { CLK_OPS_DEFAULT(PXO) }; 106static struct clock tcxo_clk = { CLK_OPS_DEFAULT(TCXO) }; 107static struct clock wcnxo_clk = { CLK_OPS_DEFAULT(WCNXO) }; 108static struct clock slpxo_clk = { CLK_OPS_DEFAULT(SLPXO) }; 109 110static int 111apq8064_gate_enable(clock_sys_t* sys, enum clock_gate gate, enum clock_gate_mode mode) 112{ 113 (void)sys; 114 (void)gate; 115 (void)mode; 116 return 0; 117} 118 119void 120clk_print_clock_tree(clock_sys_t* sys) 121{ 122 clk_t *clk = clk_get_clock(sys, CLK_MASTER); 123 clk_print_tree(clk, ""); 124} 125 126static int apq8064_clock_sys_init_common(clock_sys_t* clk_sys) 127{ 128 clk_sys->gate_enable = &apq8064_gate_enable; 129 clk_sys->get_clock = &ps_get_clock; 130 return 0; 131} 132 133int 134clock_sys_init(ps_io_ops_t* io_ops, clock_sys_t* clk_sys) 135{ 136 struct clock_sys_regs* d = &clk_sys_regs; 137 MAP_IF_NULL(io_ops, APQ8064_CLK_CTL0, d->block0); 138 MAP_IF_NULL(io_ops, APQ8064_CLK_CTL1, d->block1); 139 MAP_IF_NULL(io_ops, APQ8064_CLK_CTL2, d->block2); 140 MAP_IF_NULL(io_ops, APQ8064_CLK_CTL3, d->block3); 141 clk_sys->priv = d; 142 return 0; 143} 144 145int 146apq8064_clock_sys_init(void* clk_ctl_base0, void* clk_ctl_base1, 147 void* clk_ctl_base2, void* clk_ctl_base3, 148 clock_sys_t* clk_sys) 149{ 150 struct clock_sys_regs* d = &clk_sys_regs; 151 if (clk_ctl_base0) { 152 d->block0 = clk_ctl_base0; 153 } 154 if (clk_ctl_base1) { 155 d->block1 = clk_ctl_base1; 156 } 157 if (clk_ctl_base2) { 158 d->block2 = clk_ctl_base2; 159 } 160 if (clk_ctl_base3) { 161 d->block3 = clk_ctl_base3; 162 } 163 clk_sys->priv = d; 164 return apq8064_clock_sys_init_common(clk_sys); 165} 166 167clk_t* ps_clocks[] = { 168 [CLK_MASTER] = &master_clk, 169 [CLK_PXO ] = &pxo_clk, 170 [CLK_WCNXO ] = &wcnxo_clk, 171 [CLK_TCXO ] = &tcxo_clk, 172 [CLK_SLPXO ] = &slpxo_clk 173}; 174 175freq_t ps_freq_default[] = { 176 [CLK_MASTER] = 24 * MHZ, 177 [CLK_PXO ] = 27 * MHZ, 178 [CLK_WCNXO ] = 48 * MHZ, 179 [CLK_TCXO ] = 19200 * KHZ, 180 [CLK_SLPXO ] = 32768 181}; 182