diff options
Diffstat (limited to 'arch/mips/alchemy/devboards/db1200/setup.c')
-rw-r--r-- | arch/mips/alchemy/devboards/db1200/setup.c | 137 |
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 | |||
19 | const char *get_system_type(void) | ||
20 | { | ||
21 | return "Alchemy Db1200"; | ||
22 | } | ||
23 | |||
24 | static 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 | |||
30 | void board_reset(void) | ||
31 | { | ||
32 | bcsr_write(BCSR_RESETS, 0); | ||
33 | bcsr_write(BCSR_SYSTEM, 0); | ||
34 | } | ||
35 | |||
36 | void __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 | */ | ||
87 | static 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 | |||
119 | static 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 | } | ||
137 | arch_initcall(db1200_arch_init); | ||