memory: tegra186: Support icc scaling
Add Interconnect framework support to dynamically set the DRAM bandwidth from different clients. The MC driver is added as an ICC provider and the EMC driver is already a provider. Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
This commit is contained in:
1 parent
3c57813597
commit
de738636ef
1 file changed
+102
@@ -898,6 +898,14 @@ static const struct tegra_mc_client tegra186_mc_clients[] = {
|
||||
.security = 0x51c,
|
||||
},
|
||||
},
|
||||
}, {
|
||||
.id = TEGRA_ICC_MC_CPU_CLUSTER0,
|
||||
.name = "sw_cluster0",
|
||||
.type = TEGRA_ICC_NISO,
|
||||
}, {
|
||||
.id = TEGRA_ICC_MC_CPU_CLUSTER1,
|
||||
.name = "sw_cluster1",
|
||||
.type = TEGRA_ICC_NISO,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -910,6 +918,99 @@ static const struct tegra_mc_intmask tegra186_mc_intmasks[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static int tegra186_mc_icc_set(struct icc_node *src, struct icc_node *dst)
|
||||
{
|
||||
/* TODO: program PTSA */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra186_mc_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
|
||||
u32 peak_bw, u32 *agg_avg, u32 *agg_peak)
|
||||
{
|
||||
struct icc_provider *p = node->provider;
|
||||
struct tegra_mc *mc = icc_provider_to_tegra_mc(p);
|
||||
|
||||
if (node->id == TEGRA_ICC_MC_CPU_CLUSTER0 ||
|
||||
node->id == TEGRA_ICC_MC_CPU_CLUSTER1) {
|
||||
if (mc)
|
||||
peak_bw = peak_bw * mc->num_channels;
|
||||
}
|
||||
|
||||
/*
|
||||
* ISO clients need to reserve extra bandwidth up-front because
|
||||
* there could be high bandwidth pressure during initial filling
|
||||
* of the client's FIFO buffers. Secondly, we need to take into
|
||||
* account impurities of the memory subsystem.
|
||||
*/
|
||||
if (tag & TEGRA_MC_ICC_TAG_ISO)
|
||||
peak_bw = tegra_mc_scale_percents(peak_bw, 400);
|
||||
|
||||
*agg_avg += avg_bw;
|
||||
*agg_peak = max(*agg_peak, peak_bw);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra186_mc_icc_get_init_bw(struct icc_node *node, u32 *avg, u32 *peak)
|
||||
{
|
||||
*avg = 0;
|
||||
*peak = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct icc_node_data *
|
||||
tegra186_mc_of_icc_xlate_extended(const struct of_phandle_args *spec, void *data)
|
||||
{
|
||||
struct tegra_mc *mc = icc_provider_to_tegra_mc(data);
|
||||
const struct tegra_mc_client *client;
|
||||
unsigned int i, idx = spec->args[0];
|
||||
struct icc_node_data *ndata;
|
||||
struct icc_node *node;
|
||||
|
||||
list_for_each_entry(node, &mc->provider.nodes, node_list) {
|
||||
if (node->id != idx)
|
||||
continue;
|
||||
|
||||
ndata = kzalloc(sizeof(*ndata), GFP_KERNEL);
|
||||
if (!ndata)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
client = &mc->soc->clients[idx];
|
||||
ndata->node = node;
|
||||
|
||||
switch (client->sid) {
|
||||
case TEGRA186_SID_NVDISPLAY:
|
||||
case TEGRA186_SID_VI:
|
||||
/* these clients are isochronous by default */
|
||||
ndata->tag = TEGRA_MC_ICC_TAG_ISO;
|
||||
break;
|
||||
|
||||
default:
|
||||
ndata->tag = TEGRA_MC_ICC_TAG_DEFAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
return ndata;
|
||||
}
|
||||
|
||||
for (i = 0; i < mc->soc->num_clients; i++) {
|
||||
if (mc->soc->clients[i].id == idx)
|
||||
return ERR_PTR(-EPROBE_DEFER);
|
||||
}
|
||||
|
||||
dev_err(mc->dev, "invalid ICC client ID %u\n", idx);
|
||||
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
static const struct tegra_mc_icc_ops tegra186_mc_icc_ops = {
|
||||
.xlate_extended = tegra186_mc_of_icc_xlate_extended,
|
||||
.aggregate = tegra186_mc_icc_aggregate,
|
||||
.get_bw = tegra186_mc_icc_get_init_bw,
|
||||
.set = tegra186_mc_icc_set,
|
||||
};
|
||||
|
||||
const struct tegra_mc_soc tegra186_mc_soc = {
|
||||
.num_clients = ARRAY_SIZE(tegra186_mc_clients),
|
||||
.clients = tegra186_mc_clients,
|
||||
@@ -919,6 +1020,7 @@ const struct tegra_mc_soc tegra186_mc_soc = {
|
||||
.intmasks = tegra186_mc_intmasks,
|
||||
.num_intmasks = ARRAY_SIZE(tegra186_mc_intmasks),
|
||||
.ops = &tegra186_mc_ops,
|
||||
.icc_ops = &tegra186_mc_icc_ops,
|
||||
.ch_intmask = 0x0000000f,
|
||||
.global_intstatus_channel_shift = 0,
|
||||
.regs = &tegra20_mc_regs,
|
||||
|
||||
Reference in new issue
Block a user