0014-ARM-qcom-Add-SMP-support-for-KPSSv2.patch 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. From eb07c23d45ddf10fa89296e6c6c6aed553d8bbf5 Mon Sep 17 00:00:00 2001
  2. From: Rohit Vaswani <[email protected]>
  3. Date: Fri, 21 Jun 2013 17:09:13 -0700
  4. Subject: [PATCH 014/182] ARM: qcom: Add SMP support for KPSSv2
  5. Implement support for the Krait CPU release sequence when the
  6. CPUs are part of the second version of the Krait processor
  7. subsystem.
  8. Signed-off-by: Rohit Vaswani <[email protected]>
  9. Signed-off-by: Stephen Boyd <[email protected]>
  10. Signed-off-by: Kumar Gala <[email protected]>
  11. ---
  12. arch/arm/mach-qcom/platsmp.c | 123 ++++++++++++++++++++++++++++++++++++++++++
  13. 1 file changed, 123 insertions(+)
  14. --- a/arch/arm/mach-qcom/platsmp.c
  15. +++ b/arch/arm/mach-qcom/platsmp.c
  16. @@ -34,7 +34,15 @@
  17. #define L2DT_SLP BIT(3)
  18. #define CLAMP BIT(0)
  19. +#define APC_PWR_GATE_CTL 0x14
  20. +#define BHS_CNT_SHIFT 24
  21. +#define LDO_PWR_DWN_SHIFT 16
  22. +#define LDO_BYP_SHIFT 8
  23. +#define BHS_SEG_SHIFT 1
  24. +#define BHS_EN BIT(0)
  25. +
  26. #define APCS_SAW2_VCTL 0x14
  27. +#define APCS_SAW2_2_VCTL 0x1c
  28. extern void secondary_startup(void);
  29. @@ -160,6 +168,106 @@ out_acc:
  30. return ret;
  31. }
  32. +static int kpssv2_release_secondary(unsigned int cpu)
  33. +{
  34. + void __iomem *reg;
  35. + struct device_node *cpu_node, *l2_node, *acc_node, *saw_node;
  36. + void __iomem *l2_saw_base;
  37. + unsigned reg_val;
  38. + int ret;
  39. +
  40. + cpu_node = of_get_cpu_node(cpu, NULL);
  41. + if (!cpu_node)
  42. + return -ENODEV;
  43. +
  44. + acc_node = of_parse_phandle(cpu_node, "qcom,acc", 0);
  45. + if (!acc_node) {
  46. + ret = -ENODEV;
  47. + goto out_acc;
  48. + }
  49. +
  50. + l2_node = of_parse_phandle(cpu_node, "next-level-cache", 0);
  51. + if (!l2_node) {
  52. + ret = -ENODEV;
  53. + goto out_l2;
  54. + }
  55. +
  56. + saw_node = of_parse_phandle(l2_node, "qcom,saw", 0);
  57. + if (!saw_node) {
  58. + ret = -ENODEV;
  59. + goto out_saw;
  60. + }
  61. +
  62. + reg = of_iomap(acc_node, 0);
  63. + if (!reg) {
  64. + ret = -ENOMEM;
  65. + goto out_map;
  66. + }
  67. +
  68. + l2_saw_base = of_iomap(saw_node, 0);
  69. + if (!l2_saw_base) {
  70. + ret = -ENOMEM;
  71. + goto out_saw_map;
  72. + }
  73. +
  74. + /* Turn on the BHS, turn off LDO Bypass and power down LDO */
  75. + reg_val = (64 << BHS_CNT_SHIFT) | (0x3f << LDO_PWR_DWN_SHIFT) | BHS_EN;
  76. + writel_relaxed(reg_val, reg + APC_PWR_GATE_CTL);
  77. + mb();
  78. + /* wait for the BHS to settle */
  79. + udelay(1);
  80. +
  81. + /* Turn on BHS segments */
  82. + reg_val |= 0x3f << BHS_SEG_SHIFT;
  83. + writel_relaxed(reg_val, reg + APC_PWR_GATE_CTL);
  84. + mb();
  85. + /* wait for the BHS to settle */
  86. + udelay(1);
  87. +
  88. + /* Finally turn on the bypass so that BHS supplies power */
  89. + reg_val |= 0x3f << LDO_BYP_SHIFT;
  90. + writel_relaxed(reg_val, reg + APC_PWR_GATE_CTL);
  91. +
  92. + /* enable max phases */
  93. + writel_relaxed(0x10003, l2_saw_base + APCS_SAW2_2_VCTL);
  94. + mb();
  95. + udelay(50);
  96. +
  97. + reg_val = COREPOR_RST | CLAMP;
  98. + writel_relaxed(reg_val, reg + APCS_CPU_PWR_CTL);
  99. + mb();
  100. + udelay(2);
  101. +
  102. + reg_val &= ~CLAMP;
  103. + writel_relaxed(reg_val, reg + APCS_CPU_PWR_CTL);
  104. + mb();
  105. + udelay(2);
  106. +
  107. + reg_val &= ~COREPOR_RST;
  108. + writel_relaxed(reg_val, reg + APCS_CPU_PWR_CTL);
  109. + mb();
  110. +
  111. + reg_val |= CORE_PWRD_UP;
  112. + writel_relaxed(reg_val, reg + APCS_CPU_PWR_CTL);
  113. + mb();
  114. +
  115. + ret = 0;
  116. +
  117. + iounmap(l2_saw_base);
  118. +out_saw_map:
  119. + iounmap(reg);
  120. +out_map:
  121. + of_node_put(saw_node);
  122. +out_saw:
  123. + of_node_put(l2_node);
  124. +out_l2:
  125. + of_node_put(acc_node);
  126. +out_acc:
  127. + of_node_put(cpu_node);
  128. +
  129. + return ret;
  130. +}
  131. +
  132. static DEFINE_PER_CPU(int, cold_boot_done);
  133. static int qcom_boot_secondary(unsigned int cpu, int (*func)(unsigned int))
  134. @@ -204,6 +312,11 @@ static int kpssv1_boot_secondary(unsigne
  135. return qcom_boot_secondary(cpu, kpssv1_release_secondary);
  136. }
  137. +static int kpssv2_boot_secondary(unsigned int cpu, struct task_struct *idle)
  138. +{
  139. + return qcom_boot_secondary(cpu, kpssv2_release_secondary);
  140. +}
  141. +
  142. static void __init qcom_smp_prepare_cpus(unsigned int max_cpus)
  143. {
  144. int cpu, map;
  145. @@ -253,3 +366,13 @@ static struct smp_operations qcom_smp_kp
  146. #endif
  147. };
  148. CPU_METHOD_OF_DECLARE(qcom_smp_kpssv1, "qcom,kpss-acc-v1", &qcom_smp_kpssv1_ops);
  149. +
  150. +static struct smp_operations qcom_smp_kpssv2_ops __initdata = {
  151. + .smp_prepare_cpus = qcom_smp_prepare_cpus,
  152. + .smp_secondary_init = qcom_secondary_init,
  153. + .smp_boot_secondary = kpssv2_boot_secondary,
  154. +#ifdef CONFIG_HOTPLUG_CPU
  155. + .cpu_die = qcom_cpu_die,
  156. +#endif
  157. +};
  158. +CPU_METHOD_OF_DECLARE(qcom_smp_kpssv2, "qcom,kpss-acc-v2", &qcom_smp_kpssv2_ops);