forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-10 61598093bbdd283a7edc367d900f223070ead8d2
kernel/drivers/clk/tegra/clk-periph-gate.c
....@@ -1,17 +1,6 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
3
- *
4
- * This program is free software; you can redistribute it and/or modify it
5
- * under the terms and conditions of the GNU General Public License,
6
- * version 2, as published by the Free Software Foundation.
7
- *
8
- * This program is distributed in the hope it will be useful, but WITHOUT
9
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11
- * more details.
12
- *
13
- * You should have received a copy of the GNU General Public License
14
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
154 */
165
176 #include <linux/clk-provider.h>
....@@ -59,18 +48,9 @@
5948 return state;
6049 }
6150
62
-static int clk_periph_enable(struct clk_hw *hw)
51
+static void clk_periph_enable_locked(struct clk_hw *hw)
6352 {
6453 struct tegra_clk_periph_gate *gate = to_clk_periph_gate(hw);
65
- unsigned long flags = 0;
66
-
67
- spin_lock_irqsave(&periph_ref_lock, flags);
68
-
69
- gate->enable_refcnt[gate->clk_num]++;
70
- if (gate->enable_refcnt[gate->clk_num] > 1) {
71
- spin_unlock_irqrestore(&periph_ref_lock, flags);
72
- return 0;
73
- }
7454
7555 write_enb_set(periph_clk_to_bit(gate), gate);
7656 udelay(2);
....@@ -89,6 +69,32 @@
8969 udelay(1);
9070 writel_relaxed(0, gate->clk_base + LVL2_CLK_GATE_OVRE);
9171 }
72
+}
73
+
74
+static void clk_periph_disable_locked(struct clk_hw *hw)
75
+{
76
+ struct tegra_clk_periph_gate *gate = to_clk_periph_gate(hw);
77
+
78
+ /*
79
+ * If peripheral is in the APB bus then read the APB bus to
80
+ * flush the write operation in apb bus. This will avoid the
81
+ * peripheral access after disabling clock
82
+ */
83
+ if (gate->flags & TEGRA_PERIPH_ON_APB)
84
+ tegra_read_chipid();
85
+
86
+ write_enb_clr(periph_clk_to_bit(gate), gate);
87
+}
88
+
89
+static int clk_periph_enable(struct clk_hw *hw)
90
+{
91
+ struct tegra_clk_periph_gate *gate = to_clk_periph_gate(hw);
92
+ unsigned long flags = 0;
93
+
94
+ spin_lock_irqsave(&periph_ref_lock, flags);
95
+
96
+ if (!gate->enable_refcnt[gate->clk_num]++)
97
+ clk_periph_enable_locked(hw);
9298
9399 spin_unlock_irqrestore(&periph_ref_lock, flags);
94100
....@@ -102,21 +108,28 @@
102108
103109 spin_lock_irqsave(&periph_ref_lock, flags);
104110
105
- gate->enable_refcnt[gate->clk_num]--;
106
- if (gate->enable_refcnt[gate->clk_num] > 0) {
107
- spin_unlock_irqrestore(&periph_ref_lock, flags);
108
- return;
109
- }
111
+ WARN_ON(!gate->enable_refcnt[gate->clk_num]);
112
+
113
+ if (--gate->enable_refcnt[gate->clk_num] == 0)
114
+ clk_periph_disable_locked(hw);
115
+
116
+ spin_unlock_irqrestore(&periph_ref_lock, flags);
117
+}
118
+
119
+static void clk_periph_disable_unused(struct clk_hw *hw)
120
+{
121
+ struct tegra_clk_periph_gate *gate = to_clk_periph_gate(hw);
122
+ unsigned long flags = 0;
123
+
124
+ spin_lock_irqsave(&periph_ref_lock, flags);
110125
111126 /*
112
- * If peripheral is in the APB bus then read the APB bus to
113
- * flush the write operation in apb bus. This will avoid the
114
- * peripheral access after disabling clock
127
+ * Some clocks are duplicated and some of them are marked as critical,
128
+ * like fuse and fuse_burn for example, thus the enable_refcnt will
129
+ * be non-zero here if the "unused" duplicate is disabled by CCF.
115130 */
116
- if (gate->flags & TEGRA_PERIPH_ON_APB)
117
- tegra_read_chipid();
118
-
119
- write_enb_clr(periph_clk_to_bit(gate), gate);
131
+ if (!gate->enable_refcnt[gate->clk_num])
132
+ clk_periph_disable_locked(hw);
120133
121134 spin_unlock_irqrestore(&periph_ref_lock, flags);
122135 }
....@@ -125,6 +138,7 @@
125138 .is_enabled = clk_periph_is_enabled,
126139 .enable = clk_periph_enable,
127140 .disable = clk_periph_disable,
141
+ .disable_unused = clk_periph_disable_unused,
128142 };
129143
130144 struct clk *tegra_clk_register_periph_gate(const char *name,
....@@ -133,7 +147,7 @@
133147 {
134148 struct tegra_clk_periph_gate *gate;
135149 struct clk *clk;
136
- struct clk_init_data init = {};
150
+ struct clk_init_data init;
137151 const struct tegra_clk_periph_regs *pregs;
138152
139153 pregs = get_reg_bank(clk_num);
....@@ -158,9 +172,6 @@
158172 gate->flags = gate_flags;
159173 gate->enable_refcnt = enable_refcnt;
160174 gate->regs = pregs;
161
-
162
- if (read_enb(gate) & periph_clk_to_bit(gate))
163
- enable_refcnt[clk_num]++;
164175
165176 /* Data in .init is copied by clk_register(), so stack variable OK */
166177 gate->hw.init = &init;