diff options
author | Dmitry Osipenko <digetx@gmail.com> | 2018-04-13 07:33:54 -0400 |
---|---|---|
committer | Thierry Reding <treding@nvidia.com> | 2018-04-30 04:12:21 -0400 |
commit | cb557757e1aace04fbfb94ab731c3cf7e33b95f8 (patch) | |
tree | 7c1f8689bdc35005185ca56a8c2bd64868325e3d | |
parent | 20e92462cdfb2772e9d784ec355c90b61ec10222 (diff) |
memory: tegra: Add Tegra20 memory controller hot resets
Define the table of memory controller hot resets for Tegra20 and add
specific to Tegra20 hot reset operations.
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
-rw-r--r-- | drivers/memory/tegra/tegra20.c | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/drivers/memory/tegra/tegra20.c b/drivers/memory/tegra/tegra20.c index 512a3418cb80..7119e532471c 100644 --- a/drivers/memory/tegra/tegra20.c +++ b/drivers/memory/tegra/tegra20.c | |||
@@ -6,6 +6,8 @@ | |||
6 | * published by the Free Software Foundation. | 6 | * published by the Free Software Foundation. |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <dt-bindings/memory/tegra20-mc.h> | ||
10 | |||
9 | #include "mc.h" | 11 | #include "mc.h" |
10 | 12 | ||
11 | static const struct tegra_mc_client tegra20_mc_clients[] = { | 13 | static const struct tegra_mc_client tegra20_mc_clients[] = { |
@@ -168,6 +170,119 @@ static const struct tegra_mc_client tegra20_mc_clients[] = { | |||
168 | }, | 170 | }, |
169 | }; | 171 | }; |
170 | 172 | ||
173 | #define TEGRA20_MC_RESET(_name, _control, _status, _reset, _bit) \ | ||
174 | { \ | ||
175 | .name = #_name, \ | ||
176 | .id = TEGRA20_MC_RESET_##_name, \ | ||
177 | .control = _control, \ | ||
178 | .status = _status, \ | ||
179 | .reset = _reset, \ | ||
180 | .bit = _bit, \ | ||
181 | } | ||
182 | |||
183 | static const struct tegra_mc_reset tegra20_mc_resets[] = { | ||
184 | TEGRA20_MC_RESET(AVPC, 0x100, 0x140, 0x104, 0), | ||
185 | TEGRA20_MC_RESET(DC, 0x100, 0x144, 0x104, 1), | ||
186 | TEGRA20_MC_RESET(DCB, 0x100, 0x148, 0x104, 2), | ||
187 | TEGRA20_MC_RESET(EPP, 0x100, 0x14c, 0x104, 3), | ||
188 | TEGRA20_MC_RESET(2D, 0x100, 0x150, 0x104, 4), | ||
189 | TEGRA20_MC_RESET(HC, 0x100, 0x154, 0x104, 5), | ||
190 | TEGRA20_MC_RESET(ISP, 0x100, 0x158, 0x104, 6), | ||
191 | TEGRA20_MC_RESET(MPCORE, 0x100, 0x15c, 0x104, 7), | ||
192 | TEGRA20_MC_RESET(MPEA, 0x100, 0x160, 0x104, 8), | ||
193 | TEGRA20_MC_RESET(MPEB, 0x100, 0x164, 0x104, 9), | ||
194 | TEGRA20_MC_RESET(MPEC, 0x100, 0x168, 0x104, 10), | ||
195 | TEGRA20_MC_RESET(3D, 0x100, 0x16c, 0x104, 11), | ||
196 | TEGRA20_MC_RESET(PPCS, 0x100, 0x170, 0x104, 12), | ||
197 | TEGRA20_MC_RESET(VDE, 0x100, 0x174, 0x104, 13), | ||
198 | TEGRA20_MC_RESET(VI, 0x100, 0x178, 0x104, 14), | ||
199 | }; | ||
200 | |||
201 | static int terga20_mc_hotreset_assert(struct tegra_mc *mc, | ||
202 | const struct tegra_mc_reset *rst) | ||
203 | { | ||
204 | unsigned long flags; | ||
205 | u32 value; | ||
206 | |||
207 | spin_lock_irqsave(&mc->lock, flags); | ||
208 | |||
209 | value = mc_readl(mc, rst->reset); | ||
210 | mc_writel(mc, value & ~BIT(rst->bit), rst->reset); | ||
211 | |||
212 | spin_unlock_irqrestore(&mc->lock, flags); | ||
213 | |||
214 | return 0; | ||
215 | } | ||
216 | |||
217 | static int terga20_mc_hotreset_deassert(struct tegra_mc *mc, | ||
218 | const struct tegra_mc_reset *rst) | ||
219 | { | ||
220 | unsigned long flags; | ||
221 | u32 value; | ||
222 | |||
223 | spin_lock_irqsave(&mc->lock, flags); | ||
224 | |||
225 | value = mc_readl(mc, rst->reset); | ||
226 | mc_writel(mc, value | BIT(rst->bit), rst->reset); | ||
227 | |||
228 | spin_unlock_irqrestore(&mc->lock, flags); | ||
229 | |||
230 | return 0; | ||
231 | } | ||
232 | |||
233 | static int terga20_mc_block_dma(struct tegra_mc *mc, | ||
234 | const struct tegra_mc_reset *rst) | ||
235 | { | ||
236 | unsigned long flags; | ||
237 | u32 value; | ||
238 | |||
239 | spin_lock_irqsave(&mc->lock, flags); | ||
240 | |||
241 | value = mc_readl(mc, rst->control) & ~BIT(rst->bit); | ||
242 | mc_writel(mc, value, rst->control); | ||
243 | |||
244 | spin_unlock_irqrestore(&mc->lock, flags); | ||
245 | |||
246 | return 0; | ||
247 | } | ||
248 | |||
249 | static bool terga20_mc_dma_idling(struct tegra_mc *mc, | ||
250 | const struct tegra_mc_reset *rst) | ||
251 | { | ||
252 | return mc_readl(mc, rst->status) == 0; | ||
253 | } | ||
254 | |||
255 | static int terga20_mc_reset_status(struct tegra_mc *mc, | ||
256 | const struct tegra_mc_reset *rst) | ||
257 | { | ||
258 | return (mc_readl(mc, rst->reset) & BIT(rst->bit)) == 0; | ||
259 | } | ||
260 | |||
261 | static int terga20_mc_unblock_dma(struct tegra_mc *mc, | ||
262 | const struct tegra_mc_reset *rst) | ||
263 | { | ||
264 | unsigned long flags; | ||
265 | u32 value; | ||
266 | |||
267 | spin_lock_irqsave(&mc->lock, flags); | ||
268 | |||
269 | value = mc_readl(mc, rst->control) | BIT(rst->bit); | ||
270 | mc_writel(mc, value, rst->control); | ||
271 | |||
272 | spin_unlock_irqrestore(&mc->lock, flags); | ||
273 | |||
274 | return 0; | ||
275 | } | ||
276 | |||
277 | const struct tegra_mc_reset_ops terga20_mc_reset_ops = { | ||
278 | .hotreset_assert = terga20_mc_hotreset_assert, | ||
279 | .hotreset_deassert = terga20_mc_hotreset_deassert, | ||
280 | .block_dma = terga20_mc_block_dma, | ||
281 | .dma_idling = terga20_mc_dma_idling, | ||
282 | .unblock_dma = terga20_mc_unblock_dma, | ||
283 | .reset_status = terga20_mc_reset_status, | ||
284 | }; | ||
285 | |||
171 | const struct tegra_mc_soc tegra20_mc_soc = { | 286 | const struct tegra_mc_soc tegra20_mc_soc = { |
172 | .clients = tegra20_mc_clients, | 287 | .clients = tegra20_mc_clients, |
173 | .num_clients = ARRAY_SIZE(tegra20_mc_clients), | 288 | .num_clients = ARRAY_SIZE(tegra20_mc_clients), |
@@ -175,4 +290,7 @@ const struct tegra_mc_soc tegra20_mc_soc = { | |||
175 | .client_id_mask = 0x3f, | 290 | .client_id_mask = 0x3f, |
176 | .intmask = MC_INT_SECURITY_VIOLATION | MC_INT_INVALID_GART_PAGE | | 291 | .intmask = MC_INT_SECURITY_VIOLATION | MC_INT_INVALID_GART_PAGE | |
177 | MC_INT_DECERR_EMEM, | 292 | MC_INT_DECERR_EMEM, |
293 | .reset_ops = &terga20_mc_reset_ops, | ||
294 | .resets = tegra20_mc_resets, | ||
295 | .num_resets = ARRAY_SIZE(tegra20_mc_resets), | ||
178 | }; | 296 | }; |