diff options
-rw-r--r-- | src/arch/arm/Makefile.inc | 3 | ||||
-rw-r--r-- | src/arch/arm/clock.c | 36 | ||||
-rw-r--r-- | src/arch/arm/include/arch/clock.h | 25 | ||||
-rw-r--r-- | src/arch/arm64/armv8/lib/Makefile.inc | 2 | ||||
-rw-r--r-- | src/arch/arm64/armv8/lib/clock.c | 32 | ||||
-rw-r--r-- | src/arch/arm64/include/arch/clock.h | 25 | ||||
-rw-r--r-- | src/soc/nvidia/tegra124/clock.c | 3 | ||||
-rw-r--r-- | src/soc/nvidia/tegra132/clock.c | 84 |
8 files changed, 172 insertions, 38 deletions
diff --git a/src/arch/arm/Makefile.inc b/src/arch/arm/Makefile.inc index 96c8b494b2..0fcbf6c232 100644 --- a/src/arch/arm/Makefile.inc +++ b/src/arch/arm/Makefile.inc @@ -60,6 +60,7 @@ bootblock-y += memset.S bootblock-y += memcpy.S bootblock-y += memmove.S bootblock-y += div0.c +bootblock-y += clock.c $(objcbfs)/bootblock.debug: $(src)/arch/arm/bootblock.ld $(obj)/ldoptions $$(bootblock-objs) $$(VERSTAGE_LIB) @printf " LINK $(subst $(obj)/,,$(@))\n" @@ -91,6 +92,7 @@ romstage-y += eabi_compat.c romstage-y += memset.S romstage-y += memcpy.S romstage-y += memmove.S +romstage-y += clock.c VBOOT_STUB_DEPS += $(obj)/arch/arm/eabi_compat.rmodules_arm.o @@ -115,6 +117,7 @@ ramstage-y += tables.c ramstage-y += memset.S ramstage-y += memcpy.S ramstage-y += memmove.S +ramstage-y += clock.c ramstage-srcs += $(wildcard src/mainboard/$(MAINBOARDDIR)/mainboard.c) $(objcbfs)/ramstage.debug: $$(ramstage-objs) $(src)/arch/arm/ramstage.ld $(obj)/ldoptions diff --git a/src/arch/arm/clock.c b/src/arch/arm/clock.c new file mode 100644 index 0000000000..5f68e6fa9d --- /dev/null +++ b/src/arch/arm/clock.c @@ -0,0 +1,36 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +#include <stdint.h> +#include <arch/clock.h> + +void set_cntfrq(uint32_t freq) +{ + __asm__ __volatile__("mcr p15, 0, %0, c14, c0, 0\n" :: "r"(freq)); +} diff --git a/src/arch/arm/include/arch/clock.h b/src/arch/arm/include/arch/clock.h new file mode 100644 index 0000000000..a11fbd4999 --- /dev/null +++ b/src/arch/arm/include/arch/clock.h @@ -0,0 +1,25 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __ARM_CLOCK_H_ +#define __ARM_CLOCK_H_ + +void set_cntfrq(uint32_t); + +#endif //__ARM_CLOCK_H_ diff --git a/src/arch/arm64/armv8/lib/Makefile.inc b/src/arch/arm64/armv8/lib/Makefile.inc index bda203b0d5..3e393bbe23 100644 --- a/src/arch/arm64/armv8/lib/Makefile.inc +++ b/src/arch/arm64/armv8/lib/Makefile.inc @@ -20,7 +20,7 @@ ## ################################################################################ -lib_access = pstate.c sysctrl.c cache.c tlb.c misc.c +lib_access = pstate.c sysctrl.c cache.c tlb.c misc.c clock.c ifeq ($(CONFIG_ARCH_BOOTBLOCK_ARMV8_64),y) bootblock-y += $(lib_access) diff --git a/src/arch/arm64/armv8/lib/clock.c b/src/arch/arm64/armv8/lib/clock.c new file mode 100644 index 0000000000..00c9208e5e --- /dev/null +++ b/src/arch/arm64/armv8/lib/clock.c @@ -0,0 +1,32 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Google Inc + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * clock.c: Functions for accessing clock and timer related registers + * Reference: ARM Architecture Reference Manual, ARMv8-A edition + */ + +#include <stdint.h> + +#include <arch/clock.h> + +void set_cntfrq(uint32_t freq) +{ + __asm__ __volatile__("msr cntfrq_el0, %0" :: "r"(freq)); +} diff --git a/src/arch/arm64/include/arch/clock.h b/src/arch/arm64/include/arch/clock.h new file mode 100644 index 0000000000..a11fbd4999 --- /dev/null +++ b/src/arch/arm64/include/arch/clock.h @@ -0,0 +1,25 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __ARM_CLOCK_H_ +#define __ARM_CLOCK_H_ + +void set_cntfrq(uint32_t); + +#endif //__ARM_CLOCK_H_ diff --git a/src/soc/nvidia/tegra124/clock.c b/src/soc/nvidia/tegra124/clock.c index e3c0e71a7e..fa332835b2 100644 --- a/src/soc/nvidia/tegra124/clock.c +++ b/src/soc/nvidia/tegra124/clock.c @@ -20,6 +20,7 @@ #include <soc/addressmap.h> #include <soc/clock.h> #include <stdlib.h> +#include <arch/clock.h> #include "clk_rst.h" #include "flow.h" #include "maincpu.h" @@ -181,7 +182,7 @@ void clock_init_arm_generic_timer(void) { uint32_t freq = clock_get_osc_khz() * 1000; // Set the cntfrq register. - __asm__ __volatile__("mcr p15, 0, %0, c14, c0, 0\n" :: "r"(freq)); + set_cntfrq(freq); // Record the system timer frequency. write32(freq, &sysctr->cntfid0); diff --git a/src/soc/nvidia/tegra132/clock.c b/src/soc/nvidia/tegra132/clock.c index 5237712ef3..2da7ea1d04 100644 --- a/src/soc/nvidia/tegra132/clock.c +++ b/src/soc/nvidia/tegra132/clock.c @@ -20,6 +20,7 @@ #include <soc/addressmap.h> #include <soc/clock.h> #include <stdlib.h> +#include <arch/clock.h> #include "clk_rst.h" #include "flow.h" #include "maincpu.h" @@ -180,12 +181,12 @@ int clock_get_pll_input_khz(void) void clock_init_arm_generic_timer(void) { uint32_t freq = clock_get_osc_khz() * 1000; - // Set the cntfrq register. - __asm__ __volatile__("mcr p15, 0, %0, c14, c0, 0\n" :: "r"(freq)); + /* Set the cntfrq register. */ + set_cntfrq(freq); - // Record the system timer frequency. + /* Record the system timer frequency. */ write32(freq, &sysctr->cntfid0); - // Enable the system counter. + /* Enable the system counter. */ uint32_t cntcr = read32(&sysctr->cntcr); cntcr |= SYSCTR_CNTCR_EN | SYSCTR_CNTCR_HDBG; write32(cntcr, &sysctr->cntcr); @@ -282,7 +283,7 @@ static void graphics_pll(void) * I don't want to find out in a few months * that it is needed. */ - u32 scfg = (1<<28) | (1<<24) | (1<<22); + u32 scfg = (1 << 28) | (1 << 24) | (1 << 22); writel(scfg, cfg); init_pll(&clk_rst->plldp_base, &clk_rst->plldp_misc, osc_table[osc].plldp, PLLDPD2_MISC_LOCK_ENABLE); @@ -309,8 +310,9 @@ clock_display(u32 frequency) * iterate all possible values. Note Tegra 124 supports 11 bits for n, * but our pll_fields has only 10 bits for n. * - * Note values undershoot or overshoot target output frequency may not - * work if the values are not in "safe" range by panel specification. + * Note, values that undershoot or overshoot the target output frequency + * may not work if the values are not in "safe" range by panel + * specification. */ struct pllpad_dividers plld = { 0 }; u32 ref = clock_get_pll_input_khz() * 1000, m, n, p = 0; @@ -366,11 +368,10 @@ clock_display(u32 frequency) else plld.cpcon = 12; - if (best_diff) { + if (best_diff) printk(BIOS_ERR, "%s: Failed to match output frequency %u, " "best difference is %u.\n", __func__, frequency, best_diff); - } printk(BIOS_DEBUG, "%s: PLLD=%u ref=%u, m/n/p/cpcon=%u/%u/%u/%u\n", __func__, (ref / plld.m * plld.n) >> plld.p, ref, plld.m, plld.n, @@ -424,10 +425,10 @@ void clock_sdram(u32 m, u32 n, u32 p, u32 setup, u32 ph45, u32 ph90, u32 misc1 = ((setup << PLLM_MISC1_SETUP_SHIFT) | (ph45 << PLLM_MISC1_PD_LSHIFT_PH45_SHIFT) | (ph90 << PLLM_MISC1_PD_LSHIFT_PH90_SHIFT) | - (ph135 << PLLM_MISC1_PD_LSHIFT_PH135_SHIFT)), - misc2 = ((kvco << PLLM_MISC2_KVCO_SHIFT) | - (kcp << PLLM_MISC2_KCP_SHIFT)), - base; + (ph135 << PLLM_MISC1_PD_LSHIFT_PH135_SHIFT)); + u32 misc2 = ((kvco << PLLM_MISC2_KVCO_SHIFT) | + (kcp << PLLM_MISC2_KCP_SHIFT)); + u32 base; if (same_freq) emc_source |= CLK_SOURCE_EMC_MC_EMC_SAME_FREQ; @@ -455,9 +456,9 @@ void clock_sdram(u32 m, u32 n, u32 p, u32 setup, u32 ph45, u32 ph90, /* stable_time is required, before we can start to check lock. */ udelay(stable_time); - while (!(readl(&clk_rst->pllm_base) & PLL_BASE_LOCK)) { + while (!(readl(&clk_rst->pllm_base) & PLL_BASE_LOCK)) udelay(1); - } + /* * After PLLM reports being locked, we have to delay 10us before * enabling PLLM_OUT. @@ -484,7 +485,7 @@ void clock_cpu0_config_and_reset(void *entry) /* Set active CPU cluster to G */ clrbits_le32(&flow->cluster_control, 1); - // Set up cclk_brst and divider. + /* Set up cclk_brst and divider. */ write32((CRC_CCLK_BRST_POL_PLLX_OUT0 << 0) | (CRC_CCLK_BRST_POL_PLLX_OUT0 << 4) | (CRC_CCLK_BRST_POL_PLLX_OUT0 << 8) | @@ -494,21 +495,21 @@ void clock_cpu0_config_and_reset(void *entry) write32(CRC_SUPER_CCLK_DIVIDER_SUPER_CDIV_ENB, &clk_rst->super_cclk_div); - // Enable the clocks for CPUs 0-3. + /* Enable the clocks for CPUs 0-3. */ uint32_t cpu_cmplx_clr = read32(&clk_rst->clk_cpu_cmplx_clr); cpu_cmplx_clr |= CRC_CLK_CLR_CPU0_STP | CRC_CLK_CLR_CPU1_STP | CRC_CLK_CLR_CPU2_STP | CRC_CLK_CLR_CPU3_STP; write32(cpu_cmplx_clr, &clk_rst->clk_cpu_cmplx_clr); - // Enable other CPU related clocks. + /* Enable other CPU related clocks. */ setbits_le32(&clk_rst->clk_out_enb_l, CLK_L_CPU); setbits_le32(&clk_rst->clk_out_enb_v, CLK_V_CPUG); setbits_le32(&clk_rst->clk_out_enb_v, CLK_V_CPULP); - // Disable the reset on the non-CPU parts of the fast cluster. + /* Disable the reset on the non-CPU parts of the fast cluster. */ write32(CRC_RST_CPUG_CLR_NONCPU, &clk_rst->rst_cpug_cmplx_clr); - // Disable the various resets on the CPUs. + /* Disable the various resets on the CPUs. */ write32(CRC_RST_CPUG_CLR_CPU0 | CRC_RST_CPUG_CLR_CPU1 | CRC_RST_CPUG_CLR_CPU2 | CRC_RST_CPUG_CLR_CPU3 | CRC_RST_CPUG_CLR_DBG0 | CRC_RST_CPUG_CLR_DBG1 | @@ -520,10 +521,10 @@ void clock_cpu0_config_and_reset(void *entry) CRC_RST_CPUG_CLR_L2 | CRC_RST_CPUG_CLR_PDBG, &clk_rst->rst_cpug_cmplx_clr); - // Disable the reset on the non-CPU parts of the slow cluster. + /* Disable the reset on the non-CPU parts of the slow cluster. */ write32(CRC_RST_CPULP_CLR_NONCPU, &clk_rst->rst_cpulp_cmplx_clr); - // Disable the various resets on the LP CPU. + /* Disable the various resets on the LP CPU. */ write32(CRC_RST_CPULP_CLR_CPU0 | CRC_RST_CPULP_CLR_DBG0 | CRC_RST_CPULP_CLR_CORE0 | CRC_RST_CPULP_CLR_CX0 | CRC_RST_CPULP_CLR_L2 | CRC_RST_CPULP_CLR_PDBG, @@ -532,11 +533,10 @@ void clock_cpu0_config_and_reset(void *entry) void clock_halt_avp(void) { - for (;;) { + for (;;) write32(FLOW_EVENT_JTAG | FLOW_EVENT_LIC_IRQ | FLOW_EVENT_GIC_IRQ | FLOW_MODE_WAITEVENT, &flow->halt_cop_events); - } } void clock_init(void) @@ -601,22 +601,34 @@ void clock_init(void) void clock_enable_clear_reset(u32 l, u32 h, u32 u, u32 v, u32 w, u32 x) { - if (l) writel(l, &clk_rst->clk_enb_l_set); - if (h) writel(h, &clk_rst->clk_enb_h_set); - if (u) writel(u, &clk_rst->clk_enb_u_set); - if (v) writel(v, &clk_rst->clk_enb_v_set); - if (w) writel(w, &clk_rst->clk_enb_w_set); - if (x) writel(x, &clk_rst->clk_enb_x_set); + if (l) + writel(l, &clk_rst->clk_enb_l_set); + if (h) + writel(h, &clk_rst->clk_enb_h_set); + if (u) + writel(u, &clk_rst->clk_enb_u_set); + if (v) + writel(v, &clk_rst->clk_enb_v_set); + if (w) + writel(w, &clk_rst->clk_enb_w_set); + if (x) + writel(x, &clk_rst->clk_enb_x_set); /* Give clocks time to stabilize. */ udelay(IO_STABILIZATION_DELAY); - if (l) writel(l, &clk_rst->rst_dev_l_clr); - if (h) writel(h, &clk_rst->rst_dev_h_clr); - if (u) writel(u, &clk_rst->rst_dev_u_clr); - if (v) writel(v, &clk_rst->rst_dev_v_clr); - if (w) writel(w, &clk_rst->rst_dev_w_clr); - if (x) writel(x, &clk_rst->rst_dev_x_clr); + if (l) + writel(l, &clk_rst->rst_dev_l_clr); + if (h) + writel(h, &clk_rst->rst_dev_h_clr); + if (u) + writel(u, &clk_rst->rst_dev_u_clr); + if (v) + writel(v, &clk_rst->rst_dev_v_clr); + if (w) + writel(w, &clk_rst->rst_dev_w_clr); + if (x) + writel(x, &clk_rst->rst_dev_x_clr); } void clock_reset_l(u32 bit) |