core.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. /*
  2. * linux/arch/arm/mach-ebsa110/core.c
  3. *
  4. * Copyright (C) 1998-2001 Russell King
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License version 2 as
  8. * published by the Free Software Foundation.
  9. *
  10. * Extra MM routines for the EBSA-110 architecture
  11. */
  12. #include <linux/kernel.h>
  13. #include <linux/mm.h>
  14. #include <linux/interrupt.h>
  15. #include <linux/serial_8250.h>
  16. #include <linux/init.h>
  17. #include <linux/io.h>
  18. #include <mach/hardware.h>
  19. #include <asm/irq.h>
  20. #include <asm/setup.h>
  21. #include <asm/mach-types.h>
  22. #include <asm/pgtable.h>
  23. #include <asm/page.h>
  24. #include <asm/system_misc.h>
  25. #include <asm/mach/arch.h>
  26. #include <asm/mach/irq.h>
  27. #include <asm/mach/map.h>
  28. #include <asm/mach/time.h>
  29. #include "core.h"
  30. static void ebsa110_mask_irq(struct irq_data *d)
  31. {
  32. __raw_writeb(1 << d->irq, IRQ_MCLR);
  33. }
  34. static void ebsa110_unmask_irq(struct irq_data *d)
  35. {
  36. __raw_writeb(1 << d->irq, IRQ_MSET);
  37. }
  38. static struct irq_chip ebsa110_irq_chip = {
  39. .irq_ack = ebsa110_mask_irq,
  40. .irq_mask = ebsa110_mask_irq,
  41. .irq_unmask = ebsa110_unmask_irq,
  42. };
  43. static void __init ebsa110_init_irq(void)
  44. {
  45. unsigned long flags;
  46. unsigned int irq;
  47. local_irq_save(flags);
  48. __raw_writeb(0xff, IRQ_MCLR);
  49. __raw_writeb(0x55, IRQ_MSET);
  50. __raw_writeb(0x00, IRQ_MSET);
  51. if (__raw_readb(IRQ_MASK) != 0x55)
  52. while (1);
  53. __raw_writeb(0xff, IRQ_MCLR); /* clear all interrupt enables */
  54. local_irq_restore(flags);
  55. for (irq = 0; irq < NR_IRQS; irq++) {
  56. irq_set_chip_and_handler(irq, &ebsa110_irq_chip,
  57. handle_level_irq);
  58. irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE);
  59. }
  60. }
  61. static struct map_desc ebsa110_io_desc[] __initdata = {
  62. /*
  63. * sparse external-decode ISAIO space
  64. */
  65. { /* IRQ_STAT/IRQ_MCLR */
  66. .virtual = (unsigned long)IRQ_STAT,
  67. .pfn = __phys_to_pfn(TRICK4_PHYS),
  68. .length = TRICK4_SIZE,
  69. .type = MT_DEVICE
  70. }, { /* IRQ_MASK/IRQ_MSET */
  71. .virtual = (unsigned long)IRQ_MASK,
  72. .pfn = __phys_to_pfn(TRICK3_PHYS),
  73. .length = TRICK3_SIZE,
  74. .type = MT_DEVICE
  75. }, { /* SOFT_BASE */
  76. .virtual = (unsigned long)SOFT_BASE,
  77. .pfn = __phys_to_pfn(TRICK1_PHYS),
  78. .length = TRICK1_SIZE,
  79. .type = MT_DEVICE
  80. }, { /* PIT_BASE */
  81. .virtual = (unsigned long)PIT_BASE,
  82. .pfn = __phys_to_pfn(TRICK0_PHYS),
  83. .length = TRICK0_SIZE,
  84. .type = MT_DEVICE
  85. },
  86. /*
  87. * self-decode ISAIO space
  88. */
  89. {
  90. .virtual = ISAIO_BASE,
  91. .pfn = __phys_to_pfn(ISAIO_PHYS),
  92. .length = ISAIO_SIZE,
  93. .type = MT_DEVICE
  94. }, {
  95. .virtual = ISAMEM_BASE,
  96. .pfn = __phys_to_pfn(ISAMEM_PHYS),
  97. .length = ISAMEM_SIZE,
  98. .type = MT_DEVICE
  99. }
  100. };
  101. static void __init ebsa110_map_io(void)
  102. {
  103. iotable_init(ebsa110_io_desc, ARRAY_SIZE(ebsa110_io_desc));
  104. }
  105. static void __iomem *ebsa110_ioremap_caller(phys_addr_t cookie, size_t size,
  106. unsigned int flags, void *caller)
  107. {
  108. return (void __iomem *)cookie;
  109. }
  110. static void ebsa110_iounmap(volatile void __iomem *io_addr)
  111. {}
  112. static void __init ebsa110_init_early(void)
  113. {
  114. arch_ioremap_caller = ebsa110_ioremap_caller;
  115. arch_iounmap = ebsa110_iounmap;
  116. }
  117. #define PIT_CTRL (PIT_BASE + 0x0d)
  118. #define PIT_T2 (PIT_BASE + 0x09)
  119. #define PIT_T1 (PIT_BASE + 0x05)
  120. #define PIT_T0 (PIT_BASE + 0x01)
  121. /*
  122. * This is the rate at which your MCLK signal toggles (in Hz)
  123. * This was measured on a 10 digit frequency counter sampling
  124. * over 1 second.
  125. */
  126. #define MCLK 47894000
  127. /*
  128. * This is the rate at which the PIT timers get clocked
  129. */
  130. #define CLKBY7 (MCLK / 7)
  131. /*
  132. * This is the counter value. We tick at 200Hz on this platform.
  133. */
  134. #define COUNT ((CLKBY7 + (HZ / 2)) / HZ)
  135. /*
  136. * Get the time offset from the system PIT. Note that if we have missed an
  137. * interrupt, then the PIT counter will roll over (ie, be negative).
  138. * This actually works out to be convenient.
  139. */
  140. static u32 ebsa110_gettimeoffset(void)
  141. {
  142. unsigned long offset, count;
  143. __raw_writeb(0x40, PIT_CTRL);
  144. count = __raw_readb(PIT_T1);
  145. count |= __raw_readb(PIT_T1) << 8;
  146. /*
  147. * If count > COUNT, make the number negative.
  148. */
  149. if (count > COUNT)
  150. count |= 0xffff0000;
  151. offset = COUNT;
  152. offset -= count;
  153. /*
  154. * `offset' is in units of timer counts. Convert
  155. * offset to units of microseconds.
  156. */
  157. offset = offset * (1000000 / HZ) / COUNT;
  158. return offset * 1000;
  159. }
  160. static irqreturn_t
  161. ebsa110_timer_interrupt(int irq, void *dev_id)
  162. {
  163. u32 count;
  164. /* latch and read timer 1 */
  165. __raw_writeb(0x40, PIT_CTRL);
  166. count = __raw_readb(PIT_T1);
  167. count |= __raw_readb(PIT_T1) << 8;
  168. count += COUNT;
  169. __raw_writeb(count & 0xff, PIT_T1);
  170. __raw_writeb(count >> 8, PIT_T1);
  171. timer_tick();
  172. return IRQ_HANDLED;
  173. }
  174. static struct irqaction ebsa110_timer_irq = {
  175. .name = "EBSA110 Timer Tick",
  176. .flags = IRQF_TIMER | IRQF_IRQPOLL,
  177. .handler = ebsa110_timer_interrupt,
  178. };
  179. /*
  180. * Set up timer interrupt.
  181. */
  182. void __init ebsa110_timer_init(void)
  183. {
  184. arch_gettimeoffset = ebsa110_gettimeoffset;
  185. /*
  186. * Timer 1, mode 2, LSB/MSB
  187. */
  188. __raw_writeb(0x70, PIT_CTRL);
  189. __raw_writeb(COUNT & 0xff, PIT_T1);
  190. __raw_writeb(COUNT >> 8, PIT_T1);
  191. setup_irq(IRQ_EBSA110_TIMER0, &ebsa110_timer_irq);
  192. }
  193. static struct plat_serial8250_port serial_platform_data[] = {
  194. {
  195. .iobase = 0x3f8,
  196. .irq = 1,
  197. .uartclk = 1843200,
  198. .regshift = 0,
  199. .iotype = UPIO_PORT,
  200. .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
  201. },
  202. {
  203. .iobase = 0x2f8,
  204. .irq = 2,
  205. .uartclk = 1843200,
  206. .regshift = 0,
  207. .iotype = UPIO_PORT,
  208. .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
  209. },
  210. { },
  211. };
  212. static struct platform_device serial_device = {
  213. .name = "serial8250",
  214. .id = PLAT8250_DEV_PLATFORM,
  215. .dev = {
  216. .platform_data = serial_platform_data,
  217. },
  218. };
  219. static struct resource am79c961_resources[] = {
  220. {
  221. .start = 0x220,
  222. .end = 0x238,
  223. .flags = IORESOURCE_IO,
  224. }, {
  225. .start = IRQ_EBSA110_ETHERNET,
  226. .end = IRQ_EBSA110_ETHERNET,
  227. .flags = IORESOURCE_IRQ,
  228. },
  229. };
  230. static struct platform_device am79c961_device = {
  231. .name = "am79c961",
  232. .id = -1,
  233. .num_resources = ARRAY_SIZE(am79c961_resources),
  234. .resource = am79c961_resources,
  235. };
  236. static struct platform_device *ebsa110_devices[] = {
  237. &serial_device,
  238. &am79c961_device,
  239. };
  240. /*
  241. * EBSA110 idling methodology:
  242. *
  243. * We can not execute the "wait for interrupt" instruction since that
  244. * will stop our MCLK signal (which provides the clock for the glue
  245. * logic, and therefore the timer interrupt).
  246. *
  247. * Instead, we spin, polling the IRQ_STAT register for the occurrence
  248. * of any interrupt with core clock down to the memory clock.
  249. */
  250. static void ebsa110_idle(void)
  251. {
  252. const char *irq_stat = (char *)0xff000000;
  253. /* disable clock switching */
  254. asm volatile ("mcr p15, 0, ip, c15, c2, 2" : : : "cc");
  255. /* wait for an interrupt to occur */
  256. while (!*irq_stat);
  257. /* enable clock switching */
  258. asm volatile ("mcr p15, 0, ip, c15, c1, 2" : : : "cc");
  259. }
  260. static int __init ebsa110_init(void)
  261. {
  262. arm_pm_idle = ebsa110_idle;
  263. return platform_add_devices(ebsa110_devices, ARRAY_SIZE(ebsa110_devices));
  264. }
  265. arch_initcall(ebsa110_init);
  266. static void ebsa110_restart(enum reboot_mode mode, const char *cmd)
  267. {
  268. soft_restart(0x80000000);
  269. }
  270. MACHINE_START(EBSA110, "EBSA110")
  271. /* Maintainer: Russell King */
  272. .atag_offset = 0x400,
  273. .reserve_lp0 = 1,
  274. .reserve_lp2 = 1,
  275. .map_io = ebsa110_map_io,
  276. .init_early = ebsa110_init_early,
  277. .init_irq = ebsa110_init_irq,
  278. .init_time = ebsa110_timer_init,
  279. .restart = ebsa110_restart,
  280. MACHINE_END