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

Commit 4d035516 authored by Paul Burton's avatar Paul Burton Committed by Ralf Baechle
Browse files

MIPS: Enable L2 prefetching for CM >= 2.5



On systems with CM 2.5 & beyond there may be L2 prefetch units present
which are not enabled by default. Detect them, configuring & enabling
prefetching when available.

Signed-off-by: default avatarPaul Burton <paul.burton@imgtec.com>
Cc: linux-mips@linux-mips.org
Cc: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
Cc: linux-kernel@vger.kernel.org
Cc: James Hogan <james.hogan@imgtec.com>
Cc: Markos Chandras <markos.chandras@imgtec.com>
Patchwork: https://patchwork.linux-mips.org/patch/11180/


Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent 37f2a174
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -195,6 +195,8 @@ BUILD_CM_R_(gic_status, MIPS_CM_GCB_OFS + 0xd0)
BUILD_CM_R_(cpc_status,		MIPS_CM_GCB_OFS + 0xf0)
BUILD_CM_RW(l2_config,		MIPS_CM_GCB_OFS + 0x130)
BUILD_CM_RW(sys_config2,	MIPS_CM_GCB_OFS + 0x150)
BUILD_CM_RW(l2_pft_control,	MIPS_CM_GCB_OFS + 0x300)
BUILD_CM_RW(l2_pft_control_b,	MIPS_CM_GCB_OFS + 0x308)

/* Core Local & Core Other register accessor functions */
BUILD_CM_Cx_RW(reset_release,	0x00)
@@ -245,6 +247,7 @@ BUILD_CM_Cx_R_(tcid_8_priority, 0x80)
		 ((minor) << CM_GCR_REV_MINOR_SHF))

#define CM_REV_CM2				CM_ENCODE_REV(6, 0)
#define CM_REV_CM2_5				CM_ENCODE_REV(7, 0)
#define CM_REV_CM3				CM_ENCODE_REV(8, 0)

/* GCR_ERROR_CAUSE register fields */
@@ -321,6 +324,20 @@ BUILD_CM_Cx_R_(tcid_8_priority, 0x80)
#define CM_GCR_SYS_CONFIG2_MAXVPW_SHF		0
#define CM_GCR_SYS_CONFIG2_MAXVPW_MSK		(_ULCAST_(0xf) << 0)

/* GCR_L2_PFT_CONTROL register fields */
#define CM_GCR_L2_PFT_CONTROL_PAGEMASK_SHF	12
#define CM_GCR_L2_PFT_CONTROL_PAGEMASK_MSK	(_ULCAST_(0xfffff) << 12)
#define CM_GCR_L2_PFT_CONTROL_PFTEN_SHF		8
#define CM_GCR_L2_PFT_CONTROL_PFTEN_MSK		(_ULCAST_(0x1) << 8)
#define CM_GCR_L2_PFT_CONTROL_NPFT_SHF		0
#define CM_GCR_L2_PFT_CONTROL_NPFT_MSK		(_ULCAST_(0xff) << 0)

/* GCR_L2_PFT_CONTROL_B register fields */
#define CM_GCR_L2_PFT_CONTROL_B_CEN_SHF		8
#define CM_GCR_L2_PFT_CONTROL_B_CEN_MSK		(_ULCAST_(0x1) << 8)
#define CM_GCR_L2_PFT_CONTROL_B_PORTID_SHF	0
#define CM_GCR_L2_PFT_CONTROL_B_PORTID_MSK	(_ULCAST_(0xff) << 0)

/* GCR_Cx_COHERENCE register fields */
#define CM_GCR_Cx_COHERENCE_COHDOMAINEN_SHF	0
#define CM_GCR_Cx_COHERENCE_COHDOMAINEN_MSK	(_ULCAST_(0xff) << 0)
+60 −1
Original line number Diff line number Diff line
@@ -51,11 +51,69 @@ static void mips_sc_disable(void)
	/* L2 cache is permanently enabled */
}

static void mips_sc_prefetch_enable(void)
{
	unsigned long pftctl;

	if (mips_cm_revision() < CM_REV_CM2_5)
		return;

	/*
	 * If there is one or more L2 prefetch unit present then enable
	 * prefetching for both code & data, for all ports.
	 */
	pftctl = read_gcr_l2_pft_control();
	if (pftctl & CM_GCR_L2_PFT_CONTROL_NPFT_MSK) {
		pftctl &= ~CM_GCR_L2_PFT_CONTROL_PAGEMASK_MSK;
		pftctl |= PAGE_MASK & CM_GCR_L2_PFT_CONTROL_PAGEMASK_MSK;
		pftctl |= CM_GCR_L2_PFT_CONTROL_PFTEN_MSK;
		write_gcr_l2_pft_control(pftctl);

		pftctl = read_gcr_l2_pft_control_b();
		pftctl |= CM_GCR_L2_PFT_CONTROL_B_PORTID_MSK;
		pftctl |= CM_GCR_L2_PFT_CONTROL_B_CEN_MSK;
		write_gcr_l2_pft_control_b(pftctl);
	}
}

static void mips_sc_prefetch_disable(void)
{
	unsigned long pftctl;

	if (mips_cm_revision() < CM_REV_CM2_5)
		return;

	pftctl = read_gcr_l2_pft_control();
	pftctl &= ~CM_GCR_L2_PFT_CONTROL_PFTEN_MSK;
	write_gcr_l2_pft_control(pftctl);

	pftctl = read_gcr_l2_pft_control_b();
	pftctl &= ~CM_GCR_L2_PFT_CONTROL_B_PORTID_MSK;
	pftctl &= ~CM_GCR_L2_PFT_CONTROL_B_CEN_MSK;
	write_gcr_l2_pft_control_b(pftctl);
}

static bool mips_sc_prefetch_is_enabled(void)
{
	unsigned long pftctl;

	if (mips_cm_revision() < CM_REV_CM2_5)
		return false;

	pftctl = read_gcr_l2_pft_control();
	if (!(pftctl & CM_GCR_L2_PFT_CONTROL_NPFT_MSK))
		return false;
	return !!(pftctl & CM_GCR_L2_PFT_CONTROL_PFTEN_MSK);
}

static struct bcache_ops mips_sc_ops = {
	.bc_enable = mips_sc_enable,
	.bc_disable = mips_sc_disable,
	.bc_wback_inv = mips_sc_wback_inv,
	.bc_inv = mips_sc_inv
	.bc_inv = mips_sc_inv,
	.bc_prefetch_enable = mips_sc_prefetch_enable,
	.bc_prefetch_disable = mips_sc_prefetch_disable,
	.bc_prefetch_is_enabled = mips_sc_prefetch_is_enabled,
};

/*
@@ -186,6 +244,7 @@ int mips_sc_init(void)
	int found = mips_sc_probe();
	if (found) {
		mips_sc_enable();
		mips_sc_prefetch_enable();
		bcops = &mips_sc_ops;
	}
	return found;