root/drivers/soc/bcm/brcmstb/biuctrl.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. cbc_readl
  2. cbc_writel
  3. mcp_write_pairing_set
  4. mcp_b53_set
  5. setup_hifcpubiuctrl_regs
  6. brcmstb_cpu_credit_reg_suspend
  7. brcmstb_cpu_credit_reg_resume
  8. brcmstb_biuctrl_init

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Broadcom STB SoCs Bus Unit Interface controls
   4  *
   5  * Copyright (C) 2015, Broadcom Corporation
   6  */
   7 
   8 #define pr_fmt(fmt)     "brcmstb: " KBUILD_MODNAME ": " fmt
   9 
  10 #include <linux/kernel.h>
  11 #include <linux/io.h>
  12 #include <linux/of_address.h>
  13 #include <linux/syscore_ops.h>
  14 #include <linux/soc/brcmstb/brcmstb.h>
  15 
  16 #define  CPU_CREDIT_REG_MCPx_WR_PAIRING_EN_MASK 0x70000000
  17 #define CPU_CREDIT_REG_MCPx_READ_CRED_MASK      0xf
  18 #define CPU_CREDIT_REG_MCPx_WRITE_CRED_MASK     0xf
  19 #define CPU_CREDIT_REG_MCPx_READ_CRED_SHIFT(x)  ((x) * 8)
  20 #define CPU_CREDIT_REG_MCPx_WRITE_CRED_SHIFT(x) (((x) * 8) + 4)
  21 
  22 #define CPU_MCP_FLOW_REG_MCPx_RDBUFF_CRED_SHIFT(x)      ((x) * 8)
  23 #define CPU_MCP_FLOW_REG_MCPx_RDBUFF_CRED_MASK          0xff
  24 
  25 #define CPU_WRITEBACK_CTRL_REG_WB_THROTTLE_THRESHOLD_MASK       0xf
  26 #define CPU_WRITEBACK_CTRL_REG_WB_THROTTLE_TIMEOUT_MASK         0xf
  27 #define CPU_WRITEBACK_CTRL_REG_WB_THROTTLE_TIMEOUT_SHIFT        4
  28 #define CPU_WRITEBACK_CTRL_REG_WB_THROTTLE_ENABLE               BIT(8)
  29 
  30 static void __iomem *cpubiuctrl_base;
  31 static bool mcp_wr_pairing_en;
  32 static const int *cpubiuctrl_regs;
  33 
  34 static inline u32 cbc_readl(int reg)
  35 {
  36         int offset = cpubiuctrl_regs[reg];
  37 
  38         if (offset == -1)
  39                 return (u32)-1;
  40 
  41         return readl_relaxed(cpubiuctrl_base + offset);
  42 }
  43 
  44 static inline void cbc_writel(u32 val, int reg)
  45 {
  46         int offset = cpubiuctrl_regs[reg];
  47 
  48         if (offset == -1)
  49                 return;
  50 
  51         writel(val, cpubiuctrl_base + offset);
  52 }
  53 
  54 enum cpubiuctrl_regs {
  55         CPU_CREDIT_REG = 0,
  56         CPU_MCP_FLOW_REG,
  57         CPU_WRITEBACK_CTRL_REG
  58 };
  59 
  60 static const int b15_cpubiuctrl_regs[] = {
  61         [CPU_CREDIT_REG] = 0x184,
  62         [CPU_MCP_FLOW_REG] = -1,
  63         [CPU_WRITEBACK_CTRL_REG] = -1,
  64 };
  65 
  66 /* Odd cases, e.g: 7260 */
  67 static const int b53_cpubiuctrl_no_wb_regs[] = {
  68         [CPU_CREDIT_REG] = 0x0b0,
  69         [CPU_MCP_FLOW_REG] = 0x0b4,
  70         [CPU_WRITEBACK_CTRL_REG] = -1,
  71 };
  72 
  73 static const int b53_cpubiuctrl_regs[] = {
  74         [CPU_CREDIT_REG] = 0x0b0,
  75         [CPU_MCP_FLOW_REG] = 0x0b4,
  76         [CPU_WRITEBACK_CTRL_REG] = 0x22c,
  77 };
  78 
  79 #define NUM_CPU_BIUCTRL_REGS    3
  80 
  81 static int __init mcp_write_pairing_set(void)
  82 {
  83         u32 creds = 0;
  84 
  85         if (!cpubiuctrl_base)
  86                 return -1;
  87 
  88         creds = cbc_readl(CPU_CREDIT_REG);
  89         if (mcp_wr_pairing_en) {
  90                 pr_info("MCP: Enabling write pairing\n");
  91                 cbc_writel(creds | CPU_CREDIT_REG_MCPx_WR_PAIRING_EN_MASK,
  92                            CPU_CREDIT_REG);
  93         } else if (creds & CPU_CREDIT_REG_MCPx_WR_PAIRING_EN_MASK) {
  94                 pr_info("MCP: Disabling write pairing\n");
  95                 cbc_writel(creds & ~CPU_CREDIT_REG_MCPx_WR_PAIRING_EN_MASK,
  96                            CPU_CREDIT_REG);
  97         } else {
  98                 pr_info("MCP: Write pairing already disabled\n");
  99         }
 100 
 101         return 0;
 102 }
 103 
 104 static const u32 b53_mach_compat[] = {
 105         0x7268,
 106         0x7271,
 107         0x7278,
 108 };
 109 
 110 static void __init mcp_b53_set(void)
 111 {
 112         unsigned int i;
 113         u32 reg;
 114 
 115         reg = brcmstb_get_family_id();
 116 
 117         for (i = 0; i < ARRAY_SIZE(b53_mach_compat); i++) {
 118                 if (BRCM_ID(reg) == b53_mach_compat[i])
 119                         break;
 120         }
 121 
 122         if (i == ARRAY_SIZE(b53_mach_compat))
 123                 return;
 124 
 125         /* Set all 3 MCP interfaces to 8 credits */
 126         reg = cbc_readl(CPU_CREDIT_REG);
 127         for (i = 0; i < 3; i++) {
 128                 reg &= ~(CPU_CREDIT_REG_MCPx_WRITE_CRED_MASK <<
 129                          CPU_CREDIT_REG_MCPx_WRITE_CRED_SHIFT(i));
 130                 reg &= ~(CPU_CREDIT_REG_MCPx_READ_CRED_MASK <<
 131                          CPU_CREDIT_REG_MCPx_READ_CRED_SHIFT(i));
 132                 reg |= 8 << CPU_CREDIT_REG_MCPx_WRITE_CRED_SHIFT(i);
 133                 reg |= 8 << CPU_CREDIT_REG_MCPx_READ_CRED_SHIFT(i);
 134         }
 135         cbc_writel(reg, CPU_CREDIT_REG);
 136 
 137         /* Max out the number of in-flight Jwords reads on the MCP interface */
 138         reg = cbc_readl(CPU_MCP_FLOW_REG);
 139         for (i = 0; i < 3; i++)
 140                 reg |= CPU_MCP_FLOW_REG_MCPx_RDBUFF_CRED_MASK <<
 141                         CPU_MCP_FLOW_REG_MCPx_RDBUFF_CRED_SHIFT(i);
 142         cbc_writel(reg, CPU_MCP_FLOW_REG);
 143 
 144         /* Enable writeback throttling, set timeout to 128 cycles, 256 cycles
 145          * threshold
 146          */
 147         reg = cbc_readl(CPU_WRITEBACK_CTRL_REG);
 148         reg |= CPU_WRITEBACK_CTRL_REG_WB_THROTTLE_ENABLE;
 149         reg &= ~CPU_WRITEBACK_CTRL_REG_WB_THROTTLE_THRESHOLD_MASK;
 150         reg &= ~(CPU_WRITEBACK_CTRL_REG_WB_THROTTLE_TIMEOUT_MASK <<
 151                  CPU_WRITEBACK_CTRL_REG_WB_THROTTLE_TIMEOUT_SHIFT);
 152         reg |= 8;
 153         reg |= 7 << CPU_WRITEBACK_CTRL_REG_WB_THROTTLE_TIMEOUT_SHIFT;
 154         cbc_writel(reg, CPU_WRITEBACK_CTRL_REG);
 155 }
 156 
 157 static int __init setup_hifcpubiuctrl_regs(struct device_node *np)
 158 {
 159         struct device_node *cpu_dn;
 160         int ret = 0;
 161 
 162         cpubiuctrl_base = of_iomap(np, 0);
 163         if (!cpubiuctrl_base) {
 164                 pr_err("failed to remap BIU control base\n");
 165                 ret = -ENOMEM;
 166                 goto out;
 167         }
 168 
 169         mcp_wr_pairing_en = of_property_read_bool(np, "brcm,write-pairing");
 170 
 171         cpu_dn = of_get_cpu_node(0, NULL);
 172         if (!cpu_dn) {
 173                 pr_err("failed to obtain CPU device node\n");
 174                 ret = -ENODEV;
 175                 goto out;
 176         }
 177 
 178         if (of_device_is_compatible(cpu_dn, "brcm,brahma-b15"))
 179                 cpubiuctrl_regs = b15_cpubiuctrl_regs;
 180         else if (of_device_is_compatible(cpu_dn, "brcm,brahma-b53"))
 181                 cpubiuctrl_regs = b53_cpubiuctrl_regs;
 182         else {
 183                 pr_err("unsupported CPU\n");
 184                 ret = -EINVAL;
 185         }
 186         of_node_put(cpu_dn);
 187 
 188         if (BRCM_ID(brcmstb_get_family_id()) == 0x7260)
 189                 cpubiuctrl_regs = b53_cpubiuctrl_no_wb_regs;
 190 out:
 191         of_node_put(np);
 192         return ret;
 193 }
 194 
 195 #ifdef CONFIG_PM_SLEEP
 196 static u32 cpubiuctrl_reg_save[NUM_CPU_BIUCTRL_REGS];
 197 
 198 static int brcmstb_cpu_credit_reg_suspend(void)
 199 {
 200         unsigned int i;
 201 
 202         if (!cpubiuctrl_base)
 203                 return 0;
 204 
 205         for (i = 0; i < NUM_CPU_BIUCTRL_REGS; i++)
 206                 cpubiuctrl_reg_save[i] = cbc_readl(i);
 207 
 208         return 0;
 209 }
 210 
 211 static void brcmstb_cpu_credit_reg_resume(void)
 212 {
 213         unsigned int i;
 214 
 215         if (!cpubiuctrl_base)
 216                 return;
 217 
 218         for (i = 0; i < NUM_CPU_BIUCTRL_REGS; i++)
 219                 cbc_writel(cpubiuctrl_reg_save[i], i);
 220 }
 221 
 222 static struct syscore_ops brcmstb_cpu_credit_syscore_ops = {
 223         .suspend = brcmstb_cpu_credit_reg_suspend,
 224         .resume = brcmstb_cpu_credit_reg_resume,
 225 };
 226 #endif
 227 
 228 
 229 static int __init brcmstb_biuctrl_init(void)
 230 {
 231         struct device_node *np;
 232         int ret;
 233 
 234         /* We might be running on a multi-platform kernel, don't make this a
 235          * fatal error, just bail out early
 236          */
 237         np = of_find_compatible_node(NULL, NULL, "brcm,brcmstb-cpu-biu-ctrl");
 238         if (!np)
 239                 return 0;
 240 
 241         ret = setup_hifcpubiuctrl_regs(np);
 242         if (ret)
 243                 return ret;
 244 
 245         ret = mcp_write_pairing_set();
 246         if (ret) {
 247                 pr_err("MCP: Unable to disable write pairing!\n");
 248                 return ret;
 249         }
 250 
 251         mcp_b53_set();
 252 #ifdef CONFIG_PM_SLEEP
 253         register_syscore_ops(&brcmstb_cpu_credit_syscore_ops);
 254 #endif
 255         return 0;
 256 }
 257 early_initcall(brcmstb_biuctrl_init);

/* [<][>][^][v][top][bottom][index][help] */