platsmp.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. /*
  2. * linux/arch/arm/mach-tegra/platsmp.c
  3. *
  4. * Copyright (C) 2002 ARM Ltd.
  5. * All Rights Reserved
  6. *
  7. * Copyright (C) 2009 Palm
  8. * All Rights Reserved
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License version 2 as
  12. * published by the Free Software Foundation.
  13. */
  14. #include <linux/init.h>
  15. #include <linux/errno.h>
  16. #include <linux/delay.h>
  17. #include <linux/device.h>
  18. #include <linux/jiffies.h>
  19. #include <linux/smp.h>
  20. #include <linux/io.h>
  21. #include <asm/cacheflush.h>
  22. #include <asm/hardware/gic.h>
  23. #include <asm/mach-types.h>
  24. #include <asm/smp_scu.h>
  25. #include <mach/clk.h>
  26. #include <mach/iomap.h>
  27. #include <mach/powergate.h>
  28. #include "fuse.h"
  29. #include "flowctrl.h"
  30. #include "reset.h"
  31. extern void tegra_secondary_startup(void);
  32. static void __iomem *scu_base = IO_ADDRESS(TEGRA_ARM_PERIF_BASE);
  33. #define EVP_CPU_RESET_VECTOR \
  34. (IO_ADDRESS(TEGRA_EXCEPTION_VECTORS_BASE) + 0x100)
  35. #define CLK_RST_CONTROLLER_CLK_CPU_CMPLX \
  36. (IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x4c)
  37. #define CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET \
  38. (IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x340)
  39. #define CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR \
  40. (IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x344)
  41. #define CLK_RST_CONTROLLER_CLK_CPU_CMPLX_CLR \
  42. (IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x34c)
  43. #define CPU_CLOCK(cpu) (0x1<<(8+cpu))
  44. #define CPU_RESET(cpu) (0x1111ul<<(cpu))
  45. void __cpuinit platform_secondary_init(unsigned int cpu)
  46. {
  47. /*
  48. * if any interrupts are already enabled for the primary
  49. * core (e.g. timer irq), then they will not have been enabled
  50. * for us: do so
  51. */
  52. gic_secondary_init(0);
  53. }
  54. static int tegra20_power_up_cpu(unsigned int cpu)
  55. {
  56. u32 reg;
  57. /* Enable the CPU clock. */
  58. reg = readl(CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
  59. writel(reg & ~CPU_CLOCK(cpu), CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
  60. barrier();
  61. reg = readl(CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
  62. /* Clear flow controller CSR. */
  63. flowctrl_write_cpu_csr(cpu, 0);
  64. return 0;
  65. }
  66. static int tegra30_power_up_cpu(unsigned int cpu)
  67. {
  68. u32 reg;
  69. int ret, pwrgateid;
  70. unsigned long timeout;
  71. pwrgateid = tegra_cpu_powergate_id(cpu);
  72. if (pwrgateid < 0)
  73. return pwrgateid;
  74. /* If this is the first boot, toggle powergates directly. */
  75. if (!tegra_powergate_is_powered(pwrgateid)) {
  76. ret = tegra_powergate_power_on(pwrgateid);
  77. if (ret)
  78. return ret;
  79. /* Wait for the power to come up. */
  80. timeout = jiffies + 10*HZ;
  81. while (tegra_powergate_is_powered(pwrgateid)) {
  82. if (time_after(jiffies, timeout))
  83. return -ETIMEDOUT;
  84. udelay(10);
  85. }
  86. }
  87. /* CPU partition is powered. Enable the CPU clock. */
  88. writel(CPU_CLOCK(cpu), CLK_RST_CONTROLLER_CLK_CPU_CMPLX_CLR);
  89. reg = readl(CLK_RST_CONTROLLER_CLK_CPU_CMPLX_CLR);
  90. udelay(10);
  91. /* Remove I/O clamps. */
  92. ret = tegra_powergate_remove_clamping(pwrgateid);
  93. udelay(10);
  94. /* Clear flow controller CSR. */
  95. flowctrl_write_cpu_csr(cpu, 0);
  96. return 0;
  97. }
  98. int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
  99. {
  100. int status;
  101. /*
  102. * Force the CPU into reset. The CPU must remain in reset when the
  103. * flow controller state is cleared (which will cause the flow
  104. * controller to stop driving reset if the CPU has been power-gated
  105. * via the flow controller). This will have no effect on first boot
  106. * of the CPU since it should already be in reset.
  107. */
  108. writel(CPU_RESET(cpu), CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET);
  109. dmb();
  110. /*
  111. * Unhalt the CPU. If the flow controller was used to power-gate the
  112. * CPU this will cause the flow controller to stop driving reset.
  113. * The CPU will remain in reset because the clock and reset block
  114. * is now driving reset.
  115. */
  116. flowctrl_write_cpu_halt(cpu, 0);
  117. switch (tegra_chip_id) {
  118. case TEGRA20:
  119. status = tegra20_power_up_cpu(cpu);
  120. break;
  121. case TEGRA30:
  122. status = tegra30_power_up_cpu(cpu);
  123. break;
  124. default:
  125. status = -EINVAL;
  126. break;
  127. }
  128. if (status)
  129. goto done;
  130. /* Take the CPU out of reset. */
  131. writel(CPU_RESET(cpu), CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR);
  132. wmb();
  133. done:
  134. return status;
  135. }
  136. /*
  137. * Initialise the CPU possible map early - this describes the CPUs
  138. * which may be present or become present in the system.
  139. */
  140. void __init smp_init_cpus(void)
  141. {
  142. unsigned int i, ncores = scu_get_core_count(scu_base);
  143. if (ncores > nr_cpu_ids) {
  144. pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
  145. ncores, nr_cpu_ids);
  146. ncores = nr_cpu_ids;
  147. }
  148. for (i = 0; i < ncores; i++)
  149. set_cpu_possible(i, true);
  150. set_smp_cross_call(gic_raise_softirq);
  151. }
  152. void __init platform_smp_prepare_cpus(unsigned int max_cpus)
  153. {
  154. tegra_cpu_reset_handler_init();
  155. scu_enable(scu_base);
  156. }