biuctrl.c 6.0 KB

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