platsmp.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. /*
  2. * arch/arm/mach-ox820/platsmp.c
  3. *
  4. * Copyright (C) 2002 ARM Ltd.
  5. * All Rights Reserved
  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 version 2 as
  9. * published by the Free Software Foundation.
  10. */
  11. #include <linux/init.h>
  12. #include <linux/device.h>
  13. #include <linux/jiffies.h>
  14. #include <linux/smp.h>
  15. #include <linux/io.h>
  16. #include <linux/dma-mapping.h>
  17. #include <linux/cache.h>
  18. #include <asm/cacheflush.h>
  19. #include <asm/smp_scu.h>
  20. #include <asm/tlbflush.h>
  21. #include <asm/cputype.h>
  22. #include <linux/delay.h>
  23. #include <asm/fiq.h>
  24. #include <linux/irqchip/arm-gic.h>
  25. #include <mach/iomap.h>
  26. #include <mach/smp.h>
  27. #include <mach/hardware.h>
  28. #include <mach/irqs.h>
  29. #ifdef CONFIG_DMA_CACHE_FIQ_BROADCAST
  30. #define FIQ_GENERATE 0x00000002
  31. #define OXNAS_MAP_AREA 0x01000000
  32. #define OXNAS_UNMAP_AREA 0x02000000
  33. #define OXNAS_FLUSH_RANGE 0x03000000
  34. struct fiq_req {
  35. union {
  36. struct {
  37. const void *addr;
  38. size_t size;
  39. } map;
  40. struct {
  41. const void *addr;
  42. size_t size;
  43. } unmap;
  44. struct {
  45. const void *start;
  46. const void *end;
  47. } flush;
  48. };
  49. volatile uint flags;
  50. void __iomem *reg;
  51. } ____cacheline_aligned;
  52. static struct fiq_handler fh = {
  53. .name = "oxnas-fiq"
  54. };
  55. DEFINE_PER_CPU(struct fiq_req, fiq_data);
  56. static inline void __cpuinit ox820_set_fiq_regs(unsigned int cpu)
  57. {
  58. struct pt_regs FIQ_regs;
  59. struct fiq_req *fiq_req = &per_cpu(fiq_data, !cpu);
  60. FIQ_regs.ARM_r8 = 0;
  61. FIQ_regs.ARM_ip = (unsigned int)fiq_req;
  62. FIQ_regs.ARM_sp = (int)(cpu ? RPSC_IRQ_SOFT : RPSA_IRQ_SOFT);
  63. fiq_req->reg = cpu ? RPSC_IRQ_SOFT : RPSA_IRQ_SOFT;
  64. set_fiq_regs(&FIQ_regs);
  65. }
  66. static void __init ox820_init_fiq(void)
  67. {
  68. void *fiqhandler_start;
  69. unsigned int fiqhandler_length;
  70. int ret;
  71. fiqhandler_start = &ox820_fiq_start;
  72. fiqhandler_length = &ox820_fiq_end - &ox820_fiq_start;
  73. ret = claim_fiq(&fh);
  74. if (ret)
  75. return;
  76. set_fiq_handler(fiqhandler_start, fiqhandler_length);
  77. writel(IRQ_SOFT, RPSA_FIQ_IRQ_TO_FIQ);
  78. writel(1, RPSA_FIQ_ENABLE);
  79. writel(IRQ_SOFT, RPSC_FIQ_IRQ_TO_FIQ);
  80. writel(1, RPSC_FIQ_ENABLE);
  81. }
  82. void fiq_dma_map_area(const void *addr, size_t size, int dir)
  83. {
  84. unsigned long flags;
  85. struct fiq_req *req;
  86. raw_local_irq_save(flags);
  87. /* currently, not possible to take cpu0 down, so only check cpu1 */
  88. if (!cpu_online(1)) {
  89. raw_local_irq_restore(flags);
  90. v6_dma_map_area(addr, size, dir);
  91. return;
  92. }
  93. req = this_cpu_ptr(&fiq_data);
  94. req->map.addr = addr;
  95. req->map.size = size;
  96. req->flags = dir | OXNAS_MAP_AREA;
  97. smp_mb();
  98. writel_relaxed(FIQ_GENERATE, req->reg);
  99. v6_dma_map_area(addr, size, dir);
  100. while (req->flags)
  101. barrier();
  102. raw_local_irq_restore(flags);
  103. }
  104. void fiq_dma_unmap_area(const void *addr, size_t size, int dir)
  105. {
  106. unsigned long flags;
  107. struct fiq_req *req;
  108. raw_local_irq_save(flags);
  109. /* currently, not possible to take cpu0 down, so only check cpu1 */
  110. if (!cpu_online(1)) {
  111. raw_local_irq_restore(flags);
  112. v6_dma_unmap_area(addr, size, dir);
  113. return;
  114. }
  115. req = this_cpu_ptr(&fiq_data);
  116. req->unmap.addr = addr;
  117. req->unmap.size = size;
  118. req->flags = dir | OXNAS_UNMAP_AREA;
  119. smp_mb();
  120. writel_relaxed(FIQ_GENERATE, req->reg);
  121. v6_dma_unmap_area(addr, size, dir);
  122. while (req->flags)
  123. barrier();
  124. raw_local_irq_restore(flags);
  125. }
  126. void fiq_dma_flush_range(const void *start, const void *end)
  127. {
  128. unsigned long flags;
  129. struct fiq_req *req;
  130. raw_local_irq_save(flags);
  131. /* currently, not possible to take cpu0 down, so only check cpu1 */
  132. if (!cpu_online(1)) {
  133. raw_local_irq_restore(flags);
  134. v6_dma_flush_range(start, end);
  135. return;
  136. }
  137. req = this_cpu_ptr(&fiq_data);
  138. req->flush.start = start;
  139. req->flush.end = end;
  140. req->flags = OXNAS_FLUSH_RANGE;
  141. smp_mb();
  142. writel_relaxed(FIQ_GENERATE, req->reg);
  143. v6_dma_flush_range(start, end);
  144. while (req->flags)
  145. barrier();
  146. raw_local_irq_restore(flags);
  147. }
  148. void fiq_flush_kern_dcache_area(void *addr, size_t size)
  149. {
  150. fiq_dma_flush_range(addr, addr + size);
  151. }
  152. #else
  153. #define ox820_set_fiq_regs(cpu) do {} while (0) /* nothing */
  154. #define ox820_init_fiq() do {} while (0) /* nothing */
  155. #endif /* DMA_CACHE_FIQ_BROADCAST */
  156. static DEFINE_SPINLOCK(boot_lock);
  157. void __cpuinit ox820_secondary_init(unsigned int cpu)
  158. {
  159. /*
  160. * Setup Secondary Core FIQ regs
  161. */
  162. ox820_set_fiq_regs(1);
  163. /*
  164. * let the primary processor know we're out of the
  165. * pen, then head off into the C entry point
  166. */
  167. write_pen_release(-1);
  168. /*
  169. * Synchronise with the boot thread.
  170. */
  171. spin_lock(&boot_lock);
  172. spin_unlock(&boot_lock);
  173. }
  174. int __cpuinit ox820_boot_secondary(unsigned int cpu, struct task_struct *idle)
  175. {
  176. unsigned long timeout;
  177. /*
  178. * Set synchronisation state between this boot processor
  179. * and the secondary one
  180. */
  181. spin_lock(&boot_lock);
  182. /*
  183. * This is really belt and braces; we hold unintended secondary
  184. * CPUs in the holding pen until we're ready for them. However,
  185. * since we haven't sent them a soft interrupt, they shouldn't
  186. * be there.
  187. */
  188. write_pen_release(cpu);
  189. writel(1, IOMEM(OXNAS_GICN_BASE_VA(cpu) + GIC_CPU_CTRL));
  190. /*
  191. * Send the secondary CPU a soft interrupt, thereby causing
  192. * the boot monitor to read the system wide flags register,
  193. * and branch to the address found there.
  194. */
  195. arch_send_wakeup_ipi_mask(cpumask_of(cpu));
  196. timeout = jiffies + (1 * HZ);
  197. while (time_before(jiffies, timeout)) {
  198. smp_rmb();
  199. if (read_pen_release() == -1)
  200. break;
  201. udelay(10);
  202. }
  203. /*
  204. * now the secondary core is starting up let it run its
  205. * calibrations, then wait for it to finish
  206. */
  207. spin_unlock(&boot_lock);
  208. return read_pen_release() != -1 ? -ENOSYS : 0;
  209. }
  210. void *scu_base_addr(void)
  211. {
  212. return IOMEM(OXNAS_SCU_BASE_VA);
  213. }
  214. /*
  215. * Initialise the CPU possible map early - this describes the CPUs
  216. * which may be present or become present in the system.
  217. */
  218. static void __init ox820_smp_init_cpus(void)
  219. {
  220. void __iomem *scu_base = scu_base_addr();
  221. unsigned int i, ncores;
  222. ncores = scu_base ? scu_get_core_count(scu_base) : 1;
  223. /* sanity check */
  224. if (ncores > nr_cpu_ids) {
  225. pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
  226. ncores, nr_cpu_ids);
  227. ncores = nr_cpu_ids;
  228. }
  229. for (i = 0; i < ncores; i++)
  230. set_cpu_possible(i, true);
  231. }
  232. static void __init ox820_smp_prepare_cpus(unsigned int max_cpus)
  233. {
  234. scu_enable(scu_base_addr());
  235. /*
  236. * Write the address of secondary startup into the
  237. * system-wide flags register. The BootMonitor waits
  238. * until it receives a soft interrupt, and then the
  239. * secondary CPU branches to this address.
  240. */
  241. writel(virt_to_phys(ox820_secondary_startup),
  242. HOLDINGPEN_LOCATION);
  243. ox820_init_fiq();
  244. ox820_set_fiq_regs(0);
  245. }
  246. struct smp_operations ox820_smp_ops __initdata = {
  247. .smp_init_cpus = ox820_smp_init_cpus,
  248. .smp_prepare_cpus = ox820_smp_prepare_cpus,
  249. .smp_secondary_init = ox820_secondary_init,
  250. .smp_boot_secondary = ox820_boot_secondary,
  251. #ifdef CONFIG_HOTPLUG_CPU
  252. .cpu_die = ox820_cpu_die,
  253. #endif
  254. };