diff options
author | Aaron Durbin <adurbin@chromium.org> | 2016-08-06 13:42:37 -0500 |
---|---|---|
committer | Aaron Durbin <adurbin@chromium.org> | 2016-08-09 01:32:21 +0200 |
commit | 9ba069957b1591628ea4d5e2a9ff8553efa52c71 (patch) | |
tree | 0f370b43773242ce704158c676f964432230cb3b /src/soc/nvidia/tegra132/clock.c | |
parent | 0c634159a35ff567fc4897df25dddddd181a1a8c (diff) |
soc/nvidia/tegra132: remove tegra132 support
As no more mainboards are utilizing this SoC support code remove
it. It can be resurrected if ever needed.
BUG=chrome-os-partner:55932
Change-Id: Ic3caf6e6c9b62d012679b996abaa525c8bf679a9
Signed-off-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-on: https://review.coreboot.org/16108
Tested-by: build bot (Jenkins)
Reviewed-by: Furquan Shaikh <furquan@google.com>
Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net>
Diffstat (limited to 'src/soc/nvidia/tegra132/clock.c')
-rw-r--r-- | src/soc/nvidia/tegra132/clock.c | 726 |
1 files changed, 0 insertions, 726 deletions
diff --git a/src/soc/nvidia/tegra132/clock.c b/src/soc/nvidia/tegra132/clock.c deleted file mode 100644 index be12b856b1..0000000000 --- a/src/soc/nvidia/tegra132/clock.c +++ /dev/null @@ -1,726 +0,0 @@ -/* - * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved. - * Copyright 2014 Google Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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. - */ -#include <arch/clock.h> -#include <arch/io.h> -#include <console/console.h> -#include <delay.h> -#include <stdlib.h> -#include <soc/addressmap.h> -#include <soc/clk_rst.h> -#include <soc/clock.h> -#include <soc/clst_clk.h> -#include <soc/flow.h> -#include <soc/maincpu.h> -#include <soc/pmc.h> -#include <soc/sysctr.h> - -static struct clst_clk_ctlr *clst_clk = (void *)TEGRA_CLUSTER_CLOCK_BASE; -static struct flow_ctlr *flow = (void *)TEGRA_FLOW_BASE; -static struct tegra_pmc_regs *pmc = (void *)TEGRA_PMC_BASE; -static struct sysctr_regs *sysctr = (void *)TEGRA_SYSCTR0_BASE; - -struct pll_dividers { - u32 n : 10; - u32 m : 8; - u32 p : 4; - u32 cpcon : 4; - u32 lfcon : 4; - u32 : 2; -}; - -/* Some PLLs have more restrictive divider bit lengths or are missing some - * fields. Make sure to use the right struct in the osc_table definition to get - * compile-time checking, but keep the bits aligned with struct pll_dividers so - * they can be used interchangeably at run time. Add new formats as required. */ -struct pllcx_dividers { - u32 n : 8; - u32 : 2; - u32 m : 8; - u32 p : 4; - u32 : 10; -}; -struct pllpad_dividers { - u32 n : 10; - u32 m : 5; - u32 : 3; - u32 p : 3; - u32 : 1; - u32 cpcon : 4; - u32 : 6; -}; -struct pllu_dividers { - u32 n : 10; - u32 m : 5; - u32 : 3; - u32 p : 1; - u32 : 3; - u32 cpcon : 4; - u32 lfcon : 4; - u32 : 2; -}; - -union __attribute__((transparent_union)) pll_fields { - u32 raw; - struct pll_dividers div; - struct pllcx_dividers cx; - struct pllpad_dividers pad; - struct pllu_dividers u; -}; - -/* This table defines the frequency dividers for every PLL to turn the external - * OSC clock into the frequencies defined by TEGRA_PLL*_KHZ in soc/clock.h. - * All PLLs have three dividers (n, m and p), with the governing formula for - * the output frequency being CF = (IN / m), VCO = CF * n and OUT = VCO / (2^p). - * All divisor configurations must meet the PLL's constraints for VCO and CF: - * PLLX: 12 MHz < CF < 50 MHz, 700 MHz < VCO < 3000 MHz - * PLLC: 12 MHz < CF < 50 MHz, 600 MHz < VCO < 1400 MHz - * PLLM: 12 MHz < CF < 50 MHz, 400 MHz < VCO < 1066 MHz - * PLLP: 1 MHz < CF < 6 MHz, 200 MHz < VCO < 700 MHz - * PLLD: 1 MHz < CF < 6 MHz, 500 MHz < VCO < 1000 MHz - * PLLU: 1 MHz < CF < 6 MHz, 480 MHz < VCO < 960 MHz - * PLLDP: 12 MHz < CF < 38 MHz, 600 MHz < VCO < 1200 MHz - * (values taken from Linux' drivers/clk/tegra/clk-tegra124.c). */ -struct { - int khz; - struct pllcx_dividers pllx; /* target: CONFIG_PLLX_KHZ */ - struct pllcx_dividers pllc; /* target: 600 MHz */ - /* PLLM is set up dynamically by clock_sdram(). */ - /* PLLP is hardwired to 408 MHz in HW (unless we set BASE_OVRD). */ - struct pllu_dividers pllu; /* target; 960 MHz */ - struct pllcx_dividers plldp; /* target; 270 MHz */ - /* PLLDP treats p differently (OUT = VCO / (p + 1) for p < 6). */ -} static const osc_table[16] = { - [OSC_FREQ_12]{ - .khz = 12000, - .pllx = {.n = TEGRA_PLLX_KHZ / 12000, .m = 1, .p = 0}, - .pllc = {.n = 50, .m = 1, .p = 0}, - .pllu = {.n = 960, .m = 12, .p = 0, .cpcon = 12, .lfcon = 2}, - .plldp = {.n = 90, .m = 1, .p = 3}, - }, - [OSC_FREQ_13]{ - .khz = 13000, - .pllx = {.n = TEGRA_PLLX_KHZ / 13000, .m = 1, .p = 0}, - .pllc = {.n = 46, .m = 1, .p = 0}, /* 598.0 MHz */ - .pllu = {.n = 960, .m = 13, .p = 0, .cpcon = 12, .lfcon = 2}, - .plldp = {.n = 83, .m = 1, .p = 3}, /* 269.8 MHz */ - }, - [OSC_FREQ_16P8]{ - .khz = 16800, - .pllx = {.n = TEGRA_PLLX_KHZ / 16800, .m = 1, .p = 0}, - .pllc = {.n = 71, .m = 1, .p = 1}, /* 596.4 MHz */ - .pllu = {.n = 400, .m = 7, .p = 0, .cpcon = 5, .lfcon = 2}, - .plldp = {.n = 64, .m = 1, .p = 3}, /* 268.8 MHz */ - }, - [OSC_FREQ_19P2]{ - .khz = 19200, - .pllx = {.n = TEGRA_PLLX_KHZ / 19200, .m = 1, .p = 0}, - .pllc = {.n = 62, .m = 1, .p = 1}, /* 595.2 MHz */ - .pllu = {.n = 200, .m = 4, .p = 0, .cpcon = 3, .lfcon = 2}, - .plldp = {.n = 56, .m = 1, .p = 3}, /* 268.8 MHz */ - }, - [OSC_FREQ_26]{ - .khz = 26000, - .pllx = {.n = TEGRA_PLLX_KHZ / 26000, .m = 1, .p = 0}, - .pllc = {.n = 23, .m = 1, .p = 0}, /* 598.0 MHz */ - .pllu = {.n = 960, .m = 26, .p = 0, .cpcon = 12, .lfcon = 2}, - .plldp = {.n = 83, .m = 2, .p = 3}, /* 269.8 MHz */ - }, - /* These oscillators get predivided as PLL inputs... n/m/p divisors for - * 38.4 should always match 19.2, and 48 should always match 12. */ - [OSC_FREQ_38P4]{ - .khz = 38400, - .pllx = {.n = TEGRA_PLLX_KHZ / 19200, .m = 1, .p = 0}, - .pllc = {.n = 62, .m = 1, .p = 1}, /* 595.2 MHz */ - .pllu = {.n = 200, .m = 4, .p = 0, .cpcon = 3, .lfcon = 2}, - .plldp = {.n = 56, .m = 1, .p = 3}, /* 268.8 MHz */ - }, - [OSC_FREQ_48]{ - .khz = 48000, - .pllx = {.n = TEGRA_PLLX_KHZ / 12000, .m = 1, .p = 0}, - .pllc = {.n = 50, .m = 1, .p = 0}, - .pllu = {.n = 960, .m = 12, .p = 0, .cpcon = 12, .lfcon = 2}, - .plldp = {.n = 90, .m = 1, .p = 3}, - }, -}; - -/* Get the oscillator frequency, from the corresponding hardware - * configuration field. This is actually a per-soc thing. Avoid the - * temptation to make it common. - */ -static u32 clock_get_osc_bits(void) -{ - return (read32(CLK_RST_REG(osc_ctrl)) & OSC_FREQ_MASK) >> OSC_FREQ_SHIFT; -} - -int clock_get_osc_khz(void) -{ - return osc_table[clock_get_osc_bits()].khz; -} - -int clock_get_pll_input_khz(void) -{ - u32 osc_ctrl = read32(CLK_RST_REG(osc_ctrl)); - u32 osc_bits = (osc_ctrl & OSC_FREQ_MASK) >> OSC_FREQ_SHIFT; - u32 pll_ref_div = (osc_ctrl & OSC_PREDIV_MASK) >> OSC_PREDIV_SHIFT; - return osc_table[osc_bits].khz >> pll_ref_div; -} - -void clock_init_arm_generic_timer(void) -{ - uint32_t freq = clock_get_osc_khz() * 1000; - /* Set the cntfrq register. */ - set_cntfrq(freq); - - /* Record the system timer frequency. */ - write32(&sysctr->cntfid0, freq); - /* Enable the system counter. */ - uint32_t cntcr = read32(&sysctr->cntcr); - cntcr |= SYSCTR_CNTCR_EN | SYSCTR_CNTCR_HDBG; - write32(&sysctr->cntcr, cntcr); -} - -#define SOR0_CLK_SEL0 (1 << 14) -#define SOR0_CLK_SEL1 (1 << 15) - -void sor_clock_stop(void) -{ - /* The Serial Output Resource clock has to be off - * before we start the plldp. Learned the hard way. - * FIXME: this has to be cleaned up a bit more. - * Waiting on some new info from Nvidia. - */ - clrbits_le32(CLK_RST_REG(clk_src_sor), SOR0_CLK_SEL0 | SOR0_CLK_SEL1); -} - -void sor_clock_start(void) -{ - /* uses PLLP, has a non-standard bit layout. */ - setbits_le32(CLK_RST_REG(clk_src_sor), SOR0_CLK_SEL0); -} - -static void init_pll(u32 *base, u32 *misc, const union pll_fields pll, u32 lock) -{ - u32 dividers = pll.div.n << PLL_BASE_DIVN_SHIFT | - pll.div.m << PLL_BASE_DIVM_SHIFT | - pll.div.p << PLL_BASE_DIVP_SHIFT; - u32 misc_con = pll.div.cpcon << PLL_MISC_CPCON_SHIFT | - pll.div.lfcon << PLL_MISC_LFCON_SHIFT; - - /* Write dividers but BYPASS the PLL while we're messing with it. */ - write32(base, dividers | PLL_BASE_BYPASS); - /* - * Set Lock bit, CPCON and LFCON fields (default to 0 if it doesn't - * exist for this PLL) - */ - write32(misc, lock | misc_con); - - /* Enable PLL and take it back out of BYPASS */ - write32(base, dividers | PLL_BASE_ENABLE); - - /* Wait for lock ready */ - while (!(read32(base) & PLL_BASE_LOCK)); -} - -static void init_utmip_pll(void) -{ - int khz = clock_get_pll_input_khz(); - - /* Shut off PLL crystal clock while we mess with it */ - clrbits_le32(CLK_RST_REG(utmip_pll_cfg2), 1 << 30); /* PHY_XTAL_CLKEN */ - udelay(1); - - write32(CLK_RST_REG(utmip_pll_cfg0), /* 960MHz * 1 / 80 == 12 MHz */ - 80 << 16 | /* (rst) phy_divn */ - 1 << 8); /* (rst) phy_divm */ - - write32(CLK_RST_REG(utmip_pll_cfg1), - div_round_up(khz, 8000) << 27 | /* pllu_enbl_cnt / 8 (1us) */ - 0 << 16 | /* PLLU pwrdn */ - 0 << 14 | /* pll_enable pwrdn */ - 0 << 12 | /* pll_active pwrdn */ - div_round_up(khz, 102) << 0); /* phy_stbl_cnt / 256 (2.5ms) */ - - /* TODO: TRM can't decide if actv is 5us or 10us, keep an eye on it */ - write32(CLK_RST_REG(utmip_pll_cfg2), - 0 << 24 | /* SAMP_D/XDEV pwrdn */ - div_round_up(khz, 3200) << 18 | /* phy_actv_cnt / 16 (5us) */ - div_round_up(khz, 256) << 6 | /* pllu_stbl_cnt / 256 (1ms) */ - 0 << 4 | /* SAMP_C/USB3 pwrdn */ - 0 << 2 | /* SAMP_B/XHOST pwrdn */ - 0 << 0); /* SAMP_A/USBD pwrdn */ - - setbits_le32(CLK_RST_REG(utmip_pll_cfg2), 1 << 30); /* PHY_XTAL_CLKEN */ -} - -/* Graphics just has to be different. There's a few more bits we - * need to set in here, but it makes sense just to restrict all the - * special bits to this one function. - */ -static void graphics_pll(void) -{ - int osc = clock_get_osc_bits(); - u32 *cfg = CLK_RST_REG(plldp_ss_cfg); - /* the vendor code sets the dither bit (28) - * an undocumented bit (24) - * and clamp while we mess with it (22) - * Dither is pretty important to display port - * so we really do need to handle these bits. - * I'm not willing to not clamp it, even if - * it might "mostly work" with it not set, - * I don't want to find out in a few months - * that it is needed. - */ - u32 scfg = (1 << 28) | (1 << 24) | (1 << 22); - write32(cfg, scfg); - init_pll(CLK_RST_REG(plldp_base), CLK_RST_REG(plldp_misc), - osc_table[osc].plldp, PLLDPD2_MISC_LOCK_ENABLE); - /* leave dither and undoc bits set, release clamp */ - scfg = (1<<28) | (1<<24); - write32(cfg, scfg); -} - -/* - * Init PLLD clock source. - * - * @frequency: the requested plld frequency - * - * Return the plld frequency if success, otherwise return 0. - */ -u32 clock_configure_plld(u32 frequency) -{ - /** - * plld (fo) = vco >> p, where 500MHz < vco < 1000MHz - * = (cf * n) >> p, where 1MHz < cf < 6MHz - * = ((ref / m) * n) >> p - * - * Iterate the possible values of p (3 bits, 2^7) to find out a minimum - * safe vco, then find best (m, n). since m has only 5 bits, we can - * iterate all possible values. Note Tegra 124 supports 11 bits for n, - * but our pll_fields has only 10 bits for n. - * - * 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; - u32 cf, vco, rounded_rate = frequency; - u32 diff, best_diff; - const u32 max_m = 1 << 5, max_n = 1 << 10, max_p = 1 << 3, - mhz = 1000 * 1000, min_vco = 500 * mhz, max_vco = 1000 * mhz, - min_cf = 1 * mhz, max_cf = 6 * mhz; - - for (vco = frequency; vco < min_vco && p < max_p; p++) - vco <<= 1; - - if (vco < min_vco || vco > max_vco) { - printk(BIOS_ERR, "%s: Cannot find out a supported VCO" - " for Frequency (%u).\n", __func__, frequency); - return 0; - } - - plld.p = p; - best_diff = vco; - - for (m = 1; m < max_m && best_diff; m++) { - cf = ref / m; - if (cf < min_cf) - break; - if (cf > max_cf) - continue; - - n = vco / cf; - if (n >= max_n) - continue; - - diff = vco - n * cf; - if (n + 1 < max_n && diff > cf / 2) { - n++; - diff = cf - diff; - } - - if (diff >= best_diff) - continue; - - best_diff = diff; - plld.m = m; - plld.n = n; - } - - if (plld.n < 50) - plld.cpcon = 2; - else if (plld.n < 300) - plld.cpcon = 3; - else if (plld.n < 600) - plld.cpcon = 8; - else - plld.cpcon = 12; - - if (best_diff) { - printk(BIOS_WARNING, "%s: Failed to match output frequency %u, " - "best difference is %u.\n", __func__, frequency, - best_diff); - rounded_rate = (ref / plld.m * plld.n) >> plld.p; - } - - printk(BIOS_DEBUG, "%s: PLLD=%u ref=%u, m/n/p/cpcon=%u/%u/%u/%u\n", - __func__, rounded_rate, ref, plld.m, plld.n, plld.p, plld.cpcon); - - init_pll(CLK_RST_REG(plld_base), CLK_RST_REG(plld_misc), plld, - (PLLUD_MISC_LOCK_ENABLE | PLLD_MISC_CLK_ENABLE)); - - if (rounded_rate != frequency) - printk(BIOS_DEBUG, "PLLD rate: %u vs %u\n", rounded_rate, - frequency); - - return rounded_rate; -} - -/* Initialize the UART and put it on CLK_M so we can use it during clock_init(). - * Will later move it to PLLP in clock_config(). The divisor must be very small - * to accommodate 12KHz OSCs, so we override the 16.0 UART divider with the 15.1 - * CLK_SOURCE divider to get more precision. (This might still not be enough for - * some OSCs... if you use 13KHz, be prepared to have a bad time.) The 1900 has - * been determined through trial and error (must lead to div 13 at 24MHz). */ -void clock_early_uart(void) -{ - write32(CLK_RST_REG(clk_src_uarta), - CLK_SRC_DEV_ID(UARTA, CLK_M) << CLK_SOURCE_SHIFT | - CLK_UART_DIV_OVERRIDE | CLK_DIVIDER(TEGRA_CLK_M_KHZ, 1900)); - - clock_enable_clear_reset_l(CLK_L_UARTA); -} - -/* Enable output clock (CLK1~3) for external peripherals. */ -void clock_external_output(int clk_id) -{ - switch (clk_id) { - case 1: - setbits_le32(&pmc->clk_out_cntrl, 1 << 2); - break; - case 2: - setbits_le32(&pmc->clk_out_cntrl, 1 << 10); - break; - case 3: - setbits_le32(&pmc->clk_out_cntrl, 1 << 18); - break; - default: - printk(BIOS_CRIT, "ERROR: Unknown output clock id %d\n", - clk_id); - break; - } -} - -/* Start PLLM for SDRAM. */ -void clock_sdram(u32 m, u32 n, u32 p, u32 setup, u32 ph45, u32 ph90, - u32 ph135, u32 kvco, u32 kcp, u32 stable_time, u32 emc_source, - u32 same_freq) -{ - 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)); - 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; - else - emc_source &= ~CLK_SOURCE_EMC_MC_EMC_SAME_FREQ; - - /* - * Note PLLM_BASE.PLLM_OUT1_RSTN must be in RESET_ENABLE mode, and - * PLLM_BASE.ENABLE must be in DISABLE state (both are the default - * values after coldboot reset). - */ - - write32(CLK_RST_REG(pllm_misc1), misc1); - write32(CLK_RST_REG(pllm_misc2), misc2); - - /* PLLM.BASE needs BYPASS=0, different from general init_pll */ - base = read32(CLK_RST_REG(pllm_base)); - base &= ~(PLLCMX_BASE_DIVN_MASK | PLLCMX_BASE_DIVM_MASK | - PLLM_BASE_DIVP_MASK | PLL_BASE_BYPASS); - base |= ((m << PLL_BASE_DIVM_SHIFT) | (n << PLL_BASE_DIVN_SHIFT) | - (p << PLL_BASE_DIVP_SHIFT)); - write32(CLK_RST_REG(pllm_base), base); - - setbits_le32(CLK_RST_REG(pllm_base), PLL_BASE_ENABLE); - /* stable_time is required, before we can start to check lock. */ - udelay(stable_time); - - while (!(read32(CLK_RST_REG(pllm_base)) & PLL_BASE_LOCK)) - udelay(1); - - /* - * After PLLM reports being locked, we have to delay 10us before - * enabling PLLM_OUT. - */ - udelay(10); - - /* Put OUT1 out of reset state (start to output). */ - setbits_le32(CLK_RST_REG(pllm_out), PLLM_OUT1_RSTN_RESET_DISABLE); - - /* Enable and start MEM(MC) and EMC. */ - clock_enable_clear_reset(0, CLK_H_MEM | CLK_H_EMC, 0, 0, 0, 0); - write32(CLK_RST_REG(clk_src_emc), emc_source); - udelay(IO_STABILIZATION_DELAY); -} - -void clock_cpu0_config(void) -{ - u32 reg; - u32 osc = clock_get_osc_bits(); - u32 timeout = 0; - - /* disable IDDQ */ - reg = read32(&clst_clk->pllx_misc3); - reg &= ~PLLX_IDDQ; - write32(&clst_clk->pllx_misc3, reg); - - /* init pllx */ - init_pll(&clst_clk->pllx_base, &clst_clk->pllx_misc, - osc_table[osc].pllx, PLLPAXS_MISC_LOCK_ENABLE); - - /* - * Change CPU clock source to PLLX_OUT0_LJ - * when above pllx programming has taken effect. - */ - do { - if (read32(&clst_clk->misc_ctrl) & CLK_SWITCH_MATCH) { - write32(&clst_clk->cclk_brst_pol, - (CC_CCLK_BRST_POL_PLLX_OUT0_LJ << 28)); - break; - } - - /* wait and try again */ - if (timeout >= CLK_SWITCH_TIMEOUT_US) { - printk(BIOS_ERR, "%s: PLLX programming timeout. " - "Switching CPU clock has falied.\n", - __func__); - break; - } - udelay(10); - timeout += 10; - - } while (1); -} - -void clock_halt_avp(void) -{ - for (;;) - write32(&flow->halt_cop_events, - FLOW_EVENT_JTAG | FLOW_EVENT_LIC_IRQ | - FLOW_EVENT_GIC_IRQ | FLOW_MODE_WAITEVENT); -} - -void clock_init(void) -{ - u32 osc = clock_get_osc_bits(); - - /* Set PLLC dynramp_step A to 0x2b and B to 0xb (from U-Boot -- why? */ - write32(CLK_RST_REG(pllc_misc2), 0x2b << 17 | 0xb << 9); - - /* Max out the AVP clock before everything else (need PLLC for that). */ - init_pll(CLK_RST_REG(pllc_base), CLK_RST_REG(pllc_misc), - osc_table[osc].pllc, PLLC_MISC_LOCK_ENABLE); - - /* Typical ratios are 1:2:2 or 1:2:3 sclk:hclk:pclk (See: APB DMA - * features section in the TRM). */ - write32(CLK_RST_REG(clk_sys_rate), /* pclk = hclk = sclk/2 */ - 1 << HCLK_DIVISOR_SHIFT | 0 << PCLK_DIVISOR_SHIFT); - write32(CLK_RST_REG(pllc_out), - CLK_DIVIDER(TEGRA_PLLC_KHZ, 300000) << PLL_OUT_RATIO_SHIFT | - PLL_OUT_CLKEN | PLL_OUT_RSTN); - write32(CLK_RST_REG(sclk_brst_pol), /* sclk = 300 MHz */ - SCLK_SYS_STATE_RUN << SCLK_SYS_STATE_SHIFT | - SCLK_SOURCE_PLLC_OUT1 << SCLK_RUN_SHIFT); - - /* Change the oscillator drive strength (from U-Boot -- why?) */ - clrsetbits_le32(CLK_RST_REG(osc_ctrl), OSC_XOFS_MASK, - OSC_DRIVE_STRENGTH << OSC_XOFS_SHIFT); - - /* - * Ambiguous quote from u-boot. TODO: what's this mean? - * "should update same value in PMC_OSC_EDPD_OVER XOFS - * field for warmboot " - */ - clrsetbits_le32(&pmc->osc_edpd_over, PMC_OSC_EDPD_OVER_XOFS_MASK, - OSC_DRIVE_STRENGTH << PMC_OSC_EDPD_OVER_XOFS_SHIFT); - - /* Set up PLLP_OUT(1|2|3|4) divisor to generate (9.6|48|102|204)MHz */ - write32(CLK_RST_REG(pllp_outa), - (CLK_DIVIDER(TEGRA_PLLP_KHZ, 9600) << PLL_OUT_RATIO_SHIFT | - PLL_OUT_OVR | PLL_OUT_CLKEN | PLL_OUT_RSTN) << PLL_OUT1_SHIFT | - (CLK_DIVIDER(TEGRA_PLLP_KHZ, 48000) << PLL_OUT_RATIO_SHIFT | - PLL_OUT_OVR | PLL_OUT_CLKEN | PLL_OUT_RSTN) << PLL_OUT2_SHIFT); - write32(CLK_RST_REG(pllp_outb), - (CLK_DIVIDER(TEGRA_PLLP_KHZ, 102000) << PLL_OUT_RATIO_SHIFT | - PLL_OUT_OVR | PLL_OUT_CLKEN | PLL_OUT_RSTN) << PLL_OUT3_SHIFT | - (CLK_DIVIDER(TEGRA_PLLP_KHZ, 204000) << PLL_OUT_RATIO_SHIFT | - PLL_OUT_OVR | PLL_OUT_CLKEN | PLL_OUT_RSTN) << PLL_OUT4_SHIFT); - - /* init pllu */ - init_pll(CLK_RST_REG(pllu_base), CLK_RST_REG(pllu_misc), - osc_table[osc].pllu, PLLUD_MISC_LOCK_ENABLE); - - init_utmip_pll(); - graphics_pll(); -} - -void clock_grp_enable_clear_reset(u32 val, u32* clk_enb_set_reg, - u32 *rst_dev_clr_reg) -{ - write32(clk_enb_set_reg, val); - udelay(IO_STABILIZATION_DELAY); - write32(rst_dev_clr_reg, val); -} - -static u32 * const clk_enb_set_arr[DEV_CONFIG_BLOCKS] = { - CLK_RST_REG(clk_enb_l_set), - CLK_RST_REG(clk_enb_h_set), - CLK_RST_REG(clk_enb_u_set), - CLK_RST_REG(clk_enb_v_set), - CLK_RST_REG(clk_enb_w_set), - CLK_RST_REG(clk_enb_x_set), -}; - -static u32 * const clk_enb_clr_arr[DEV_CONFIG_BLOCKS] = { - CLK_RST_REG(clk_enb_l_clr), - CLK_RST_REG(clk_enb_h_clr), - CLK_RST_REG(clk_enb_u_clr), - CLK_RST_REG(clk_enb_v_clr), - CLK_RST_REG(clk_enb_w_clr), - CLK_RST_REG(clk_enb_x_clr), -}; - -static u32 * const rst_dev_set_arr[DEV_CONFIG_BLOCKS] = { - CLK_RST_REG(rst_dev_l_set), - CLK_RST_REG(rst_dev_h_set), - CLK_RST_REG(rst_dev_u_set), - CLK_RST_REG(rst_dev_v_set), - CLK_RST_REG(rst_dev_w_set), - CLK_RST_REG(rst_dev_x_set), -}; - -static u32 * const rst_dev_clr_arr[DEV_CONFIG_BLOCKS] = { - CLK_RST_REG(rst_dev_l_clr), - CLK_RST_REG(rst_dev_h_clr), - CLK_RST_REG(rst_dev_u_clr), - CLK_RST_REG(rst_dev_v_clr), - CLK_RST_REG(rst_dev_w_clr), - CLK_RST_REG(rst_dev_x_clr), -}; - -static void clock_write_regs(u32 * const regs[DEV_CONFIG_BLOCKS], - u32 bits[DEV_CONFIG_BLOCKS]) -{ - int i = 0; - - for (; i < DEV_CONFIG_BLOCKS; i++) - if (bits[i]) - write32(regs[i], bits[i]); -} - -void clock_enable_regs(u32 bits[DEV_CONFIG_BLOCKS]) -{ - clock_write_regs(clk_enb_set_arr, bits); -} - -void clock_disable_regs(u32 bits[DEV_CONFIG_BLOCKS]) -{ - clock_write_regs(clk_enb_clr_arr, bits); -} - -void clock_set_reset_regs(u32 bits[DEV_CONFIG_BLOCKS]) -{ - clock_write_regs(rst_dev_set_arr, bits); -} - -void clock_clr_reset_regs(u32 bits[DEV_CONFIG_BLOCKS]) -{ - clock_write_regs(rst_dev_clr_arr, bits); -} - -void clock_enable_clear_reset(u32 l, u32 h, u32 u, u32 v, u32 w, u32 x) -{ - clock_enable(l, h, u, v, w, x); - - /* Give clocks time to stabilize. */ - udelay(IO_STABILIZATION_DELAY); - - clock_clr_reset(l, h, u, v, w, x); -} - -static void clock_reset_dev(u32 *setaddr, u32 *clraddr, u32 bit) -{ - write32(setaddr, bit); - udelay(LOGIC_STABILIZATION_DELAY); - write32(clraddr, bit); -} - -void clock_reset_l(u32 bit) -{ - clock_reset_dev(CLK_RST_REG(rst_dev_l_set), CLK_RST_REG(rst_dev_l_clr), - bit); -} - -void clock_reset_h(u32 bit) -{ - clock_reset_dev(CLK_RST_REG(rst_dev_h_set), CLK_RST_REG(rst_dev_h_clr), - bit); -} - -void clock_reset_u(u32 bit) -{ - clock_reset_dev(CLK_RST_REG(rst_dev_u_set), CLK_RST_REG(rst_dev_u_clr), - bit); -} - -void clock_reset_v(u32 bit) -{ - clock_reset_dev(CLK_RST_REG(rst_dev_v_set), CLK_RST_REG(rst_dev_v_clr), - bit); -} - -void clock_reset_w(u32 bit) -{ - clock_reset_dev(CLK_RST_REG(rst_dev_w_set), CLK_RST_REG(rst_dev_w_clr), - bit); -} - -void clock_reset_x(u32 bit) -{ - clock_reset_dev(CLK_RST_REG(rst_dev_x_set), CLK_RST_REG(rst_dev_x_clr), - bit); -} - -/* Enable/unreset all audio toys under AHUB */ -void clock_enable_audio(void) -{ - /* - * Confirmed by NVIDIA hardware team, we need to take ALL audio devices - * connected to AHUB (AUDIO, APBIF, I2S, DAM, AMX, ADX, SPDIF, AFC) out - * of reset and clock-enabled, otherwise reading AHUB devices (in our - * case, I2S/APBIF/AUDIO<XBAR>) will hang. - */ - clock_enable_clear_reset(CLK_L_I2S0 | CLK_L_I2S1 | CLK_L_I2S2 | CLK_L_SPDIF, - 0, 0, - CLK_V_I2S3 | CLK_V_I2S4 | CLK_V_AUDIO | CLK_V_APBIF | - CLK_V_DAM0 | CLK_V_DAM1 | CLK_V_DAM2 | CLK_V_EXTPERIPH1, - CLK_W_AMX0 | CLK_W_ADX0, - CLK_X_ADX1 | CLK_X_AFC0 | CLK_X_AFC1 | CLK_X_AFC2 | - CLK_X_AFC3 | CLK_X_AFC4 | CLK_X_AFC5 | CLK_X_AMX1); -} |