clk: tegra: Add Tegra210B01 support

This is based on the downstream Nvidia 5.10 kernel. That version was
semi-integrated into the Tegra210 clock driver. Looking at the existing
Tegra210 support, it made more sense to make this a fully independent
driver, so that is implemented here.

Co-authored-by: Thomas Makin <halorocker89@gmail.com>
Change-Id: Iadee08494eff823155e228063bee8f7a280cbcef
Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
This commit is contained in:
Aaron Kling
2025-05-14 11:32:04 -05:00
committed by Thomas Makin
parent 07ed2fb23b
commit d5fb30731c
6 changed files with 3485 additions and 3 deletions

View File

@@ -27,6 +27,7 @@ obj-$(CONFIG_TEGRA124_CLK_EMC) += clk-tegra124-emc.o
obj-$(CONFIG_ARCH_TEGRA_132_SOC) += clk-tegra124.o
obj-y += cvb.o
obj-$(CONFIG_ARCH_TEGRA_210_SOC) += clk-tegra210.o
obj-$(CONFIG_ARCH_TEGRA_210_SOC) += clk-tegra210b01.o
obj-$(CONFIG_ARCH_TEGRA_210_SOC) += clk-tegra210-emc.o
obj-$(CONFIG_CLK_TEGRA_BPMP) += clk-bpmp.o
obj-y += clk-utils.o

View File

@@ -878,6 +878,9 @@ static void __init periph_clk_init(void __iomem *clk_base,
if (!bank)
continue;
if (tegra_clks[data->clk_id].use_integer_div)
data->periph.divider.flags |= TEGRA_DIVIDER_INT;
data->periph.gate.regs = bank;
clk = tegra_clk_register_periph_data(clk_base, data);
*dt_clk = clk;

File diff suppressed because it is too large Load Diff

View File

@@ -31,7 +31,7 @@ int div_frac_get(unsigned long rate, unsigned parent_rate, u8 width,
if (flags & TEGRA_DIVIDER_INT)
divider_ux1 *= mul;
if (divider_ux1 < mul)
if (!div1_5_not_allowed && divider_ux1 < mul)
return 0;
divider_ux1 -= mul;
@@ -39,5 +39,8 @@ int div_frac_get(unsigned long rate, unsigned parent_rate, u8 width,
if (divider_ux1 > div_mask(width))
return div_mask(width);
if (div1_5_not_allowed && (divider_ux1 > 0) && (divider_ux1 < mul))
divider_ux1 = (flags & TEGRA_DIVIDER_ROUND_UP) ? mul : 0;
return divider_ux1;
}

View File

@@ -26,6 +26,7 @@ static struct tegra_cpu_car_ops dummy_car_ops;
struct tegra_cpu_car_ops *tegra_cpu_car_ops = &dummy_car_ops;
int *periph_clk_enb_refcnt;
bool div1_5_not_allowed;
static int periph_banks;
static u32 *periph_state_ctx;
static struct clk **clks;
@@ -291,13 +292,27 @@ void tegra_init_from_table(struct tegra_clk_init_table *tbl,
}
}
if (tbl->rate)
if (clk_set_rate(clk, tbl->rate)) {
if (tbl->rate) {
bool can_set_rate = true;
if ((tbl->flags & TEGRA_TABLE_RATE_CHANGE_OVERCLOCK) &&
__clk_is_enabled(clk)) {
if (tbl->rate != clk_get_rate(clk)) {
pr_err("%s: Can't set rate %lu of %s\n",
__func__, tbl->rate,
__clk_get_name(clk));
WARN_ON(1);
}
can_set_rate = false;
}
if (can_set_rate && clk_set_rate(clk, tbl->rate)) {
pr_err("%s: Failed to set rate %lu of %s\n",
__func__, tbl->rate,
__clk_get_name(clk));
WARN_ON(1);
}
}
if (tbl->state)
if (clk_prepare_enable(clk)) {

View File

@@ -87,6 +87,7 @@ struct tegra_clk_sync_source {
extern const struct clk_ops tegra_clk_sync_source_ops;
extern int *periph_clk_enb_refcnt;
extern bool div1_5_not_allowed;
struct clk *tegra_clk_register_sync_source(const char *name,
unsigned long max_rate);
@@ -801,14 +802,18 @@ struct clk *tegra_clk_register_sdmmc_mux_div(const char *name,
* @parent_id: parent clock id as mentioned in device tree bindings
* @rate: rate to set
* @state: enable/disable
* @flags: clock initialization flags
*/
struct tegra_clk_init_table {
unsigned int clk_id;
unsigned int parent_id;
unsigned long rate;
int state;
u32 flags;
};
#define TEGRA_TABLE_RATE_CHANGE_OVERCLOCK BIT(0)
/**
* struct clk_duplicate - duplicate clocks
* @clk_id: clock id as mentioned in device tree bindings
@@ -831,6 +836,7 @@ struct tegra_clk_duplicate {
struct tegra_clk {
int dt_id;
bool present;
bool use_integer_div;
};
struct tegra_devclk {