biuctrl.c 6.4 KB

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