Linux-libre 4.9.86-gnu
[librecmc/linux-libre.git] / drivers / soc / bcm / brcmstb / biuctrl.c
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 }