diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/sparc/kernel/tadpole.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'arch/sparc/kernel/tadpole.c')
-rw-r--r-- | arch/sparc/kernel/tadpole.c | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/arch/sparc/kernel/tadpole.c b/arch/sparc/kernel/tadpole.c new file mode 100644 index 000000000000..f476a5f4af6a --- /dev/null +++ b/arch/sparc/kernel/tadpole.c | |||
@@ -0,0 +1,126 @@ | |||
1 | /* tadpole.c: Probing for the tadpole clock stopping h/w at boot time. | ||
2 | * | ||
3 | * Copyright (C) 1996 David Redman (djhr@tadpole.co.uk) | ||
4 | */ | ||
5 | |||
6 | #include <linux/string.h> | ||
7 | #include <linux/kernel.h> | ||
8 | #include <linux/sched.h> | ||
9 | #include <linux/init.h> | ||
10 | |||
11 | #include <asm/asi.h> | ||
12 | #include <asm/oplib.h> | ||
13 | #include <asm/io.h> | ||
14 | |||
15 | #define MACIO_SCSI_CSR_ADDR 0x78400000 | ||
16 | #define MACIO_EN_DMA 0x00000200 | ||
17 | #define CLOCK_INIT_DONE 1 | ||
18 | |||
19 | static int clk_state; | ||
20 | static volatile unsigned char *clk_ctrl; | ||
21 | void (*cpu_pwr_save)(void); | ||
22 | |||
23 | static inline unsigned int ldphys(unsigned int addr) | ||
24 | { | ||
25 | unsigned long data; | ||
26 | |||
27 | __asm__ __volatile__("\n\tlda [%1] %2, %0\n\t" : | ||
28 | "=r" (data) : | ||
29 | "r" (addr), "i" (ASI_M_BYPASS)); | ||
30 | return data; | ||
31 | } | ||
32 | |||
33 | static void clk_init(void) | ||
34 | { | ||
35 | __asm__ __volatile__("mov 0x6c, %%g1\n\t" | ||
36 | "mov 0x4c, %%g2\n\t" | ||
37 | "mov 0xdf, %%g3\n\t" | ||
38 | "stb %%g1, [%0+3]\n\t" | ||
39 | "stb %%g2, [%0+3]\n\t" | ||
40 | "stb %%g3, [%0+3]\n\t" : : | ||
41 | "r" (clk_ctrl) : | ||
42 | "g1", "g2", "g3"); | ||
43 | } | ||
44 | |||
45 | static void clk_slow(void) | ||
46 | { | ||
47 | __asm__ __volatile__("mov 0xcc, %%g2\n\t" | ||
48 | "mov 0x4c, %%g3\n\t" | ||
49 | "mov 0xcf, %%g4\n\t" | ||
50 | "mov 0xdf, %%g5\n\t" | ||
51 | "stb %%g2, [%0+3]\n\t" | ||
52 | "stb %%g3, [%0+3]\n\t" | ||
53 | "stb %%g4, [%0+3]\n\t" | ||
54 | "stb %%g5, [%0+3]\n\t" : : | ||
55 | "r" (clk_ctrl) : | ||
56 | "g2", "g3", "g4", "g5"); | ||
57 | } | ||
58 | |||
59 | /* | ||
60 | * Tadpole is guaranteed to be UP, using local_irq_save. | ||
61 | */ | ||
62 | static void tsu_clockstop(void) | ||
63 | { | ||
64 | unsigned int mcsr; | ||
65 | unsigned long flags; | ||
66 | |||
67 | if (!clk_ctrl) | ||
68 | return; | ||
69 | if (!(clk_state & CLOCK_INIT_DONE)) { | ||
70 | local_irq_save(flags); | ||
71 | clk_init(); | ||
72 | clk_state |= CLOCK_INIT_DONE; /* all done */ | ||
73 | local_irq_restore(flags); | ||
74 | return; | ||
75 | } | ||
76 | if (!(clk_ctrl[2] & 1)) | ||
77 | return; /* no speed up yet */ | ||
78 | |||
79 | local_irq_save(flags); | ||
80 | |||
81 | /* if SCSI DMA in progress, don't slow clock */ | ||
82 | mcsr = ldphys(MACIO_SCSI_CSR_ADDR); | ||
83 | if ((mcsr&MACIO_EN_DMA) != 0) { | ||
84 | local_irq_restore(flags); | ||
85 | return; | ||
86 | } | ||
87 | /* TODO... the minimum clock setting ought to increase the | ||
88 | * memory refresh interval.. | ||
89 | */ | ||
90 | clk_slow(); | ||
91 | local_irq_restore(flags); | ||
92 | } | ||
93 | |||
94 | static void swift_clockstop(void) | ||
95 | { | ||
96 | if (!clk_ctrl) | ||
97 | return; | ||
98 | clk_ctrl[0] = 0; | ||
99 | } | ||
100 | |||
101 | void __init clock_stop_probe(void) | ||
102 | { | ||
103 | unsigned int node, clk_nd; | ||
104 | char name[20]; | ||
105 | |||
106 | prom_getstring(prom_root_node, "name", name, sizeof(name)); | ||
107 | if (strncmp(name, "Tadpole", 7)) | ||
108 | return; | ||
109 | node = prom_getchild(prom_root_node); | ||
110 | node = prom_searchsiblings(node, "obio"); | ||
111 | node = prom_getchild(node); | ||
112 | clk_nd = prom_searchsiblings(node, "clk-ctrl"); | ||
113 | if (!clk_nd) | ||
114 | return; | ||
115 | printk("Clock Stopping h/w detected... "); | ||
116 | clk_ctrl = (char *) prom_getint(clk_nd, "address"); | ||
117 | clk_state = 0; | ||
118 | if (name[10] == '\0') { | ||
119 | cpu_pwr_save = tsu_clockstop; | ||
120 | printk("enabled (S3)\n"); | ||
121 | } else if ((name[10] == 'X') || (name[10] == 'G')) { | ||
122 | cpu_pwr_save = swift_clockstop; | ||
123 | printk("enabled (%s)\n",name+7); | ||
124 | } else | ||
125 | printk("disabled %s\n",name+7); | ||
126 | } | ||