setup.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. /*
  2. * Alchemy/AMD/RMI DB1200 board setup.
  3. *
  4. * Licensed under the terms outlined in the file COPYING in the root of
  5. * this source archive.
  6. */
  7. #include <linux/init.h>
  8. #include <linux/interrupt.h>
  9. #include <linux/io.h>
  10. #include <linux/kernel.h>
  11. #include <linux/pm.h>
  12. #include <asm/mach-au1x00/au1000.h>
  13. #include <asm/mach-db1x00/bcsr.h>
  14. #include <asm/mach-db1x00/db1200.h>
  15. #include <asm/processor.h>
  16. #include <asm/reboot.h>
  17. const char *get_system_type(void)
  18. {
  19. return "Alchemy Db1200";
  20. }
  21. static void board_power_off(void)
  22. {
  23. bcsr_write(BCSR_RESETS, 0);
  24. bcsr_write(BCSR_SYSTEM, BCSR_SYSTEM_PWROFF | BCSR_SYSTEM_RESET);
  25. }
  26. void board_reset(void)
  27. {
  28. bcsr_write(BCSR_RESETS, 0);
  29. bcsr_write(BCSR_SYSTEM, 0);
  30. }
  31. void __init board_setup(void)
  32. {
  33. unsigned long freq0, clksrc, div, pfc;
  34. unsigned short whoami;
  35. bcsr_init(DB1200_BCSR_PHYS_ADDR,
  36. DB1200_BCSR_PHYS_ADDR + DB1200_BCSR_HEXLED_OFS);
  37. whoami = bcsr_read(BCSR_WHOAMI);
  38. printk(KERN_INFO "Alchemy/AMD/RMI DB1200 Board, CPLD Rev %d"
  39. " Board-ID %d Daughtercard ID %d\n",
  40. (whoami >> 4) & 0xf, (whoami >> 8) & 0xf, whoami & 0xf);
  41. /* SMBus/SPI on PSC0, Audio on PSC1 */
  42. pfc = __raw_readl((void __iomem *)SYS_PINFUNC);
  43. pfc &= ~(SYS_PINFUNC_P0A | SYS_PINFUNC_P0B);
  44. pfc &= ~(SYS_PINFUNC_P1A | SYS_PINFUNC_P1B | SYS_PINFUNC_FS3);
  45. pfc |= SYS_PINFUNC_P1C; /* SPI is configured later */
  46. __raw_writel(pfc, (void __iomem *)SYS_PINFUNC);
  47. wmb();
  48. /* Clock configurations: PSC0: ~50MHz via Clkgen0, derived from
  49. * CPU clock; all other clock generators off/unused.
  50. */
  51. div = (get_au1x00_speed() + 25000000) / 50000000;
  52. if (div & 1)
  53. div++;
  54. div = ((div >> 1) - 1) & 0xff;
  55. freq0 = div << SYS_FC_FRDIV0_BIT;
  56. __raw_writel(freq0, (void __iomem *)SYS_FREQCTRL0);
  57. wmb();
  58. freq0 |= SYS_FC_FE0; /* enable F0 */
  59. __raw_writel(freq0, (void __iomem *)SYS_FREQCTRL0);
  60. wmb();
  61. /* psc0_intclk comes 1:1 from F0 */
  62. clksrc = SYS_CS_MUX_FQ0 << SYS_CS_ME0_BIT;
  63. __raw_writel(clksrc, (void __iomem *)SYS_CLKSRC);
  64. wmb();
  65. pm_power_off = board_power_off;
  66. _machine_halt = board_power_off;
  67. _machine_restart = (void(*)(char *))board_reset;
  68. }
  69. /* use the hexleds to count the number of times the cpu has entered
  70. * wait, the dots to indicate whether the CPU is currently idle or
  71. * active (dots off = sleeping, dots on = working) for cases where
  72. * the number doesn't change for a long(er) period of time.
  73. */
  74. static void db1200_wait(void)
  75. {
  76. __asm__(" .set push \n"
  77. " .set mips3 \n"
  78. " .set noreorder \n"
  79. " cache 0x14, 0(%0) \n"
  80. " cache 0x14, 32(%0) \n"
  81. " cache 0x14, 64(%0) \n"
  82. /* dots off: we're about to call wait */
  83. " lui $26, 0xb980 \n"
  84. " ori $27, $0, 3 \n"
  85. " sb $27, 0x18($26) \n"
  86. " sync \n"
  87. " nop \n"
  88. " wait \n"
  89. " nop \n"
  90. " nop \n"
  91. " nop \n"
  92. " nop \n"
  93. " nop \n"
  94. /* dots on: there's work to do, increment cntr */
  95. " lui $26, 0xb980 \n"
  96. " sb $0, 0x18($26) \n"
  97. " lui $26, 0xb9c0 \n"
  98. " lb $27, 0($26) \n"
  99. " addiu $27, $27, 1 \n"
  100. " sb $27, 0($26) \n"
  101. " sync \n"
  102. " .set pop \n"
  103. : : "r" (db1200_wait));
  104. }
  105. static int __init db1200_arch_init(void)
  106. {
  107. /* GPIO7 is low-level triggered CPLD cascade */
  108. set_irq_type(AU1200_GPIO7_INT, IRQF_TRIGGER_LOW);
  109. bcsr_init_irq(DB1200_INT_BEGIN, DB1200_INT_END, AU1200_GPIO7_INT);
  110. /* do not autoenable these: CPLD has broken edge int handling,
  111. * and the CD handler setup requires manual enabling to work
  112. * around that.
  113. */
  114. irq_to_desc(DB1200_SD0_INSERT_INT)->status |= IRQ_NOAUTOEN;
  115. irq_to_desc(DB1200_SD0_EJECT_INT)->status |= IRQ_NOAUTOEN;
  116. if (cpu_wait)
  117. cpu_wait = db1200_wait;
  118. return 0;
  119. }
  120. arch_initcall(db1200_arch_init);