From 6dbcc962e48e4f2395806469ba59f19fb18aa64a Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Tue, 13 Sep 2016 10:45:55 -0600 Subject: [PATCH] ARM: tegra: add peripheral clock init table Currently, Tegra peripheral drivers control two aspects of their HW module clock(s): 1) The clock enable/rate for the peripheral clock itself. 2) The system-level clock tree setup, i.e. the clock parent. Aspect 1 is reasonable, but aspect 2 is a system-level decision, not something that an individual peripheral driver should in general know about or influence. Such system-level knowledge ties the driver to a specific SoC implementation, even when they use generic APIs for clock manipulation, since they must have SoC-specific knowledge such as parent clock IDs. Limited exceptions exist, such as where peripheral HW is expected to dynamically switch between clock sources at run-time, such as CPU clock scaling or display clock conflict management in a multi-head scenario. This patch enhances the Tegra core code to perform system-level clock tree setup, in a similar fashion to the Linux kernel Tegra clock driver. This will allow future patches to simplify peripheral drivers by removing the clock parent setup logic. This change is required prior to converting peripheral drivers to use the standard clock APIs, since: 1) The clock uclass doesn't currently support a set_parent() operation. Adding one is possible, but not necessary at the moment. 2) The clock APIs retrieve all clock IDs from device tree, and the DT bindings for almost all peripherals only includes information about the relevant peripheral clocks, and not any potential parent clocks. Signed-off-by: Stephen Warren Signed-off-by: Tom Warren --- arch/arm/include/asm/arch-tegra/clock.h | 6 ++++++ arch/arm/mach-tegra/clock.c | 15 +++++++++++++++ arch/arm/mach-tegra/tegra114/clock.c | 23 +++++++++++++++++++++++ arch/arm/mach-tegra/tegra124/clock.c | 23 +++++++++++++++++++++++ arch/arm/mach-tegra/tegra20/clock.c | 21 +++++++++++++++++++++ arch/arm/mach-tegra/tegra210/clock.c | 23 +++++++++++++++++++++++ arch/arm/mach-tegra/tegra30/clock.c | 23 +++++++++++++++++++++++ 7 files changed, 134 insertions(+) diff --git a/arch/arm/include/asm/arch-tegra/clock.h b/arch/arm/include/asm/arch-tegra/clock.h index 7daf8bc163..e0737f574a 100644 --- a/arch/arm/include/asm/arch-tegra/clock.h +++ b/arch/arm/include/asm/arch-tegra/clock.h @@ -362,6 +362,12 @@ struct clk_pll_info { }; extern struct clk_pll_info tegra_pll_info_table[CLOCK_ID_PLL_COUNT]; +struct periph_clk_init { + enum periph_id periph_id; + enum clock_id parent_clock_id; +}; +extern struct periph_clk_init periph_clk_init_table[]; + /** * Enable output clock for external peripherals * diff --git a/arch/arm/mach-tegra/clock.c b/arch/arm/mach-tegra/clock.c index 36eabc8f57..597f6286d6 100644 --- a/arch/arm/mach-tegra/clock.c +++ b/arch/arm/mach-tegra/clock.c @@ -612,6 +612,8 @@ int clock_verify(void) void clock_init(void) { + int i; + pll_rate[CLOCK_ID_CGENERAL] = clock_get_rate(CLOCK_ID_CGENERAL); pll_rate[CLOCK_ID_MEMORY] = clock_get_rate(CLOCK_ID_MEMORY); pll_rate[CLOCK_ID_PERIPH] = clock_get_rate(CLOCK_ID_PERIPH); @@ -630,6 +632,19 @@ void clock_init(void) debug("PLLU = %d\n", pll_rate[CLOCK_ID_USB]); debug("PLLD = %d\n", pll_rate[CLOCK_ID_DISPLAY]); debug("PLLX = %d\n", pll_rate[CLOCK_ID_XCPU]); + + for (i = 0; periph_clk_init_table[i].periph_id != -1; i++) { + enum periph_id periph_id; + enum clock_id parent; + int source, mux_bits, divider_bits; + + periph_id = periph_clk_init_table[i].periph_id; + parent = periph_clk_init_table[i].parent_clock_id; + + source = get_periph_clock_source(periph_id, parent, &mux_bits, + ÷r_bits); + clock_ll_set_source_bits(periph_id, mux_bits, source); + } } static void set_avp_clock_source(u32 src) diff --git a/arch/arm/mach-tegra/tegra114/clock.c b/arch/arm/mach-tegra/tegra114/clock.c index e6ef873c8d..6620206be0 100644 --- a/arch/arm/mach-tegra/tegra114/clock.c +++ b/arch/arm/mach-tegra/tegra114/clock.c @@ -699,3 +699,26 @@ void arch_timer_init(void) writel(val, &sysctr->cntcr); debug("%s: TSC CNTCR = 0x%08X\n", __func__, val); } + +struct periph_clk_init periph_clk_init_table[] = { + { PERIPH_ID_SBC1, CLOCK_ID_PERIPH }, + { PERIPH_ID_SBC2, CLOCK_ID_PERIPH }, + { PERIPH_ID_SBC3, CLOCK_ID_PERIPH }, + { PERIPH_ID_SBC4, CLOCK_ID_PERIPH }, + { PERIPH_ID_SBC5, CLOCK_ID_PERIPH }, + { PERIPH_ID_SBC6, CLOCK_ID_PERIPH }, + { PERIPH_ID_HOST1X, CLOCK_ID_PERIPH }, + { PERIPH_ID_DISP1, CLOCK_ID_CGENERAL }, + { PERIPH_ID_NDFLASH, CLOCK_ID_PERIPH }, + { PERIPH_ID_SDMMC1, CLOCK_ID_PERIPH }, + { PERIPH_ID_SDMMC2, CLOCK_ID_PERIPH }, + { PERIPH_ID_SDMMC3, CLOCK_ID_PERIPH }, + { PERIPH_ID_SDMMC4, CLOCK_ID_PERIPH }, + { PERIPH_ID_PWM, CLOCK_ID_SFROM32KHZ }, + { PERIPH_ID_I2C1, CLOCK_ID_PERIPH }, + { PERIPH_ID_I2C2, CLOCK_ID_PERIPH }, + { PERIPH_ID_I2C3, CLOCK_ID_PERIPH }, + { PERIPH_ID_I2C4, CLOCK_ID_PERIPH }, + { PERIPH_ID_I2C5, CLOCK_ID_PERIPH }, + { -1, }, +}; diff --git a/arch/arm/mach-tegra/tegra124/clock.c b/arch/arm/mach-tegra/tegra124/clock.c index 1e71146236..84b679c1c5 100644 --- a/arch/arm/mach-tegra/tegra124/clock.c +++ b/arch/arm/mach-tegra/tegra124/clock.c @@ -1107,3 +1107,26 @@ struct clk_pll_simple *clock_get_simple_pll(enum clock_id clkid) return NULL; } + +struct periph_clk_init periph_clk_init_table[] = { + { PERIPH_ID_SBC1, CLOCK_ID_PERIPH }, + { PERIPH_ID_SBC2, CLOCK_ID_PERIPH }, + { PERIPH_ID_SBC3, CLOCK_ID_PERIPH }, + { PERIPH_ID_SBC4, CLOCK_ID_PERIPH }, + { PERIPH_ID_SBC5, CLOCK_ID_PERIPH }, + { PERIPH_ID_SBC6, CLOCK_ID_PERIPH }, + { PERIPH_ID_HOST1X, CLOCK_ID_PERIPH }, + { PERIPH_ID_DISP1, CLOCK_ID_CGENERAL }, + { PERIPH_ID_SDMMC1, CLOCK_ID_PERIPH }, + { PERIPH_ID_SDMMC2, CLOCK_ID_PERIPH }, + { PERIPH_ID_SDMMC3, CLOCK_ID_PERIPH }, + { PERIPH_ID_SDMMC4, CLOCK_ID_PERIPH }, + { PERIPH_ID_PWM, CLOCK_ID_SFROM32KHZ }, + { PERIPH_ID_I2C1, CLOCK_ID_PERIPH }, + { PERIPH_ID_I2C2, CLOCK_ID_PERIPH }, + { PERIPH_ID_I2C3, CLOCK_ID_PERIPH }, + { PERIPH_ID_I2C4, CLOCK_ID_PERIPH }, + { PERIPH_ID_I2C5, CLOCK_ID_PERIPH }, + { PERIPH_ID_I2C6, CLOCK_ID_PERIPH }, + { -1, }, +}; diff --git a/arch/arm/mach-tegra/tegra20/clock.c b/arch/arm/mach-tegra/tegra20/clock.c index cd9fb9a553..d11e89bd25 100644 --- a/arch/arm/mach-tegra/tegra20/clock.c +++ b/arch/arm/mach-tegra/tegra20/clock.c @@ -717,3 +717,24 @@ int tegra_plle_enable(void) return 0; } + +struct periph_clk_init periph_clk_init_table[] = { + { PERIPH_ID_SPI1, CLOCK_ID_PERIPH }, + { PERIPH_ID_SBC1, CLOCK_ID_PERIPH }, + { PERIPH_ID_SBC2, CLOCK_ID_PERIPH }, + { PERIPH_ID_SBC3, CLOCK_ID_PERIPH }, + { PERIPH_ID_SBC4, CLOCK_ID_PERIPH }, + { PERIPH_ID_HOST1X, CLOCK_ID_PERIPH }, + { PERIPH_ID_DISP1, CLOCK_ID_CGENERAL }, + { PERIPH_ID_NDFLASH, CLOCK_ID_PERIPH }, + { PERIPH_ID_SDMMC1, CLOCK_ID_PERIPH }, + { PERIPH_ID_SDMMC2, CLOCK_ID_PERIPH }, + { PERIPH_ID_SDMMC3, CLOCK_ID_PERIPH }, + { PERIPH_ID_SDMMC4, CLOCK_ID_PERIPH }, + { PERIPH_ID_PWM, CLOCK_ID_SFROM32KHZ }, + { PERIPH_ID_DVC_I2C, CLOCK_ID_PERIPH }, + { PERIPH_ID_I2C1, CLOCK_ID_PERIPH }, + { PERIPH_ID_I2C2, CLOCK_ID_PERIPH }, + { PERIPH_ID_I2C3, CLOCK_ID_PERIPH }, + { -1, }, +}; diff --git a/arch/arm/mach-tegra/tegra210/clock.c b/arch/arm/mach-tegra/tegra210/clock.c index f0052e7934..d51c1481ea 100644 --- a/arch/arm/mach-tegra/tegra210/clock.c +++ b/arch/arm/mach-tegra/tegra210/clock.c @@ -1225,3 +1225,26 @@ int tegra_plle_enable(void) return 0; } + +struct periph_clk_init periph_clk_init_table[] = { + { PERIPH_ID_SBC1, CLOCK_ID_PERIPH }, + { PERIPH_ID_SBC2, CLOCK_ID_PERIPH }, + { PERIPH_ID_SBC3, CLOCK_ID_PERIPH }, + { PERIPH_ID_SBC4, CLOCK_ID_PERIPH }, + { PERIPH_ID_SBC5, CLOCK_ID_PERIPH }, + { PERIPH_ID_SBC6, CLOCK_ID_PERIPH }, + { PERIPH_ID_HOST1X, CLOCK_ID_PERIPH }, + { PERIPH_ID_DISP1, CLOCK_ID_CGENERAL }, + { PERIPH_ID_SDMMC1, CLOCK_ID_PERIPH }, + { PERIPH_ID_SDMMC2, CLOCK_ID_PERIPH }, + { PERIPH_ID_SDMMC3, CLOCK_ID_PERIPH }, + { PERIPH_ID_SDMMC4, CLOCK_ID_PERIPH }, + { PERIPH_ID_PWM, CLOCK_ID_SFROM32KHZ }, + { PERIPH_ID_I2C1, CLOCK_ID_PERIPH }, + { PERIPH_ID_I2C2, CLOCK_ID_PERIPH }, + { PERIPH_ID_I2C3, CLOCK_ID_PERIPH }, + { PERIPH_ID_I2C4, CLOCK_ID_PERIPH }, + { PERIPH_ID_I2C5, CLOCK_ID_PERIPH }, + { PERIPH_ID_I2C6, CLOCK_ID_PERIPH }, + { -1, }, +}; diff --git a/arch/arm/mach-tegra/tegra30/clock.c b/arch/arm/mach-tegra/tegra30/clock.c index 1f104f288e..52a6dcebdf 100644 --- a/arch/arm/mach-tegra/tegra30/clock.c +++ b/arch/arm/mach-tegra/tegra30/clock.c @@ -763,3 +763,26 @@ int tegra_plle_enable(void) return 0; } + +struct periph_clk_init periph_clk_init_table[] = { + { PERIPH_ID_SBC1, CLOCK_ID_PERIPH }, + { PERIPH_ID_SBC2, CLOCK_ID_PERIPH }, + { PERIPH_ID_SBC3, CLOCK_ID_PERIPH }, + { PERIPH_ID_SBC4, CLOCK_ID_PERIPH }, + { PERIPH_ID_SBC5, CLOCK_ID_PERIPH }, + { PERIPH_ID_SBC6, CLOCK_ID_PERIPH }, + { PERIPH_ID_HOST1X, CLOCK_ID_PERIPH }, + { PERIPH_ID_DISP1, CLOCK_ID_CGENERAL }, + { PERIPH_ID_NDFLASH, CLOCK_ID_PERIPH }, + { PERIPH_ID_SDMMC1, CLOCK_ID_PERIPH }, + { PERIPH_ID_SDMMC2, CLOCK_ID_PERIPH }, + { PERIPH_ID_SDMMC3, CLOCK_ID_PERIPH }, + { PERIPH_ID_SDMMC4, CLOCK_ID_PERIPH }, + { PERIPH_ID_PWM, CLOCK_ID_SFROM32KHZ }, + { PERIPH_ID_DVC_I2C, CLOCK_ID_PERIPH }, + { PERIPH_ID_I2C1, CLOCK_ID_PERIPH }, + { PERIPH_ID_I2C2, CLOCK_ID_PERIPH }, + { PERIPH_ID_I2C3, CLOCK_ID_PERIPH }, + { PERIPH_ID_I2C4, CLOCK_ID_PERIPH }, + { -1, }, +}; -- 2.39.5