aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc/kernel/chmc.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/chmc.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/chmc.c')
-rw-r--r--arch/sparc/kernel/chmc.c863
1 files changed, 863 insertions, 0 deletions
diff --git a/arch/sparc/kernel/chmc.c b/arch/sparc/kernel/chmc.c
new file mode 100644
index 000000000000..3b9f4d6e14a9
--- /dev/null
+++ b/arch/sparc/kernel/chmc.c
@@ -0,0 +1,863 @@
1/* chmc.c: Driver for UltraSPARC-III memory controller.
2 *
3 * Copyright (C) 2001, 2007, 2008 David S. Miller (davem@davemloft.net)
4 */
5
6#include <linux/module.h>
7#include <linux/kernel.h>
8#include <linux/types.h>
9#include <linux/slab.h>
10#include <linux/list.h>
11#include <linux/string.h>
12#include <linux/sched.h>
13#include <linux/smp.h>
14#include <linux/errno.h>
15#include <linux/init.h>
16#include <linux/of.h>
17#include <linux/of_device.h>
18#include <asm/spitfire.h>
19#include <asm/chmctrl.h>
20#include <asm/cpudata.h>
21#include <asm/oplib.h>
22#include <asm/prom.h>
23#include <asm/head.h>
24#include <asm/io.h>
25#include <asm/memctrl.h>
26
27#define DRV_MODULE_NAME "chmc"
28#define PFX DRV_MODULE_NAME ": "
29#define DRV_MODULE_VERSION "0.2"
30
31MODULE_AUTHOR("David S. Miller (davem@davemloft.net)");
32MODULE_DESCRIPTION("UltraSPARC-III memory controller driver");
33MODULE_LICENSE("GPL");
34MODULE_VERSION(DRV_MODULE_VERSION);
35
36static int mc_type;
37#define MC_TYPE_SAFARI 1
38#define MC_TYPE_JBUS 2
39
40static dimm_printer_t us3mc_dimm_printer;
41
42#define CHMCTRL_NDGRPS 2
43#define CHMCTRL_NDIMMS 4
44
45#define CHMC_DIMMS_PER_MC (CHMCTRL_NDGRPS * CHMCTRL_NDIMMS)
46
47/* OBP memory-layout property format. */
48struct chmc_obp_map {
49 unsigned char dimm_map[144];
50 unsigned char pin_map[576];
51};
52
53#define DIMM_LABEL_SZ 8
54
55struct chmc_obp_mem_layout {
56 /* One max 8-byte string label per DIMM. Usually
57 * this matches the label on the motherboard where
58 * that DIMM resides.
59 */
60 char dimm_labels[CHMC_DIMMS_PER_MC][DIMM_LABEL_SZ];
61
62 /* If symmetric use map[0], else it is
63 * asymmetric and map[1] should be used.
64 */
65 char symmetric;
66
67 struct chmc_obp_map map[2];
68};
69
70#define CHMCTRL_NBANKS 4
71
72struct chmc_bank_info {
73 struct chmc *p;
74 int bank_id;
75
76 u64 raw_reg;
77 int valid;
78 int uk;
79 int um;
80 int lk;
81 int lm;
82 int interleave;
83 unsigned long base;
84 unsigned long size;
85};
86
87struct chmc {
88 struct list_head list;
89 int portid;
90
91 struct chmc_obp_mem_layout layout_prop;
92 int layout_size;
93
94 void __iomem *regs;
95
96 u64 timing_control1;
97 u64 timing_control2;
98 u64 timing_control3;
99 u64 timing_control4;
100 u64 memaddr_control;
101
102 struct chmc_bank_info logical_banks[CHMCTRL_NBANKS];
103};
104
105#define JBUSMC_REGS_SIZE 8
106
107#define JB_MC_REG1_DIMM2_BANK3 0x8000000000000000UL
108#define JB_MC_REG1_DIMM1_BANK1 0x4000000000000000UL
109#define JB_MC_REG1_DIMM2_BANK2 0x2000000000000000UL
110#define JB_MC_REG1_DIMM1_BANK0 0x1000000000000000UL
111#define JB_MC_REG1_XOR 0x0000010000000000UL
112#define JB_MC_REG1_ADDR_GEN_2 0x000000e000000000UL
113#define JB_MC_REG1_ADDR_GEN_2_SHIFT 37
114#define JB_MC_REG1_ADDR_GEN_1 0x0000001c00000000UL
115#define JB_MC_REG1_ADDR_GEN_1_SHIFT 34
116#define JB_MC_REG1_INTERLEAVE 0x0000000001800000UL
117#define JB_MC_REG1_INTERLEAVE_SHIFT 23
118#define JB_MC_REG1_DIMM2_PTYPE 0x0000000000200000UL
119#define JB_MC_REG1_DIMM2_PTYPE_SHIFT 21
120#define JB_MC_REG1_DIMM1_PTYPE 0x0000000000100000UL
121#define JB_MC_REG1_DIMM1_PTYPE_SHIFT 20
122
123#define PART_TYPE_X8 0
124#define PART_TYPE_X4 1
125
126#define INTERLEAVE_NONE 0
127#define INTERLEAVE_SAME 1
128#define INTERLEAVE_INTERNAL 2
129#define INTERLEAVE_BOTH 3
130
131#define ADDR_GEN_128MB 0
132#define ADDR_GEN_256MB 1
133#define ADDR_GEN_512MB 2
134#define ADDR_GEN_1GB 3
135
136#define JB_NUM_DIMM_GROUPS 2
137#define JB_NUM_DIMMS_PER_GROUP 2
138#define JB_NUM_DIMMS (JB_NUM_DIMM_GROUPS * JB_NUM_DIMMS_PER_GROUP)
139
140struct jbusmc_obp_map {
141 unsigned char dimm_map[18];
142 unsigned char pin_map[144];
143};
144
145struct jbusmc_obp_mem_layout {
146 /* One max 8-byte string label per DIMM. Usually
147 * this matches the label on the motherboard where
148 * that DIMM resides.
149 */
150 char dimm_labels[JB_NUM_DIMMS][DIMM_LABEL_SZ];
151
152 /* If symmetric use map[0], else it is
153 * asymmetric and map[1] should be used.
154 */
155 char symmetric;
156
157 struct jbusmc_obp_map map;
158
159 char _pad;
160};
161
162struct jbusmc_dimm_group {
163 struct jbusmc *controller;
164 int index;
165 u64 base_addr;
166 u64 size;
167};
168
169struct jbusmc {
170 void __iomem *regs;
171 u64 mc_reg_1;
172 u32 portid;
173 struct jbusmc_obp_mem_layout layout;
174 int layout_len;
175 int num_dimm_groups;
176 struct jbusmc_dimm_group dimm_groups[JB_NUM_DIMM_GROUPS];
177 struct list_head list;
178};
179
180static DEFINE_SPINLOCK(mctrl_list_lock);
181static LIST_HEAD(mctrl_list);
182
183static void mc_list_add(struct list_head *list)
184{
185 spin_lock(&mctrl_list_lock);
186 list_add(list, &mctrl_list);
187 spin_unlock(&mctrl_list_lock);
188}
189
190static void mc_list_del(struct list_head *list)
191{
192 spin_lock(&mctrl_list_lock);
193 list_del_init(list);
194 spin_unlock(&mctrl_list_lock);
195}
196
197#define SYNDROME_MIN -1
198#define SYNDROME_MAX 144
199
200/* Covert syndrome code into the way the bits are positioned
201 * on the bus.
202 */
203static int syndrome_to_qword_code(int syndrome_code)
204{
205 if (syndrome_code < 128)
206 syndrome_code += 16;
207 else if (syndrome_code < 128 + 9)
208 syndrome_code -= (128 - 7);
209 else if (syndrome_code < (128 + 9 + 3))
210 syndrome_code -= (128 + 9 - 4);
211 else
212 syndrome_code -= (128 + 9 + 3);
213 return syndrome_code;
214}
215
216/* All this magic has to do with how a cache line comes over the wire
217 * on Safari and JBUS. A 64-bit line comes over in 1 or more quadword
218 * cycles, each of which transmit ECC/MTAG info as well as the actual
219 * data.
220 */
221#define L2_LINE_SIZE 64
222#define L2_LINE_ADDR_MSK (L2_LINE_SIZE - 1)
223#define QW_PER_LINE 4
224#define QW_BYTES (L2_LINE_SIZE / QW_PER_LINE)
225#define QW_BITS 144
226#define SAFARI_LAST_BIT (576 - 1)
227#define JBUS_LAST_BIT (144 - 1)
228
229static void get_pin_and_dimm_str(int syndrome_code, unsigned long paddr,
230 int *pin_p, char **dimm_str_p, void *_prop,
231 int base_dimm_offset)
232{
233 int qword_code = syndrome_to_qword_code(syndrome_code);
234 int cache_line_offset;
235 int offset_inverse;
236 int dimm_map_index;
237 int map_val;
238
239 if (mc_type == MC_TYPE_JBUS) {
240 struct jbusmc_obp_mem_layout *p = _prop;
241
242 /* JBUS */
243 cache_line_offset = qword_code;
244 offset_inverse = (JBUS_LAST_BIT - cache_line_offset);
245 dimm_map_index = offset_inverse / 8;
246 map_val = p->map.dimm_map[dimm_map_index];
247 map_val = ((map_val >> ((7 - (offset_inverse & 7)))) & 1);
248 *dimm_str_p = p->dimm_labels[base_dimm_offset + map_val];
249 *pin_p = p->map.pin_map[cache_line_offset];
250 } else {
251 struct chmc_obp_mem_layout *p = _prop;
252 struct chmc_obp_map *mp;
253 int qword;
254
255 /* Safari */
256 if (p->symmetric)
257 mp = &p->map[0];
258 else
259 mp = &p->map[1];
260
261 qword = (paddr & L2_LINE_ADDR_MSK) / QW_BYTES;
262 cache_line_offset = ((3 - qword) * QW_BITS) + qword_code;
263 offset_inverse = (SAFARI_LAST_BIT - cache_line_offset);
264 dimm_map_index = offset_inverse >> 2;
265 map_val = mp->dimm_map[dimm_map_index];
266 map_val = ((map_val >> ((3 - (offset_inverse & 3)) << 1)) & 0x3);
267 *dimm_str_p = p->dimm_labels[base_dimm_offset + map_val];
268 *pin_p = mp->pin_map[cache_line_offset];
269 }
270}
271
272static struct jbusmc_dimm_group *jbusmc_find_dimm_group(unsigned long phys_addr)
273{
274 struct jbusmc *p;
275
276 list_for_each_entry(p, &mctrl_list, list) {
277 int i;
278
279 for (i = 0; i < p->num_dimm_groups; i++) {
280 struct jbusmc_dimm_group *dp = &p->dimm_groups[i];
281
282 if (phys_addr < dp->base_addr ||
283 (dp->base_addr + dp->size) <= phys_addr)
284 continue;
285
286 return dp;
287 }
288 }
289 return NULL;
290}
291
292static int jbusmc_print_dimm(int syndrome_code,
293 unsigned long phys_addr,
294 char *buf, int buflen)
295{
296 struct jbusmc_obp_mem_layout *prop;
297 struct jbusmc_dimm_group *dp;
298 struct jbusmc *p;
299 int first_dimm;
300
301 dp = jbusmc_find_dimm_group(phys_addr);
302 if (dp == NULL ||
303 syndrome_code < SYNDROME_MIN ||
304 syndrome_code > SYNDROME_MAX) {
305 buf[0] = '?';
306 buf[1] = '?';
307 buf[2] = '?';
308 buf[3] = '\0';
309 }
310 p = dp->controller;
311 prop = &p->layout;
312
313 first_dimm = dp->index * JB_NUM_DIMMS_PER_GROUP;
314
315 if (syndrome_code != SYNDROME_MIN) {
316 char *dimm_str;
317 int pin;
318
319 get_pin_and_dimm_str(syndrome_code, phys_addr, &pin,
320 &dimm_str, prop, first_dimm);
321 sprintf(buf, "%s, pin %3d", dimm_str, pin);
322 } else {
323 int dimm;
324
325 /* Multi-bit error, we just dump out all the
326 * dimm labels associated with this dimm group.
327 */
328 for (dimm = 0; dimm < JB_NUM_DIMMS_PER_GROUP; dimm++) {
329 sprintf(buf, "%s ",
330 prop->dimm_labels[first_dimm + dimm]);
331 buf += strlen(buf);
332 }
333 }
334
335 return 0;
336}
337
338static u64 __devinit jbusmc_dimm_group_size(u64 base,
339 const struct linux_prom64_registers *mem_regs,
340 int num_mem_regs)
341{
342 u64 max = base + (8UL * 1024 * 1024 * 1024);
343 u64 max_seen = base;
344 int i;
345
346 for (i = 0; i < num_mem_regs; i++) {
347 const struct linux_prom64_registers *ent;
348 u64 this_base;
349 u64 this_end;
350
351 ent = &mem_regs[i];
352 this_base = ent->phys_addr;
353 this_end = this_base + ent->reg_size;
354 if (base < this_base || base >= this_end)
355 continue;
356 if (this_end > max)
357 this_end = max;
358 if (this_end > max_seen)
359 max_seen = this_end;
360 }
361
362 return max_seen - base;
363}
364
365static void __devinit jbusmc_construct_one_dimm_group(struct jbusmc *p,
366 unsigned long index,
367 const struct linux_prom64_registers *mem_regs,
368 int num_mem_regs)
369{
370 struct jbusmc_dimm_group *dp = &p->dimm_groups[index];
371
372 dp->controller = p;
373 dp->index = index;
374
375 dp->base_addr = (p->portid * (64UL * 1024 * 1024 * 1024));
376 dp->base_addr += (index * (8UL * 1024 * 1024 * 1024));
377 dp->size = jbusmc_dimm_group_size(dp->base_addr, mem_regs, num_mem_regs);
378}
379
380static void __devinit jbusmc_construct_dimm_groups(struct jbusmc *p,
381 const struct linux_prom64_registers *mem_regs,
382 int num_mem_regs)
383{
384 if (p->mc_reg_1 & JB_MC_REG1_DIMM1_BANK0) {
385 jbusmc_construct_one_dimm_group(p, 0, mem_regs, num_mem_regs);
386 p->num_dimm_groups++;
387 }
388 if (p->mc_reg_1 & JB_MC_REG1_DIMM2_BANK2) {
389 jbusmc_construct_one_dimm_group(p, 1, mem_regs, num_mem_regs);
390 p->num_dimm_groups++;
391 }
392}
393
394static int __devinit jbusmc_probe(struct of_device *op,
395 const struct of_device_id *match)
396{
397 const struct linux_prom64_registers *mem_regs;
398 struct device_node *mem_node;
399 int err, len, num_mem_regs;
400 struct jbusmc *p;
401 const u32 *prop;
402 const void *ml;
403
404 err = -ENODEV;
405 mem_node = of_find_node_by_path("/memory");
406 if (!mem_node) {
407 printk(KERN_ERR PFX "Cannot find /memory node.\n");
408 goto out;
409 }
410 mem_regs = of_get_property(mem_node, "reg", &len);
411 if (!mem_regs) {
412 printk(KERN_ERR PFX "Cannot get reg property of /memory node.\n");
413 goto out;
414 }
415 num_mem_regs = len / sizeof(*mem_regs);
416
417 err = -ENOMEM;
418 p = kzalloc(sizeof(*p), GFP_KERNEL);
419 if (!p) {
420 printk(KERN_ERR PFX "Cannot allocate struct jbusmc.\n");
421 goto out;
422 }
423
424 INIT_LIST_HEAD(&p->list);
425
426 err = -ENODEV;
427 prop = of_get_property(op->node, "portid", &len);
428 if (!prop || len != 4) {
429 printk(KERN_ERR PFX "Cannot find portid.\n");
430 goto out_free;
431 }
432
433 p->portid = *prop;
434
435 prop = of_get_property(op->node, "memory-control-register-1", &len);
436 if (!prop || len != 8) {
437 printk(KERN_ERR PFX "Cannot get memory control register 1.\n");
438 goto out_free;
439 }
440
441 p->mc_reg_1 = ((u64)prop[0] << 32) | (u64) prop[1];
442
443 err = -ENOMEM;
444 p->regs = of_ioremap(&op->resource[0], 0, JBUSMC_REGS_SIZE, "jbusmc");
445 if (!p->regs) {
446 printk(KERN_ERR PFX "Cannot map jbusmc regs.\n");
447 goto out_free;
448 }
449
450 err = -ENODEV;
451 ml = of_get_property(op->node, "memory-layout", &p->layout_len);
452 if (!ml) {
453 printk(KERN_ERR PFX "Cannot get memory layout property.\n");
454 goto out_iounmap;
455 }
456 if (p->layout_len > sizeof(p->layout)) {
457 printk(KERN_ERR PFX "Unexpected memory-layout size %d\n",
458 p->layout_len);
459 goto out_iounmap;
460 }
461 memcpy(&p->layout, ml, p->layout_len);
462
463 jbusmc_construct_dimm_groups(p, mem_regs, num_mem_regs);
464
465 mc_list_add(&p->list);
466
467 printk(KERN_INFO PFX "UltraSPARC-IIIi memory controller at %s\n",
468 op->node->full_name);
469
470 dev_set_drvdata(&op->dev, p);
471
472 err = 0;
473
474out:
475 return err;
476
477out_iounmap:
478 of_iounmap(&op->resource[0], p->regs, JBUSMC_REGS_SIZE);
479
480out_free:
481 kfree(p);
482 goto out;
483}
484
485/* Does BANK decode PHYS_ADDR? */
486static int chmc_bank_match(struct chmc_bank_info *bp, unsigned long phys_addr)
487{
488 unsigned long upper_bits = (phys_addr & PA_UPPER_BITS) >> PA_UPPER_BITS_SHIFT;
489 unsigned long lower_bits = (phys_addr & PA_LOWER_BITS) >> PA_LOWER_BITS_SHIFT;
490
491 /* Bank must be enabled to match. */
492 if (bp->valid == 0)
493 return 0;
494
495 /* Would BANK match upper bits? */
496 upper_bits ^= bp->um; /* What bits are different? */
497 upper_bits = ~upper_bits; /* Invert. */
498 upper_bits |= bp->uk; /* What bits don't matter for matching? */
499 upper_bits = ~upper_bits; /* Invert. */
500
501 if (upper_bits)
502 return 0;
503
504 /* Would BANK match lower bits? */
505 lower_bits ^= bp->lm; /* What bits are different? */
506 lower_bits = ~lower_bits; /* Invert. */
507 lower_bits |= bp->lk; /* What bits don't matter for matching? */
508 lower_bits = ~lower_bits; /* Invert. */
509
510 if (lower_bits)
511 return 0;
512
513 /* I always knew you'd be the one. */
514 return 1;
515}
516
517/* Given PHYS_ADDR, search memory controller banks for a match. */
518static struct chmc_bank_info *chmc_find_bank(unsigned long phys_addr)
519{
520 struct chmc *p;
521
522 list_for_each_entry(p, &mctrl_list, list) {
523 int bank_no;
524
525 for (bank_no = 0; bank_no < CHMCTRL_NBANKS; bank_no++) {
526 struct chmc_bank_info *bp;
527
528 bp = &p->logical_banks[bank_no];
529 if (chmc_bank_match(bp, phys_addr))
530 return bp;
531 }
532 }
533
534 return NULL;
535}
536
537/* This is the main purpose of this driver. */
538static int chmc_print_dimm(int syndrome_code,
539 unsigned long phys_addr,
540 char *buf, int buflen)
541{
542 struct chmc_bank_info *bp;
543 struct chmc_obp_mem_layout *prop;
544 int bank_in_controller, first_dimm;
545
546 bp = chmc_find_bank(phys_addr);
547 if (bp == NULL ||
548 syndrome_code < SYNDROME_MIN ||
549 syndrome_code > SYNDROME_MAX) {
550 buf[0] = '?';
551 buf[1] = '?';
552 buf[2] = '?';
553 buf[3] = '\0';
554 return 0;
555 }
556
557 prop = &bp->p->layout_prop;
558 bank_in_controller = bp->bank_id & (CHMCTRL_NBANKS - 1);
559 first_dimm = (bank_in_controller & (CHMCTRL_NDGRPS - 1));
560 first_dimm *= CHMCTRL_NDIMMS;
561
562 if (syndrome_code != SYNDROME_MIN) {
563 char *dimm_str;
564 int pin;
565
566 get_pin_and_dimm_str(syndrome_code, phys_addr, &pin,
567 &dimm_str, prop, first_dimm);
568 sprintf(buf, "%s, pin %3d", dimm_str, pin);
569 } else {
570 int dimm;
571
572 /* Multi-bit error, we just dump out all the
573 * dimm labels associated with this bank.
574 */
575 for (dimm = 0; dimm < CHMCTRL_NDIMMS; dimm++) {
576 sprintf(buf, "%s ",
577 prop->dimm_labels[first_dimm + dimm]);
578 buf += strlen(buf);
579 }
580 }
581 return 0;
582}
583
584/* Accessing the registers is slightly complicated. If you want
585 * to get at the memory controller which is on the same processor
586 * the code is executing, you must use special ASI load/store else
587 * you go through the global mapping.
588 */
589static u64 chmc_read_mcreg(struct chmc *p, unsigned long offset)
590{
591 unsigned long ret, this_cpu;
592
593 preempt_disable();
594
595 this_cpu = real_hard_smp_processor_id();
596
597 if (p->portid == this_cpu) {
598 __asm__ __volatile__("ldxa [%1] %2, %0"
599 : "=r" (ret)
600 : "r" (offset), "i" (ASI_MCU_CTRL_REG));
601 } else {
602 __asm__ __volatile__("ldxa [%1] %2, %0"
603 : "=r" (ret)
604 : "r" (p->regs + offset),
605 "i" (ASI_PHYS_BYPASS_EC_E));
606 }
607
608 preempt_enable();
609
610 return ret;
611}
612
613#if 0 /* currently unused */
614static void chmc_write_mcreg(struct chmc *p, unsigned long offset, u64 val)
615{
616 if (p->portid == smp_processor_id()) {
617 __asm__ __volatile__("stxa %0, [%1] %2"
618 : : "r" (val),
619 "r" (offset), "i" (ASI_MCU_CTRL_REG));
620 } else {
621 __asm__ __volatile__("ldxa %0, [%1] %2"
622 : : "r" (val),
623 "r" (p->regs + offset),
624 "i" (ASI_PHYS_BYPASS_EC_E));
625 }
626}
627#endif
628
629static void chmc_interpret_one_decode_reg(struct chmc *p, int which_bank, u64 val)
630{
631 struct chmc_bank_info *bp = &p->logical_banks[which_bank];
632
633 bp->p = p;
634 bp->bank_id = (CHMCTRL_NBANKS * p->portid) + which_bank;
635 bp->raw_reg = val;
636 bp->valid = (val & MEM_DECODE_VALID) >> MEM_DECODE_VALID_SHIFT;
637 bp->uk = (val & MEM_DECODE_UK) >> MEM_DECODE_UK_SHIFT;
638 bp->um = (val & MEM_DECODE_UM) >> MEM_DECODE_UM_SHIFT;
639 bp->lk = (val & MEM_DECODE_LK) >> MEM_DECODE_LK_SHIFT;
640 bp->lm = (val & MEM_DECODE_LM) >> MEM_DECODE_LM_SHIFT;
641
642 bp->base = (bp->um);
643 bp->base &= ~(bp->uk);
644 bp->base <<= PA_UPPER_BITS_SHIFT;
645
646 switch(bp->lk) {
647 case 0xf:
648 default:
649 bp->interleave = 1;
650 break;
651
652 case 0xe:
653 bp->interleave = 2;
654 break;
655
656 case 0xc:
657 bp->interleave = 4;
658 break;
659
660 case 0x8:
661 bp->interleave = 8;
662 break;
663
664 case 0x0:
665 bp->interleave = 16;
666 break;
667 };
668
669 /* UK[10] is reserved, and UK[11] is not set for the SDRAM
670 * bank size definition.
671 */
672 bp->size = (((unsigned long)bp->uk &
673 ((1UL << 10UL) - 1UL)) + 1UL) << PA_UPPER_BITS_SHIFT;
674 bp->size /= bp->interleave;
675}
676
677static void chmc_fetch_decode_regs(struct chmc *p)
678{
679 if (p->layout_size == 0)
680 return;
681
682 chmc_interpret_one_decode_reg(p, 0,
683 chmc_read_mcreg(p, CHMCTRL_DECODE1));
684 chmc_interpret_one_decode_reg(p, 1,
685 chmc_read_mcreg(p, CHMCTRL_DECODE2));
686 chmc_interpret_one_decode_reg(p, 2,
687 chmc_read_mcreg(p, CHMCTRL_DECODE3));
688 chmc_interpret_one_decode_reg(p, 3,
689 chmc_read_mcreg(p, CHMCTRL_DECODE4));
690}
691
692static int __devinit chmc_probe(struct of_device *op,
693 const struct of_device_id *match)
694{
695 struct device_node *dp = op->node;
696 unsigned long ver;
697 const void *pval;
698 int len, portid;
699 struct chmc *p;
700 int err;
701
702 err = -ENODEV;
703 __asm__ ("rdpr %%ver, %0" : "=r" (ver));
704 if ((ver >> 32UL) == __JALAPENO_ID ||
705 (ver >> 32UL) == __SERRANO_ID)
706 goto out;
707
708 portid = of_getintprop_default(dp, "portid", -1);
709 if (portid == -1)
710 goto out;
711
712 pval = of_get_property(dp, "memory-layout", &len);
713 if (pval && len > sizeof(p->layout_prop)) {
714 printk(KERN_ERR PFX "Unexpected memory-layout property "
715 "size %d.\n", len);
716 goto out;
717 }
718
719 err = -ENOMEM;
720 p = kzalloc(sizeof(*p), GFP_KERNEL);
721 if (!p) {
722 printk(KERN_ERR PFX "Could not allocate struct chmc.\n");
723 goto out;
724 }
725
726 p->portid = portid;
727 p->layout_size = len;
728 if (!pval)
729 p->layout_size = 0;
730 else
731 memcpy(&p->layout_prop, pval, len);
732
733 p->regs = of_ioremap(&op->resource[0], 0, 0x48, "chmc");
734 if (!p->regs) {
735 printk(KERN_ERR PFX "Could not map registers.\n");
736 goto out_free;
737 }
738
739 if (p->layout_size != 0UL) {
740 p->timing_control1 = chmc_read_mcreg(p, CHMCTRL_TCTRL1);
741 p->timing_control2 = chmc_read_mcreg(p, CHMCTRL_TCTRL2);
742 p->timing_control3 = chmc_read_mcreg(p, CHMCTRL_TCTRL3);
743 p->timing_control4 = chmc_read_mcreg(p, CHMCTRL_TCTRL4);
744 p->memaddr_control = chmc_read_mcreg(p, CHMCTRL_MACTRL);
745 }
746
747 chmc_fetch_decode_regs(p);
748
749 mc_list_add(&p->list);
750
751 printk(KERN_INFO PFX "UltraSPARC-III memory controller at %s [%s]\n",
752 dp->full_name,
753 (p->layout_size ? "ACTIVE" : "INACTIVE"));
754
755 dev_set_drvdata(&op->dev, p);
756
757 err = 0;
758
759out:
760 return err;
761
762out_free:
763 kfree(p);
764 goto out;
765}
766
767static int __devinit us3mc_probe(struct of_device *op,
768 const struct of_device_id *match)
769{
770 if (mc_type == MC_TYPE_SAFARI)
771 return chmc_probe(op, match);
772 else if (mc_type == MC_TYPE_JBUS)
773 return jbusmc_probe(op, match);
774 return -ENODEV;
775}
776
777static void __devexit chmc_destroy(struct of_device *op, struct chmc *p)
778{
779 list_del(&p->list);
780 of_iounmap(&op->resource[0], p->regs, 0x48);
781 kfree(p);
782}
783
784static void __devexit jbusmc_destroy(struct of_device *op, struct jbusmc *p)
785{
786 mc_list_del(&p->list);
787 of_iounmap(&op->resource[0], p->regs, JBUSMC_REGS_SIZE);
788 kfree(p);
789}
790
791static int __devexit us3mc_remove(struct of_device *op)
792{
793 void *p = dev_get_drvdata(&op->dev);
794
795 if (p) {
796 if (mc_type == MC_TYPE_SAFARI)
797 chmc_destroy(op, p);
798 else if (mc_type == MC_TYPE_JBUS)
799 jbusmc_destroy(op, p);
800 }
801 return 0;
802}
803
804static const struct of_device_id us3mc_match[] = {
805 {
806 .name = "memory-controller",
807 },
808 {},
809};
810MODULE_DEVICE_TABLE(of, us3mc_match);
811
812static struct of_platform_driver us3mc_driver = {
813 .name = "us3mc",
814 .match_table = us3mc_match,
815 .probe = us3mc_probe,
816 .remove = __devexit_p(us3mc_remove),
817};
818
819static inline bool us3mc_platform(void)
820{
821 if (tlb_type == cheetah || tlb_type == cheetah_plus)
822 return true;
823 return false;
824}
825
826static int __init us3mc_init(void)
827{
828 unsigned long ver;
829 int ret;
830
831 if (!us3mc_platform())
832 return -ENODEV;
833
834 __asm__ __volatile__("rdpr %%ver, %0" : "=r" (ver));
835 if ((ver >> 32UL) == __JALAPENO_ID ||
836 (ver >> 32UL) == __SERRANO_ID) {
837 mc_type = MC_TYPE_JBUS;
838 us3mc_dimm_printer = jbusmc_print_dimm;
839 } else {
840 mc_type = MC_TYPE_SAFARI;
841 us3mc_dimm_printer = chmc_print_dimm;
842 }
843
844 ret = register_dimm_printer(us3mc_dimm_printer);
845
846 if (!ret) {
847 ret = of_register_driver(&us3mc_driver, &of_bus_type);
848 if (ret)
849 unregister_dimm_printer(us3mc_dimm_printer);
850 }
851 return ret;
852}
853
854static void __exit us3mc_cleanup(void)
855{
856 if (us3mc_platform()) {
857 unregister_dimm_printer(us3mc_dimm_printer);
858 of_unregister_driver(&us3mc_driver);
859 }
860}
861
862module_init(us3mc_init);
863module_exit(us3mc_cleanup);