Skip to content

Commit 3f4e557

Browse files
committed
Merge tag 'for-5.14-clk' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux into clk-nvidia
Pull Tegra clk driver updates from Thierry Reding: This contains a few fixes across the board and adds stubs to allow certain drivers to be compile-tested. One other notable change added here is that clock enabling no longer deasserts the reset. Drivers are now supposed to do that explicitly because doing it implicitly can get in the way of certain power-up sequences. * tag 'for-5.14-clk' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux: clk: tegra: tegra124-emc: Fix clock imbalance in emc_set_timing() clk: tegra: Add stubs needed for compile-testing clk: tegra: Don't deassert reset on enabling clocks clk: tegra: Mark external clocks as not having reset control clk: tegra: cclk: Handle thermal DIV2 CPU frequency throttling clk: tegra: Don't allow zero clock rate for PLLs clk: tegra: Halve SCLK rate on Tegra20 clk: tegra: Ensure that PLLU configuration is applied properly clk: tegra: Fix refcounting of gate clocks clk: tegra30: Use 300MHz for video decoder by default
2 parents 6efb943 + f13570e commit 3f4e557

File tree

11 files changed

+170
-80
lines changed

11 files changed

+170
-80
lines changed

drivers/clk/tegra/clk-periph-gate.c

Lines changed: 47 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -48,36 +48,45 @@ static int clk_periph_is_enabled(struct clk_hw *hw)
4848
return state;
4949
}
5050

51-
static int clk_periph_enable(struct clk_hw *hw)
51+
static void clk_periph_enable_locked(struct clk_hw *hw)
5252
{
5353
struct tegra_clk_periph_gate *gate = to_clk_periph_gate(hw);
54-
unsigned long flags = 0;
55-
56-
spin_lock_irqsave(&periph_ref_lock, flags);
57-
58-
gate->enable_refcnt[gate->clk_num]++;
59-
if (gate->enable_refcnt[gate->clk_num] > 1) {
60-
spin_unlock_irqrestore(&periph_ref_lock, flags);
61-
return 0;
62-
}
6354

6455
write_enb_set(periph_clk_to_bit(gate), gate);
6556
udelay(2);
6657

67-
if (!(gate->flags & TEGRA_PERIPH_NO_RESET) &&
68-
!(gate->flags & TEGRA_PERIPH_MANUAL_RESET)) {
69-
if (read_rst(gate) & periph_clk_to_bit(gate)) {
70-
udelay(5); /* reset propogation delay */
71-
write_rst_clr(periph_clk_to_bit(gate), gate);
72-
}
73-
}
74-
7558
if (gate->flags & TEGRA_PERIPH_WAR_1005168) {
7659
writel_relaxed(0, gate->clk_base + LVL2_CLK_GATE_OVRE);
7760
writel_relaxed(BIT(22), gate->clk_base + LVL2_CLK_GATE_OVRE);
7861
udelay(1);
7962
writel_relaxed(0, gate->clk_base + LVL2_CLK_GATE_OVRE);
8063
}
64+
}
65+
66+
static void clk_periph_disable_locked(struct clk_hw *hw)
67+
{
68+
struct tegra_clk_periph_gate *gate = to_clk_periph_gate(hw);
69+
70+
/*
71+
* If peripheral is in the APB bus then read the APB bus to
72+
* flush the write operation in apb bus. This will avoid the
73+
* peripheral access after disabling clock
74+
*/
75+
if (gate->flags & TEGRA_PERIPH_ON_APB)
76+
tegra_read_chipid();
77+
78+
write_enb_clr(periph_clk_to_bit(gate), gate);
79+
}
80+
81+
static int clk_periph_enable(struct clk_hw *hw)
82+
{
83+
struct tegra_clk_periph_gate *gate = to_clk_periph_gate(hw);
84+
unsigned long flags = 0;
85+
86+
spin_lock_irqsave(&periph_ref_lock, flags);
87+
88+
if (!gate->enable_refcnt[gate->clk_num]++)
89+
clk_periph_enable_locked(hw);
8190

8291
spin_unlock_irqrestore(&periph_ref_lock, flags);
8392

@@ -91,21 +100,28 @@ static void clk_periph_disable(struct clk_hw *hw)
91100

92101
spin_lock_irqsave(&periph_ref_lock, flags);
93102

94-
gate->enable_refcnt[gate->clk_num]--;
95-
if (gate->enable_refcnt[gate->clk_num] > 0) {
96-
spin_unlock_irqrestore(&periph_ref_lock, flags);
97-
return;
98-
}
103+
WARN_ON(!gate->enable_refcnt[gate->clk_num]);
104+
105+
if (--gate->enable_refcnt[gate->clk_num] == 0)
106+
clk_periph_disable_locked(hw);
107+
108+
spin_unlock_irqrestore(&periph_ref_lock, flags);
109+
}
110+
111+
static void clk_periph_disable_unused(struct clk_hw *hw)
112+
{
113+
struct tegra_clk_periph_gate *gate = to_clk_periph_gate(hw);
114+
unsigned long flags = 0;
115+
116+
spin_lock_irqsave(&periph_ref_lock, flags);
99117

100118
/*
101-
* If peripheral is in the APB bus then read the APB bus to
102-
* flush the write operation in apb bus. This will avoid the
103-
* peripheral access after disabling clock
119+
* Some clocks are duplicated and some of them are marked as critical,
120+
* like fuse and fuse_burn for example, thus the enable_refcnt will
121+
* be non-zero here if the "unused" duplicate is disabled by CCF.
104122
*/
105-
if (gate->flags & TEGRA_PERIPH_ON_APB)
106-
tegra_read_chipid();
107-
108-
write_enb_clr(periph_clk_to_bit(gate), gate);
123+
if (!gate->enable_refcnt[gate->clk_num])
124+
clk_periph_disable_locked(hw);
109125

110126
spin_unlock_irqrestore(&periph_ref_lock, flags);
111127
}
@@ -114,6 +130,7 @@ const struct clk_ops tegra_clk_periph_gate_ops = {
114130
.is_enabled = clk_periph_is_enabled,
115131
.enable = clk_periph_enable,
116132
.disable = clk_periph_disable,
133+
.disable_unused = clk_periph_disable_unused,
117134
};
118135

