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>
14 #include <linux/errno.h>
21 #include <asm/oplib.h>
27 #define DRV_MODULE_NAME "chmc"
28 #define PFX DRV_MODULE_NAME ": "
29 #define DRV_MODULE_VERSION "0.2"
37 #define MC_TYPE_SAFARI 1
38 #define MC_TYPE_JBUS 2
42 #define CHMCTRL_NDGRPS 2
43 #define CHMCTRL_NDIMMS 4
45 #define CHMC_DIMMS_PER_MC (CHMCTRL_NDGRPS * CHMCTRL_NDIMMS)
53 #define DIMM_LABEL_SZ 8
70 #define CHMCTRL_NBANKS 4
105 #define JBUSMC_REGS_SIZE 8
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
123 #define PART_TYPE_X8 0
124 #define PART_TYPE_X4 1
126 #define INTERLEAVE_NONE 0
127 #define INTERLEAVE_SAME 1
128 #define INTERLEAVE_INTERNAL 2
129 #define INTERLEAVE_BOTH 3
131 #define ADDR_GEN_128MB 0
132 #define ADDR_GEN_256MB 1
133 #define ADDR_GEN_512MB 2
134 #define ADDR_GEN_1GB 3
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)
185 spin_lock(&mctrl_list_lock);
186 list_add(list, &mctrl_list);
187 spin_unlock(&mctrl_list_lock);
192 spin_lock(&mctrl_list_lock);
194 spin_unlock(&mctrl_list_lock);
197 #define SYNDROME_MIN -1
198 #define SYNDROME_MAX 144
203 static int syndrome_to_qword_code(
int syndrome_code)
205 if (syndrome_code < 128)
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);
212 syndrome_code -= (128 + 9 + 3);
213 return syndrome_code;
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)
226 #define SAFARI_LAST_BIT (576 - 1)
227 #define JBUS_LAST_BIT (144 - 1)
229 static 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)
233 int qword_code = syndrome_to_qword_code(syndrome_code);
234 int cache_line_offset;
243 cache_line_offset = qword_code;
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];
262 cache_line_offset = ((3 -
qword) *
QW_BITS) + qword_code;
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];
292 static int jbusmc_print_dimm(
int syndrome_code,
293 unsigned long phys_addr,
301 dp = jbusmc_find_dimm_group(phys_addr);
320 get_pin_and_dimm_str(syndrome_code, phys_addr, &pin,
321 &dimm_str, prop, first_dimm);
322 sprintf(buf,
"%s, pin %3d", dimm_str, pin);
343 u64 max = base + (8
UL * 1024 * 1024 * 1024);
347 for (i = 0; i < num_mem_regs; i++) {
354 this_end = this_base + ent->
reg_size;
355 if (base < this_base || base >= this_end)
359 if (this_end > max_seen)
363 return max_seen - base;
366 static void __devinit jbusmc_construct_one_dimm_group(
struct jbusmc *p,
377 dp->
base_addr += (index * (8
UL * 1024 * 1024 * 1024));
378 dp->
size = jbusmc_dimm_group_size(dp->
base_addr, mem_regs, num_mem_regs);
386 jbusmc_construct_one_dimm_group(p, 0, mem_regs, num_mem_regs);
390 jbusmc_construct_one_dimm_group(p, 1, mem_regs, num_mem_regs);
399 int err,
len, num_mem_regs;
415 num_mem_regs = len /
sizeof(*mem_regs);
424 INIT_LIST_HEAD(&p->
list);
428 if (!prop || len != 4) {
436 if (!prop || len != 8) {
463 jbusmc_construct_dimm_groups(p, mem_regs, num_mem_regs);
465 mc_list_add(&p->
list);
468 op->
dev.of_node->full_name);
486 static int chmc_bank_match(
struct chmc_bank_info *bp,
unsigned long phys_addr)
496 upper_bits ^= bp->
um;
497 upper_bits = ~upper_bits;
498 upper_bits |= bp->
uk;
499 upper_bits = ~upper_bits;
505 lower_bits ^= bp->
lm;
506 lower_bits = ~lower_bits;
507 lower_bits |= bp->
lk;
508 lower_bits = ~lower_bits;
518 static struct chmc_bank_info *chmc_find_bank(
unsigned long phys_addr)
529 if (chmc_bank_match(bp, phys_addr))
538 static int chmc_print_dimm(
int syndrome_code,
539 unsigned long phys_addr,
540 char *buf,
int buflen)
544 int bank_in_controller, first_dimm;
546 bp = chmc_find_bank(phys_addr);
557 prop = &bp->
p->layout_prop;
558 bank_in_controller = bp->
bank_id & (CHMCTRL_NBANKS - 1);
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);
589 static u64 chmc_read_mcreg(
struct chmc *p,
unsigned long offset)
591 unsigned long ret, this_cpu;
597 if (p->
portid == this_cpu) {
598 __asm__ __volatile__(
"ldxa [%1] %2, %0"
602 __asm__ __volatile__(
"ldxa [%1] %2, %0"
604 :
"r" (p->
regs + offset),
614 static void chmc_write_mcreg(
struct chmc *p,
unsigned long offset,
u64 val)
617 __asm__ __volatile__(
"stxa %0, [%1] %2"
621 __asm__ __volatile__(
"ldxa %0, [%1] %2"
623 "r" (p->
regs + offset),
629 static void chmc_interpret_one_decode_reg(
struct chmc *p,
int which_bank,
u64 val)
677 static void chmc_fetch_decode_regs(
struct chmc *p)
682 chmc_interpret_one_decode_reg(p, 0,
684 chmc_interpret_one_decode_reg(p, 1,
686 chmc_interpret_one_decode_reg(p, 2,
688 chmc_interpret_one_decode_reg(p, 3,
702 __asm__ (
"rdpr %%ver, %0" :
"=r" (ver));
746 chmc_fetch_decode_regs(p);
748 mc_list_add(&p->
list);
769 return chmc_probe(op);
771 return jbusmc_probe(op);
784 mc_list_del(&p->
list);
797 jbusmc_destroy(op, p);
804 .name =
"memory-controller",
814 .of_match_table = us3mc_match,
816 .probe = us3mc_probe,
820 static inline bool us3mc_platform(
void)
827 static int __init us3mc_init(
void)
832 if (!us3mc_platform())
835 __asm__ __volatile__(
"rdpr %%ver, %0" :
"=r" (ver));
839 us3mc_dimm_printer = jbusmc_print_dimm;
842 us3mc_dimm_printer = chmc_print_dimm;
855 static void __exit us3mc_cleanup(
void)
857 if (us3mc_platform()) {