spear13xx.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. /*
  2. * arch/arm/mach-spear13xx/spear13xx.c
  3. *
  4. * SPEAr13XX machines common source file
  5. *
  6. * Copyright (C) 2012 ST Microelectronics
  7. * Viresh Kumar <viresh.linux@gmail.com>
  8. *
  9. * This file is licensed under the terms of the GNU General Public
  10. * License version 2. This program is licensed "as is" without any
  11. * warranty of any kind, whether express or implied.
  12. */
  13. #define pr_fmt(fmt) "SPEAr13xx: " fmt
  14. #include <linux/amba/pl022.h>
  15. #include <linux/clk.h>
  16. #include <linux/dw_dmac.h>
  17. #include <linux/err.h>
  18. #include <linux/of_irq.h>
  19. #include <asm/hardware/cache-l2x0.h>
  20. #include <asm/hardware/gic.h>
  21. #include <asm/mach/map.h>
  22. #include <asm/smp_twd.h>
  23. #include <mach/dma.h>
  24. #include <mach/generic.h>
  25. #include <mach/spear.h>
  26. /* common dw_dma filter routine to be used by peripherals */
  27. bool dw_dma_filter(struct dma_chan *chan, void *slave)
  28. {
  29. struct dw_dma_slave *dws = (struct dw_dma_slave *)slave;
  30. if (chan->device->dev == dws->dma_dev) {
  31. chan->private = slave;
  32. return true;
  33. } else {
  34. return false;
  35. }
  36. }
  37. /* ssp device registration */
  38. static struct dw_dma_slave ssp_dma_param[] = {
  39. {
  40. /* Tx */
  41. .cfg_hi = DWC_CFGH_DST_PER(DMA_REQ_SSP0_TX),
  42. .cfg_lo = 0,
  43. .src_master = DMA_MASTER_MEMORY,
  44. .dst_master = DMA_MASTER_SSP0,
  45. }, {
  46. /* Rx */
  47. .cfg_hi = DWC_CFGH_SRC_PER(DMA_REQ_SSP0_RX),
  48. .cfg_lo = 0,
  49. .src_master = DMA_MASTER_SSP0,
  50. .dst_master = DMA_MASTER_MEMORY,
  51. }
  52. };
  53. struct pl022_ssp_controller pl022_plat_data = {
  54. .bus_id = 0,
  55. .enable_dma = 1,
  56. .dma_filter = dw_dma_filter,
  57. .dma_rx_param = &ssp_dma_param[1],
  58. .dma_tx_param = &ssp_dma_param[0],
  59. .num_chipselect = 3,
  60. };
  61. /* CF device registration */
  62. struct dw_dma_slave cf_dma_priv = {
  63. .cfg_hi = 0,
  64. .cfg_lo = 0,
  65. .src_master = 0,
  66. .dst_master = 0,
  67. };
  68. /* dmac device registeration */
  69. struct dw_dma_platform_data dmac_plat_data = {
  70. .nr_channels = 8,
  71. .chan_allocation_order = CHAN_ALLOCATION_DESCENDING,
  72. .chan_priority = CHAN_PRIORITY_DESCENDING,
  73. };
  74. void __init spear13xx_l2x0_init(void)
  75. {
  76. /*
  77. * 512KB (64KB/way), 8-way associativity, parity supported
  78. *
  79. * FIXME: 9th bit, of Auxillary Controller register must be set
  80. * for some spear13xx devices for stable L2 operation.
  81. *
  82. * Enable Early BRESP, L2 prefetch for Instruction and Data,
  83. * write alloc and 'Full line of zero' options
  84. *
  85. */
  86. writel_relaxed(0x06, VA_L2CC_BASE + L2X0_PREFETCH_CTRL);
  87. /*
  88. * Program following latencies in order to make
  89. * SPEAr1340 work at 600 MHz
  90. */
  91. writel_relaxed(0x221, VA_L2CC_BASE + L2X0_TAG_LATENCY_CTRL);
  92. writel_relaxed(0x441, VA_L2CC_BASE + L2X0_DATA_LATENCY_CTRL);
  93. l2x0_init(VA_L2CC_BASE, 0x70A60001, 0xfe00ffff);
  94. }
  95. /*
  96. * Following will create 16MB static virtual/physical mappings
  97. * PHYSICAL VIRTUAL
  98. * 0xB3000000 0xFE000000
  99. * 0xE0000000 0xFD000000
  100. * 0xEC000000 0xFC000000
  101. * 0xED000000 0xFB000000
  102. */
  103. struct map_desc spear13xx_io_desc[] __initdata = {
  104. {
  105. .virtual = VA_PERIP_GRP2_BASE,
  106. .pfn = __phys_to_pfn(PERIP_GRP2_BASE),
  107. .length = SZ_16M,
  108. .type = MT_DEVICE
  109. }, {
  110. .virtual = VA_PERIP_GRP1_BASE,
  111. .pfn = __phys_to_pfn(PERIP_GRP1_BASE),
  112. .length = SZ_16M,
  113. .type = MT_DEVICE
  114. }, {
  115. .virtual = VA_A9SM_AND_MPMC_BASE,
  116. .pfn = __phys_to_pfn(A9SM_AND_MPMC_BASE),
  117. .length = SZ_16M,
  118. .type = MT_DEVICE
  119. }, {
  120. .virtual = (unsigned long)VA_L2CC_BASE,
  121. .pfn = __phys_to_pfn(L2CC_BASE),
  122. .length = SZ_4K,
  123. .type = MT_DEVICE
  124. },
  125. };
  126. /* This will create static memory mapping for selected devices */
  127. void __init spear13xx_map_io(void)
  128. {
  129. iotable_init(spear13xx_io_desc, ARRAY_SIZE(spear13xx_io_desc));
  130. }
  131. static void __init spear13xx_clk_init(void)
  132. {
  133. if (of_machine_is_compatible("st,spear1310"))
  134. spear1310_clk_init();
  135. else if (of_machine_is_compatible("st,spear1340"))
  136. spear1340_clk_init();
  137. else
  138. pr_err("%s: Unknown machine\n", __func__);
  139. }
  140. static void __init spear13xx_timer_init(void)
  141. {
  142. char pclk_name[] = "osc_24m_clk";
  143. struct clk *gpt_clk, *pclk;
  144. spear13xx_clk_init();
  145. /* get the system timer clock */
  146. gpt_clk = clk_get_sys("gpt0", NULL);
  147. if (IS_ERR(gpt_clk)) {
  148. pr_err("%s:couldn't get clk for gpt\n", __func__);
  149. BUG();
  150. }
  151. /* get the suitable parent clock for timer*/
  152. pclk = clk_get(NULL, pclk_name);
  153. if (IS_ERR(pclk)) {
  154. pr_err("%s:couldn't get %s as parent for gpt\n", __func__,
  155. pclk_name);
  156. BUG();
  157. }
  158. clk_set_parent(gpt_clk, pclk);
  159. clk_put(gpt_clk);
  160. clk_put(pclk);
  161. spear_setup_of_timer();
  162. twd_local_timer_of_register();
  163. }
  164. struct sys_timer spear13xx_timer = {
  165. .init = spear13xx_timer_init,
  166. };
  167. static const struct of_device_id gic_of_match[] __initconst = {
  168. { .compatible = "arm,cortex-a9-gic", .data = gic_of_init },
  169. { /* Sentinel */ }
  170. };
  171. void __init spear13xx_dt_init_irq(void)
  172. {
  173. of_irq_init(gic_of_match);
  174. }