xref: /openbmc/linux/drivers/soc/bcm/brcmstb/biuctrl.c (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
11802d0beSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
234642650SFlorian Fainelli /*
334642650SFlorian Fainelli  * Broadcom STB SoCs Bus Unit Interface controls
434642650SFlorian Fainelli  *
534642650SFlorian Fainelli  * Copyright (C) 2015, Broadcom Corporation
634642650SFlorian Fainelli  */
734642650SFlorian Fainelli 
834642650SFlorian Fainelli #define pr_fmt(fmt)	"brcmstb: " KBUILD_MODNAME ": " fmt
934642650SFlorian Fainelli 
1034642650SFlorian Fainelli #include <linux/kernel.h>
1134642650SFlorian Fainelli #include <linux/io.h>
1234642650SFlorian Fainelli #include <linux/of_address.h>
1334642650SFlorian Fainelli #include <linux/syscore_ops.h>
14a536bcc9SBen Dooks #include <linux/soc/brcmstb/brcmstb.h>
1534642650SFlorian Fainelli 
169eda7c1fSFlorian Fainelli #define RACENPREF_MASK			0x3
179eda7c1fSFlorian Fainelli #define RACPREFINST_SHIFT		0
189eda7c1fSFlorian Fainelli #define RACENINST_SHIFT			2
199eda7c1fSFlorian Fainelli #define RACPREFDATA_SHIFT		4
209eda7c1fSFlorian Fainelli #define RACENDATA_SHIFT			6
219eda7c1fSFlorian Fainelli #define RAC_CPU_SHIFT			8
229eda7c1fSFlorian Fainelli #define RACCFG_MASK			0xff
23091353c8SFlorian Fainelli #define DPREF_LINE_2_SHIFT		24
24091353c8SFlorian Fainelli #define DPREF_LINE_2_MASK		0xff
259eda7c1fSFlorian Fainelli 
269eda7c1fSFlorian Fainelli /* Bitmask to enable instruction and data prefetching with a 256-bytes stride */
279eda7c1fSFlorian Fainelli #define RAC_DATA_INST_EN_MASK		(1 << RACPREFINST_SHIFT | \
289eda7c1fSFlorian Fainelli 					 RACENPREF_MASK << RACENINST_SHIFT | \
299eda7c1fSFlorian Fainelli 					 1 << RACPREFDATA_SHIFT | \
309eda7c1fSFlorian Fainelli 					 RACENPREF_MASK << RACENDATA_SHIFT)
319eda7c1fSFlorian Fainelli 
3234642650SFlorian Fainelli #define  CPU_CREDIT_REG_MCPx_WR_PAIRING_EN_MASK	0x70000000
33b4b32e32SFlorian Fainelli #define CPU_CREDIT_REG_MCPx_READ_CRED_MASK	0xf
34b4b32e32SFlorian Fainelli #define CPU_CREDIT_REG_MCPx_WRITE_CRED_MASK	0xf
35b4b32e32SFlorian Fainelli #define CPU_CREDIT_REG_MCPx_READ_CRED_SHIFT(x)	((x) * 8)
36b4b32e32SFlorian Fainelli #define CPU_CREDIT_REG_MCPx_WRITE_CRED_SHIFT(x)	(((x) * 8) + 4)
37b4b32e32SFlorian Fainelli 
38b4b32e32SFlorian Fainelli #define CPU_MCP_FLOW_REG_MCPx_RDBUFF_CRED_SHIFT(x)	((x) * 8)
39b4b32e32SFlorian Fainelli #define CPU_MCP_FLOW_REG_MCPx_RDBUFF_CRED_MASK		0xff
40b4b32e32SFlorian Fainelli 
41b4b32e32SFlorian Fainelli #define CPU_WRITEBACK_CTRL_REG_WB_THROTTLE_THRESHOLD_MASK	0xf
42b4b32e32SFlorian Fainelli #define CPU_WRITEBACK_CTRL_REG_WB_THROTTLE_TIMEOUT_MASK		0xf
43b4b32e32SFlorian Fainelli #define CPU_WRITEBACK_CTRL_REG_WB_THROTTLE_TIMEOUT_SHIFT	4
44b4b32e32SFlorian Fainelli #define CPU_WRITEBACK_CTRL_REG_WB_THROTTLE_ENABLE		BIT(8)
4534642650SFlorian Fainelli 
4634642650SFlorian Fainelli static void __iomem *cpubiuctrl_base;
4734642650SFlorian Fainelli static bool mcp_wr_pairing_en;
48584e55d5SFlorian Fainelli static const int *cpubiuctrl_regs;
49584e55d5SFlorian Fainelli 
509eda7c1fSFlorian Fainelli enum cpubiuctrl_regs {
519eda7c1fSFlorian Fainelli 	CPU_CREDIT_REG = 0,
529eda7c1fSFlorian Fainelli 	CPU_MCP_FLOW_REG,
539eda7c1fSFlorian Fainelli 	CPU_WRITEBACK_CTRL_REG,
549eda7c1fSFlorian Fainelli 	RAC_CONFIG0_REG,
55091353c8SFlorian Fainelli 	RAC_CONFIG1_REG,
569eda7c1fSFlorian Fainelli 	NUM_CPU_BIUCTRL_REGS,
579eda7c1fSFlorian Fainelli };
589eda7c1fSFlorian Fainelli 
cbc_readl(int reg)59584e55d5SFlorian Fainelli static inline u32 cbc_readl(int reg)
60584e55d5SFlorian Fainelli {
61584e55d5SFlorian Fainelli 	int offset = cpubiuctrl_regs[reg];
62584e55d5SFlorian Fainelli 
639eda7c1fSFlorian Fainelli 	if (offset == -1 ||
64091353c8SFlorian Fainelli 	    (IS_ENABLED(CONFIG_CACHE_B15_RAC) && reg >= RAC_CONFIG0_REG))
65584e55d5SFlorian Fainelli 		return (u32)-1;
66584e55d5SFlorian Fainelli 
67584e55d5SFlorian Fainelli 	return readl_relaxed(cpubiuctrl_base + offset);
68584e55d5SFlorian Fainelli }
69584e55d5SFlorian Fainelli 
cbc_writel(u32 val,int reg)70584e55d5SFlorian Fainelli static inline void cbc_writel(u32 val, int reg)
71584e55d5SFlorian Fainelli {
72584e55d5SFlorian Fainelli 	int offset = cpubiuctrl_regs[reg];
73584e55d5SFlorian Fainelli 
749eda7c1fSFlorian Fainelli 	if (offset == -1 ||
75091353c8SFlorian Fainelli 	    (IS_ENABLED(CONFIG_CACHE_B15_RAC) && reg >= RAC_CONFIG0_REG))
76584e55d5SFlorian Fainelli 		return;
77584e55d5SFlorian Fainelli 
786b23af07SFlorian Fainelli 	writel(val, cpubiuctrl_base + offset);
79584e55d5SFlorian Fainelli }
80584e55d5SFlorian Fainelli 
81584e55d5SFlorian Fainelli static const int b15_cpubiuctrl_regs[] = {
82584e55d5SFlorian Fainelli 	[CPU_CREDIT_REG] = 0x184,
836451d644SFlorian Fainelli 	[CPU_MCP_FLOW_REG] = -1,
846451d644SFlorian Fainelli 	[CPU_WRITEBACK_CTRL_REG] = -1,
859eda7c1fSFlorian Fainelli 	[RAC_CONFIG0_REG] = -1,
86091353c8SFlorian Fainelli 	[RAC_CONFIG1_REG] = -1,
87584e55d5SFlorian Fainelli };
88584e55d5SFlorian Fainelli 
893098f5ebSFlorian Fainelli /* Odd cases, e.g: 7260A0 */
90b4b32e32SFlorian Fainelli static const int b53_cpubiuctrl_no_wb_regs[] = {
91b4b32e32SFlorian Fainelli 	[CPU_CREDIT_REG] = 0x0b0,
92b4b32e32SFlorian Fainelli 	[CPU_MCP_FLOW_REG] = 0x0b4,
93b4b32e32SFlorian Fainelli 	[CPU_WRITEBACK_CTRL_REG] = -1,
949eda7c1fSFlorian Fainelli 	[RAC_CONFIG0_REG] = 0x78,
95091353c8SFlorian Fainelli 	[RAC_CONFIG1_REG] = 0x7c,
96b4b32e32SFlorian Fainelli };
97b4b32e32SFlorian Fainelli 
98584e55d5SFlorian Fainelli static const int b53_cpubiuctrl_regs[] = {
99584e55d5SFlorian Fainelli 	[CPU_CREDIT_REG] = 0x0b0,
1006451d644SFlorian Fainelli 	[CPU_MCP_FLOW_REG] = 0x0b4,
1016451d644SFlorian Fainelli 	[CPU_WRITEBACK_CTRL_REG] = 0x22c,
1029eda7c1fSFlorian Fainelli 	[RAC_CONFIG0_REG] = 0x78,
103091353c8SFlorian Fainelli 	[RAC_CONFIG1_REG] = 0x7c,
104584e55d5SFlorian Fainelli };
105584e55d5SFlorian Fainelli 
106ea1e84d1SFlorian Fainelli static const int a72_cpubiuctrl_regs[] = {
107ea1e84d1SFlorian Fainelli 	[CPU_CREDIT_REG] = 0x18,
108ea1e84d1SFlorian Fainelli 	[CPU_MCP_FLOW_REG] = 0x1c,
109ea1e84d1SFlorian Fainelli 	[CPU_WRITEBACK_CTRL_REG] = 0x20,
1109eda7c1fSFlorian Fainelli 	[RAC_CONFIG0_REG] = 0x08,
111091353c8SFlorian Fainelli 	[RAC_CONFIG1_REG] = 0x0c,
112ea1e84d1SFlorian Fainelli };
113ea1e84d1SFlorian Fainelli 
mcp_write_pairing_set(void)11434642650SFlorian Fainelli static int __init mcp_write_pairing_set(void)
11534642650SFlorian Fainelli {
11634642650SFlorian Fainelli 	u32 creds = 0;
11734642650SFlorian Fainelli 
11834642650SFlorian Fainelli 	if (!cpubiuctrl_base)
11934642650SFlorian Fainelli 		return -1;
12034642650SFlorian Fainelli 
121584e55d5SFlorian Fainelli 	creds = cbc_readl(CPU_CREDIT_REG);
12234642650SFlorian Fainelli 	if (mcp_wr_pairing_en) {
12334642650SFlorian Fainelli 		pr_info("MCP: Enabling write pairing\n");
124584e55d5SFlorian Fainelli 		cbc_writel(creds | CPU_CREDIT_REG_MCPx_WR_PAIRING_EN_MASK,
125584e55d5SFlorian Fainelli 			   CPU_CREDIT_REG);
12634642650SFlorian Fainelli 	} else if (creds & CPU_CREDIT_REG_MCPx_WR_PAIRING_EN_MASK) {
12734642650SFlorian Fainelli 		pr_info("MCP: Disabling write pairing\n");
128584e55d5SFlorian Fainelli 		cbc_writel(creds & ~CPU_CREDIT_REG_MCPx_WR_PAIRING_EN_MASK,
129584e55d5SFlorian Fainelli 			   CPU_CREDIT_REG);
13034642650SFlorian Fainelli 	} else {
13134642650SFlorian Fainelli 		pr_info("MCP: Write pairing already disabled\n");
13234642650SFlorian Fainelli 	}
13334642650SFlorian Fainelli 
13434642650SFlorian Fainelli 	return 0;
13534642650SFlorian Fainelli }
13634642650SFlorian Fainelli 
137add427c4SFlorian Fainelli static const u32 a72_b53_mach_compat[] = {
138add427c4SFlorian Fainelli 	0x7211,
139e8377f49SFlorian Fainelli 	0x72113,
1406e42e16aSFlorian Fainelli 	0x72116,
141b2f91a39SFlorian Fainelli 	0x7216,
1425dfd145aSFlorian Fainelli 	0x72164,
1434029f3b4SFlorian Fainelli 	0x72165,
144b2f91a39SFlorian Fainelli 	0x7255,
1453098f5ebSFlorian Fainelli 	0x7260,
146b4b32e32SFlorian Fainelli 	0x7268,
147b4b32e32SFlorian Fainelli 	0x7271,
148b4b32e32SFlorian Fainelli 	0x7278,
149b4b32e32SFlorian Fainelli };
150b4b32e32SFlorian Fainelli 
1519eda7c1fSFlorian Fainelli /* The read-ahead cache present in the Brahma-B53 CPU is a special piece of
1529eda7c1fSFlorian Fainelli  * hardware after the integrated L2 cache of the B53 CPU complex whose purpose
1539eda7c1fSFlorian Fainelli  * is to prefetch instruction and/or data with a line size of either 64 bytes
1549eda7c1fSFlorian Fainelli  * or 256 bytes. The rationale is that the data-bus of the CPU interface is
1559eda7c1fSFlorian Fainelli  * optimized for 256-byte transactions, and enabling the read-ahead cache
1569eda7c1fSFlorian Fainelli  * provides a significant performance boost (typically twice the performance
1579eda7c1fSFlorian Fainelli  * for a memcpy benchmark application).
1589eda7c1fSFlorian Fainelli  *
1599eda7c1fSFlorian Fainelli  * The read-ahead cache is transparent for Virtual Address cache maintenance
1609eda7c1fSFlorian Fainelli  * operations: IC IVAU, DC IVAC, DC CVAC, DC CVAU and DC CIVAC.  So no special
1619eda7c1fSFlorian Fainelli  * handling is needed for the DMA API above and beyond what is included in the
1629eda7c1fSFlorian Fainelli  * arm64 implementation.
1639eda7c1fSFlorian Fainelli  *
1649eda7c1fSFlorian Fainelli  * In addition, since the Point of Unification is typically between L1 and L2
1659eda7c1fSFlorian Fainelli  * for the Brahma-B53 processor no special read-ahead cache handling is needed
1669eda7c1fSFlorian Fainelli  * for the IC IALLU and IC IALLUIS cache maintenance operations.
1679eda7c1fSFlorian Fainelli  *
1689eda7c1fSFlorian Fainelli  * However, it is not possible to specify the cache level (L3) for the cache
1699eda7c1fSFlorian Fainelli  * maintenance instructions operating by set/way to operate on the read-ahead
1709eda7c1fSFlorian Fainelli  * cache.  The read-ahead cache will maintain coherency when inner cache lines
1719eda7c1fSFlorian Fainelli  * are cleaned by set/way, but if it is necessary to invalidate inner cache
1729eda7c1fSFlorian Fainelli  * lines by set/way to maintain coherency with system masters operating on
1739eda7c1fSFlorian Fainelli  * shared memory that does not have hardware support for coherency, then it
1749eda7c1fSFlorian Fainelli  * will also be necessary to explicitly invalidate the read-ahead cache.
1759eda7c1fSFlorian Fainelli  */
a72_b53_rac_enable_all(struct device_node * np)1769eda7c1fSFlorian Fainelli static void __init a72_b53_rac_enable_all(struct device_node *np)
1779eda7c1fSFlorian Fainelli {
1789eda7c1fSFlorian Fainelli 	unsigned int cpu;
17910e7dd54SFlorian Fainelli 	u32 enable = 0, pref_dist, shift;
1809eda7c1fSFlorian Fainelli 
1819eda7c1fSFlorian Fainelli 	if (IS_ENABLED(CONFIG_CACHE_B15_RAC))
1829eda7c1fSFlorian Fainelli 		return;
1839eda7c1fSFlorian Fainelli 
1849eda7c1fSFlorian Fainelli 	if (WARN(num_possible_cpus() > 4, "RAC only supports 4 CPUs\n"))
1859eda7c1fSFlorian Fainelli 		return;
1869eda7c1fSFlorian Fainelli 
187091353c8SFlorian Fainelli 	pref_dist = cbc_readl(RAC_CONFIG1_REG);
188091353c8SFlorian Fainelli 	for_each_possible_cpu(cpu) {
18910e7dd54SFlorian Fainelli 		shift = cpu * RAC_CPU_SHIFT + RACPREFDATA_SHIFT;
1909eda7c1fSFlorian Fainelli 		enable |= RAC_DATA_INST_EN_MASK << (cpu * RAC_CPU_SHIFT);
19110e7dd54SFlorian Fainelli 		if (cpubiuctrl_regs == a72_cpubiuctrl_regs) {
19210e7dd54SFlorian Fainelli 			enable &= ~(RACENPREF_MASK << shift);
19310e7dd54SFlorian Fainelli 			enable |= 3 << shift;
194091353c8SFlorian Fainelli 			pref_dist |= 1 << (cpu + DPREF_LINE_2_SHIFT);
195091353c8SFlorian Fainelli 		}
19610e7dd54SFlorian Fainelli 	}
1979eda7c1fSFlorian Fainelli 
1989eda7c1fSFlorian Fainelli 	cbc_writel(enable, RAC_CONFIG0_REG);
199091353c8SFlorian Fainelli 	cbc_writel(pref_dist, RAC_CONFIG1_REG);
2009eda7c1fSFlorian Fainelli 
2019eda7c1fSFlorian Fainelli 	pr_info("%pOF: Broadcom %s read-ahead cache\n",
2029eda7c1fSFlorian Fainelli 		np, cpubiuctrl_regs == a72_cpubiuctrl_regs ?
2039eda7c1fSFlorian Fainelli 		"Cortex-A72" : "Brahma-B53");
2049eda7c1fSFlorian Fainelli }
2059eda7c1fSFlorian Fainelli 
mcp_a72_b53_set(void)206add427c4SFlorian Fainelli static void __init mcp_a72_b53_set(void)
207b4b32e32SFlorian Fainelli {
208b4b32e32SFlorian Fainelli 	unsigned int i;
209b4b32e32SFlorian Fainelli 	u32 reg;
210b4b32e32SFlorian Fainelli 
211b4b32e32SFlorian Fainelli 	reg = brcmstb_get_family_id();
212b4b32e32SFlorian Fainelli 
213add427c4SFlorian Fainelli 	for (i = 0; i < ARRAY_SIZE(a72_b53_mach_compat); i++) {
214add427c4SFlorian Fainelli 		if (BRCM_ID(reg) == a72_b53_mach_compat[i])
215b4b32e32SFlorian Fainelli 			break;
216b4b32e32SFlorian Fainelli 	}
217b4b32e32SFlorian Fainelli 
218add427c4SFlorian Fainelli 	if (i == ARRAY_SIZE(a72_b53_mach_compat))
219b4b32e32SFlorian Fainelli 		return;
220b4b32e32SFlorian Fainelli 
221b4b32e32SFlorian Fainelli 	/* Set all 3 MCP interfaces to 8 credits */
222b4b32e32SFlorian Fainelli 	reg = cbc_readl(CPU_CREDIT_REG);
223b4b32e32SFlorian Fainelli 	for (i = 0; i < 3; i++) {
224b4b32e32SFlorian Fainelli 		reg &= ~(CPU_CREDIT_REG_MCPx_WRITE_CRED_MASK <<
225b4b32e32SFlorian Fainelli 			 CPU_CREDIT_REG_MCPx_WRITE_CRED_SHIFT(i));
226b4b32e32SFlorian Fainelli 		reg &= ~(CPU_CREDIT_REG_MCPx_READ_CRED_MASK <<
227b4b32e32SFlorian Fainelli 			 CPU_CREDIT_REG_MCPx_READ_CRED_SHIFT(i));
228b4b32e32SFlorian Fainelli 		reg |= 8 << CPU_CREDIT_REG_MCPx_WRITE_CRED_SHIFT(i);
229b4b32e32SFlorian Fainelli 		reg |= 8 << CPU_CREDIT_REG_MCPx_READ_CRED_SHIFT(i);
230b4b32e32SFlorian Fainelli 	}
231b4b32e32SFlorian Fainelli 	cbc_writel(reg, CPU_CREDIT_REG);
232b4b32e32SFlorian Fainelli 
233b4b32e32SFlorian Fainelli 	/* Max out the number of in-flight Jwords reads on the MCP interface */
234b4b32e32SFlorian Fainelli 	reg = cbc_readl(CPU_MCP_FLOW_REG);
235b4b32e32SFlorian Fainelli 	for (i = 0; i < 3; i++)
236b4b32e32SFlorian Fainelli 		reg |= CPU_MCP_FLOW_REG_MCPx_RDBUFF_CRED_MASK <<
237b4b32e32SFlorian Fainelli 			CPU_MCP_FLOW_REG_MCPx_RDBUFF_CRED_SHIFT(i);
238b4b32e32SFlorian Fainelli 	cbc_writel(reg, CPU_MCP_FLOW_REG);
239b4b32e32SFlorian Fainelli 
240b4b32e32SFlorian Fainelli 	/* Enable writeback throttling, set timeout to 128 cycles, 256 cycles
241b4b32e32SFlorian Fainelli 	 * threshold
242b4b32e32SFlorian Fainelli 	 */
243b4b32e32SFlorian Fainelli 	reg = cbc_readl(CPU_WRITEBACK_CTRL_REG);
244b4b32e32SFlorian Fainelli 	reg |= CPU_WRITEBACK_CTRL_REG_WB_THROTTLE_ENABLE;
245b4b32e32SFlorian Fainelli 	reg &= ~CPU_WRITEBACK_CTRL_REG_WB_THROTTLE_THRESHOLD_MASK;
246b4b32e32SFlorian Fainelli 	reg &= ~(CPU_WRITEBACK_CTRL_REG_WB_THROTTLE_TIMEOUT_MASK <<
247b4b32e32SFlorian Fainelli 		 CPU_WRITEBACK_CTRL_REG_WB_THROTTLE_TIMEOUT_SHIFT);
248b4b32e32SFlorian Fainelli 	reg |= 8;
249b4b32e32SFlorian Fainelli 	reg |= 7 << CPU_WRITEBACK_CTRL_REG_WB_THROTTLE_TIMEOUT_SHIFT;
250b4b32e32SFlorian Fainelli 	cbc_writel(reg, CPU_WRITEBACK_CTRL_REG);
251b4b32e32SFlorian Fainelli }
252b4b32e32SFlorian Fainelli 
setup_hifcpubiuctrl_regs(struct device_node * np)253a7818298SSudeep Holla static int __init setup_hifcpubiuctrl_regs(struct device_node *np)
25434642650SFlorian Fainelli {
255a7818298SSudeep Holla 	struct device_node *cpu_dn;
2563098f5ebSFlorian Fainelli 	u32 family_id;
25734642650SFlorian Fainelli 	int ret = 0;
25834642650SFlorian Fainelli 
25934642650SFlorian Fainelli 	cpubiuctrl_base = of_iomap(np, 0);
26034642650SFlorian Fainelli 	if (!cpubiuctrl_base) {
26134642650SFlorian Fainelli 		pr_err("failed to remap BIU control base\n");
26234642650SFlorian Fainelli 		ret = -ENOMEM;
26334642650SFlorian Fainelli 		goto out;
26434642650SFlorian Fainelli 	}
26534642650SFlorian Fainelli 
26634642650SFlorian Fainelli 	mcp_wr_pairing_en = of_property_read_bool(np, "brcm,write-pairing");
26722f7a911SFlorian Fainelli 
26822f7a911SFlorian Fainelli 	cpu_dn = of_get_cpu_node(0, NULL);
26922f7a911SFlorian Fainelli 	if (!cpu_dn) {
27022f7a911SFlorian Fainelli 		pr_err("failed to obtain CPU device node\n");
27122f7a911SFlorian Fainelli 		ret = -ENODEV;
27222f7a911SFlorian Fainelli 		goto out;
27322f7a911SFlorian Fainelli 	}
27422f7a911SFlorian Fainelli 
27522f7a911SFlorian Fainelli 	if (of_device_is_compatible(cpu_dn, "brcm,brahma-b15"))
276584e55d5SFlorian Fainelli 		cpubiuctrl_regs = b15_cpubiuctrl_regs;
27722f7a911SFlorian Fainelli 	else if (of_device_is_compatible(cpu_dn, "brcm,brahma-b53"))
278584e55d5SFlorian Fainelli 		cpubiuctrl_regs = b53_cpubiuctrl_regs;
279ea1e84d1SFlorian Fainelli 	else if (of_device_is_compatible(cpu_dn, "arm,cortex-a72"))
280ea1e84d1SFlorian Fainelli 		cpubiuctrl_regs = a72_cpubiuctrl_regs;
28122f7a911SFlorian Fainelli 	else {
28222f7a911SFlorian Fainelli 		pr_err("unsupported CPU\n");
28322f7a911SFlorian Fainelli 		ret = -EINVAL;
28422f7a911SFlorian Fainelli 	}
28522f7a911SFlorian Fainelli 	of_node_put(cpu_dn);
286b4b32e32SFlorian Fainelli 
2873098f5ebSFlorian Fainelli 	family_id = brcmstb_get_family_id();
2883098f5ebSFlorian Fainelli 	if (BRCM_ID(family_id) == 0x7260 && BRCM_REV(family_id) == 0)
289b4b32e32SFlorian Fainelli 		cpubiuctrl_regs = b53_cpubiuctrl_no_wb_regs;
29034642650SFlorian Fainelli out:
291*c3fbced9SZhaoyang Li 	if (ret && cpubiuctrl_base) {
292*c3fbced9SZhaoyang Li 		iounmap(cpubiuctrl_base);
293*c3fbced9SZhaoyang Li 		cpubiuctrl_base = NULL;
294*c3fbced9SZhaoyang Li 	}
29534642650SFlorian Fainelli 	return ret;
29634642650SFlorian Fainelli }
29734642650SFlorian Fainelli 
29834642650SFlorian Fainelli #ifdef CONFIG_PM_SLEEP
299584e55d5SFlorian Fainelli static u32 cpubiuctrl_reg_save[NUM_CPU_BIUCTRL_REGS];
30034642650SFlorian Fainelli 
brcmstb_cpu_credit_reg_suspend(void)30134642650SFlorian Fainelli static int brcmstb_cpu_credit_reg_suspend(void)
30234642650SFlorian Fainelli {
303584e55d5SFlorian Fainelli 	unsigned int i;
304584e55d5SFlorian Fainelli 
305584e55d5SFlorian Fainelli 	if (!cpubiuctrl_base)
306584e55d5SFlorian Fainelli 		return 0;
307584e55d5SFlorian Fainelli 
308584e55d5SFlorian Fainelli 	for (i = 0; i < NUM_CPU_BIUCTRL_REGS; i++)
309584e55d5SFlorian Fainelli 		cpubiuctrl_reg_save[i] = cbc_readl(i);
310584e55d5SFlorian Fainelli 
31134642650SFlorian Fainelli 	return 0;
31234642650SFlorian Fainelli }
31334642650SFlorian Fainelli 
brcmstb_cpu_credit_reg_resume(void)31434642650SFlorian Fainelli static void brcmstb_cpu_credit_reg_resume(void)
31534642650SFlorian Fainelli {
316584e55d5SFlorian Fainelli 	unsigned int i;
317584e55d5SFlorian Fainelli 
318584e55d5SFlorian Fainelli 	if (!cpubiuctrl_base)
319584e55d5SFlorian Fainelli 		return;
320584e55d5SFlorian Fainelli 
321584e55d5SFlorian Fainelli 	for (i = 0; i < NUM_CPU_BIUCTRL_REGS; i++)
322584e55d5SFlorian Fainelli 		cbc_writel(cpubiuctrl_reg_save[i], i);
32334642650SFlorian Fainelli }
32434642650SFlorian Fainelli 
32534642650SFlorian Fainelli static struct syscore_ops brcmstb_cpu_credit_syscore_ops = {
32634642650SFlorian Fainelli 	.suspend = brcmstb_cpu_credit_reg_suspend,
32734642650SFlorian Fainelli 	.resume = brcmstb_cpu_credit_reg_resume,
32834642650SFlorian Fainelli };
32934642650SFlorian Fainelli #endif
33034642650SFlorian Fainelli 
33134642650SFlorian Fainelli 
brcmstb_biuctrl_init(void)332f780429aSFlorian Fainelli static int __init brcmstb_biuctrl_init(void)
33334642650SFlorian Fainelli {
334a7818298SSudeep Holla 	struct device_node *np;
33534642650SFlorian Fainelli 	int ret;
33634642650SFlorian Fainelli 
337a7818298SSudeep Holla 	/* We might be running on a multi-platform kernel, don't make this a
338a7818298SSudeep Holla 	 * fatal error, just bail out early
339a7818298SSudeep Holla 	 */
340a7818298SSudeep Holla 	np = of_find_compatible_node(NULL, NULL, "brcm,brcmstb-cpu-biu-ctrl");
341a7818298SSudeep Holla 	if (!np)
342a7818298SSudeep Holla 		return 0;
343a7818298SSudeep Holla 
344490cad5aSFlorian Fainelli 	ret = setup_hifcpubiuctrl_regs(np);
345490cad5aSFlorian Fainelli 	if (ret)
3469a073d4fSLiang He 		goto out_put;
34734642650SFlorian Fainelli 
34834642650SFlorian Fainelli 	ret = mcp_write_pairing_set();
34934642650SFlorian Fainelli 	if (ret) {
35034642650SFlorian Fainelli 		pr_err("MCP: Unable to disable write pairing!\n");
3519a073d4fSLiang He 		goto out_put;
35234642650SFlorian Fainelli 	}
35334642650SFlorian Fainelli 
3549eda7c1fSFlorian Fainelli 	a72_b53_rac_enable_all(np);
355add427c4SFlorian Fainelli 	mcp_a72_b53_set();
35634642650SFlorian Fainelli #ifdef CONFIG_PM_SLEEP
35734642650SFlorian Fainelli 	register_syscore_ops(&brcmstb_cpu_credit_syscore_ops);
35834642650SFlorian Fainelli #endif
3599a073d4fSLiang He 	ret = 0;
3609a073d4fSLiang He out_put:
3619a073d4fSLiang He 	of_node_put(np);
3629a073d4fSLiang He 	return ret;
36334642650SFlorian Fainelli }
364f780429aSFlorian Fainelli early_initcall(brcmstb_biuctrl_init);
365