bcm63xx_pmb.c 5.1 KB

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