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__ */