Commit ddeceab0 authored by Thierry Reding's avatar Thierry Reding Committed by Krzysztof Kozlowski
Browse files

memory: tegra: Extract setup code into callback



Separate the setup code for Tegra30 and later into a ->setup() callback
and set it for all applicable chips.

Signed-off-by: default avatarThierry Reding <treding@nvidia.com>
Link: https://lore.kernel.org/r/20210602163302.120041-7-thierry.reding@gmail.com


Signed-off-by: default avatarKrzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
parent c64738e9
Loading
Loading
Loading
Loading
+70 −57
Original line number Diff line number Diff line
@@ -299,38 +299,6 @@ static int tegra_mc_reset_setup(struct tegra_mc *mc)
	return 0;
}

static int tegra_mc_setup_latency_allowance(struct tegra_mc *mc)
{
	unsigned long long tick;
	unsigned int i;
	u32 value;

	/* compute the number of MC clock cycles per tick */
	tick = (unsigned long long)mc->tick * clk_get_rate(mc->clk);
	do_div(tick, NSEC_PER_SEC);

	value = mc_readl(mc, MC_EMEM_ARB_CFG);
	value &= ~MC_EMEM_ARB_CFG_CYCLES_PER_UPDATE_MASK;
	value |= MC_EMEM_ARB_CFG_CYCLES_PER_UPDATE(tick);
	mc_writel(mc, value, MC_EMEM_ARB_CFG);

	/* write latency allowance defaults */
	for (i = 0; i < mc->soc->num_clients; i++) {
		const struct tegra_mc_client *client = &mc->soc->clients[i];
		u32 value;

		value = mc_readl(mc, client->regs.la.reg);
		value &= ~(client->regs.la.mask << client->regs.la.shift);
		value |= (client->regs.la.def & client->regs.la.mask) << client->regs.la.shift;
		mc_writel(mc, value, client->regs.la.reg);
	}

	/* latch new values */
	mc_writel(mc, MC_TIMING_UPDATE, MC_TIMING_CONTROL);

	return 0;
}

int tegra_mc_write_emem_configuration(struct tegra_mc *mc, unsigned long rate)
{
	unsigned int i;
@@ -368,6 +336,43 @@ unsigned int tegra_mc_get_emem_device_count(struct tegra_mc *mc)
}
EXPORT_SYMBOL_GPL(tegra_mc_get_emem_device_count);

#if defined(CONFIG_ARCH_TEGRA_3x_SOC) || \
    defined(CONFIG_ARCH_TEGRA_114_SOC) || \
    defined(CONFIG_ARCH_TEGRA_124_SOC) || \
    defined(CONFIG_ARCH_TEGRA_132_SOC) || \
    defined(CONFIG_ARCH_TEGRA_210_SOC)
static int tegra_mc_setup_latency_allowance(struct tegra_mc *mc)
{
	unsigned long long tick;
	unsigned int i;
	u32 value;

	/* compute the number of MC clock cycles per tick */
	tick = (unsigned long long)mc->tick * clk_get_rate(mc->clk);
	do_div(tick, NSEC_PER_SEC);

	value = mc_readl(mc, MC_EMEM_ARB_CFG);
	value &= ~MC_EMEM_ARB_CFG_CYCLES_PER_UPDATE_MASK;
	value |= MC_EMEM_ARB_CFG_CYCLES_PER_UPDATE(tick);
	mc_writel(mc, value, MC_EMEM_ARB_CFG);

	/* write latency allowance defaults */
	for (i = 0; i < mc->soc->num_clients; i++) {
		const struct tegra_mc_client *client = &mc->soc->clients[i];
		u32 value;

		value = mc_readl(mc, client->regs.la.reg);
		value &= ~(client->regs.la.mask << client->regs.la.shift);
		value |= (client->regs.la.def & client->regs.la.mask) << client->regs.la.shift;
		mc_writel(mc, value, client->regs.la.reg);
	}

	/* latch new values */
	mc_writel(mc, MC_TIMING_UPDATE, MC_TIMING_CONTROL);

	return 0;
}

static int load_one_timing(struct tegra_mc *mc,
			   struct tegra_mc_timing *timing,
			   struct device_node *node)
@@ -459,6 +464,39 @@ static int tegra_mc_setup_timings(struct tegra_mc *mc)
	return 0;
}