119136
struct clk *tegra_clk_register_periph_gate(const char *name,
@@ -148,9 +165,6 @@ struct clk *tegra_clk_register_periph_gate(const char *name,
148165
gate->enable_refcnt = enable_refcnt;
149166
gate->regs = pregs;
150167

151-
if (read_enb(gate) & periph_clk_to_bit(gate))
152-
enable_refcnt[clk_num]++;
153-
154168
/* Data in .init is copied by clk_register(), so stack variable OK */
155169
gate->hw.init = &init;
156170

drivers/clk/tegra/clk-periph.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,15 @@ static void clk_periph_disable(struct clk_hw *hw)
100100
gate_ops->disable(gate_hw);
101101
}
102102

103+
static void clk_periph_disable_unused(struct clk_hw *hw)
104+
{
105+
struct tegra_clk_periph *periph = to_clk_periph(hw);
106+
const struct clk_ops *gate_ops = periph->gate_ops;
107+
struct clk_hw *gate_hw = &periph->gate.hw;
108+
109+
gate_ops->disable_unused(gate_hw);
110+
}
111+
103112
static void clk_periph_restore_context(struct clk_hw *hw)
104113
{
105114
struct tegra_clk_periph *periph = to_clk_periph(hw);
@@ -126,6 +135,7 @@ const struct clk_ops tegra_clk_periph_ops = {
126135
.is_enabled = clk_periph_is_enabled,
127136
.enable = clk_periph_enable,
128137
.disable = clk_periph_disable,
138+
.disable_unused = clk_periph_disable_unused,
129139
.restore_context = clk_periph_restore_context,
130140
};
131141

@@ -135,6 +145,7 @@ static const struct clk_ops tegra_clk_periph_nodiv_ops = {
135145
.is_enabled = clk_periph_is_enabled,
136146
.enable = clk_periph_enable,
137147
.disable = clk_periph_disable,
148+
.disable_unused = clk_periph_disable_unused,
138149
.restore_context = clk_periph_restore_context,
139150
};
140151

drivers/clk/tegra/clk-pll.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -558,6 +558,9 @@ static int _calc_rate(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg,
558558
u32 p_div = 0;
559559
int ret;
560560

561+
if (!rate)
562+
return -EINVAL;
563+
561564
switch (parent_rate) {
562565
case 12000000:
563566
case 26000000:
@@ -1131,7 +1134,8 @@ static int clk_pllu_enable(struct clk_hw *hw)
11311134
if (pll->lock)
11321135
spin_lock_irqsave(pll->lock, flags);
11331136

1134-
_clk_pll_enable(hw);
1137+
if (!clk_pll_is_enabled(hw))
1138+
_clk_pll_enable(hw);
11351139

11361140
ret = clk_pll_wait_for_lock(pll);
11371141
if (ret < 0)
@@ -1748,15 +1752,13 @@ static int clk_pllu_tegra114_enable(struct clk_hw *hw)
17481752
return -EINVAL;
17491753
}
17501754

1751-
if (clk_pll_is_enabled(hw))
1752-
return 0;
1753-
17541755
input_rate = clk_hw_get_rate(__clk_get_hw(osc));
17551756

17561757
if (pll->lock)
17571758
spin_lock_irqsave(pll->lock, flags);
17581759

1759-
_clk_pll_enable(hw);
1760+
if (!clk_pll_is_enabled(hw))
1761+
_clk_pll_enable(hw);
17601762

17611763
ret = clk_pll_wait_for_lock(pll);
17621764
if (ret < 0)

drivers/clk/tegra/clk-tegra-periph.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -712,9 +712,9 @@ static struct tegra_periph_init_data periph_clks[] = {
712712
MUX8("ndflash", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_NDFLASH, 13, TEGRA_PERIPH_ON_APB, tegra_clk_ndflash_8),
713713
MUX8("ndspeed", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_NDSPEED, 80, TEGRA_PERIPH_ON_APB, tegra_clk_ndspeed_8),
714714
MUX8("hdmi", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_HDMI, 51, 0, tegra_clk_hdmi),
715-
MUX8("extern1", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN1, 120, 0, tegra_clk_extern1),
716-
MUX8("extern2", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN2, 121, 0, tegra_clk_extern2),
717-
MUX8("extern3", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN3, 122, 0, tegra_clk_extern3),
715+
MUX8("extern1", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN1, 120, TEGRA_PERIPH_NO_RESET, tegra_clk_extern1),
716+
MUX8("extern2", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN2, 121, TEGRA_PERIPH_NO_RESET, tegra_clk_extern2),
717+
MUX8("extern3", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN3, 122, TEGRA_PERIPH_NO_RESET, tegra_clk_extern3),
718718
MUX8("soc_therm", mux_pllm_pllc_pllp_plla, CLK_SOURCE_SOC_THERM, 78, TEGRA_PERIPH_ON_APB, tegra_clk_soc_therm),
719719
MUX8("soc_therm", mux_clkm_pllc_pllp_plla, CLK_SOURCE_SOC_THERM, 78, TEGRA_PERIPH_ON_APB, tegra_clk_soc_therm_8),
720720
MUX8("vi_sensor", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI_SENSOR, 164, TEGRA_PERIPH_NO_RESET, tegra_clk_vi_sensor_8),

drivers/clk/tegra/clk-tegra-super-cclk.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525

2626
#define SUPER_CDIV_ENB BIT(31)
2727

28+
#define TSENSOR_SLOWDOWN BIT(23)
29+
2830
static struct tegra_clk_super_mux *cclk_super;
2931
static bool cclk_on_pllx;
3032

@@ -47,10 +49,20 @@ static int cclk_super_set_rate(struct clk_hw *hw, unsigned long rate,
4749
static unsigned long cclk_super_recalc_rate(struct clk_hw *hw,
4850
unsigned long parent_rate)
4951
{
52+
struct tegra_clk_super_mux *super = to_clk_super_mux(hw);
53+
u32 val = readl_relaxed(super->reg);
54+
unsigned int div2;
55+
56+
/* check whether thermal throttling is active */
57+
if (val & TSENSOR_SLOWDOWN)
58+
div2 = 1;
59+
else
60+
div2 = 0;
61+
5062
if (cclk_super_get_parent(hw) == PLLX_INDEX)
51-
return parent_rate;
63+
return parent_rate >> div2;
5264

53-
return tegra_clk_super_ops.recalc_rate(hw, parent_rate);
65+
return tegra_clk_super_ops.recalc_rate(hw, parent_rate) >> div2;
5466
}
5567

5668
static int cclk_super_determine_rate(struct clk_hw *hw,

drivers/clk/tegra/clk-tegra124-emc.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,8 +249,10 @@ static int emc_set_timing(struct tegra_clk_emc *tegra,
249249
div = timing->parent_rate / (timing->rate / 2) - 2;
250250

251251
err = tegra->prepare_timing_change(emc, timing->rate);
252-
if (err)
252+
if (err) {
253+
clk_disable_unprepare(timing->parent);
253254
return err;
255+
}
254256

255257
spin_lock_irqsave(tegra->lock, flags);
256258

drivers/clk/tegra/clk-tegra20.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1021,9 +1021,9 @@ static struct tegra_clk_init_table init_table[] __initdata = {
10211021
{ TEGRA20_CLK_PLL_P_OUT3, TEGRA20_CLK_CLK_MAX, 72000000, 1 },
10221022
{ TEGRA20_CLK_PLL_P_OUT4, TEGRA20_CLK_CLK_MAX, 24000000, 1 },
10231023
{ TEGRA20_CLK_PLL_C, TEGRA20_CLK_CLK_MAX, 600000000, 0 },
1024-
{ TEGRA20_CLK_PLL_C_OUT1, TEGRA20_CLK_CLK_MAX, 240000000, 0 },
1025-
{ TEGRA20_CLK_SCLK, TEGRA20_CLK_PLL_C_OUT1, 240000000, 0 },
1026-
{ TEGRA20_CLK_HCLK, TEGRA20_CLK_CLK_MAX, 240000000, 0 },
1024+
{ TEGRA20_CLK_PLL_C_OUT1, TEGRA20_CLK_CLK_MAX, 120000000, 0 },
1025+
{ TEGRA20_CLK_SCLK, TEGRA20_CLK_PLL_C_OUT1, 120000000, 0 },
1026+
{ TEGRA20_CLK_HCLK, TEGRA20_CLK_CLK_MAX, 120000000, 0 },
10271027
{ TEGRA20_CLK_PCLK, TEGRA20_CLK_CLK_MAX, 60000000, 0 },
10281028
{ TEGRA20_CLK_CSITE, TEGRA20_CLK_CLK_MAX, 0, 1 },
10291029
{ TEGRA20_CLK_CCLK, TEGRA20_CLK_CLK_MAX, 0, 1 },

drivers/clk/tegra/clk-tegra30.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -930,7 +930,7 @@ static void __init tegra30_super_clk_init(void)
930930
/* CCLKG */
931931
clk = tegra_clk_register_super_cclk("cclk_g", cclk_g_parents,
932932
ARRAY_SIZE(cclk_g_parents),
933-
CLK_SET_RATE_PARENT,
933+
CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE,
934934
clk_base + CCLKG_BURST_POLICY,
935935
0, NULL);
936936
clks[TEGRA30_CLK_CCLK_G] = clk;
@@ -1006,7 +1006,7 @@ static struct tegra_periph_init_data tegra_periph_clk_list[] = {
10061006
TEGRA_INIT_DATA_MUX("dam0", mux_pllacp_clkm, CLK_SOURCE_DAM0, 108, 0, TEGRA30_CLK_DAM0),
10071007
TEGRA_INIT_DATA_MUX("dam1", mux_pllacp_clkm, CLK_SOURCE_DAM1, 109, 0, TEGRA30_CLK_DAM1),
10081008
TEGRA_INIT_DATA_MUX("dam2", mux_pllacp_clkm, CLK_SOURCE_DAM2, 110, 0, TEGRA30_CLK_DAM2),
1009-
TEGRA_INIT_DATA_INT("3d2", mux_pllmcpa, CLK_SOURCE_3D2, 98, TEGRA_PERIPH_MANUAL_RESET, TEGRA30_CLK_GR3D2),
1009+
TEGRA_INIT_DATA_INT("3d2", mux_pllmcpa, CLK_SOURCE_3D2, 98, 0, TEGRA30_CLK_GR3D2),
10101010
TEGRA_INIT_DATA_INT("se", mux_pllpcm_clkm, CLK_SOURCE_SE, 127, 0, TEGRA30_CLK_SE),
10111011
TEGRA_INIT_DATA_MUX8("hdmi", mux_pllpmdacd2_clkm, CLK_SOURCE_HDMI, 51, 0, TEGRA30_CLK_HDMI),
10121012
TEGRA_INIT_DATA("pwm", NULL, NULL, pwm_parents, CLK_SOURCE_PWM, 28, 2, 0, 0, 8, 1, 0, 17, TEGRA_PERIPH_ON_APB, TEGRA30_CLK_PWM),
@@ -1245,7 +1245,7 @@ static struct tegra_clk_init_table init_table[] __initdata = {
12451245
{ TEGRA30_CLK_GR3D, TEGRA30_CLK_PLL_C, 300000000, 0 },
12461246
{ TEGRA30_CLK_GR3D2, TEGRA30_CLK_PLL_C, 300000000, 0 },
12471247
{ TEGRA30_CLK_PLL_U, TEGRA30_CLK_CLK_MAX, 480000000, 0 },
1248-
{ TEGRA30_CLK_VDE, TEGRA30_CLK_PLL_C, 600000000, 0 },
1248+
{ TEGRA30_CLK_VDE, TEGRA30_CLK_PLL_C, 300000000, 0 },
12491249
{ TEGRA30_CLK_SPDIF_IN_SYNC, TEGRA30_CLK_CLK_MAX, 24000000, 0 },
12501250
{ TEGRA30_CLK_I2S0_SYNC, TEGRA30_CLK_CLK_MAX, 24000000, 0 },
12511251
{ TEGRA30_CLK_I2S1_SYNC, TEGRA30_CLK_CLK_MAX, 24000000, 0 },

drivers/clk/tegra/clk.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -553,9 +553,6 @@ struct tegra_clk_periph_regs {
553553
* Flags:
554554
* TEGRA_PERIPH_NO_RESET - This flag indicates that reset is not allowed
555555
* for this module.
556-
* TEGRA_PERIPH_MANUAL_RESET - This flag indicates not to reset module
557-
* after clock enable and driver for the module is responsible for
558-
* doing reset.
559556
* TEGRA_PERIPH_ON_APB - If peripheral is in the APB bus then read the
560557
* bus to flush the write operation in apb bus. This flag indicates
561558
* that this peripheral is in apb bus.
@@ -577,7 +574,6 @@ struct tegra_clk_periph_gate {
577574
#define TEGRA_CLK_PERIPH_GATE_MAGIC 0x17760309
578575

579576
#define TEGRA_PERIPH_NO_RESET BIT(0)
580-
#define TEGRA_PERIPH_MANUAL_RESET BIT(1)
581577
#define TEGRA_PERIPH_ON_APB BIT(2)
582578
#define TEGRA_PERIPH_WAR_1005168 BIT(3)
583579
#define TEGRA_PERIPH_NO_DIV BIT(4)

drivers/soc/tegra/pmc.c

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -743,11 +743,6 @@ static int tegra_powergate_enable_clocks(struct tegra_powergate *pg)
743743
return err;
744744
}
745745

746-
int __weak tegra210_clk_handle_mbist_war(unsigned int id)
747-
{
748-
return 0;
749-
}
750-
751746
static int tegra_powergate_power_up(struct tegra_powergate *pg,
752747
bool disable_clocks)
753748
{

0 commit comments

Comments
 (0)