cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

chmc.c (20521B)


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