From 8fdcf3287cf3bc3391f1a853857b16fc208b3340 Mon Sep 17 00:00:00 2001 From: Furquan Shaikh Date: Fri, 5 Sep 2014 14:29:24 -0700 Subject: [PATCH] tegra132: Fix clock apis Instead of directly using the clk_src_id based on enum for clock source, every device needs to have its own set of clk source ids defined. This prevents accidentally selecting a wrong clk source if the ids are different from host1x's. Also, clk_src_id is separated from clk_src_freq_id. clk_src_id is the clk src id represented in CLK_SOURCE_ registers, whereas clk_src_freq_id is used for handling the common clock sources based on id to get the proper frequency in software. [pg: integrated a later commit to fix the build] BUG=chrome-os-partner:31821 BRANCH=None TEST=Compiles successfully and boots to kernel prompt Change-Id: I5d40fb49b81e8838b2be071d32c466213215e0d6 Signed-off-by: Patrick Georgi Original-Commit-Id: 27d5d6a34d1c826c6095c18368efb78c228d4ca8 Original-Change-Id: I5c88bed62841ebd81665cf8ffd82b0d88255f927 Original-Signed-off-by: Furquan Shaikh Original-Reviewed-on: https://chromium-review.googlesource.com/216761 Original-Tested-by: Furquan Shaikh Original-Reviewed-by: Aaron Durbin Original-Commit-Queue: Furquan Shaikh Original-Commit-Id: 13c30c50a9e8a7f3c48673a2f6c144ba546129b6 Original-Change-Id: I6659858c24e925aec9495bf64344c0000ad19b4c Original-Signed-off-by: Tom Warren Original-Reviewed-on: https://chromium-review.googlesource.com/217342 Original-Reviewed-by: Aaron Durbin Reviewed-on: http://review.coreboot.org/9033 Tested-by: build bot (Jenkins) Reviewed-by: Stefan Reinauer --- src/soc/nvidia/tegra132/clock.c | 3 +- src/soc/nvidia/tegra132/funitcfg.c | 8 +- src/soc/nvidia/tegra132/include/soc/clock.h | 82 +++++++++++-------- .../nvidia/tegra132/include/soc/funitcfg.h | 4 +- 4 files changed, 59 insertions(+), 38 deletions(-) diff --git a/src/soc/nvidia/tegra132/clock.c b/src/soc/nvidia/tegra132/clock.c index 6640505b34..1dbec797ef 100644 --- a/src/soc/nvidia/tegra132/clock.c +++ b/src/soc/nvidia/tegra132/clock.c @@ -400,7 +400,8 @@ clock_display(u32 frequency) * been determined through trial and error (must lead to div 13 at 24MHz). */ void clock_early_uart(void) { - write32(CLK_M << CLK_SOURCE_SHIFT | CLK_UART_DIV_OVERRIDE | + write32(CLK_SRC_DEV_ID(UARTA, CLK_M) << CLK_SOURCE_SHIFT | + CLK_UART_DIV_OVERRIDE | CLK_DIVIDER(TEGRA_CLK_M_KHZ, 1900), &clk_rst->clk_src_uarta); setbits_le32(&clk_rst->clk_out_enb_l, CLK_L_UARTA); udelay(2); diff --git a/src/soc/nvidia/tegra132/funitcfg.c b/src/soc/nvidia/tegra132/funitcfg.c index 205e3762b4..41bbc4ad8a 100644 --- a/src/soc/nvidia/tegra132/funitcfg.c +++ b/src/soc/nvidia/tegra132/funitcfg.c @@ -98,11 +98,11 @@ static const struct funit_cfg_data funit_data[] = { _Static_assert(ARRAY_SIZE(funit_data) == FUNIT_INDEX_MAX, "funit_cfg_data array not filled out!"); -static inline uint32_t get_clk_src_freq(uint32_t clk_src) +static inline uint32_t get_clk_src_freq(uint32_t clk_src_freq_id) { uint32_t freq = 0; - switch(clk_src) { + switch (clk_src_freq_id) { case CLK_M: freq = TEGRA_CLK_M_KHZ; break; @@ -111,7 +111,7 @@ static inline uint32_t get_clk_src_freq(uint32_t clk_src) break; default: printk(BIOS_SPEW, "%s ERROR: Unknown clk_src %d\n", - __func__,clk_src); + __func__, clk_src_freq_id); } return freq; @@ -125,7 +125,7 @@ static void configure_clock(const struct funit_cfg * const entry, uint32_t clk_div_mask; uint32_t clk_src_freq; - clk_src_freq = get_clk_src_freq(entry->clk_src_id); + clk_src_freq = get_clk_src_freq(entry->clk_src_freq_id); if (strncmp(funit->name, funit_i2c, strlen(funit_i2c)) == 0) { /* I2C funit */ diff --git a/src/soc/nvidia/tegra132/include/soc/clock.h b/src/soc/nvidia/tegra132/include/soc/clock.h index 711741ba9e..4f822e4a77 100644 --- a/src/soc/nvidia/tegra132/include/soc/clock.h +++ b/src/soc/nvidia/tegra132/include/soc/clock.h @@ -176,6 +176,52 @@ enum { CLK_X_SPARE = 0x1 << 0, }; +enum { + PLLP = 0, + PLLC2 = 1, + PLLC = 2, + PLLC3 = 3, + PLLM = 4, + CLK_M = 5, + CLK_S = 6, + PLLE = 7, + PLLA = 8, + UNUSED = 100, +}; + +#define CLK_SRC_DEV_ID(dev, src) CLK_SRC_##dev##_##src +#define CLK_SRC_FREQ_ID(dev, src) CLK_SRC_FREQ_##dev##_##src + +#define CLK_SRC_DEVICE(dev, a, b, c, d, e, f, g) \ + CLK_SRC_DEV_ID(dev, a) = 0, \ + CLK_SRC_DEV_ID(dev, b) = 1, \ + CLK_SRC_DEV_ID(dev, c) = 2, \ + CLK_SRC_DEV_ID(dev, d) = 3, \ + CLK_SRC_DEV_ID(dev, e) = 4, \ + CLK_SRC_DEV_ID(dev, f) = 5, \ + CLK_SRC_DEV_ID(dev, g) = 6, \ + CLK_SRC_FREQ_ID(dev, a) = a, \ + CLK_SRC_FREQ_ID(dev, b) = b, \ + CLK_SRC_FREQ_ID(dev, c) = c, \ + CLK_SRC_FREQ_ID(dev, d) = d, \ + CLK_SRC_FREQ_ID(dev, e) = e, \ + CLK_SRC_FREQ_ID(dev, f) = f, \ + CLK_SRC_FREQ_ID(dev, g) = g + +enum { + CLK_SRC_DEVICE(host1x, PLLM, PLLC2, PLLC, PLLC3, PLLP, UNUSED, PLLA), + CLK_SRC_DEVICE(I2C2, PLLP, PLLC2, PLLC, PLLC3, PLLM, UNUSED, CLK_M), + CLK_SRC_DEVICE(I2C3, PLLP, PLLC2, PLLC, PLLC3, PLLM, UNUSED, CLK_M), + CLK_SRC_DEVICE(I2C5, PLLP, PLLC2, PLLC, PLLC3, PLLM, UNUSED, CLK_M), + CLK_SRC_DEVICE(I2C6, PLLP, PLLC2, PLLC, PLLC3, PLLM, UNUSED, CLK_M), + CLK_SRC_DEVICE(mselect, PLLP, PLLC2, PLLC, PLLC3, PLLM, CLK_S, CLK_M), + CLK_SRC_DEVICE(SBC1, PLLP, PLLC2, PLLC, PLLC3, PLLM, UNUSED, CLK_M), + CLK_SRC_DEVICE(SBC4, PLLP, PLLC2, PLLC, PLLC3, PLLM, UNUSED, CLK_M), + CLK_SRC_DEVICE(SDMMC3, PLLP, PLLC2, PLLC, PLLC3, PLLM, PLLE, CLK_M), + CLK_SRC_DEVICE(SDMMC4, PLLP, PLLC2, PLLC, PLLC3, PLLM, PLLE, CLK_M), + CLK_SRC_DEVICE(UARTA, PLLP, PLLC2, PLLC, PLLC3, PLLM, UNUSED, CLK_M), +}; + /* PLL stabilization delay in usec */ #define CLOCK_PLL_STABLE_DELAY_US 300 @@ -242,38 +288,10 @@ static inline void _clock_set_div(u32 *reg, const char *name, u32 div, #define CLK_DIV_MASK 0xff #define CLK_DIV_MASK_I2C 0xffff -#define clock_configure_irregular_source(device, src, freq, src_id) \ - _clock_set_div(&clk_rst->clk_src_##device, #device, \ - get_clk_div(TEGRA_##src##_KHZ, freq), CLK_DIV_MASK, src_id) - -/* 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) \ - clock_configure_irregular_source(device, src, freq, src) - -/* The I2C divisors are not 7.1 divisors like the others, they divide by n + 1 - * directly. Also, there are internal divisors in the I2C controller itself. - * We can deal with those here and make it easier to select what the actual - * bus frequency will be. The 0x19 value is the default divisor in the - * clk_divisor register in the controller, and 8 is just a magic number in the - * documentation. - */ -#define clock_configure_i2c_scl_freq(device, src, freq) \ - _clock_set_div(&clk_rst->clk_src_##device, #device, \ - get_i2c_clk_div(TEGRA_##src##_KHZ, freq), \ - CLK_DIV_MASK_I2C, src) - -enum clock_source { /* Careful: Not true for all sources, always check TRM! */ - PLLP = 0, - PLLC2 = 1, - PLLC = 2, - PLLD = 2, - PLLC3 = 3, - PLLA = 3, - PLLM = 4, - PLLD2 = 5, - CLK_M = 6, -}; +#define clock_configure_source(device, src, freq) \ + _clock_set_div(&clk_rst->clk_src_##device, #device, \ + get_clk_div(TEGRA_##src##_KHZ, freq), CLK_DIV_MASK, \ + CLK_SRC_DEV_ID(device, src)) /* soc-specific */ #define TEGRA_CLK_M_KHZ clock_get_osc_khz() diff --git a/src/soc/nvidia/tegra132/include/soc/funitcfg.h b/src/soc/nvidia/tegra132/include/soc/funitcfg.h index 516bc65445..cf49d0ab8c 100644 --- a/src/soc/nvidia/tegra132/include/soc/funitcfg.h +++ b/src/soc/nvidia/tegra132/include/soc/funitcfg.h @@ -61,6 +61,7 @@ enum { struct funit_cfg { uint32_t funit_index; uint32_t clk_src_id; + uint32_t clk_src_freq_id; uint32_t clk_dev_freq_khz; struct pad_config const* pad_cfg; size_t pad_cfg_size; @@ -69,7 +70,8 @@ struct funit_cfg { #define FUNIT_CFG(_funit,_clk_src,_clk_freq,_cfg,_cfg_size) \ { \ .funit_index = FUNIT_INDEX(_funit), \ - .clk_src_id = _clk_src, \ + .clk_src_id = CLK_SRC_DEV_ID(_funit, _clk_src), \ + .clk_src_freq_id = CLK_SRC_FREQ_ID(_funit, _clk_src), \ .clk_dev_freq_khz = _clk_freq, \ .pad_cfg = _cfg, \ .pad_cfg_size = _cfg_size, \