Blame view

arch/sparc/kernel/central.c 6.03 KB
d979f1792   David S. Miller   [SPARC64]: __inli...
1
  /* central.c: Central FHC driver for Sunfire/Starfire/Wildfire.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
   *
b69416b51   David S. Miller   sparc64: Rewrite ...
3
   * Copyright (C) 1997, 1999, 2008 David S. Miller (davem@davemloft.net)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4
5
6
7
   */
  
  #include <linux/kernel.h>
  #include <linux/types.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
8
  #include <linux/slab.h>
7b64db608   Paul Gortmaker   sparc: add export...
9
  #include <linux/export.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
10
  #include <linux/string.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
11
  #include <linux/init.h>
b69416b51   David S. Miller   sparc64: Rewrite ...
12
13
  #include <linux/of_device.h>
  #include <linux/platform_device.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
14

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
15
  #include <asm/fhc.h>
b69416b51   David S. Miller   sparc64: Rewrite ...
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
  #include <asm/upa.h>
  
  struct clock_board {
  	void __iomem		*clock_freq_regs;
  	void __iomem		*clock_regs;
  	void __iomem		*clock_ver_reg;
  	int			num_slots;
  	struct resource		leds_resource;
  	struct platform_device	leds_pdev;
  };
  
  struct fhc {
  	void __iomem		*pregs;
  	bool			central;
  	bool			jtag_master;
  	int			board_num;
  	struct resource		leds_resource;
  	struct platform_device	leds_pdev;
  };
  
  static int __devinit clock_board_calc_nslots(struct clock_board *p)
  {
  	u8 reg = upa_readb(p->clock_regs + CLOCK_STAT1) & 0xc0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
39

b69416b51   David S. Miller   sparc64: Rewrite ...
40
41
42
  	switch (reg) {
  	case 0x40:
  		return 16;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
43

b69416b51   David S. Miller   sparc64: Rewrite ...
44
45
  	case 0xc0:
  		return 8;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
46

b69416b51   David S. Miller   sparc64: Rewrite ...
47
48
49
50
51
52
53
54
55
56
57
58
59
  	case 0x80:
  		reg = 0;
  		if (p->clock_ver_reg)
  			reg = upa_readb(p->clock_ver_reg);
  		if (reg) {
  			if (reg & 0x80)
  				return 4;
  			else
  				return 5;
  		}
  		/* Fallthrough */
  	default:
  		return 4;
cecc4e922   David S. Miller   [SPARC64]: Conver...
60
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
61
  }
4ebb24f70   Grant Likely   dt/sparc: Elimina...
62
  static int __devinit clock_board_probe(struct platform_device *op)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
63
  {
b69416b51   David S. Miller   sparc64: Rewrite ...
64
65
  	struct clock_board *p = kzalloc(sizeof(*p), GFP_KERNEL);
  	int err = -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
66

b69416b51   David S. Miller   sparc64: Rewrite ...
67
68
69
70
  	if (!p) {
  		printk(KERN_ERR "clock_board: Cannot allocate struct clock_board
  ");
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
71
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
72

b69416b51   David S. Miller   sparc64: Rewrite ...
73
74
75
76
77
78
79
80
  	p->clock_freq_regs = of_ioremap(&op->resource[0], 0,
  					resource_size(&op->resource[0]),
  					"clock_board_freq");
  	if (!p->clock_freq_regs) {
  		printk(KERN_ERR "clock_board: Cannot map clock_freq_regs
  ");
  		goto out_free;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
81

b69416b51   David S. Miller   sparc64: Rewrite ...
82
83
84
85
86
87
88
89
  	p->clock_regs = of_ioremap(&op->resource[1], 0,
  				   resource_size(&op->resource[1]),
  				   "clock_board_regs");
  	if (!p->clock_regs) {
  		printk(KERN_ERR "clock_board: Cannot map clock_regs
  ");
  		goto out_unmap_clock_freq_regs;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
90

b69416b51   David S. Miller   sparc64: Rewrite ...
91
92
93
94
95
96
97
98
99
100
  	if (op->resource[2].flags) {
  		p->clock_ver_reg = of_ioremap(&op->resource[2], 0,
  					      resource_size(&op->resource[2]),
  					      "clock_ver_reg");
  		if (!p->clock_ver_reg) {
  			printk(KERN_ERR "clock_board: Cannot map clock_ver_reg
  ");
  			goto out_unmap_clock_regs;
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
101

b69416b51   David S. Miller   sparc64: Rewrite ...
102
  	p->num_slots = clock_board_calc_nslots(p);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
103

b69416b51   David S. Miller   sparc64: Rewrite ...
104
105
  	p->leds_resource.start = (unsigned long)
  		(p->clock_regs + CLOCK_CTRL);
093171465   Roel Kluin   sparc: leds_resou...
106
  	p->leds_resource.end = p->leds_resource.start;
b69416b51   David S. Miller   sparc64: Rewrite ...
107
  	p->leds_resource.name = "leds";
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
108

b69416b51   David S. Miller   sparc64: Rewrite ...
109
  	p->leds_pdev.name = "sunfire-clockboard-leds";
b7c18c1b2   David S. Miller   sparc64: Initiali...
110
  	p->leds_pdev.id = -1;
b69416b51   David S. Miller   sparc64: Rewrite ...
111
112
113
  	p->leds_pdev.resource = &p->leds_resource;
  	p->leds_pdev.num_resources = 1;
  	p->leds_pdev.dev.parent = &op->dev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
114

b69416b51   David S. Miller   sparc64: Rewrite ...
115
116
117
118
119
120
  	err = platform_device_register(&p->leds_pdev);
  	if (err) {
  		printk(KERN_ERR "clock_board: Could not register LEDS "
  		       "platform device
  ");
  		goto out_unmap_clock_ver_reg;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
121
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
122

b69416b51   David S. Miller   sparc64: Rewrite ...
123
124
125
  	printk(KERN_INFO "clock_board: Detected %d slot Enterprise system.
  ",
  	       p->num_slots);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
126

b69416b51   David S. Miller   sparc64: Rewrite ...
127
128
129
  	err = 0;
  out:
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
130

b69416b51   David S. Miller   sparc64: Rewrite ...
131
132
133
134
  out_unmap_clock_ver_reg:
  	if (p->clock_ver_reg)
  		of_iounmap(&op->resource[2], p->clock_ver_reg,
  			   resource_size(&op->resource[2]));
cecc4e922   David S. Miller   [SPARC64]: Conver...
135

b69416b51   David S. Miller   sparc64: Rewrite ...
136
137
138
  out_unmap_clock_regs:
  	of_iounmap(&op->resource[1], p->clock_regs,
  		   resource_size(&op->resource[1]));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
139

b69416b51   David S. Miller   sparc64: Rewrite ...
140
141
142
  out_unmap_clock_freq_regs:
  	of_iounmap(&op->resource[0], p->clock_freq_regs,
  		   resource_size(&op->resource[0]));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
143

b69416b51   David S. Miller   sparc64: Rewrite ...
144
145
146
  out_free:
  	kfree(p);
  	goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
147
  }
3628aa065   David S. Miller   sparc64: Fix sect...
148
  static const struct of_device_id clock_board_match[] = {
b69416b51   David S. Miller   sparc64: Rewrite ...
149
150
151
152
153
  	{
  		.name = "clock-board",
  	},
  	{},
  };
4ebb24f70   Grant Likely   dt/sparc: Elimina...
154
  static struct platform_driver clock_board_driver = {
b69416b51   David S. Miller   sparc64: Rewrite ...
155
  	.probe		= clock_board_probe,
4018294b5   Grant Likely   of: Remove duplic...
156
157
158
159
  	.driver = {
  		.name = "clock_board",
  		.owner = THIS_MODULE,
  		.of_match_table = clock_board_match,
b69416b51   David S. Miller   sparc64: Rewrite ...
160
161
  	},
  };
4ebb24f70   Grant Likely   dt/sparc: Elimina...
162
  static int __devinit fhc_probe(struct platform_device *op)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
163
  {
b69416b51   David S. Miller   sparc64: Rewrite ...
164
165
166
  	struct fhc *p = kzalloc(sizeof(*p), GFP_KERNEL);
  	int err = -ENOMEM;
  	u32 reg;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
167

b69416b51   David S. Miller   sparc64: Rewrite ...
168
169
170
171
  	if (!p) {
  		printk(KERN_ERR "fhc: Cannot allocate struct fhc
  ");
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
172
  	}
61c7a080a   Grant Likely   of: Always use 's...
173
  	if (!strcmp(op->dev.of_node->parent->name, "central"))
b69416b51   David S. Miller   sparc64: Rewrite ...
174
  		p->central = true;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
175

b69416b51   David S. Miller   sparc64: Rewrite ...
176
177
178
179
180
181
182
  	p->pregs = of_ioremap(&op->resource[0], 0,
  			      resource_size(&op->resource[0]),
  			      "fhc_pregs");
  	if (!p->pregs) {
  		printk(KERN_ERR "fhc: Cannot map pregs
  ");
  		goto out_free;
cecc4e922   David S. Miller   [SPARC64]: Conver...
183
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
184

b69416b51   David S. Miller   sparc64: Rewrite ...
185
186
187
188
  	if (p->central) {
  		reg = upa_readl(p->pregs + FHC_PREGS_BSR);
  		p->board_num = ((reg >> 16) & 1) | ((reg >> 12) & 0x0e);
  	} else {
61c7a080a   Grant Likely   of: Always use 's...
189
  		p->board_num = of_getintprop_default(op->dev.of_node, "board#", -1);
b69416b51   David S. Miller   sparc64: Rewrite ...
190
191
192
193
194
195
196
197
  		if (p->board_num == -1) {
  			printk(KERN_ERR "fhc: No board# property
  ");
  			goto out_unmap_pregs;
  		}
  		if (upa_readl(p->pregs + FHC_PREGS_JCTRL) & FHC_JTAG_CTRL_MENAB)
  			p->jtag_master = true;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
198

b69416b51   David S. Miller   sparc64: Rewrite ...
199
200
201
  	if (!p->central) {
  		p->leds_resource.start = (unsigned long)
  			(p->pregs + FHC_PREGS_CTRL);
093171465   Roel Kluin   sparc: leds_resou...
202
  		p->leds_resource.end = p->leds_resource.start;
b69416b51   David S. Miller   sparc64: Rewrite ...
203
204
205
  		p->leds_resource.name = "leds";
  
  		p->leds_pdev.name = "sunfire-fhc-leds";
b7c18c1b2   David S. Miller   sparc64: Initiali...
206
  		p->leds_pdev.id = p->board_num;
b69416b51   David S. Miller   sparc64: Rewrite ...
207
208
209
210
211
212
213
214
215
216
217
218
219
  		p->leds_pdev.resource = &p->leds_resource;
  		p->leds_pdev.num_resources = 1;
  		p->leds_pdev.dev.parent = &op->dev;
  
  		err = platform_device_register(&p->leds_pdev);
  		if (err) {
  			printk(KERN_ERR "fhc: Could not register LEDS "
  			       "platform device
  ");
  			goto out_unmap_pregs;
  		}
  	}
  	reg = upa_readl(p->pregs + FHC_PREGS_CTRL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
220

b69416b51   David S. Miller   sparc64: Rewrite ...
221
222
  	if (!p->central)
  		reg |= FHC_CONTROL_IXIST;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
223

b69416b51   David S. Miller   sparc64: Rewrite ...
224
225
226
  	reg &= ~(FHC_CONTROL_AOFF |
  		 FHC_CONTROL_BOFF |
  		 FHC_CONTROL_SLINE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
227

b69416b51   David S. Miller   sparc64: Rewrite ...
228
229
  	upa_writel(reg, p->pregs + FHC_PREGS_CTRL);
  	upa_readl(p->pregs + FHC_PREGS_CTRL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
230

b69416b51   David S. Miller   sparc64: Rewrite ...
231
232
233
234
235
236
237
238
239
240
  	reg = upa_readl(p->pregs + FHC_PREGS_ID);
  	printk(KERN_INFO "fhc: Board #%d, Version[%x] PartID[%x] Manuf[%x] %s
  ",
  	       p->board_num,
  	       (reg & FHC_ID_VERS) >> 28,
  	       (reg & FHC_ID_PARTID) >> 12,
  	       (reg & FHC_ID_MANUF) >> 1,
  	       (p->jtag_master ?
  		"(JTAG Master)" :
  		(p->central ? "(Central)" : "")));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
241

b69416b51   David S. Miller   sparc64: Rewrite ...
242
  	err = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
243

b69416b51   David S. Miller   sparc64: Rewrite ...
244
245
  out:
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
246

b69416b51   David S. Miller   sparc64: Rewrite ...
247
248
  out_unmap_pregs:
  	of_iounmap(&op->resource[0], p->pregs, resource_size(&op->resource[0]));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
249

b69416b51   David S. Miller   sparc64: Rewrite ...
250
251
252
  out_free:
  	kfree(p);
  	goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
253
  }
3628aa065   David S. Miller   sparc64: Fix sect...
254
  static const struct of_device_id fhc_match[] = {
b69416b51   David S. Miller   sparc64: Rewrite ...
255
256
257
258
259
  	{
  		.name = "fhc",
  	},
  	{},
  };
4ebb24f70   Grant Likely   dt/sparc: Elimina...
260
  static struct platform_driver fhc_driver = {
b69416b51   David S. Miller   sparc64: Rewrite ...
261
  	.probe		= fhc_probe,
4018294b5   Grant Likely   of: Remove duplic...
262
263
264
265
  	.driver = {
  		.name = "fhc",
  		.owner = THIS_MODULE,
  		.of_match_table = fhc_match,
b69416b51   David S. Miller   sparc64: Rewrite ...
266
267
268
269
  	},
  };
  
  static int __init sunfire_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
270
  {
4ebb24f70   Grant Likely   dt/sparc: Elimina...
271
272
  	(void) platform_driver_register(&fhc_driver);
  	(void) platform_driver_register(&clock_board_driver);
b69416b51   David S. Miller   sparc64: Rewrite ...
273
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
274
  }
b69416b51   David S. Miller   sparc64: Rewrite ...
275
276
  
  subsys_initcall(sunfire_init);