|
@@ -40,6 +40,7 @@
|
|
|
|
|
|
#define CLK_SOURCE_CSITE 0x1d4
|
|
|
#define CLK_SOURCE_EMC 0x19c
|
|
|
+#define CLK_SOURCE_SOR1 0x410
|
|
|
|
|
|
#define PLLC_BASE 0x80
|
|
|
#define PLLC_OUT 0x84
|
|
@@ -264,6 +265,7 @@ static DEFINE_SPINLOCK(pll_d_lock);
|
|
|
static DEFINE_SPINLOCK(pll_e_lock);
|
|
|
static DEFINE_SPINLOCK(pll_re_lock);
|
|
|
static DEFINE_SPINLOCK(pll_u_lock);
|
|
|
+static DEFINE_SPINLOCK(sor1_lock);
|
|
|
static DEFINE_SPINLOCK(emc_lock);
|
|
|
|
|
|
/* possible OSC frequencies in Hz */
|
|
@@ -2628,10 +2630,35 @@ static int tegra210_init_pllu(void)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static const char * const sor1_out_parents[] = {
|
|
|
+ /*
|
|
|
+ * Bit 0 of the mux selects sor1_pad_clkout, irrespective of bit 1, so
|
|
|
+ * the sor1_pad_clkout parent appears twice in the list below. This is
|
|
|
+ * merely to support clk_get_parent() if firmware happened to set
|
|
|
+ * these bits to 0b11. While not an invalid setting, code should
|
|
|
+ * always set the bits to 0b01 to select sor1_pad_clkout.
|
|
|
+ */
|
|
|
+ "sor_safe", "sor1_pad_clkout", "sor1", "sor1_pad_clkout",
|
|
|
+};
|
|
|
+
|
|
|
+static const char * const sor1_parents[] = {
|
|
|
+ "pll_p", "pll_d_out0", "pll_d2_out0", "clk_m",
|
|
|
+};
|
|
|
+
|
|
|
+static u32 sor1_parents_idx[] = { 0, 2, 5, 6 };
|
|
|
+
|
|
|
+static struct tegra_periph_init_data tegra210_periph[] = {
|
|
|
+ TEGRA_INIT_DATA_TABLE("sor1", NULL, NULL, sor1_parents,
|
|
|
+ CLK_SOURCE_SOR1, 29, 0x7, 0, 0, 8, 1,
|
|
|
+ TEGRA_DIVIDER_ROUND_UP, 183, 0, tegra_clk_sor1,
|
|
|
+ sor1_parents_idx, 0, &sor1_lock),
|
|
|
+};
|
|
|
+
|
|
|
static __init void tegra210_periph_clk_init(void __iomem *clk_base,
|
|
|
void __iomem *pmc_base)
|
|
|
{
|
|
|
struct clk *clk;
|
|
|
+ unsigned int i;
|
|
|
|
|
|
/* xusb_ss_div2 */
|
|
|
clk = clk_register_fixed_factor(NULL, "xusb_ss_div2", "xusb_ss_src", 0,
|
|
@@ -2650,6 +2677,12 @@ static __init void tegra210_periph_clk_init(void __iomem *clk_base,
|
|
|
1, 17, 207);
|
|
|
clks[TEGRA210_CLK_DPAUX1] = clk;
|
|
|
|
|
|
+ clk = clk_register_mux_table(NULL, "sor1_out", sor1_out_parents,
|
|
|
+ ARRAY_SIZE(sor1_out_parents), 0,
|
|
|
+ clk_base + CLK_SOURCE_SOR1, 14, 0x3,
|
|
|
+ 0, NULL, &sor1_lock);
|
|
|
+ clks[TEGRA210_CLK_SOR1_OUT] = clk;
|
|
|
+
|
|
|
/* pll_d_dsi_out */
|
|
|
clk = clk_register_gate(NULL, "pll_d_dsi_out", "pll_d_out0", 0,
|
|
|
clk_base + PLLD_MISC0, 21, 0, &pll_d_lock);
|
|
@@ -2694,6 +2727,20 @@ static __init void tegra210_periph_clk_init(void __iomem *clk_base,
|
|
|
0, NULL);
|
|
|
clks[TEGRA210_CLK_ACLK] = clk;
|
|
|
|
|
|
+ for (i = 0; i < ARRAY_SIZE(tegra210_periph); i++) {
|
|
|
+ struct tegra_periph_init_data *init = &tegra210_periph[i];
|
|
|
+ struct clk **clkp;
|
|
|
+
|
|
|
+ clkp = tegra_lookup_dt_id(init->clk_id, tegra210_clks);
|
|
|
+ if (!clkp) {
|
|
|
+ pr_warn("clock %u not found\n", init->clk_id);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ clk = tegra_clk_register_periph_data(clk_base, init);
|
|
|
+ *clkp = clk;
|
|
|
+ }
|
|
|
+
|
|
|
tegra_periph_clk_init(clk_base, pmc_base, tegra210_clks, &pll_p_params);
|
|
|
}
|
|
|
|