Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 75461f5c authored by Russell King's avatar Russell King
Browse files

ARM: l2c: implement fixups for L2 cache controller quirks/errata



Rather than putting quirk handling in __l2c_init(), move it out to a
separate function which individual implementations can specify.  This
helps to localise the quirks to those implementations which require
them.

Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent 40266d6f
Loading
Loading
Loading
Loading
+101 −11
Original line number Original line Diff line number Diff line
@@ -32,6 +32,7 @@ struct l2c_init_data {
	unsigned num_lock;
	unsigned num_lock;
	void (*of_parse)(const struct device_node *, u32 *, u32 *);
	void (*of_parse)(const struct device_node *, u32 *, u32 *);
	void (*enable)(void __iomem *, u32, unsigned);
	void (*enable)(void __iomem *, u32, unsigned);
	void (*fixup)(void __iomem *, u32, struct outer_cache_fns *);
	void (*save)(void __iomem *);
	void (*save)(void __iomem *);
	struct outer_cache_fns outer_cache;
	struct outer_cache_fns outer_cache;
};
};
@@ -394,9 +395,80 @@ static const struct l2c_init_data l2x0_init_fns __initconst = {
	},
	},
};
};


/*
 * L2C-310 specific code.
 *
 * Errata:
 * 588369: PL310 R0P0->R1P0, fixed R2P0.
 *	Affects: all clean+invalidate operations
 *	clean and invalidate skips the invalidate step, so we need to issue
 *	separate operations.  We also require the above debug workaround
 *	enclosing this code fragment on affected parts.  On unaffected parts,
 *	we must not use this workaround without the debug register writes
 *	to avoid exposing a problem similar to 727915.
 *
 * 727915: PL310 R2P0->R3P0, fixed R3P1.
 *	Affects: clean+invalidate by way
 *	clean and invalidate by way runs in the background, and a store can
 *	hit the line between the clean operation and invalidate operation,
 *	resulting in the store being lost.
 *
 * 753970: PL310 R3P0, fixed R3P1.
 *	Affects: sync
 *	prevents merging writes after the sync operation, until another L2C
 *	operation is performed (or a number of other conditions.)
 *
 * 769419: PL310 R0P0->R3P1, fixed R3P2.
 *	Affects: store buffer
 *	store buffer is not automatically drained.
 */
static void __init l2c310_fixup(void __iomem *base, u32 cache_id,
	struct outer_cache_fns *fns)
{
	unsigned revision = cache_id & L2X0_CACHE_ID_RTL_MASK;
	const char *errata[4];
	unsigned n = 0;

	if (revision <= L310_CACHE_ID_RTL_R3P0)
		fns->set_debug = pl310_set_debug;

	if (IS_ENABLED(CONFIG_PL310_ERRATA_753970) &&
	    revision == L310_CACHE_ID_RTL_R3P0) {
		sync_reg_offset = L2X0_DUMMY_REG;
		errata[n++] = "753970";
	}

	if (IS_ENABLED(CONFIG_PL310_ERRATA_769419))
		errata[n++] = "769419";

	if (n) {
		unsigned i;

		pr_info("L2C-310 errat%s", n > 1 ? "a" : "um");
		for (i = 0; i < n; i++)
			pr_cont(" %s", errata[i]);
		pr_cont(" enabled\n");
	}
}

static const struct l2c_init_data l2c310_init_fns __initconst = {
	.num_lock = 8,
	.enable = l2c_enable,
	.fixup = l2c310_fixup,
	.outer_cache = {
		.inv_range = l2x0_inv_range,
		.clean_range = l2x0_clean_range,
		.flush_range = l2x0_flush_range,
		.flush_all = l2x0_flush_all,
		.disable = l2x0_disable,
		.sync = l2x0_cache_sync,
	},
};

