From 5ab100b0bad22814261f9b755b59394562c9145a Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 27 Oct 2013 06:27:20 -0700 Subject: [PATCH] tegra124: nyan: Move mainboard level clock stuff into the mainboard source. The decision about what clocks and units to enable and what sources and divisors to use had been configured in the tegra124 source, but really those decisions need to be made on a mainboard to mainboard basis. This code keeps some generic mechanism in the tegra124 directory but moves most of the rest of it to the nyan directory. It would be good to abstract the source and divisor setting functions a bit more since that code is still pretty big, and requires knowledge of the clock and reset controller and its constants and bitfields. Also we should move code related to function units which aren't actually used in the bootblock into later stages so they can be updated. BUG=None TEST=Built and booted on nyan. BRANCH=None Change-Id: Ied7ecceced3016f1fcb32101d780b7c235b881db Signed-off-by: Gabe Black Reviewed-on: https://chromium-review.googlesource.com/174843 Reviewed-by: Gabe Black Commit-Queue: Gabe Black Tested-by: Gabe Black --- src/mainboard/google/nyan/bootblock.c | 54 ++++++++++++++- src/soc/nvidia/tegra124/clock.c | 76 ++++----------------- src/soc/nvidia/tegra124/include/soc/clock.h | 9 ++- 3 files changed, 73 insertions(+), 66 deletions(-) diff --git a/src/mainboard/google/nyan/bootblock.c b/src/mainboard/google/nyan/bootblock.c index 614f76ee6a..33cd49410e 100644 --- a/src/mainboard/google/nyan/bootblock.c +++ b/src/mainboard/google/nyan/bootblock.c @@ -17,19 +17,71 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include #include #include #include +#include #include #include +#include #include #include /* FIXME: move back to soc code? */ #include "pmic.h" +static struct clk_rst_ctlr *clk_rst = (void *)TEGRA_CLK_RST_BASE; + +static void set_clock_sources(void) +{ + clock_configure_source(mselect, PLLP, 102000); + + /* TODO: is the 1.333MHz correct? This may have always been bogus... */ + clock_configure_source(i2c1, CLK_M, 1333); + clock_configure_source(i2c2, CLK_M, 1333); + clock_configure_source(i2c3, CLK_M, 1333); + clock_configure_source(i2c4, CLK_M, 1333); + clock_configure_source(i2c5, CLK_M, 1333); + + /* UARTA gets PLLP, deactivate CLK_UART_DIV_OVERRIDE */ + writel(PLLP << CLK_SOURCE_SHIFT, &clk_rst->clk_src_uarta); + + /* + * MMC3 and MMC4: Set base clock frequency for SD Clock to Tegra MMC's + * maximum speed (48MHz) so we can change SDCLK by second stage divisor + * in payloads, without touching base clock. + */ + clock_configure_source(sdmmc3, PLLP, 48000); + clock_configure_source(sdmmc4, PLLP, 48000); + + /* PLLP and PLLM are switched for HOST1x for no apparent reason. */ + write32(4 /* PLLP! */ << CLK_SOURCE_SHIFT | + /* TODO(rminnich): The divisor isn't accurate enough to get to + * 144MHz (it goes to 163 instead). What should we do here? */ + CLK_DIVIDER(TEGRA_PLLP_KHZ, 144000), + &clk_rst->clk_src_host1x); + + /* DISP1 doesn't support a divisor. Use PLLC which runs at 600MHz. */ + clock_configure_source(disp1, PLLC, 600000); +} + void bootblock_mainboard_init(void) { - clock_config(); + set_clock_sources(); + + clock_enable_clear_reset( + // l clocks. + CLK_L_CACHE2 | CLK_L_GPIO | CLK_L_TMR | CLK_L_I2C1 | + CLK_L_SDMMC4, + // h clocks. + CLK_H_EMC | CLK_H_I2C2 | CLK_H_I2C5 | CLK_H_SBC1 | CLK_H_PMC | + CLK_H_APBDMA | CLK_H_MEM, + // u clocks. + CLK_U_I2C3 | CLK_U_CSITE | CLK_U_SDMMC3, + // v clocks. + CLK_V_MSELECT | CLK_V_I2C4, + // w clocks. + CLK_W_DVFS); // I2C1 clock. pinmux_set_config(PINMUX_GEN1_I2C_SCL_INDEX, diff --git a/src/soc/nvidia/tegra124/clock.c b/src/soc/nvidia/tegra124/clock.c index ab6e0e157f..12ca61f889 100644 --- a/src/soc/nvidia/tegra124/clock.c +++ b/src/soc/nvidia/tegra124/clock.c @@ -24,13 +24,6 @@ #include "pmc.h" #include "sysctr.h" -/* Warning: Some devices just use different bits for the same sources for no - * apparent reason. *Always* double-check the TRM before trusting this macro. */ -#define clock_configure_source(device, src, freq) \ - clrsetbits_le32(&clk_rst->clk_src_##device, \ - CLK_SOURCE_MASK | CLK_DIVISOR_MASK, \ - src << CLK_SOURCE_SHIFT | CLK_DIVIDER(TEGRA_##src##_KHZ, freq)); - static struct clk_rst_ctlr *clk_rst = (void *)TEGRA_CLK_RST_BASE; static struct flow_ctlr *flow = (void *)TEGRA_FLOW_BASE; static struct tegra_pmc_regs *pmc = (void *)TEGRA_PMC_BASE; @@ -332,66 +325,21 @@ void clock_init(void) writel(val, &clk_rst->clk_sys_rate); } -void clock_config(void) +void clock_enable_clear_reset(u32 l, u32 h, u32 u, u32 v, u32 w) { - /* Enable clocks for the required peripherals. */ /* TODO: can (should?) we use the _SET and _CLR registers here? */ - setbits_le32(&clk_rst->clk_out_enb_l, - CLK_L_CACHE2 | CLK_L_GPIO | CLK_L_TMR | CLK_L_I2C1 | - CLK_L_SDMMC4 | CLK_L_DISP1 | CLK_L_HOST1X); - setbits_le32(&clk_rst->clk_out_enb_h, - CLK_H_EMC | CLK_H_I2C2 | CLK_H_I2C5 | CLK_H_SBC1 | - CLK_H_PMC | CLK_H_APBDMA | CLK_H_MEM); - setbits_le32(&clk_rst->clk_out_enb_u, - CLK_U_I2C3 | CLK_U_CSITE | CLK_U_SDMMC3); - setbits_le32(&clk_rst->clk_out_enb_v, CLK_V_MSELECT | CLK_V_I2C4); - setbits_le32(&clk_rst->clk_out_enb_w, CLK_W_DVFS); + setbits_le32(&clk_rst->clk_out_enb_l, l); + setbits_le32(&clk_rst->clk_out_enb_h, h); + setbits_le32(&clk_rst->clk_out_enb_u, u); + setbits_le32(&clk_rst->clk_out_enb_v, v); + setbits_le32(&clk_rst->clk_out_enb_w, w); - /* Give clock time to stabilize */ + /* Give clocks time to stabilize. */ udelay(IO_STABILIZATION_DELAY); - clock_configure_source(mselect, PLLP, 102000); - - /* TODO: is the 1.333MHz correct? This may have always been bogus... */ - clock_configure_source(i2c1, CLK_M, 1333); - clock_configure_source(i2c2, CLK_M, 1333); - clock_configure_source(i2c3, CLK_M, 1333); - clock_configure_source(i2c4, CLK_M, 1333); - clock_configure_source(i2c5, CLK_M, 1333); - - /* Move UARTA to PLLP and remove the CLK_UART_DIV_OVERRIDE */ - write32(PLLP << CLK_SOURCE_SHIFT, &clk_rst->clk_src_uarta); - - /* MMC3 and MMC4: Set base clock frequency for SD Clock to Tegra MMC's - * maximum speed (48MHz) so we can change SDCLK by second stage divisor - * in payloads, without touching base clock. - */ - clock_configure_source(sdmmc3, PLLP, 48000); - clock_configure_source(sdmmc4, PLLP, 48000); - - /* PLLP and PLLM are switched for HOST1x for no apparent reason. */ - write32(4 /* PLLP! */ << CLK_SOURCE_SHIFT | - /* TODO(rminnich): The divisor isn't accurate enough to get to - * 144MHz (it goes to 163 instead). What should we do here? */ - CLK_DIVIDER(TEGRA_PLLP_KHZ, 144000), - &clk_rst->clk_src_host1x); - - /* DISP1 doesn't support a divisor. Use PLLC which runs at 600MHz. */ - clock_configure_source(disp1, PLLC, 600000); - - /* Give clock time to stabilize. */ - udelay(IO_STABILIZATION_DELAY); - - /* Take required peripherals out of reset. */ - - clrbits_le32(&clk_rst->rst_dev_l, - CLK_L_CACHE2 | CLK_L_GPIO | CLK_L_TMR | CLK_L_I2C1 | - CLK_L_SDMMC4 | CLK_L_DISP1 | CLK_L_HOST1X); - clrbits_le32(&clk_rst->rst_dev_h, - CLK_H_EMC | CLK_H_I2C2 | CLK_H_I2C5 | CLK_H_SBC1 | - CLK_H_PMC | CLK_H_APBDMA | CLK_H_MEM); - clrbits_le32(&clk_rst->rst_dev_u, - CLK_U_I2C3 | CLK_U_CSITE | CLK_U_SDMMC3); - clrbits_le32(&clk_rst->rst_dev_v, CLK_V_MSELECT | CLK_V_I2C4); - clrbits_le32(&clk_rst->rst_dev_w, CLK_W_DVFS); + clrbits_le32(&clk_rst->rst_dev_l, l); + clrbits_le32(&clk_rst->rst_dev_h, h); + clrbits_le32(&clk_rst->rst_dev_u, u); + clrbits_le32(&clk_rst->rst_dev_v, v); + clrbits_le32(&clk_rst->rst_dev_w, w); } diff --git a/src/soc/nvidia/tegra124/include/soc/clock.h b/src/soc/nvidia/tegra124/include/soc/clock.h index c229e4e866..c95a9ccc1d 100644 --- a/src/soc/nvidia/tegra124/include/soc/clock.h +++ b/src/soc/nvidia/tegra124/include/soc/clock.h @@ -155,6 +155,13 @@ enum { /* Calculate clock frequency value from reference and clock divider value */ #define CLK_FREQUENCY(REF, REG) (((REF) * 2) / (REG + 2)) +/* Warning: Some devices just use different bits for the same sources for no + * apparent reason. *Always* double-check the TRM before trusting this macro. */ +#define clock_configure_source(device, src, freq) \ + clrsetbits_le32(&clk_rst->clk_src_##device, \ + CLK_SOURCE_MASK | CLK_DIVISOR_MASK, \ + src << CLK_SOURCE_SHIFT | CLK_DIVIDER(TEGRA_##src##_KHZ, freq)); + enum clock_source { /* Careful: Not true for all sources, always check TRM! */ PLLP = 0, PLLC2 = 1, @@ -178,7 +185,7 @@ enum clock_source { /* Careful: Not true for all sources, always check TRM! */ int clock_get_osc_khz(void); void clock_early_uart(void); void clock_cpu0_config_and_reset(void * entry); -void clock_config(void); +void clock_enable_clear_reset(u32 l, u32 h, u32 u, u32 v, u32 w); void clock_init(void); void clock_init_arm_generic_timer(void); #endif /* __SOC_NVIDIA_TEGRA124_CLOCK_H__ */