1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.
6 #include <linux/of_device.h>
7 #include <linux/slab.h>
8 #include <linux/string.h>
10 #include <dt-bindings/memory/tegra20-mc.h>
14 static const struct tegra_mc_client tegra20_mc_clients[] = {
92 .name = "ppcsahbdmar",
95 .name = "ppcsahbslvr",
158 .name = "ppcsahbdmaw",
161 .name = "ppcsahbslvw",
174 #define TEGRA20_MC_RESET(_name, _control, _status, _reset, _bit) \
177 .id = TEGRA20_MC_RESET_##_name, \
178 .control = _control, \
184 static const struct tegra_mc_reset tegra20_mc_resets[] = {
185 TEGRA20_MC_RESET(AVPC, 0x100, 0x140, 0x104, 0),
186 TEGRA20_MC_RESET(DC, 0x100, 0x144, 0x104, 1),
187 TEGRA20_MC_RESET(DCB, 0x100, 0x148, 0x104, 2),
188 TEGRA20_MC_RESET(EPP, 0x100, 0x14c, 0x104, 3),
189 TEGRA20_MC_RESET(2D, 0x100, 0x150, 0x104, 4),
190 TEGRA20_MC_RESET(HC, 0x100, 0x154, 0x104, 5),
191 TEGRA20_MC_RESET(ISP, 0x100, 0x158, 0x104, 6),
192 TEGRA20_MC_RESET(MPCORE, 0x100, 0x15c, 0x104, 7),
193 TEGRA20_MC_RESET(MPEA, 0x100, 0x160, 0x104, 8),
194 TEGRA20_MC_RESET(MPEB, 0x100, 0x164, 0x104, 9),
195 TEGRA20_MC_RESET(MPEC, 0x100, 0x168, 0x104, 10),
196 TEGRA20_MC_RESET(3D, 0x100, 0x16c, 0x104, 11),
197 TEGRA20_MC_RESET(PPCS, 0x100, 0x170, 0x104, 12),
198 TEGRA20_MC_RESET(VDE, 0x100, 0x174, 0x104, 13),
199 TEGRA20_MC_RESET(VI, 0x100, 0x178, 0x104, 14),
202 static int tegra20_mc_hotreset_assert(struct tegra_mc *mc,
203 const struct tegra_mc_reset *rst)
208 spin_lock_irqsave(&mc->lock, flags);
210 value = mc_readl(mc, rst->reset);
211 mc_writel(mc, value & ~BIT(rst->bit), rst->reset);
213 spin_unlock_irqrestore(&mc->lock, flags);
218 static int tegra20_mc_hotreset_deassert(struct tegra_mc *mc,
219 const struct tegra_mc_reset *rst)
224 spin_lock_irqsave(&mc->lock, flags);
226 value = mc_readl(mc, rst->reset);
227 mc_writel(mc, value | BIT(rst->bit), rst->reset);
229 spin_unlock_irqrestore(&mc->lock, flags);
234 static int tegra20_mc_block_dma(struct tegra_mc *mc,
235 const struct tegra_mc_reset *rst)
240 spin_lock_irqsave(&mc->lock, flags);
242 value = mc_readl(mc, rst->control) & ~BIT(rst->bit);
243 mc_writel(mc, value, rst->control);
245 spin_unlock_irqrestore(&mc->lock, flags);
250 static bool tegra20_mc_dma_idling(struct tegra_mc *mc,
251 const struct tegra_mc_reset *rst)
253 return mc_readl(mc, rst->status) == 0;
256 static int tegra20_mc_reset_status(struct tegra_mc *mc,
257 const struct tegra_mc_reset *rst)
259 return (mc_readl(mc, rst->reset) & BIT(rst->bit)) == 0;
262 static int tegra20_mc_unblock_dma(struct tegra_mc *mc,
263 const struct tegra_mc_reset *rst)
268 spin_lock_irqsave(&mc->lock, flags);
270 value = mc_readl(mc, rst->control) | BIT(rst->bit);
271 mc_writel(mc, value, rst->control);
273 spin_unlock_irqrestore(&mc->lock, flags);
278 static const struct tegra_mc_reset_ops tegra20_mc_reset_ops = {
279 .hotreset_assert = tegra20_mc_hotreset_assert,
280 .hotreset_deassert = tegra20_mc_hotreset_deassert,
281 .block_dma = tegra20_mc_block_dma,
282 .dma_idling = tegra20_mc_dma_idling,
283 .unblock_dma = tegra20_mc_unblock_dma,
284 .reset_status = tegra20_mc_reset_status,
287 static int tegra20_mc_icc_set(struct icc_node *src, struct icc_node *dst)
290 * It should be possible to tune arbitration knobs here, but the
291 * default values are known to work well on all devices. Hence
292 * nothing to do here so far.
297 static int tegra20_mc_icc_aggreate(struct icc_node *node, u32 tag, u32 avg_bw,
298 u32 peak_bw, u32 *agg_avg, u32 *agg_peak)
301 * ISO clients need to reserve extra bandwidth up-front because
302 * there could be high bandwidth pressure during initial filling
303 * of the client's FIFO buffers. Secondly, we need to take into
304 * account impurities of the memory subsystem.
306 if (tag & TEGRA_MC_ICC_TAG_ISO)
307 peak_bw = tegra_mc_scale_percents(peak_bw, 300);
310 *agg_peak = max(*agg_peak, peak_bw);
315 static struct icc_node_data *
316 tegra20_mc_of_icc_xlate_extended(struct of_phandle_args *spec, void *data)
318 struct tegra_mc *mc = icc_provider_to_tegra_mc(data);
319 unsigned int i, idx = spec->args[0];
320 struct icc_node_data *ndata;
321 struct icc_node *node;
323 list_for_each_entry(node, &mc->provider.nodes, node_list) {
327 ndata = kzalloc(sizeof(*ndata), GFP_KERNEL);
329 return ERR_PTR(-ENOMEM);
333 /* these clients are isochronous by default */
334 if (strstarts(node->name, "display") ||
335 strstarts(node->name, "vi"))
336 ndata->tag = TEGRA_MC_ICC_TAG_ISO;
338 ndata->tag = TEGRA_MC_ICC_TAG_DEFAULT;
343 for (i = 0; i < mc->soc->num_clients; i++) {
344 if (mc->soc->clients[i].id == idx)
345 return ERR_PTR(-EPROBE_DEFER);
348 dev_err(mc->dev, "invalid ICC client ID %u\n", idx);
350 return ERR_PTR(-EINVAL);
353 static const struct tegra_mc_icc_ops tegra20_mc_icc_ops = {
354 .xlate_extended = tegra20_mc_of_icc_xlate_extended,
355 .aggregate = tegra20_mc_icc_aggreate,
356 .set = tegra20_mc_icc_set,
359 const struct tegra_mc_soc tegra20_mc_soc = {
360 .clients = tegra20_mc_clients,
361 .num_clients = ARRAY_SIZE(tegra20_mc_clients),
362 .num_address_bits = 32,
363 .client_id_mask = 0x3f,
364 .intmask = MC_INT_SECURITY_VIOLATION | MC_INT_INVALID_GART_PAGE |
366 .reset_ops = &tegra20_mc_reset_ops,
367 .resets = tegra20_mc_resets,
368 .num_resets = ARRAY_SIZE(tegra20_mc_resets),
369 .icc_ops = &tegra20_mc_icc_ops,