static void __init __l2c_init(const struct l2c_init_data *data,
static void __init __l2c_init(const struct l2c_init_data *data,
	u32 aux_val, u32 aux_mask, u32 cache_id)
	u32 aux_val, u32 aux_mask, u32 cache_id)
{
{
	struct outer_cache_fns fns;
	u32 aux;
	u32 aux;
	u32 way_size = 0;
	u32 way_size = 0;
	int ways;
	int ways;
@@ -423,23 +495,20 @@ static void __init __l2c_init(const struct l2c_init_data *data,
		else
		else
			ways = 8;
			ways = 8;
		type = "L310";
		type = "L310";
#ifdef CONFIG_PL310_ERRATA_753970
		/* Unmapped register. */
		sync_reg_offset = L2X0_DUMMY_REG;
#endif
		break;
		break;

	case L2X0_CACHE_ID_PART_L210:
	case L2X0_CACHE_ID_PART_L210:
		ways = (aux >> 13) & 0xf;
		ways = (aux >> 13) & 0xf;
		type = "L210";
		type = "L210";
		break;
		break;


	case AURORA_CACHE_ID:
	case AURORA_CACHE_ID:
		sync_reg_offset = AURORA_SYNC_REG;
		ways = (aux >> 13) & 0xf;
		ways = (aux >> 13) & 0xf;
		ways = 2 << ((ways + 1) >> 2);
		ways = 2 << ((ways + 1) >> 2);
		way_size_shift = AURORA_WAY_SIZE_SHIFT;
		way_size_shift = AURORA_WAY_SIZE_SHIFT;
		type = "Aurora";
		type = "Aurora";
		break;
		break;

	default:
	default:
		/* Assume unknown chips have 8 ways */
		/* Assume unknown chips have 8 ways */
		ways = 8;
		ways = 8;
@@ -457,6 +526,10 @@ static void __init __l2c_init(const struct l2c_init_data *data,


	l2x0_size = ways * way_size * SZ_1K;
	l2x0_size = ways * way_size * SZ_1K;


	fns = data->outer_cache;
	if (data->fixup)
		data->fixup(l2x0_base, cache_id, &fns);

	/*
	/*
	 * Check if l2x0 controller is already enabled.  If we are booting
	 * Check if l2x0 controller is already enabled.  If we are booting
	 * in non-secure mode accessing the below registers will fault.
	 * in non-secure mode accessing the below registers will fault.
@@ -470,11 +543,7 @@ static void __init __l2c_init(const struct l2c_init_data *data,
	/* Save the value for resuming. */
	/* Save the value for resuming. */
	l2x0_saved_regs.aux_ctrl = aux;
	l2x0_saved_regs.aux_ctrl = aux;


	outer_cache = data->outer_cache;
	outer_cache = fns;

	if ((cache_id & L2X0_CACHE_ID_PART_MASK) == L2X0_CACHE_ID_PART_L310 &&
	    (cache_id & L2X0_CACHE_ID_RTL_MASK) <= L310_CACHE_ID_RTL_R3P0)
		outer_cache.set_debug = pl310_set_debug;


	pr_info("%s cache controller enabled\n", type);
	pr_info("%s cache controller enabled\n", type);
	pr_info("l2x0: %d ways, CACHE_ID 0x%08x, AUX_CTRL 0x%08x, Cache size: %d kB\n",
	pr_info("l2x0: %d ways, CACHE_ID 0x%08x, AUX_CTRL 0x%08x, Cache size: %d kB\n",
@@ -483,13 +552,24 @@ static void __init __l2c_init(const struct l2c_init_data *data,


void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask)
void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask)
{
{
	const struct l2c_init_data *data;
	u32 cache_id;
	u32 cache_id;


	l2x0_base = base;
	l2x0_base = base;


	cache_id = readl_relaxed(base + L2X0_CACHE_ID);
	cache_id = readl_relaxed(base + L2X0_CACHE_ID);


	__l2c_init(&l2x0_init_fns, aux_val, aux_mask, cache_id);
	switch (cache_id & L2X0_CACHE_ID_PART_MASK) {
	default:
		data = &l2x0_init_fns;
		break;

	case L2X0_CACHE_ID_PART_L310:
		data = &l2c310_init_fns;
		break;
	}

	__l2c_init(data, aux_val, aux_mask, cache_id);
}
}


#ifdef CONFIG_OF
#ifdef CONFIG_OF
@@ -659,6 +739,7 @@ static const struct l2c_init_data of_pl310_data __initconst = {
	.num_lock = 8,
	.num_lock = 8,
	.of_parse = pl310_of_parse,
	.of_parse = pl310_of_parse,
	.enable = l2c_enable,
	.enable = l2c_enable,
	.fixup = l2c310_fixup,
	.save  = pl310_save,
	.save  = pl310_save,
	.outer_cache = {
	.outer_cache = {
		.inv_range   = l2x0_inv_range,
		.inv_range   = l2x0_inv_range,
@@ -802,6 +883,12 @@ static void __init aurora_enable_no_outer(void __iomem *base, u32 aux,
	l2c_enable(base, aux, num_lock);
	l2c_enable(base, aux, num_lock);
}
}


static void __init aurora_fixup(void __iomem *base, u32 cache_id,
	struct outer_cache_fns *fns)
{
	sync_reg_offset = AURORA_SYNC_REG;
}

static void __init aurora_of_parse(const struct device_node *np,
static void __init aurora_of_parse(const struct device_node *np,
				u32 *aux_val, u32 *aux_mask)
				u32 *aux_val, u32 *aux_mask)
{
{
@@ -828,6 +915,7 @@ static const struct l2c_init_data of_aurora_with_outer_data __initconst = {
	.num_lock = 4,
	.num_lock = 4,
	.of_parse = aurora_of_parse,
	.of_parse = aurora_of_parse,
	.enable = l2c_enable,
	.enable = l2c_enable,
	.fixup = aurora_fixup,
	.save  = aurora_save,
	.save  = aurora_save,
	.outer_cache = {
	.outer_cache = {
		.inv_range   = aurora_inv_range,
		.inv_range   = aurora_inv_range,
@@ -844,6 +932,7 @@ static const struct l2c_init_data of_aurora_no_outer_data __initconst = {
	.num_lock = 4,
	.num_lock = 4,
	.of_parse = aurora_of_parse,
	.of_parse = aurora_of_parse,
	.enable = aurora_enable_no_outer,
	.enable = aurora_enable_no_outer,
	.fixup = aurora_fixup,
	.save  = aurora_save,
	.save  = aurora_save,
	.outer_cache = {
	.outer_cache = {
		.resume      = aurora_resume,
		.resume      = aurora_resume,
@@ -995,6 +1084,7 @@ static const struct l2c_init_data of_bcm_l2x0_data __initconst = {
	.num_lock = 8,
	.num_lock = 8,
	.of_parse = pl310_of_parse,
	.of_parse = pl310_of_parse,
	.enable = l2c_enable,
	.enable = l2c_enable,
	.fixup = l2c310_fixup,
	.save  = pl310_save,
	.save  = pl310_save,
	.outer_cache = {
	.outer_cache = {
		.inv_range   = bcm_inv_range,
		.inv_range   = bcm_inv_range,