int tegra30_mc_probe(struct tegra_mc *mc)
{
	int err;

	mc->clk = devm_clk_get_optional(mc->dev, "mc");
	if (IS_ERR(mc->clk)) {
		dev_err(mc->dev, "failed to get MC clock: %ld\n", PTR_ERR(mc->clk));
		return PTR_ERR(mc->clk);
	}

	/* ensure that debug features are disabled */
	mc_writel(mc, 0x00000000, MC_TIMING_CONTROL_DBG);

	err = tegra_mc_setup_latency_allowance(mc);
	if (err < 0) {
		dev_err(mc->dev, "failed to setup latency allowance: %d\n", err);
		return err;
	}

	err = tegra_mc_setup_timings(mc);
	if (err < 0) {
		dev_err(mc->dev, "failed to setup timings: %d\n", err);
		return err;
	}

	return 0;
}

const struct tegra_mc_ops tegra30_mc_ops = {
	.probe = tegra30_mc_probe,
};
#endif

static const char *const status_names[32] = {
	[ 1] = "External interrupt",
	[ 6] = "EMEM address decode error",
@@ -777,13 +815,6 @@ static int tegra_mc_probe(struct platform_device *pdev)
	if (IS_ERR(mc->regs))
		return PTR_ERR(mc->regs);

	mc->clk = devm_clk_get(&pdev->dev, "mc");
	if (IS_ERR(mc->clk)) {
		dev_err(&pdev->dev, "failed to get MC clock: %ld\n",
			PTR_ERR(mc->clk));
		return PTR_ERR(mc->clk);
	}

	mc->debugfs.root = debugfs_create_dir("mc", NULL);

	if (mc->soc->ops && mc->soc->ops->probe) {
@@ -798,25 +829,7 @@ static int tegra_mc_probe(struct platform_device *pdev)
	} else
#endif
	{
		/* ensure that debug features are disabled */
		mc_writel(mc, 0x00000000, MC_TIMING_CONTROL_DBG);

		err = tegra_mc_setup_latency_allowance(mc);
		if (err < 0) {
			dev_err(&pdev->dev,
				"failed to setup latency allowance: %d\n",
				err);
			return err;
		}

		isr = tegra_mc_irq;

		err = tegra_mc_setup_timings(mc);
		if (err < 0) {
			dev_err(&pdev->dev, "failed to setup timings: %d\n",
				err);
			return err;
		}
	}

	mc->irq = platform_get_irq(pdev, 0);
+9 −0
Original line number Diff line number Diff line
@@ -129,6 +129,15 @@ extern const struct tegra_mc_soc tegra132_mc_soc;
extern const struct tegra_mc_soc tegra210_mc_soc;
#endif

#if defined(CONFIG_ARCH_TEGRA_3x_SOC) || \
    defined(CONFIG_ARCH_TEGRA_114_SOC) || \
    defined(CONFIG_ARCH_TEGRA_124_SOC) || \
    defined(CONFIG_ARCH_TEGRA_132_SOC) || \
    defined(CONFIG_ARCH_TEGRA_210_SOC)
int tegra30_mc_probe(struct tegra_mc *mc);
extern const struct tegra_mc_ops tegra30_mc_ops;
#endif

/*
 * These IDs are for internal use of Tegra ICC drivers. The ID numbers are
 * chosen such that they don't conflict with the device-tree ICC node IDs.
+1 −0
Original line number Diff line number Diff line
@@ -1113,4 +1113,5 @@ const struct tegra_mc_soc tegra114_mc_soc = {
	.reset_ops = &tegra_mc_reset_ops_common,
	.resets = tegra114_mc_resets,
	.num_resets = ARRAY_SIZE(tegra114_mc_resets),
	.ops = &tegra30_mc_ops,
};
+2 −0
Original line number Diff line number Diff line
@@ -1274,6 +1274,7 @@ const struct tegra_mc_soc tegra124_mc_soc = {
	.resets = tegra124_mc_resets,
	.num_resets = ARRAY_SIZE(tegra124_mc_resets),
	.icc_ops = &tegra124_mc_icc_ops,
	.ops = &tegra30_mc_ops,
};
#endif /* CONFIG_ARCH_TEGRA_124_SOC */

@@ -1305,5 +1306,6 @@ const struct tegra_mc_soc tegra132_mc_soc = {
	.resets = tegra124_mc_resets,
	.num_resets = ARRAY_SIZE(tegra124_mc_resets),
	.icc_ops = &tegra124_mc_icc_ops,
	.ops = &tegra30_mc_ops,
};
#endif /* CONFIG_ARCH_TEGRA_132_SOC */
+1 −0
Original line number Diff line number Diff line
@@ -1286,4 +1286,5 @@ const struct tegra_mc_soc tegra210_mc_soc = {
	.reset_ops = &tegra_mc_reset_ops_common,
	.resets = tegra210_mc_resets,
	.num_resets = ARRAY_SIZE(tegra210_mc_resets),
	.ops = &tegra30_mc_ops,
};
Loading