1 /* $Id: chmc.c,v 1.3 2001/04/03 12:49:47 davem Exp $
2  * memctrlr.c: Driver for UltraSPARC-III memory controller.
3  *
4  * Copyright (C) 2001 David S. Miller (davem@redhat.com)
5  */
6 
7 #include <linux/module.h>
8 #include <linux/kernel.h>
9 #include <linux/types.h>
10 #include <linux/slab.h>
11 #include <linux/list.h>
12 #include <linux/init.h>
13 #include <asm/spitfire.h>
14 #include <asm/chmctrl.h>
15 #include <asm/oplib.h>
16 #include <asm/io.h>
17 
18 #define CHMCTRL_NDGRPS	2
19 #define CHMCTRL_NDIMMS	4
20 
21 #define DIMMS_PER_MC	(CHMCTRL_NDGRPS * CHMCTRL_NDIMMS)
22 
23 /* OBP memory-layout property format. */
24 struct obp_map {
25 	unsigned char	dimm_map[144];
26 	unsigned char	pin_map[576];
27 };
28 
29 #define DIMM_LABEL_SZ	8
30 
31 struct obp_mem_layout {
32 	/* One max 8-byte string label per DIMM.  Usually
33 	 * this matches the label on the motherboard where
34 	 * that DIMM resides.
35 	 */
36 	char		dimm_labels[DIMMS_PER_MC][DIMM_LABEL_SZ];
37 
38 	/* If symmetric use map[0], else it is
39 	 * asymmetric and map[1] should be used.
40 	 */
41 	char		symmetric;
42 
43 	struct obp_map	map[2];
44 };
45 
46 #define CHMCTRL_NBANKS	4
47 
48 struct bank_info {
49 	struct mctrl_info	*mp;
50 	int			bank_id;
51 
52 	u64			raw_reg;
53 	int			valid;
54 	int			uk;
55 	int			um;
56 	int			lk;
57 	int			lm;
58 	int			interleave;
59 	unsigned long		base;
60 	unsigned long		size;
61 };
62 
63 struct mctrl_info {
64 	struct list_head	list;
65 	int			portid;
66 	int			index;
67 
68 	struct obp_mem_layout	layout_prop;
69 	int			layout_size;
70 
71 	void			*regs;
72 
73 	u64			timing_control1;
74 	u64			timing_control2;
75 	u64			timing_control3;
76 	u64			timing_control4;
77 	u64			memaddr_control;
78 
79 	struct bank_info	logical_banks[CHMCTRL_NBANKS];
80 };
81 
82 static LIST_HEAD(mctrl_list);
83 
84 /* Does BANK decode PHYS_ADDR? */
bank_match(struct bank_info * bp,unsigned long phys_addr)85 static int bank_match(struct bank_info *bp, unsigned long phys_addr)
86 {
87 	unsigned long upper_bits = (phys_addr & PA_UPPER_BITS) >> PA_UPPER_BITS_SHIFT;
88 	unsigned long lower_bits = (phys_addr & PA_LOWER_BITS) >> PA_LOWER_BITS_SHIFT;
89 
90 	/* Bank must be enabled to match. */
91 	if (bp->valid == 0)
92 		return 0;
93 
94 	/* Would BANK match upper bits? */
95 	upper_bits ^= bp->um;		/* What bits are different? */
96 	upper_bits  = ~upper_bits;	/* Invert. */
97 	upper_bits |= bp->uk;		/* What bits don't matter for matching? */
98 	upper_bits  = ~upper_bits;	/* Invert. */
99 
100 	if (upper_bits)
101 		return 0;
102 
103 	/* Would BANK match lower bits? */
104 	lower_bits ^= bp->lm;		/* What bits are different? */
105 	lower_bits  = ~lower_bits;	/* Invert. */
106 	lower_bits |= bp->lk;		/* What bits don't matter for matching? */
107 	lower_bits  = ~lower_bits;	/* Invert. */
108 
109 	if (lower_bits)
110 		return 0;
111 
112 	/* I always knew you'd be the one. */
113 	return 1;
114 }
115 
116 /* Given PHYS_ADDR, search memory controller banks for a match. */
find_bank(unsigned long phys_addr)117 static struct bank_info *find_bank(unsigned long phys_addr)
118 {
119 	struct list_head *mctrl_head = &mctrl_list;
120 	struct list_head *mctrl_entry = mctrl_head->next;
121 
122 	for (;;) {
123 		struct mctrl_info *mp =
124 			list_entry(mctrl_entry, struct mctrl_info, list);
125 		int bank_no;
126 
127 		if (mctrl_entry == mctrl_head)
128 			break;
129 		mctrl_entry = mctrl_entry->next;
130 
131 		for (bank_no = 0; bank_no < CHMCTRL_NBANKS; bank_no++) {
132 			struct bank_info *bp;
133 
134 			bp = &mp->logical_banks[bank_no];
135 			if (bank_match(bp, phys_addr))
136 				return bp;
137 		}
138 	}
139 
140 	return NULL;
141 }
142 
143 /* This is the main purpose of this driver. */
144 #define SYNDROME_MIN	-1
145 #define SYNDROME_MAX	144
chmc_getunumber(int syndrome_code,unsigned long phys_addr,char * buf,int buflen)146 int chmc_getunumber(int syndrome_code,
147 		    unsigned long phys_addr,
148 		    char *buf, int buflen)
149 {
150 	struct bank_info *bp;
151 	struct obp_mem_layout *prop;
152 	int bank_in_controller, first_dimm;
153 
154 	bp = find_bank(phys_addr);
155 	if (bp == NULL ||
156 	    syndrome_code < SYNDROME_MIN ||
157 	    syndrome_code > SYNDROME_MAX) {
158 		buf[0] = '?';
159 		buf[1] = '?';
160 		buf[2] = '?';
161 		buf[3] = '\0';
162 		return 0;
163 	}
164 
165 	prop = &bp->mp->layout_prop;
166 	bank_in_controller = bp->bank_id & (CHMCTRL_NBANKS - 1);
167 	first_dimm  = (bank_in_controller & (CHMCTRL_NDGRPS - 1));
168 	first_dimm *= CHMCTRL_NDIMMS;
169 
170 	if (syndrome_code != SYNDROME_MIN) {
171 		struct obp_map *map;
172 		int qword, where_in_line, where, map_index, map_offset;
173 		unsigned int map_val;
174 
175 		/* Yaay, single bit error so we can figure out
176 		 * the exact dimm.
177 		 */
178 		if (prop->symmetric)
179 			map = &prop->map[0];
180 		else
181 			map = &prop->map[1];
182 
183 		/* Covert syndrome code into the way the bits are
184 		 * positioned on the bus.
185 		 */
186 		if (syndrome_code < 144 - 16)
187 			syndrome_code += 16;
188 		else if (syndrome_code < 144)
189 			syndrome_code -= (144 - 7);
190 		else if (syndrome_code < (144 + 3))
191 			syndrome_code -= (144 + 3 - 4);
192 		else
193 			syndrome_code -= 144 + 3;
194 
195 		/* All this magic has to do with how a cache line
196 		 * comes over the wire on Safari.  A 64-bit line
197 		 * comes over in 4 quadword cycles, each of which
198 		 * transmit ECC/MTAG info as well as the actual
199 		 * data.  144 bits per quadword, 576 total.
200 		 */
201 #define LINE_SIZE	64
202 #define LINE_ADDR_MSK	(LINE_SIZE - 1)
203 #define QW_PER_LINE	4
204 #define QW_BYTES	(LINE_SIZE / QW_PER_LINE)
205 #define QW_BITS		144
206 #define LAST_BIT	(576 - 1)
207 
208 		qword = (phys_addr & LINE_ADDR_MSK) / QW_BYTES;
209 		where_in_line = ((3 - qword) * QW_BITS) + syndrome_code;
210 		where = (LAST_BIT - where_in_line);
211 		map_index = where >> 2;
212 		map_offset = where & 0x3;
213 		map_val = map->dimm_map[map_index];
214 		map_val = ((map_val >> ((3 - map_offset) << 1)) & (2 - 1));
215 
216 		sprintf(buf, "%s, pin %3d",
217 			prop->dimm_labels[first_dimm + map_val],
218 			map->pin_map[where_in_line]);
219 	} else {
220 		int dimm;
221 
222 		/* Multi-bit error, we just dump out all the
223 		 * dimm labels assosciated with this bank.
224 		 */
225 		for (dimm = 0; dimm < CHMCTRL_NDIMMS; dimm++) {
226 			sprintf(buf, "%s ",
227 				prop->dimm_labels[first_dimm + dimm]);
228 			buf += strlen(buf);
229 		}
230 	}
231 	return 0;
232 }
233 
234 /* Accessing the registers is slightly complicated.  If you want
235  * to get at the memory controller which is on the same processor
236  * the code is executing, you must use special ASI load/store else
237  * you go through the global mapping.
238  */
read_mcreg(struct mctrl_info * mp,unsigned long offset)239 static u64 read_mcreg(struct mctrl_info *mp, unsigned long offset)
240 {
241 	unsigned long ret;
242 
243 	if (mp->portid == smp_processor_id()) {
244 		__asm__ __volatile__("ldxa	[%1] %2, %0"
245 				     : "=r" (ret)
246 				     : "r" (offset), "i" (ASI_MCU_CTRL_REG));
247 	} else {
248 		__asm__ __volatile__("ldxa	[%1] %2, %0"
249 				     : "=r" (ret)
250 				     : "r" (mp->regs + offset),
251 				       "i" (ASI_PHYS_BYPASS_EC_E));
252 	}
253 	return ret;
254 }
255 
256 #if 0 /* currently unused */
257 static void write_mcreg(struct mctrl_info *mp, unsigned long offset, u64 val)
258 {
259 	if (mp->portid == smp_processor_id()) {
260 		__asm__ __volatile__("stxa	%0, [%1] %2"
261 				     : : "r" (val),
262 				         "r" (offset), "i" (ASI_MCU_CTRL_REG));
263 	} else {
264 		__asm__ __volatile__("ldxa	%0, [%1] %2"
265 				     : : "r" (val),
266 				         "r" (mp->regs + offset),
267 				         "i" (ASI_PHYS_BYPASS_EC_E));
268 	}
269 }
270 #endif
271 
interpret_one_decode_reg(struct mctrl_info * mp,int which_bank,u64 val)272 static void interpret_one_decode_reg(struct mctrl_info *mp, int which_bank, u64 val)
273 {
274 	struct bank_info *p = &mp->logical_banks[which_bank];
275 
276 	p->mp = mp;
277 	p->bank_id = (CHMCTRL_NBANKS * mp->portid) + which_bank;
278 	p->raw_reg = val;
279 	p->valid = (val & MEM_DECODE_VALID) >> MEM_DECODE_VALID_SHIFT;
280 	p->uk = (val & MEM_DECODE_UK) >> MEM_DECODE_UK_SHIFT;
281 	p->um = (val & MEM_DECODE_UM) >> MEM_DECODE_UM_SHIFT;
282 	p->lk = (val & MEM_DECODE_LK) >> MEM_DECODE_LK_SHIFT;
283 	p->lm = (val & MEM_DECODE_LM) >> MEM_DECODE_LM_SHIFT;
284 
285 	p->base  =  (p->um);
286 	p->base &= ~(p->uk);
287 	p->base <<= PA_UPPER_BITS_SHIFT;
288 
289 	switch(p->lk) {
290 	case 0xf:
291 	default:
292 		p->interleave = 1;
293 		break;
294 
295 	case 0xe:
296 		p->interleave = 2;
297 		break;
298 
299 	case 0xc:
300 		p->interleave = 4;
301 		break;
302 
303 	case 0x8:
304 		p->interleave = 8;
305 		break;
306 
307 	case 0x0:
308 		p->interleave = 16;
309 		break;
310 	};
311 
312 	/* UK[10] is reserved, and UK[11] is not set for the SDRAM
313 	 * bank size definition.
314 	 */
315 	p->size = (((unsigned long)p->uk &
316 		    ((1UL << 10UL) - 1UL)) + 1UL) << PA_UPPER_BITS_SHIFT;
317 	p->size /= p->interleave;
318 }
319 
fetch_decode_regs(struct mctrl_info * mp)320 static void fetch_decode_regs(struct mctrl_info *mp)
321 {
322 	if (mp->layout_size == 0)
323 		return;
324 
325 	interpret_one_decode_reg(mp, 0,
326 				 read_mcreg(mp, CHMCTRL_DECODE1));
327 	interpret_one_decode_reg(mp, 1,
328 				 read_mcreg(mp, CHMCTRL_DECODE2));
329 	interpret_one_decode_reg(mp, 2,
330 				 read_mcreg(mp, CHMCTRL_DECODE3));
331 	interpret_one_decode_reg(mp, 3,
332 				 read_mcreg(mp, CHMCTRL_DECODE4));
333 }
334 
init_one_mctrl(int node,int index)335 static int init_one_mctrl(int node, int index)
336 {
337 	struct mctrl_info *mp = kmalloc(sizeof(*mp), GFP_KERNEL);
338 	int portid = prom_getintdefault(node, "portid", -1);
339 	struct linux_prom64_registers p_reg_prop;
340 	int t;
341 
342 	if (!mp)
343 		return -1;
344 	memset(mp, 0, sizeof(*mp));
345 	if (portid == -1)
346 		goto fail;
347 
348 	mp->portid = portid;
349 	mp->layout_size = prom_getproplen(node, "memory-layout");
350 	if (mp->layout_size < 0)
351 		mp->layout_size = 0;
352 	if (mp->layout_size > sizeof(mp->layout_prop))
353 		goto fail;
354 
355 	if (mp->layout_size > 0)
356 		prom_getproperty(node, "memory-layout",
357 				 (char *) &mp->layout_prop,
358 				 mp->layout_size);
359 
360 	t = prom_getproperty(node, "reg",
361 			     (char *) &p_reg_prop,
362 			     sizeof(p_reg_prop));
363 	if (t < 0 || p_reg_prop.reg_size != 0x48)
364 		goto fail;
365 
366 	mp->regs = ioremap(p_reg_prop.phys_addr, p_reg_prop.reg_size);
367 	if (mp->regs == NULL)
368 		goto fail;
369 
370 	if (mp->layout_size != 0UL) {
371 		mp->timing_control1 = read_mcreg(mp, CHMCTRL_TCTRL1);
372 		mp->timing_control2 = read_mcreg(mp, CHMCTRL_TCTRL2);
373 		mp->timing_control3 = read_mcreg(mp, CHMCTRL_TCTRL3);
374 		mp->timing_control4 = read_mcreg(mp, CHMCTRL_TCTRL4);
375 		mp->memaddr_control = read_mcreg(mp, CHMCTRL_MACTRL);
376 	}
377 
378 	fetch_decode_regs(mp);
379 
380 	mp->index = index;
381 
382 	list_add(&mp->list, &mctrl_list);
383 
384 	/* Report the device. */
385 	printk(KERN_INFO "chmc%d: US3 memory controller at %p [%s]\n",
386 	       mp->index,
387 	       mp->regs, (mp->layout_size ? "ACTIVE" : "INACTIVE"));
388 
389 	return 0;
390 
391 fail:
392 	if (mp) {
393 		if (mp->regs != NULL)
394 			iounmap(mp->regs);
395 		kfree(mp);
396 	}
397 	return -1;
398 }
399 
probe_for_string(char * name,int index)400 static int __init probe_for_string(char *name, int index)
401 {
402 	int node = prom_getchild(prom_root_node);
403 
404 	while ((node = prom_searchsiblings(node, name)) != 0) {
405 		int ret = init_one_mctrl(node, index);
406 
407 		if (!ret)
408 			index++;
409 
410 		node = prom_getsibling(node);
411 		if (!node)
412 			break;
413 	}
414 
415 	return index;
416 }
417 
chmc_init(void)418 static int __init chmc_init(void)
419 {
420 	int index;
421 
422 	/* This driver is only for cheetah platforms. */
423 	if (tlb_type != cheetah && tlb_type != cheetah_plus)
424 		return -ENODEV;
425 
426 	index = probe_for_string("memory-controller", 0);
427 	index = probe_for_string("mc-us3", index);
428 
429 	return 0;
430 }
431 
chmc_cleanup(void)432 static void __exit chmc_cleanup(void)
433 {
434 	struct list_head *head = &mctrl_list;
435 	struct list_head *tmp = head->next;
436 
437 	for (;;) {
438 		struct mctrl_info *p =
439 			list_entry(tmp, struct mctrl_info, list);
440 		if (tmp == head)
441 			break;
442 		tmp = tmp->next;
443 
444 		list_del(&p->list);
445 		iounmap(p->regs);
446 		kfree(p);
447 	}
448 }
449 
450 module_init(chmc_init);
451 module_exit(chmc_cleanup);
452