bcm63xx_pmb.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Broadcom BCM63138 PMB initialization for secondary CPU(s)
  4. *
  5. * Copyright (C) 2015 Broadcom Corporation
  6. * Author: Florian Fainelli <f.fainelli@gmail.com>
  7. */
  8. #include <linux/kernel.h>
  9. #include <linux/io.h>
  10. #include <linux/spinlock.h>
  11. #include <linux/reset/bcm63xx_pmb.h>
  12. #include <linux/of.h>
  13. #include <linux/of_address.h>
  14. #include "bcm63xx_smp.h"
  15. /* ARM Control register definitions */
  16. #define CORE_PWR_CTRL_SHIFT 0
  17. #define CORE_PWR_CTRL_MASK 0x3
  18. #define PLL_PWR_ON BIT(8)
  19. #define PLL_LDO_PWR_ON BIT(9)
  20. #define PLL_CLAMP_ON BIT(10)
  21. #define CPU_RESET_N(x) BIT(13 + (x))
  22. #define NEON_RESET_N BIT(15)
  23. #define PWR_CTRL_STATUS_SHIFT 28
  24. #define PWR_CTRL_STATUS_MASK 0x3
  25. #define PWR_DOWN_SHIFT 30
  26. #define PWR_DOWN_MASK 0x3
  27. /* CPU Power control register definitions */
  28. #define MEM_PWR_OK BIT(0)
  29. #define MEM_PWR_ON BIT(1)
  30. #define MEM_CLAMP_ON BIT(2)
  31. #define MEM_PWR_OK_STATUS BIT(4)
  32. #define MEM_PWR_ON_STATUS BIT(5)
  33. #define MEM_PDA_SHIFT 8
  34. #define MEM_PDA_MASK 0xf
  35. #define MEM_PDA_CPU_MASK 0x1
  36. #define MEM_PDA_NEON_MASK 0xf
  37. #define CLAMP_ON BIT(15)
  38. #define PWR_OK_SHIFT 16
  39. #define PWR_OK_MASK 0xf
  40. #define PWR_ON_SHIFT 20
  41. #define PWR_CPU_MASK 0x03
  42. #define PWR_NEON_MASK 0x01
  43. #define PWR_ON_MASK 0xf
  44. #define PWR_OK_STATUS_SHIFT 24
  45. #define PWR_OK_STATUS_MASK 0xf
  46. #define PWR_ON_STATUS_SHIFT 28
  47. #define PWR_ON_STATUS_MASK 0xf
  48. #define ARM_CONTROL 0x30
  49. #define ARM_PWR_CONTROL_BASE 0x34
  50. #define ARM_PWR_CONTROL(x) (ARM_PWR_CONTROL_BASE + (x) * 0x4)
  51. #define ARM_NEON_L2 0x3c
  52. /* Perform a value write, then spin until the value shifted by
  53. * shift is seen, masked with mask and is different from cond.
  54. */
  55. static int bpcm_wr_rd_mask(void __iomem *master,
  56. unsigned int addr, u32 off, u32 *val,
  57. u32 shift, u32 mask, u32 cond)
  58. {
  59. int ret;
  60. ret = bpcm_wr(master, addr, off, *val);
  61. if (ret)
  62. return ret;
  63. do {
  64. ret = bpcm_rd(master, addr, off, val);
  65. if (ret)
  66. return ret;
  67. cpu_relax();
  68. } while (((*val >> shift) & mask) != cond);
  69. return ret;
  70. }
  71. /* Global lock to serialize accesses to the PMB registers while we
  72. * are bringing up the secondary CPU
  73. */
  74. static DEFINE_SPINLOCK(pmb_lock);
  75. static int bcm63xx_pmb_get_resources(struct device_node *dn,
  76. void __iomem **base,
  77. unsigned int *cpu,
  78. unsigned int *addr)
  79. {
  80. struct of_phandle_args args;
  81. int ret;
  82. ret = of_property_read_u32(dn, "reg", cpu);
  83. if (ret) {
  84. pr_err("CPU is missing a reg node\n");
  85. return ret;
  86. }
  87. ret = of_parse_phandle_with_args(dn, "resets", "#reset-cells",
  88. 0, &args);
  89. if (ret) {
  90. pr_err("CPU is missing a resets phandle\n");
  91. return ret;
  92. }
  93. if (args.args_count != 2) {
  94. pr_err("reset-controller does not conform to reset-cells\n");
  95. return -EINVAL;
  96. }
  97. *base = of_iomap(args.np, 0);
  98. if (!*base) {
  99. pr_err("failed remapping PMB register\n");
  100. return -ENOMEM;
  101. }
  102. /* We do not need the number of zones */
  103. *addr = args.args[0];
  104. return 0;
  105. }
  106. int bcm63xx_pmb_power_on_cpu(struct device_node *dn)
  107. {
  108. void __iomem *base;
  109. unsigned int cpu, addr;
  110. unsigned long flags;
  111. u32 val, ctrl;
  112. int ret;
  113. ret = bcm63xx_pmb_get_resources(dn, &base, &cpu, &addr);
  114. if (ret)
  115. return ret;
  116. /* We would not know how to enable a third and greater CPU */
  117. WARN_ON(cpu > 1);
  118. spin_lock_irqsave(&pmb_lock, flags);
  119. /* Check if the CPU is already on and save the ARM_CONTROL register
  120. * value since we will use it later for CPU de-assert once done with
  121. * the CPU-specific power sequence
  122. */
  123. ret = bpcm_rd(base, addr, ARM_CONTROL, &ctrl);
  124. if (ret)
  125. goto out;
  126. if (ctrl & CPU_RESET_N(cpu)) {
  127. pr_info("PMB: CPU%d is already powered on\n", cpu);
  128. ret = 0;
  129. goto out;
  130. }
  131. /* Power on PLL */
  132. ret = bpcm_rd(base, addr, ARM_PWR_CONTROL(cpu), &val);
  133. if (ret)
  134. goto out;
  135. val |= (PWR_CPU_MASK << PWR_ON_SHIFT);
  136. ret = bpcm_wr_rd_mask(base, addr, ARM_PWR_CONTROL(cpu), &val,
  137. PWR_ON_STATUS_SHIFT, PWR_CPU_MASK, PWR_CPU_MASK);
  138. if (ret)
  139. goto out;
  140. val |= (PWR_CPU_MASK << PWR_OK_SHIFT);
  141. ret = bpcm_wr_rd_mask(base, addr, ARM_PWR_CONTROL(cpu), &val,
  142. PWR_OK_STATUS_SHIFT, PWR_CPU_MASK, PWR_CPU_MASK);
  143. if (ret)
  144. goto out;
  145. val &= ~CLAMP_ON;
  146. ret = bpcm_wr(base, addr, ARM_PWR_CONTROL(cpu), val);
  147. if (ret)
  148. goto out;
  149. /* Power on CPU<N> RAM */
  150. val &= ~(MEM_PDA_MASK << MEM_PDA_SHIFT);
  151. ret = bpcm_wr(base, addr, ARM_PWR_CONTROL(cpu), val);
  152. if (ret)
  153. goto out;
  154. val |= MEM_PWR_ON;
  155. ret = bpcm_wr_rd_mask(base, addr, ARM_PWR_CONTROL(cpu), &val,
  156. 0, MEM_PWR_ON_STATUS, MEM_PWR_ON_STATUS);
  157. if (ret)
  158. goto out;
  159. val |= MEM_PWR_OK;
  160. ret = bpcm_wr_rd_mask(base, addr, ARM_PWR_CONTROL(cpu), &val,
  161. 0, MEM_PWR_OK_STATUS, MEM_PWR_OK_STATUS);
  162. if (ret)
  163. goto out;
  164. val &= ~MEM_CLAMP_ON;
  165. ret = bpcm_wr(base, addr, ARM_PWR_CONTROL(cpu), val);
  166. if (ret)
  167. goto out;
  168. /* De-assert CPU reset */
  169. ctrl |= CPU_RESET_N(cpu);
  170. ret = bpcm_wr(base, addr, ARM_CONTROL, ctrl);
  171. out:
  172. spin_unlock_irqrestore(&pmb_lock, flags);
  173. iounmap(base);
  174. return ret;
  175. }