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
,