aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc/kernel/central.c
diff options
context:
space:
mode:
authorSam Ravnborg <sam@ravnborg.org>2008-12-03 06:11:52 -0500
committerDavid S. Miller <davem@davemloft.net>2008-12-04 12:17:21 -0500
commita88b5ba8bd8ac18aad65ee6c6a254e2e74876db3 (patch)
treeeb3d0ffaf53c3f7ec6083752c2097cecd1cb892a /arch/sparc/kernel/central.c
parentd670bd4f803c8b646acd20f3ba21e65458293faf (diff)
sparc,sparc64: unify kernel/
o Move all files from sparc64/kernel/ to sparc/kernel - rename as appropriate o Update sparc/Makefile to the changes o Update sparc/kernel/Makefile to include the sparc64 files NOTE: This commit changes link order on sparc64! Link order had to change for either of sparc32 and sparc64. And assuming sparc64 see more testing than sparc32 change link order on sparc64 where issues will be caught faster. Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc/kernel/central.c')
-rw-r--r--arch/sparc/kernel/central.c268
1 files changed, 268 insertions, 0 deletions
diff --git a/arch/sparc/kernel/central.c b/arch/sparc/kernel/central.c
new file mode 100644
index 000000000000..05f1c916db06
--- /dev/null
+++ b/arch/sparc/kernel/central.c
@@ -0,0 +1,268 @@
1/* central.c: Central FHC driver for Sunfire/Starfire/Wildfire.
2 *
3 * Copyright (C) 1997, 1999, 2008 David S. Miller (davem@davemloft.net)
4 */
5
6#include <linux/kernel.h>
7#include <linux/types.h>
8#include <linux/string.h>
9#include <linux/init.h>
10#include <linux/of_device.h>
11#include <linux/platform_device.h>
12
13#include <asm/fhc.h>
14#include <asm/upa.h>
15
16struct clock_board {
17 void __iomem *clock_freq_regs;
18 void __iomem *clock_regs;
19 void __iomem *clock_ver_reg;
20 int num_slots;
21 struct resource leds_resource;
22 struct platform_device leds_pdev;
23};
24
25struct fhc {
26 void __iomem *pregs;
27 bool central;
28 bool jtag_master;
29 int board_num;
30 struct resource leds_resource;
31 struct platform_device leds_pdev;
32};
33
34static int __devinit clock_board_calc_nslots(struct clock_board *p)
35{
36 u8 reg = upa_readb(p->clock_regs + CLOCK_STAT1) & 0xc0;
37
38 switch (reg) {
39 case 0x40:
40 return 16;
41
42 case 0xc0:
43 return 8;
44
45 case 0x80:
46 reg = 0;
47 if (p->clock_ver_reg)
48 reg = upa_readb(p->clock_ver_reg);
49 if (reg) {
50 if (reg & 0x80)
51 return 4;
52 else
53 return 5;
54 }
55 /* Fallthrough */
56 default:
57 return 4;
58 }
59}
60
61static int __devinit clock_board_probe(struct of_device *op,
62 const struct of_device_id *match)
63{
64 struct clock_board *p = kzalloc(sizeof(*p), GFP_KERNEL);
65 int err = -ENOMEM;
66
67 if (!p) {
68 printk(KERN_ERR "clock_board: Cannot allocate struct clock_board\n");
69 goto out;
70 }
71
72 p->clock_freq_regs = of_ioremap(&op->resource[0], 0,
73 resource_size(&op->resource[0]),
74 "clock_board_freq");
75 if (!p->clock_freq_regs) {
76 printk(KERN_ERR "clock_board: Cannot map clock_freq_regs\n");
77 goto out_free;
78 }
79
80 p->clock_regs = of_ioremap(&op->resource[1], 0,
81 resource_size(&op->resource[1]),
82 "clock_board_regs");
83 if (!p->clock_regs) {
84 printk(KERN_ERR "clock_board: Cannot map clock_regs\n");
85 goto out_unmap_clock_freq_regs;
86 }
87
88 if (op->resource[2].flags) {
89 p->clock_ver_reg = of_ioremap(&op->resource[2], 0,
90 resource_size(&op->resource[2]),
91 "clock_ver_reg");
92 if (!p->clock_ver_reg) {
93 printk(KERN_ERR "clock_board: Cannot map clock_ver_reg\n");
94 goto out_unmap_clock_regs;
95 }
96 }
97
98 p->num_slots = clock_board_calc_nslots(p);
99
100 p->leds_resource.start = (unsigned long)
101 (p->clock_regs + CLOCK_CTRL);
102 p->leds_resource.end = p->leds_resource.end;
103 p->leds_resource.name = "leds";
104
105 p->leds_pdev.name = "sunfire-clockboard-leds";
106 p->leds_pdev.resource = &p->leds_resource;
107 p->leds_pdev.num_resources = 1;
108 p->leds_pdev.dev.parent = &op->dev;
109
110 err = platform_device_register(&p->leds_pdev);
111 if (err) {
112 printk(KERN_ERR "clock_board: Could not register LEDS "
113 "platform device\n");
114 goto out_unmap_clock_ver_reg;
115 }
116
117 printk(KERN_INFO "clock_board: Detected %d slot Enterprise system.\n",
118 p->num_slots);
119
120 err = 0;
121out:
122 return err;
123
124out_unmap_clock_ver_reg:
125 if (p->clock_ver_reg)
126 of_iounmap(&op->resource[2], p->clock_ver_reg,
127 resource_size(&op->resource[2]));
128
129out_unmap_clock_regs:
130 of_iounmap(&op->resource[1], p->clock_regs,
131 resource_size(&op->resource[1]));
132
133out_unmap_clock_freq_regs:
134 of_iounmap(&op->resource[0], p->clock_freq_regs,
135 resource_size(&op->resource[0]));
136
137out_free:
138 kfree(p);
139 goto out;
140}
141
142static struct of_device_id __initdata clock_board_match[] = {
143 {
144 .name = "clock-board",
145 },
146 {},
147};
148
149static struct of_platform_driver clock_board_driver = {
150 .match_table = clock_board_match,
151 .probe = clock_board_probe,
152 .driver = {
153 .name = "clock_board",
154 },
155};
156
157static int __devinit fhc_probe(struct of_device *op,
158 const struct of_device_id *match)
159{
160 struct fhc *p = kzalloc(sizeof(*p), GFP_KERNEL);
161 int err = -ENOMEM;
162 u32 reg;
163
164 if (!p) {
165 printk(KERN_ERR "fhc: Cannot allocate struct fhc\n");
166 goto out;
167 }
168
169 if (!strcmp(op->node->parent->name, "central"))
170 p->central = true;
171
172 p->pregs = of_ioremap(&op->resource[0], 0,
173 resource_size(&op->resource[0]),
174 "fhc_pregs");
175 if (!p->pregs) {
176 printk(KERN_ERR "fhc: Cannot map pregs\n");
177 goto out_free;
178 }
179
180 if (p->central) {
181 reg = upa_readl(p->pregs + FHC_PREGS_BSR);
182 p->board_num = ((reg >> 16) & 1) | ((reg >> 12) & 0x0e);
183 } else {
184 p->board_num = of_getintprop_default(op->node, "board#", -1);
185 if (p->board_num == -1) {
186 printk(KERN_ERR "fhc: No board# property\n");
187 goto out_unmap_pregs;
188 }
189 if (upa_readl(p->pregs + FHC_PREGS_JCTRL) & FHC_JTAG_CTRL_MENAB)
190 p->jtag_master = true;
191 }
192
193 if (!p->central) {
194 p->leds_resource.start = (unsigned long)
195 (p->pregs + FHC_PREGS_CTRL);
196 p->leds_resource.end = p->leds_resource.end;
197 p->leds_resource.name = "leds";
198
199 p->leds_pdev.name = "sunfire-fhc-leds";
200 p->leds_pdev.resource = &p->leds_resource;
201 p->leds_pdev.num_resources = 1;
202 p->leds_pdev.dev.parent = &op->dev;
203
204 err = platform_device_register(&p->leds_pdev);
205 if (err) {
206 printk(KERN_ERR "fhc: Could not register LEDS "
207 "platform device\n");
208 goto out_unmap_pregs;
209 }
210 }
211 reg = upa_readl(p->pregs + FHC_PREGS_CTRL);
212
213 if (!p->central)
214 reg |= FHC_CONTROL_IXIST;
215
216 reg &= ~(FHC_CONTROL_AOFF |
217 FHC_CONTROL_BOFF |
218 FHC_CONTROL_SLINE);
219
220 upa_writel(reg, p->pregs + FHC_PREGS_CTRL);
221 upa_readl(p->pregs + FHC_PREGS_CTRL);
222
223 reg = upa_readl(p->pregs + FHC_PREGS_ID);
224 printk(KERN_INFO "fhc: Board #%d, Version[%x] PartID[%x] Manuf[%x] %s\n",
225 p->board_num,
226 (reg & FHC_ID_VERS) >> 28,
227 (reg & FHC_ID_PARTID) >> 12,
228 (reg & FHC_ID_MANUF) >> 1,
229 (p->jtag_master ?
230 "(JTAG Master)" :
231 (p->central ? "(Central)" : "")));
232
233 err = 0;
234
235out:
236 return err;
237
238out_unmap_pregs:
239 of_iounmap(&op->resource[0], p->pregs, resource_size(&op->resource[0]));
240
241out_free:
242 kfree(p);
243 goto out;
244}
245
246static struct of_device_id __initdata fhc_match[] = {
247 {
248 .name = "fhc",
249 },
250 {},
251};
252
253static struct of_platform_driver fhc_driver = {
254 .match_table = fhc_match,
255 .probe = fhc_probe,
256 .driver = {
257 .name = "fhc",
258 },
259};
260
261static int __init sunfire_init(void)
262{
263 (void) of_register_driver(&fhc_driver, &of_platform_bus_type);
264 (void) of_register_driver(&clock_board_driver, &of_platform_bus_type);
265 return 0;
266}
267
268subsys_initcall(sunfire_init);