a3458c0e40510c84c189e5db66b1ae513caafff5
[pandora-kernel.git] / arch / mips / alchemy / devboards / db1200 / setup.c
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);