18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Broadcom STB SoCs Bus Unit Interface controls
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 2015, Broadcom Corporation
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#define pr_fmt(fmt)	"brcmstb: " KBUILD_MODNAME ": " fmt
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#include <linux/kernel.h>
118c2ecf20Sopenharmony_ci#include <linux/io.h>
128c2ecf20Sopenharmony_ci#include <linux/of_address.h>
138c2ecf20Sopenharmony_ci#include <linux/syscore_ops.h>
148c2ecf20Sopenharmony_ci#include <linux/soc/brcmstb/brcmstb.h>
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci#define RACENPREF_MASK			0x3
178c2ecf20Sopenharmony_ci#define RACPREFINST_SHIFT		0
188c2ecf20Sopenharmony_ci#define RACENINST_SHIFT			2
198c2ecf20Sopenharmony_ci#define RACPREFDATA_SHIFT		4
208c2ecf20Sopenharmony_ci#define RACENDATA_SHIFT			6
218c2ecf20Sopenharmony_ci#define RAC_CPU_SHIFT			8
228c2ecf20Sopenharmony_ci#define RACCFG_MASK			0xff
238c2ecf20Sopenharmony_ci#define DPREF_LINE_2_SHIFT		24
248c2ecf20Sopenharmony_ci#define DPREF_LINE_2_MASK		0xff
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci/* Bitmask to enable instruction and data prefetching with a 256-bytes stride */
278c2ecf20Sopenharmony_ci#define RAC_DATA_INST_EN_MASK		(1 << RACPREFINST_SHIFT | \
288c2ecf20Sopenharmony_ci					 RACENPREF_MASK << RACENINST_SHIFT | \
298c2ecf20Sopenharmony_ci					 1 << RACPREFDATA_SHIFT | \
308c2ecf20Sopenharmony_ci					 RACENPREF_MASK << RACENDATA_SHIFT)
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci#define  CPU_CREDIT_REG_MCPx_WR_PAIRING_EN_MASK	0x70000000
338c2ecf20Sopenharmony_ci#define CPU_CREDIT_REG_MCPx_READ_CRED_MASK	0xf
348c2ecf20Sopenharmony_ci#define CPU_CREDIT_REG_MCPx_WRITE_CRED_MASK	0xf
358c2ecf20Sopenharmony_ci#define CPU_CREDIT_REG_MCPx_READ_CRED_SHIFT(x)	((x) * 8)
368c2ecf20Sopenharmony_ci#define CPU_CREDIT_REG_MCPx_WRITE_CRED_SHIFT(x)	(((x) * 8) + 4)
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci#define CPU_MCP_FLOW_REG_MCPx_RDBUFF_CRED_SHIFT(x)	((x) * 8)
398c2ecf20Sopenharmony_ci#define CPU_MCP_FLOW_REG_MCPx_RDBUFF_CRED_MASK		0xff
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci#define CPU_WRITEBACK_CTRL_REG_WB_THROTTLE_THRESHOLD_MASK	0xf
428c2ecf20Sopenharmony_ci#define CPU_WRITEBACK_CTRL_REG_WB_THROTTLE_TIMEOUT_MASK		0xf
438c2ecf20Sopenharmony_ci#define CPU_WRITEBACK_CTRL_REG_WB_THROTTLE_TIMEOUT_SHIFT	4
448c2ecf20Sopenharmony_ci#define CPU_WRITEBACK_CTRL_REG_WB_THROTTLE_ENABLE		BIT(8)
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_cistatic void __iomem *cpubiuctrl_base;
478c2ecf20Sopenharmony_cistatic bool mcp_wr_pairing_en;
488c2ecf20Sopenharmony_cistatic const int *cpubiuctrl_regs;
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_cienum cpubiuctrl_regs {
518c2ecf20Sopenharmony_ci	CPU_CREDIT_REG = 0,
528c2ecf20Sopenharmony_ci	CPU_MCP_FLOW_REG,
538c2ecf20Sopenharmony_ci	CPU_WRITEBACK_CTRL_REG,
548c2ecf20Sopenharmony_ci	RAC_CONFIG0_REG,
558c2ecf20Sopenharmony_ci	RAC_CONFIG1_REG,
568c2ecf20Sopenharmony_ci	NUM_CPU_BIUCTRL_REGS,
578c2ecf20Sopenharmony_ci};
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_cistatic inline u32 cbc_readl(int reg)
608c2ecf20Sopenharmony_ci{
618c2ecf20Sopenharmony_ci	int offset = cpubiuctrl_regs[reg];
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ci	if (offset == -1 ||
648c2ecf20Sopenharmony_ci	    (IS_ENABLED(CONFIG_CACHE_B15_RAC) && reg >= RAC_CONFIG0_REG))
658c2ecf20Sopenharmony_ci		return (u32)-1;
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci	return readl_relaxed(cpubiuctrl_base + offset);
688c2ecf20Sopenharmony_ci}
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_cistatic inline void cbc_writel(u32 val, int reg)
718c2ecf20Sopenharmony_ci{
728c2ecf20Sopenharmony_ci	int offset = cpubiuctrl_regs[reg];
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci	if (offset == -1 ||
758c2ecf20Sopenharmony_ci	    (IS_ENABLED(CONFIG_CACHE_B15_RAC) && reg >= RAC_CONFIG0_REG))
768c2ecf20Sopenharmony_ci		return;
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci	writel(val, cpubiuctrl_base + offset);
798c2ecf20Sopenharmony_ci}
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_cistatic const int b15_cpubiuctrl_regs[] = {
828c2ecf20Sopenharmony_ci	[CPU_CREDIT_REG] = 0x184,
838c2ecf20Sopenharmony_ci	[CPU_MCP_FLOW_REG] = -1,
848c2ecf20Sopenharmony_ci	[CPU_WRITEBACK_CTRL_REG] = -1,
858c2ecf20Sopenharmony_ci	[RAC_CONFIG0_REG] = -1,
868c2ecf20Sopenharmony_ci	[RAC_CONFIG1_REG] = -1,
878c2ecf20Sopenharmony_ci};
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ci/* Odd cases, e.g: 7260A0 */
908c2ecf20Sopenharmony_cistatic const int b53_cpubiuctrl_no_wb_regs[] = {
918c2ecf20Sopenharmony_ci	[CPU_CREDIT_REG] = 0x0b0,
928c2ecf20Sopenharmony_ci	[CPU_MCP_FLOW_REG] = 0x0b4,
938c2ecf20Sopenharmony_ci	[CPU_WRITEBACK_CTRL_REG] = -1,
948c2ecf20Sopenharmony_ci	[RAC_CONFIG0_REG] = 0x78,
958c2ecf20Sopenharmony_ci	[RAC_CONFIG1_REG] = 0x7c,
968c2ecf20Sopenharmony_ci};
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_cistatic const int b53_cpubiuctrl_regs[] = {
998c2ecf20Sopenharmony_ci	[CPU_CREDIT_REG] = 0x0b0,
1008c2ecf20Sopenharmony_ci	[CPU_MCP_FLOW_REG] = 0x0b4,
1018c2ecf20Sopenharmony_ci	[CPU_WRITEBACK_CTRL_REG] = 0x22c,
1028c2ecf20Sopenharmony_ci	[RAC_CONFIG0_REG] = 0x78,
1038c2ecf20Sopenharmony_ci	[RAC_CONFIG1_REG] = 0x7c,
1048c2ecf20Sopenharmony_ci};
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_cistatic const int a72_cpubiuctrl_regs[] = {
1078c2ecf20Sopenharmony_ci	[CPU_CREDIT_REG] = 0x18,
1088c2ecf20Sopenharmony_ci	[CPU_MCP_FLOW_REG] = 0x1c,
1098c2ecf20Sopenharmony_ci	[CPU_WRITEBACK_CTRL_REG] = 0x20,
1108c2ecf20Sopenharmony_ci	[RAC_CONFIG0_REG] = 0x08,
1118c2ecf20Sopenharmony_ci	[RAC_CONFIG1_REG] = 0x0c,
1128c2ecf20Sopenharmony_ci};
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_cistatic int __init mcp_write_pairing_set(void)
1158c2ecf20Sopenharmony_ci{
1168c2ecf20Sopenharmony_ci	u32 creds = 0;
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_ci	if (!cpubiuctrl_base)
1198c2ecf20Sopenharmony_ci		return -1;
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_ci	creds = cbc_readl(CPU_CREDIT_REG);
1228c2ecf20Sopenharmony_ci	if (mcp_wr_pairing_en) {
1238c2ecf20Sopenharmony_ci		pr_info("MCP: Enabling write pairing\n");
1248c2ecf20Sopenharmony_ci		cbc_writel(creds | CPU_CREDIT_REG_MCPx_WR_PAIRING_EN_MASK,
1258c2ecf20Sopenharmony_ci			   CPU_CREDIT_REG);
1268c2ecf20Sopenharmony_ci	} else if (creds & CPU_CREDIT_REG_MCPx_WR_PAIRING_EN_MASK) {
1278c2ecf20Sopenharmony_ci		pr_info("MCP: Disabling write pairing\n");
1288c2ecf20Sopenharmony_ci		cbc_writel(creds & ~CPU_CREDIT_REG_MCPx_WR_PAIRING_EN_MASK,
1298c2ecf20Sopenharmony_ci			   CPU_CREDIT_REG);
1308c2ecf20Sopenharmony_ci	} else {
1318c2ecf20Sopenharmony_ci		pr_info("MCP: Write pairing already disabled\n");
1328c2ecf20Sopenharmony_ci	}
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_ci	return 0;
1358c2ecf20Sopenharmony_ci}
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_cistatic const u32 a72_b53_mach_compat[] = {
1388c2ecf20Sopenharmony_ci	0x7211,
1398c2ecf20Sopenharmony_ci	0x7216,
1408c2ecf20Sopenharmony_ci	0x72164,
1418c2ecf20Sopenharmony_ci	0x72165,
1428c2ecf20Sopenharmony_ci	0x7255,
1438c2ecf20Sopenharmony_ci	0x7260,
1448c2ecf20Sopenharmony_ci	0x7268,
1458c2ecf20Sopenharmony_ci	0x7271,
1468c2ecf20Sopenharmony_ci	0x7278,
1478c2ecf20Sopenharmony_ci};
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ci/* The read-ahead cache present in the Brahma-B53 CPU is a special piece of
1508c2ecf20Sopenharmony_ci * hardware after the integrated L2 cache of the B53 CPU complex whose purpose
1518c2ecf20Sopenharmony_ci * is to prefetch instruction and/or data with a line size of either 64 bytes
1528c2ecf20Sopenharmony_ci * or 256 bytes. The rationale is that the data-bus of the CPU interface is
1538c2ecf20Sopenharmony_ci * optimized for 256-byte transactions, and enabling the read-ahead cache
1548c2ecf20Sopenharmony_ci * provides a significant performance boost (typically twice the performance
1558c2ecf20Sopenharmony_ci * for a memcpy benchmark application).
1568c2ecf20Sopenharmony_ci *
1578c2ecf20Sopenharmony_ci * The read-ahead cache is transparent for Virtual Address cache maintenance
1588c2ecf20Sopenharmony_ci * operations: IC IVAU, DC IVAC, DC CVAC, DC CVAU and DC CIVAC.  So no special
1598c2ecf20Sopenharmony_ci * handling is needed for the DMA API above and beyond what is included in the
1608c2ecf20Sopenharmony_ci * arm64 implementation.
1618c2ecf20Sopenharmony_ci *
1628c2ecf20Sopenharmony_ci * In addition, since the Point of Unification is typically between L1 and L2
1638c2ecf20Sopenharmony_ci * for the Brahma-B53 processor no special read-ahead cache handling is needed
1648c2ecf20Sopenharmony_ci * for the IC IALLU and IC IALLUIS cache maintenance operations.
1658c2ecf20Sopenharmony_ci *
1668c2ecf20Sopenharmony_ci * However, it is not possible to specify the cache level (L3) for the cache
1678c2ecf20Sopenharmony_ci * maintenance instructions operating by set/way to operate on the read-ahead
1688c2ecf20Sopenharmony_ci * cache.  The read-ahead cache will maintain coherency when inner cache lines
1698c2ecf20Sopenharmony_ci * are cleaned by set/way, but if it is necessary to invalidate inner cache
1708c2ecf20Sopenharmony_ci * lines by set/way to maintain coherency with system masters operating on
1718c2ecf20Sopenharmony_ci * shared memory that does not have hardware support for coherency, then it
1728c2ecf20Sopenharmony_ci * will also be necessary to explicitly invalidate the read-ahead cache.
1738c2ecf20Sopenharmony_ci */
1748c2ecf20Sopenharmony_cistatic void __init a72_b53_rac_enable_all(struct device_node *np)
1758c2ecf20Sopenharmony_ci{
1768c2ecf20Sopenharmony_ci	unsigned int cpu;
1778c2ecf20Sopenharmony_ci	u32 enable = 0, pref_dist, shift;
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_ci	if (IS_ENABLED(CONFIG_CACHE_B15_RAC))
1808c2ecf20Sopenharmony_ci		return;
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_ci	if (WARN(num_possible_cpus() > 4, "RAC only supports 4 CPUs\n"))
1838c2ecf20Sopenharmony_ci		return;
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_ci	pref_dist = cbc_readl(RAC_CONFIG1_REG);
1868c2ecf20Sopenharmony_ci	for_each_possible_cpu(cpu) {
1878c2ecf20Sopenharmony_ci		shift = cpu * RAC_CPU_SHIFT + RACPREFDATA_SHIFT;
1888c2ecf20Sopenharmony_ci		enable |= RAC_DATA_INST_EN_MASK << (cpu * RAC_CPU_SHIFT);
1898c2ecf20Sopenharmony_ci		if (cpubiuctrl_regs == a72_cpubiuctrl_regs) {
1908c2ecf20Sopenharmony_ci			enable &= ~(RACENPREF_MASK << shift);
1918c2ecf20Sopenharmony_ci			enable |= 3 << shift;
1928c2ecf20Sopenharmony_ci			pref_dist |= 1 << (cpu + DPREF_LINE_2_SHIFT);
1938c2ecf20Sopenharmony_ci		}
1948c2ecf20Sopenharmony_ci	}
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_ci	cbc_writel(enable, RAC_CONFIG0_REG);
1978c2ecf20Sopenharmony_ci	cbc_writel(pref_dist, RAC_CONFIG1_REG);
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci	pr_info("%pOF: Broadcom %s read-ahead cache\n",
2008c2ecf20Sopenharmony_ci		np, cpubiuctrl_regs == a72_cpubiuctrl_regs ?
2018c2ecf20Sopenharmony_ci		"Cortex-A72" : "Brahma-B53");
2028c2ecf20Sopenharmony_ci}
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_cistatic void __init mcp_a72_b53_set(void)
2058c2ecf20Sopenharmony_ci{
2068c2ecf20Sopenharmony_ci	unsigned int i;
2078c2ecf20Sopenharmony_ci	u32 reg;
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci	reg = brcmstb_get_family_id();
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(a72_b53_mach_compat); i++) {
2128c2ecf20Sopenharmony_ci		if (BRCM_ID(reg) == a72_b53_mach_compat[i])
2138c2ecf20Sopenharmony_ci			break;
2148c2ecf20Sopenharmony_ci	}
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_ci	if (i == ARRAY_SIZE(a72_b53_mach_compat))
2178c2ecf20Sopenharmony_ci		return;
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_ci	/* Set all 3 MCP interfaces to 8 credits */
2208c2ecf20Sopenharmony_ci	reg = cbc_readl(CPU_CREDIT_REG);
2218c2ecf20Sopenharmony_ci	for (i = 0; i < 3; i++) {
2228c2ecf20Sopenharmony_ci		reg &= ~(CPU_CREDIT_REG_MCPx_WRITE_CRED_MASK <<
2238c2ecf20Sopenharmony_ci			 CPU_CREDIT_REG_MCPx_WRITE_CRED_SHIFT(i));
2248c2ecf20Sopenharmony_ci		reg &= ~(CPU_CREDIT_REG_MCPx_READ_CRED_MASK <<
2258c2ecf20Sopenharmony_ci			 CPU_CREDIT_REG_MCPx_READ_CRED_SHIFT(i));
2268c2ecf20Sopenharmony_ci		reg |= 8 << CPU_CREDIT_REG_MCPx_WRITE_CRED_SHIFT(i);
2278c2ecf20Sopenharmony_ci		reg |= 8 << CPU_CREDIT_REG_MCPx_READ_CRED_SHIFT(i);
2288c2ecf20Sopenharmony_ci	}
2298c2ecf20Sopenharmony_ci	cbc_writel(reg, CPU_CREDIT_REG);
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci	/* Max out the number of in-flight Jwords reads on the MCP interface */
2328c2ecf20Sopenharmony_ci	reg = cbc_readl(CPU_MCP_FLOW_REG);
2338c2ecf20Sopenharmony_ci	for (i = 0; i < 3; i++)
2348c2ecf20Sopenharmony_ci		reg |= CPU_MCP_FLOW_REG_MCPx_RDBUFF_CRED_MASK <<
2358c2ecf20Sopenharmony_ci			CPU_MCP_FLOW_REG_MCPx_RDBUFF_CRED_SHIFT(i);
2368c2ecf20Sopenharmony_ci	cbc_writel(reg, CPU_MCP_FLOW_REG);
2378c2ecf20Sopenharmony_ci
2388c2ecf20Sopenharmony_ci	/* Enable writeback throttling, set timeout to 128 cycles, 256 cycles
2398c2ecf20Sopenharmony_ci	 * threshold
2408c2ecf20Sopenharmony_ci	 */
2418c2ecf20Sopenharmony_ci	reg = cbc_readl(CPU_WRITEBACK_CTRL_REG);
2428c2ecf20Sopenharmony_ci	reg |= CPU_WRITEBACK_CTRL_REG_WB_THROTTLE_ENABLE;
2438c2ecf20Sopenharmony_ci	reg &= ~CPU_WRITEBACK_CTRL_REG_WB_THROTTLE_THRESHOLD_MASK;
2448c2ecf20Sopenharmony_ci	reg &= ~(CPU_WRITEBACK_CTRL_REG_WB_THROTTLE_TIMEOUT_MASK <<
2458c2ecf20Sopenharmony_ci		 CPU_WRITEBACK_CTRL_REG_WB_THROTTLE_TIMEOUT_SHIFT);
2468c2ecf20Sopenharmony_ci	reg |= 8;
2478c2ecf20Sopenharmony_ci	reg |= 7 << CPU_WRITEBACK_CTRL_REG_WB_THROTTLE_TIMEOUT_SHIFT;
2488c2ecf20Sopenharmony_ci	cbc_writel(reg, CPU_WRITEBACK_CTRL_REG);
2498c2ecf20Sopenharmony_ci}
2508c2ecf20Sopenharmony_ci
2518c2ecf20Sopenharmony_cistatic int __init setup_hifcpubiuctrl_regs(struct device_node *np)
2528c2ecf20Sopenharmony_ci{
2538c2ecf20Sopenharmony_ci	struct device_node *cpu_dn;
2548c2ecf20Sopenharmony_ci	u32 family_id;
2558c2ecf20Sopenharmony_ci	int ret = 0;
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ci	cpubiuctrl_base = of_iomap(np, 0);
2588c2ecf20Sopenharmony_ci	if (!cpubiuctrl_base) {
2598c2ecf20Sopenharmony_ci		pr_err("failed to remap BIU control base\n");
2608c2ecf20Sopenharmony_ci		ret = -ENOMEM;
2618c2ecf20Sopenharmony_ci		goto out;
2628c2ecf20Sopenharmony_ci	}
2638c2ecf20Sopenharmony_ci
2648c2ecf20Sopenharmony_ci	mcp_wr_pairing_en = of_property_read_bool(np, "brcm,write-pairing");
2658c2ecf20Sopenharmony_ci
2668c2ecf20Sopenharmony_ci	cpu_dn = of_get_cpu_node(0, NULL);
2678c2ecf20Sopenharmony_ci	if (!cpu_dn) {
2688c2ecf20Sopenharmony_ci		pr_err("failed to obtain CPU device node\n");
2698c2ecf20Sopenharmony_ci		ret = -ENODEV;
2708c2ecf20Sopenharmony_ci		goto out;
2718c2ecf20Sopenharmony_ci	}
2728c2ecf20Sopenharmony_ci
2738c2ecf20Sopenharmony_ci	if (of_device_is_compatible(cpu_dn, "brcm,brahma-b15"))
2748c2ecf20Sopenharmony_ci		cpubiuctrl_regs = b15_cpubiuctrl_regs;
2758c2ecf20Sopenharmony_ci	else if (of_device_is_compatible(cpu_dn, "brcm,brahma-b53"))
2768c2ecf20Sopenharmony_ci		cpubiuctrl_regs = b53_cpubiuctrl_regs;
2778c2ecf20Sopenharmony_ci	else if (of_device_is_compatible(cpu_dn, "arm,cortex-a72"))
2788c2ecf20Sopenharmony_ci		cpubiuctrl_regs = a72_cpubiuctrl_regs;
2798c2ecf20Sopenharmony_ci	else {
2808c2ecf20Sopenharmony_ci		pr_err("unsupported CPU\n");
2818c2ecf20Sopenharmony_ci		ret = -EINVAL;
2828c2ecf20Sopenharmony_ci	}
2838c2ecf20Sopenharmony_ci	of_node_put(cpu_dn);
2848c2ecf20Sopenharmony_ci
2858c2ecf20Sopenharmony_ci	family_id = brcmstb_get_family_id();
2868c2ecf20Sopenharmony_ci	if (BRCM_ID(family_id) == 0x7260 && BRCM_REV(family_id) == 0)
2878c2ecf20Sopenharmony_ci		cpubiuctrl_regs = b53_cpubiuctrl_no_wb_regs;
2888c2ecf20Sopenharmony_ciout:
2898c2ecf20Sopenharmony_ci	of_node_put(np);
2908c2ecf20Sopenharmony_ci	return ret;
2918c2ecf20Sopenharmony_ci}
2928c2ecf20Sopenharmony_ci
2938c2ecf20Sopenharmony_ci#ifdef CONFIG_PM_SLEEP
2948c2ecf20Sopenharmony_cistatic u32 cpubiuctrl_reg_save[NUM_CPU_BIUCTRL_REGS];
2958c2ecf20Sopenharmony_ci
2968c2ecf20Sopenharmony_cistatic int brcmstb_cpu_credit_reg_suspend(void)
2978c2ecf20Sopenharmony_ci{
2988c2ecf20Sopenharmony_ci	unsigned int i;
2998c2ecf20Sopenharmony_ci
3008c2ecf20Sopenharmony_ci	if (!cpubiuctrl_base)
3018c2ecf20Sopenharmony_ci		return 0;
3028c2ecf20Sopenharmony_ci
3038c2ecf20Sopenharmony_ci	for (i = 0; i < NUM_CPU_BIUCTRL_REGS; i++)
3048c2ecf20Sopenharmony_ci		cpubiuctrl_reg_save[i] = cbc_readl(i);
3058c2ecf20Sopenharmony_ci
3068c2ecf20Sopenharmony_ci	return 0;
3078c2ecf20Sopenharmony_ci}
3088c2ecf20Sopenharmony_ci
3098c2ecf20Sopenharmony_cistatic void brcmstb_cpu_credit_reg_resume(void)
3108c2ecf20Sopenharmony_ci{
3118c2ecf20Sopenharmony_ci	unsigned int i;
3128c2ecf20Sopenharmony_ci
3138c2ecf20Sopenharmony_ci	if (!cpubiuctrl_base)
3148c2ecf20Sopenharmony_ci		return;
3158c2ecf20Sopenharmony_ci
3168c2ecf20Sopenharmony_ci	for (i = 0; i < NUM_CPU_BIUCTRL_REGS; i++)
3178c2ecf20Sopenharmony_ci		cbc_writel(cpubiuctrl_reg_save[i], i);
3188c2ecf20Sopenharmony_ci}
3198c2ecf20Sopenharmony_ci
3208c2ecf20Sopenharmony_cistatic struct syscore_ops brcmstb_cpu_credit_syscore_ops = {
3218c2ecf20Sopenharmony_ci	.suspend = brcmstb_cpu_credit_reg_suspend,
3228c2ecf20Sopenharmony_ci	.resume = brcmstb_cpu_credit_reg_resume,
3238c2ecf20Sopenharmony_ci};
3248c2ecf20Sopenharmony_ci#endif
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_ci
3278c2ecf20Sopenharmony_cistatic int __init brcmstb_biuctrl_init(void)
3288c2ecf20Sopenharmony_ci{
3298c2ecf20Sopenharmony_ci	struct device_node *np;
3308c2ecf20Sopenharmony_ci	int ret;
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_ci	/* We might be running on a multi-platform kernel, don't make this a
3338c2ecf20Sopenharmony_ci	 * fatal error, just bail out early
3348c2ecf20Sopenharmony_ci	 */
3358c2ecf20Sopenharmony_ci	np = of_find_compatible_node(NULL, NULL, "brcm,brcmstb-cpu-biu-ctrl");
3368c2ecf20Sopenharmony_ci	if (!np)
3378c2ecf20Sopenharmony_ci		return 0;
3388c2ecf20Sopenharmony_ci
3398c2ecf20Sopenharmony_ci	ret = setup_hifcpubiuctrl_regs(np);
3408c2ecf20Sopenharmony_ci	if (ret)
3418c2ecf20Sopenharmony_ci		return ret;
3428c2ecf20Sopenharmony_ci
3438c2ecf20Sopenharmony_ci	ret = mcp_write_pairing_set();
3448c2ecf20Sopenharmony_ci	if (ret) {
3458c2ecf20Sopenharmony_ci		pr_err("MCP: Unable to disable write pairing!\n");
3468c2ecf20Sopenharmony_ci		return ret;
3478c2ecf20Sopenharmony_ci	}
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_ci	a72_b53_rac_enable_all(np);
3508c2ecf20Sopenharmony_ci	mcp_a72_b53_set();
3518c2ecf20Sopenharmony_ci#ifdef CONFIG_PM_SLEEP
3528c2ecf20Sopenharmony_ci	register_syscore_ops(&brcmstb_cpu_credit_syscore_ops);
3538c2ecf20Sopenharmony_ci#endif
3548c2ecf20Sopenharmony_ci	return 0;
3558c2ecf20Sopenharmony_ci}
3568c2ecf20Sopenharmony_ciearly_initcall(brcmstb_biuctrl_init);
357