Commit 9ee195fd authored by Serge Semin's avatar Serge Semin Committed by Thomas Bogendoerfer
Browse files

mips: MAAR: Add XPA mode support



When XPA mode is enabled the normally 32-bits MAAR pair registers
are extended to be of 64-bits width as in pure 64-bits MIPS
architecture. In this case the MAAR registers can enable the
speculative loads/stores for addresses of up to 39-bits width.
But in this case the process of the MAAR initialization changes a bit.
The upper 32-bits of the registers are supposed to be accessed by mean
of the dedicated instructions mfhc0/mthc0 and there is a CP0.MAAR.VH
bit which should be set together with CP0.MAAR.VL as indication
of the boundary validity. All of these peculiarities were taken into
account in this commit so the speculative loads/stores would work
when XPA mode is enabled.

Co-developed-by: default avatarAlexey Malahov <Alexey.Malahov@baikalelectronics.ru>
Signed-off-by: default avatarAlexey Malahov <Alexey.Malahov@baikalelectronics.ru>
Signed-off-by: default avatarSerge Semin <Sergey.Semin@baikalelectronics.ru>
Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Cc: Paul Burton <paulburton@kernel.org>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: linux-pm@vger.kernel.org
Cc: devicetree@vger.kernel.org
Signed-off-by: default avatarThomas Bogendoerfer <tsbogend@alpha.franken.de>
parent bd6e3898
Loading
Loading
Loading
Loading
+15 −2
Original line number Diff line number Diff line
@@ -32,7 +32,7 @@ unsigned platform_maar_init(unsigned num_pairs);
 * @upper:	The highest address that the MAAR pair will affect. Must be
 *		aligned to one byte before a 2^16 byte boundary.
 * @attrs:	The accessibility attributes to program, eg. MIPS_MAAR_S. The
 *		MIPS_MAAR_VL attribute will automatically be set.
 *		MIPS_MAAR_VL/MIPS_MAAR_VH attributes will automatically be set.
 *
 * Program the pair of MAAR registers specified by idx to apply the attributes
 * specified by attrs to the range of addresses from lower to higher.
@@ -48,17 +48,30 @@ static inline void write_maar_pair(unsigned idx, phys_addr_t lower,
	/* Automatically set MIPS_MAAR_VL */
	attrs |= MIPS_MAAR_VL;

	/* Write the upper address & attributes (only MIPS_MAAR_VL matters) */
	/*
	 * Write the upper address & attributes (both MIPS_MAAR_VL and
	 * MIPS_MAAR_VH matter)
	 */
	write_c0_maari(idx << 1);
	back_to_back_c0_hazard();
	write_c0_maar(((upper >> 4) & MIPS_MAAR_ADDR) | attrs);
	back_to_back_c0_hazard();
#ifdef CONFIG_XPA
	upper >>= MIPS_MAARX_ADDR_SHIFT;
	writex_c0_maar(((upper >> 4) & MIPS_MAARX_ADDR) | MIPS_MAARX_VH);
	back_to_back_c0_hazard();
#endif

	/* Write the lower address & attributes */
	write_c0_maari((idx << 1) | 0x1);
	back_to_back_c0_hazard();
	write_c0_maar((lower >> 4) | attrs);
	back_to_back_c0_hazard();
#ifdef CONFIG_XPA
	lower >>= MIPS_MAARX_ADDR_SHIFT;
	writex_c0_maar(((lower >> 4) & MIPS_MAARX_ADDR) | MIPS_MAARX_VH);
	back_to_back_c0_hazard();
#endif
}

/**
+10 −0
Original line number Diff line number Diff line
@@ -761,6 +761,14 @@
#define MIPS_MAAR_ADDR_SHIFT	12
#define MIPS_MAAR_S		(_ULCAST_(1) << 1)
#define MIPS_MAAR_VL		(_ULCAST_(1) << 0)
#ifdef CONFIG_XPA
#define MIPS_MAAR_V		(MIPS_MAAR_VH | MIPS_MAAR_VL)
#else
#define MIPS_MAAR_V		MIPS_MAAR_VL
#endif
#define MIPS_MAARX_VH		(_ULCAST_(1) << 31)
#define MIPS_MAARX_ADDR		0xF
#define MIPS_MAARX_ADDR_SHIFT	32

/* MAARI bit definitions */
#define MIPS_MAARI_INDEX	(_ULCAST_(0x3f) << 0)
@@ -1723,6 +1731,8 @@ do { \
#define write_c0_lladdr(val)	__write_ulong_c0_register($17, 0, val)
#define read_c0_maar()		__read_ulong_c0_register($17, 1)
#define write_c0_maar(val)	__write_ulong_c0_register($17, 1, val)
#define readx_c0_maar()		__readx_32bit_c0_register($17, 1)
#define writex_c0_maar(val)	__writex_32bit_c0_register($17, 1, val)
#define read_c0_maari()		__read_32bit_c0_register($17, 2)
#define write_c0_maari(val)	__write_32bit_c0_register($17, 2, val)

+7 −1
Original line number Diff line number Diff line
@@ -358,17 +358,23 @@ void maar_init(void)
		write_c0_maari(i);
		back_to_back_c0_hazard();
		upper = read_c0_maar();
#ifdef CONFIG_XPA
		upper |= (phys_addr_t)readx_c0_maar() << MIPS_MAARX_ADDR_SHIFT;
#endif

		write_c0_maari(i + 1);
		back_to_back_c0_hazard();
		lower = read_c0_maar();
#ifdef CONFIG_XPA
		lower |= (phys_addr_t)readx_c0_maar() << MIPS_MAARX_ADDR_SHIFT;
#endif

		attr = lower & upper;
		lower = (lower & MIPS_MAAR_ADDR) << 4;
		upper = ((upper & MIPS_MAAR_ADDR) << 4) | 0xffff;

		pr_info("  [%d]: ", i / 2);
		if (!(attr & MIPS_MAAR_VL)) {
		if ((attr & MIPS_MAAR_V) != MIPS_MAAR_V) {
			pr_cont("disabled\n");
			continue;
		}