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