xref: /linux/drivers/soc/bcm/brcmstb/biuctrl.c (revision e5c86679d5e864947a52fb31e45a425dea3e7fa9)
1 /*
2  * Broadcom STB SoCs Bus Unit Interface controls
3  *
4  * Copyright (C) 2015, Broadcom Corporation
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  */
15 
16 #define pr_fmt(fmt)	"brcmstb: " KBUILD_MODNAME ": " fmt
17 
18 #include <linux/kernel.h>
19 #include <linux/io.h>
20 #include <linux/of_address.h>
21 #include <linux/syscore_ops.h>
22 #include <linux/soc/brcmstb/brcmstb.h>
23 
24 #define CPU_CREDIT_REG_OFFSET			0x184
25 #define  CPU_CREDIT_REG_MCPx_WR_PAIRING_EN_MASK	0x70000000
26 
27 static void __iomem *cpubiuctrl_base;
28 static bool mcp_wr_pairing_en;
29 
30 static int __init mcp_write_pairing_set(void)
31 {
32 	u32 creds = 0;
33 
34 	if (!cpubiuctrl_base)
35 		return -1;
36 
37 	creds = readl_relaxed(cpubiuctrl_base + CPU_CREDIT_REG_OFFSET);
38 	if (mcp_wr_pairing_en) {
39 		pr_info("MCP: Enabling write pairing\n");
40 		writel_relaxed(creds | CPU_CREDIT_REG_MCPx_WR_PAIRING_EN_MASK,
41 			     cpubiuctrl_base + CPU_CREDIT_REG_OFFSET);
42 	} else if (creds & CPU_CREDIT_REG_MCPx_WR_PAIRING_EN_MASK) {
43 		pr_info("MCP: Disabling write pairing\n");
44 		writel_relaxed(creds & ~CPU_CREDIT_REG_MCPx_WR_PAIRING_EN_MASK,
45 				cpubiuctrl_base + CPU_CREDIT_REG_OFFSET);
46 	} else {
47 		pr_info("MCP: Write pairing already disabled\n");
48 	}
49 
50 	return 0;
51 }
52 
53 static int __init setup_hifcpubiuctrl_regs(void)
54 {
55 	struct device_node *np;
56 	int ret = 0;
57 
58 	np = of_find_compatible_node(NULL, NULL, "brcm,brcmstb-cpu-biu-ctrl");
59 	if (!np) {
60 		pr_err("missing BIU control node\n");
61 		return -ENODEV;
62 	}
63 
64 	cpubiuctrl_base = of_iomap(np, 0);
65 	if (!cpubiuctrl_base) {
66 		pr_err("failed to remap BIU control base\n");
67 		ret = -ENOMEM;
68 		goto out;
69 	}
70 
71 	mcp_wr_pairing_en = of_property_read_bool(np, "brcm,write-pairing");
72 out:
73 	of_node_put(np);
74 	return ret;
75 }
76 
77 #ifdef CONFIG_PM_SLEEP
78 static u32 cpu_credit_reg_dump;  /* for save/restore */
79 
80 static int brcmstb_cpu_credit_reg_suspend(void)
81 {
82 	if (cpubiuctrl_base)
83 		cpu_credit_reg_dump =
84 			readl_relaxed(cpubiuctrl_base + CPU_CREDIT_REG_OFFSET);
85 	return 0;
86 }
87 
88 static void brcmstb_cpu_credit_reg_resume(void)
89 {
90 	if (cpubiuctrl_base)
91 		writel_relaxed(cpu_credit_reg_dump,
92 				cpubiuctrl_base + CPU_CREDIT_REG_OFFSET);
93 }
94 
95 static struct syscore_ops brcmstb_cpu_credit_syscore_ops = {
96 	.suspend = brcmstb_cpu_credit_reg_suspend,
97 	.resume = brcmstb_cpu_credit_reg_resume,
98 };
99 #endif
100 
101 
102 void __init brcmstb_biuctrl_init(void)
103 {
104 	int ret;
105 
106 	setup_hifcpubiuctrl_regs();
107 
108 	ret = mcp_write_pairing_set();
109 	if (ret) {
110 		pr_err("MCP: Unable to disable write pairing!\n");
111 		return;
112 	}
113 
114 #ifdef CONFIG_PM_SLEEP
115 	register_syscore_ops(&brcmstb_cpu_credit_syscore_ops);
116 #endif
117 }
118