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