uint32_t zynq_get_clock(enum zynq_periph periph) { DEBUG_ASSERT(periph < _PERIPH_MAX); // get the clock control register base addr_t clk_reg = periph_clk_ctrl_reg(periph); DEBUG_ASSERT(clk_reg != 0); int enable_bitpos = periph_clk_ctrl_enable_bitpos(periph); LTRACEF("clkreg 0x%x\n", *REG32(clk_reg)); // see if it's enabled if (enable_bitpos >= 0) { if ((*REG32(clk_reg) & (1 << enable_bitpos)) == 0) { // not enabled return 0; } } // get the source clock uint32_t srcclk; switch (BITS_SHIFT(*REG32(clk_reg), 5, 4)) { case 0: case 1: srcclk = get_io_pll_freq(); break; case 2: srcclk = get_arm_pll_freq(); break; case 3: srcclk = get_ddr_pll_freq(); break; } // get the divisor out of the register uint32_t divisor = BITS_SHIFT(*REG32(clk_reg), 13, 8); if (divisor == 0) return 0; uint32_t divisor2 = 1; if (periph_clk_ctrl_divisor_count(periph) == 2) { divisor2 = BITS_SHIFT(*REG32(clk_reg), 25, 20); if (divisor2 == 0) return 0; } uint32_t clk = srcclk / divisor / divisor2; return clk; }
void zynq_dump_clocks(void) { printf("zynq clocks:\n"); printf("\tarm pll %d\n", get_arm_pll_freq()); printf("\tddr pll %d\n", get_ddr_pll_freq()); printf("\tio pll %d\n", get_io_pll_freq()); printf("\tarm clock %d\n", zynq_get_arm_freq()); printf("\tarm timer clock %d\n", zynq_get_arm_timer_freq()); printf("\tcpu6x4x clock %d\n", get_cpu_6x4x_freq()); printf("\tcpu3x2x clock %d\n", get_cpu_3x2x_freq()); printf("\tcpu2x clock %d\n", get_cpu_2x_freq()); printf("\tcpu1x clock %d\n", get_cpu_1x_freq()); printf("peripheral clocks:\n"); for (uint i = 0; i < _PERIPH_MAX; i++) { printf("\tperiph %d (%s) clock %u\n", i, periph_to_name(i), zynq_get_clock(i)); } }
static uint32_t get_cpu_input_freq(void) { LTRACEF("ARM_CLK_CTRL 0x%x\n", SLCR_REG(ARM_CLK_CTRL)); uint32_t divisor = BITS_SHIFT(SLCR_REG(ARM_CLK_CTRL), 13, 8); uint32_t srcsel = BITS_SHIFT(SLCR_REG(ARM_CLK_CTRL), 5, 4); uint32_t srcclk; switch (srcsel) { default: case 0: case 1: // arm pll srcclk = get_arm_pll_freq(); break; case 2: // ddr pll srcclk = get_ddr_pll_freq(); break; case 3: // io pll srcclk = get_io_pll_freq(); break; } // cpu 6x4x return srcclk / divisor; }