OpenSolaris_b135/common/mc/mc-amd/mcamd_rowcol_tbl.c

/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 *
 * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#pragma ident	"%Z%%M%	%I%	%E% SMI"

#include <mcamd_api.h>
#include <mcamd_err.h>
#include <mcamd_rowcol_impl.h>

/*
 * =========== Chip-Select Bank Address Mode Encodings =======================
 */

/* Individual table declarations */
static const struct rct_bnkaddrmode bnkaddr_tbls_pre_d[];
static const struct rct_bnkaddrmode bnkaddr_tbls_d_e[];
static const struct rct_bnkaddrmode bnkaddr_tbls_f[];

/* Managing bank address mode tables */
static const struct _bnkaddrmode_tbldesc {
	uint_t	revmask;
	int	nmodes;
	const struct rct_bnkaddrmode *modetbl;
} bnkaddr_tbls[] = {
	{ MC_F_REVS_BC, 7, bnkaddr_tbls_pre_d },
	{ MC_F_REVS_DE, 11, bnkaddr_tbls_d_e },
	{ MC_F_REVS_FG, 12, bnkaddr_tbls_f },
};

/*
 * =========== DRAM Address Mappings for bank/row/column =====================
 */


/* Individual table declarations */
struct _rcbmap_tbl {
	uint_t mt_revmask;		/* revision to which this applies */
	int mt_width;			/* MC mode (64 or 128) */
	const struct rct_rcbmap mt_csmap[MC_RC_CSMODES];
};

static const struct _rcbmap_tbl dram_addrmap_pre_d_64;
static const struct _rcbmap_tbl dram_addrmap_pre_d_128;
static const struct _rcbmap_tbl dram_addrmap_d_e_64;
static const struct _rcbmap_tbl dram_addrmap_d_e_128;
static const struct _rcbmap_tbl dram_addrmap_f_64;
static const struct _rcbmap_tbl dram_addrmap_f_128;

/* Managing row/column/bank tables */
static const struct _rcbmap_tbldesc {
	int nmodes;
	const struct _rcbmap_tbl *rcbmap;
} rcbmap_tbls[] = {
	{ 7, &dram_addrmap_pre_d_64 },
	{ 7, &dram_addrmap_pre_d_128 },
	{ 11, &dram_addrmap_d_e_64 },
	{ 11, &dram_addrmap_d_e_128 },
	{ 12, &dram_addrmap_f_64 },
	{ 12, &dram_addrmap_f_128 },
};

/*
 * =========== Bank swizzling information ====================================
 */

/* Individual table declarations */
struct _bnkswzl_tbl {
	uint_t swzt_revmask;		/* revision to which this applies */
	int swzt_width;			/* MC mode (64 or 128) */
	const struct rct_bnkswzlinfo swzt_bits;
};

static const struct _bnkswzl_tbl bnswzl_info_e_64;
static const struct _bnkswzl_tbl bnswzl_info_e_128;
static const struct _bnkswzl_tbl bnswzl_info_f_64;
static const struct _bnkswzl_tbl bnswzl_info_f_128;

/* Managing bank swizzle tables */
static const struct _bnkswzl_tbl *bnkswzl_tbls[] = {
	&bnswzl_info_e_64,
	&bnswzl_info_e_128,
	&bnswzl_info_f_64,
	&bnswzl_info_f_128,
};

/*
 * ======================================================================
 * | Tables reflecting those in the BKDG				|
 * ======================================================================
 */

/*
 * DRAM Address Mapping in Interleaving Mode
 *
 * Chip-select interleave is performed by addressing across the columns
 * of the first row of internal bank-select 0 on a chip-select, then the
 * next row on internal bank-select 1, then 2 then 3;  instead of then
 * moving on to the next row of this chip-select we then rotate across
 * other chip-selects in the interleave.  The row/column/bank mappings
 * described elsewhere in this file show that a DRAM InputAddr breaks down
 * as follows, using an example for CS Mode 0000 revision CG and earlier 64-bit
 * mode; the cs size is 32MB, requiring 25 bits to address all of it.
 *
 * chip-selection bits |    offset within chip-select bits      |
 *		       | row bits | bank bits | column bits | - |
 *                      24      13 12       11 10          3 2 0
 *
 * The high-order chip-selection bits select the chip-select and the
 * offset bits offset within the chosen chip-select.
 *
 * To establish say a 2-way interleave in which we consume all of one
 * row number and all internal bank numbers on one cs before moving on
 * to the next to do the same we will target the first row bit - bit 13;
 * a 4-way interleave would use bits 14 and 13, and an 8-way interleave
 * bits 15, 14 and 13.  We swap the chosen bits with the least significant
 * high order chip-selection bits.
 *
 * The BKDG interleave tables really just describe the above.  Working
 * out the high-order bits to swap is easy since that is derived directly
 * from the chip-select size.  The low-order bits depend on the device
 * parameters since we need to target the least significant row address bits -
 * but we have that information from the rcbmap_tbls since the first row bit
 * simply follows the last bank address bit.
 */

/*
 * General notes for CS Bank Address Mode Encoding tables.
 *
 * These are indexed by chip-select mode.  Where the numbers of rows and
 * columns is ambiguous (as it is for a number of rev CG and earlier cases)
 * the bam_config should be initialized to 1 and the numbers of rows
 * and columns should be the maximums.
 */

/*
 * Chip Select Bank Address Mode Encoding for rev CG and earlier.
 */
static const struct rct_bnkaddrmode bnkaddr_tbls_pre_d[] = {
	{	/* 000 */
		32, 12, 8
	},
	{	/* 001 */
		64, 12, 9
	},
	{	/* 010 */
		128, 13, 10, 1	/* AMBIG */
	},
	{	/* 011 */
		256, 13, 11, 1	/* AMBIG */
	},
	{	/* 100 */
		512, 14, 11, 1	/* AMBIG */
	},
	{	/* 101 */
		1024, 14, 12, 1	/* AMBIG */
	},
	{	/* 110 */
		2048, 14, 12
	}
};

/*
 * Chip Select Bank Address Mode Encoding for revs D and E.
 */
static const struct rct_bnkaddrmode bnkaddr_tbls_d_e[] = {
	{	/* 0000 */
		32, 12, 8
	},
	{	/* 0001 */
		64, 12, 9
	},
	{	/* 0010 */
		128, 13, 9
	},
	{	/* 0011 */
		128, 12, 10
	},
	{	/* 0100 */
		256, 13, 10
	},
	{	/* 0101 */
		512, 14, 10
	},
	{	/* 0110 */
		256, 12, 11
	},
	{	/* 0111 */
		512, 13, 11
	},
	{	/* 1000 */
		1024, 14, 11
	},
	{	/* 1001 */
		1024, 13, 12
	},
	{	/* 1010 */
		2048, 14, 12
	}
};

/*
 * Chip Select Bank Address Mode Encoding for rev F
 */
static const struct rct_bnkaddrmode bnkaddr_tbls_f[] = {
	{	/* 0000 */
		128, 13, 9
	},
	{	/* 0001 */
		256, 13, 10
	},
	{	/* 0010 */
		512, 14, 10
	},
	{	/* 0011 */
		512, 13, 11
	},
	{	/* 0100 */
		512, 13, 10
	},
	{	/* 0101 */
		1024, 14, 10
	},
	{	/* 0110 */
		1024, 14, 11
	},
	{	/* 0111 */
		2048, 15, 10
	},
	{	/* 1000 */
		2048, 14, 11
	},
	{	/* 1001 */
		4096, 15, 11
	},
	{	/* 1010 */
		4096, 16, 10
	},
	{	/* 1011 */
		8192, 16, 11
	}

};

/*
 * General notes on Row/Column/Bank table initialisation.
 *
 * These are the tables 7, 8, 9, 10, 11 and 12 of BKDG 3.29 section 3.5.6.1.
 * They apply in non-interleave (node or cs) mode and describe how for
 * a given revision, access width, bank-swizzle mode, and current chip-select
 * mode the row, column and internal sdram bank are derived from the
 * normalizied InputAddr presented to the DRAM controller.
 *
 * The mt_csmap array is indexed by chip-select mode.  Within it the
 * bankargs, rowbits and colbits arrays are indexed by bit number, so
 * match the BKDG tables if the latter are read right-to-left.
 *
 * The bankargs list up to three bit numbers per bank bit.  For revisions
 * CG and earlier there is no bank swizzling, so just a single number
 * should be listed.  Revisions D and E have the same row/column/bank mapping,
 * but rev E has the additional feature of being able to xor two row bits
 * into each bank bit.  The consumer will know whether they are using bank
 * swizzling - if so then they should xor the bankargs bits together.
 * The first argument must be the bit number not already used in forming
 * part of the row address - eg in table 12 for csmode 0000b bank address
 * bit 0 is bit 12 xor bit 18 xor bit 21, and 18 and 21 are also mentioned in
 * the row address (bits 10 and 1) so we must list bit 12 first.  We will
 * use this information in chip-select interleave decoding in which we need
 * to know which is the first bit after column and bank address bits.
 *
 * Column address A10 is always used for the Precharge All signal.  Where
 * "PC" appears in the BKDG tables we will include MC_PC_ALL in the
 * corresponding bit position.
 *
 * For some rev CG and earlier chipselect modes the number of rows and columns
 * is ambiguous.  This is reflected in these tables by some bit being
 * duplicated between row and column address.  In practice we will follow
 * the convention of always assigning the floating bit to the row address.
 */

/*
 * Row/Column/Bank address mappings for rev CG in 64-bit mode, no interleave.
 * See BKDG 3.29 3.5.6 Table 7.
 */
static const struct _rcbmap_tbl dram_addrmap_pre_d_64 = {
	MC_F_REVS_BC,
	64,
	{
	{   /* 000 */
	    2, { 11, 12 },
	    { 19, 20, 21, 22, 23, 24, 13, 14, 15, 16, 17, 18 },
	    { 3, 4, 5, 6, 7, 8, 9, 10 }
	},
	{   /* 001 */
	    2, { 13, 12 },
	    { 19, 20, 21, 22, 23, 24, 25, 14, 15, 16, 17, 18 },
	    { 3, 4, 5, 6, 7, 8, 9, 10, 11 }
	},
	{   /* 010 */
	    2, { 13, 12 },
	    { 19, 20, 21, 22, 23, 24, 25, 14, 15, 16, 17, 18, 26 },
	    { 3, 4, 5, 6, 7, 8, 9, 10, 11, 26 }
	},
	{   /* 011 */
	    2, { 13, 14 },
	    { 19, 20, 21, 22, 23, 24, 25, 26, 15, 16, 17, 18, 27 },
	    { 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, MC_PC_ALL, 27 }
	},
	{   /* 100 */
	    2, { 13, 14 },
	    { 19, 20, 21, 22, 23, 24, 25, 26, 15, 16, 17, 18, 27, 28 },
	    { 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, MC_PC_ALL, 28 }
	},
	{   /* 101 */
	    2, { 15, 14 },
	    { 19, 20, 21, 22, 23, 24, 25, 26, 29, 16, 17, 18, 27, 28 },
	    { 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, MC_PC_ALL, 13, 28 }
	},
	{   /* 110 */
	    2, { 15, 14 },
	    { 19, 20, 21, 22, 23, 24, 25, 26, 29, 16, 17, 18, 27, 28 },
	    { 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, MC_PC_ALL, 13, 30 }
	},
	/*
	 * remainder unused
	 */
	}

};

/*
 * Row/Column/Bank address mappings for rev CG in 128-bit mode, no interleave.
 * See BKDG 3.29 3.5.6 Table 8.
 */
static const struct _rcbmap_tbl dram_addrmap_pre_d_128 = {
	MC_F_REVS_BC,
	128,
	{
	{   /* 000 */
	    2, { 12, 13 },
	    { 20, 21, 22, 23, 24, 25, 14, 15, 16, 17, 18, 19 },
	    { 4, 5, 6, 7, 8, 9, 10, 11 }
	},
	{   /* 001 */
	    2, { 14, 13 },
	    { 20, 21, 22, 23, 24, 25, 26, 15, 16, 17, 18, 19 },
	    { 4, 5, 6, 7, 8, 9, 10, 11, 12 }
	},
	{   /* 010 */
	    2, { 14, 13 },
	    { 20, 21, 22, 23, 24, 25, 26, 15, 16, 17, 18, 19, 27 },
	    { 4, 5, 6, 7, 8, 9, 10, 11, 12, 27 }
	},
	{   /* 011 */
	    2, { 14, 15 },
	    { 20, 21, 22, 23, 24, 25, 26, 27, 16, 17, 18, 19, 28 },
	    { 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, MC_PC_ALL, 28 }
	},
	{   /* 100 */
	    2, { 14, 15 },
	    { 20, 21, 22, 23, 24, 25, 26, 27, 16, 17, 18, 19, 28, 29 },
	    { 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, MC_PC_ALL, 29 }
	},
	{   /* 101 */
	    2, { 16, 15 },
	    { 20, 21, 22, 23, 24, 25, 26, 27, 30, 17, 18, 19, 28, 29 },
	    { 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, MC_PC_ALL, 14, 29 }
	},
	{   /* 110 */
	    2, { 16, 15 },
	    { 20, 21, 22, 23, 24, 25, 26, 27, 30, 17, 18, 19, 28, 29 },
	    { 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, MC_PC_ALL, 14, 31 }
	},
	/*
	 * remainder unused
	 */
	}
};

/*
 * Row/Column/Bank address mappings for rev D/E in 64-bit mode, no interleave.
 * See BKDG 3.29 3.5.6 Table 9.
 */
static const struct _rcbmap_tbl dram_addrmap_d_e_64 = {
	MC_F_REVS_DE,
	64,
	{
	{   /* 0000 */
	    2, { 11, 12 },
	    { 19, 20, 21, 22, 23, 24, 13, 14, 15, 16, 17, 18 },
	    { 3, 4, 5, 6, 7, 8, 9, 10 }
	},
	{   /* 0001 */
	    2, { 12, 13 },
	    { 19, 20, 21, 22, 23, 24, 25, 14, 15, 16, 17, 18, 26 },
	    { 3, 4, 5, 6, 7, 8, 9, 10, 11 }
	},
	{   /* 0010 */
	    2, { 12, 13 },
	    { 19, 20, 21, 22, 23, 24, 25, 14, 15, 16, 17, 18, 26 },
	    { 3, 4, 5, 6, 7, 8, 9, 10, 11 }
	},
	{   /* 0011 */
	    2, { 13, 14 },
	    { 19, 20, 21, 22, 23, 24, 25, 26, 15, 16, 17, 18, 27, 28 },
	    { 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }
	},
	{   /* 0100 */
	    2, { 13, 14 },
	    { 19, 20, 21, 22, 23, 24, 25, 26, 15, 16, 17, 18, 27, 28 },
	    { 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }
	},
	{   /* 0101 */
	    2, { 13, 14 },
	    { 19, 20, 21, 22, 23, 24, 25, 26, 15, 16, 17, 18, 27, 28 },
	    { 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }
	},
	{   /* 0110 */
	    2, { 14, 15 },
	    { 19, 20, 21, 22, 23, 24, 25, 26, 27, 16, 17, 18, 28, 29 },
	    { 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, MC_PC_ALL, 13 }
	},
	{   /* 0111 */
	    2, { 14, 15 },
	    { 19, 20, 21, 22, 23, 24, 25, 26, 27, 16, 17, 18, 28, 29 },
	    { 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, MC_PC_ALL, 13 }
	},
	{   /* 1000 */
	    2, { 14, 15 },
	    { 19, 20, 21, 22, 23, 24, 25, 26, 27, 16, 17, 18, 28, 29 },
	    { 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, MC_PC_ALL, 13 }
	},
	{   /* 1001 */
	    2, { 15, 16 },
	    { 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 17, 18, 29, 30 },
	    { 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, MC_PC_ALL, 13, 14 }
	},
	{   /* 1010 */
	    2, { 15, 16 },
	    { 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 17, 18, 29, 30 },
	    { 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, MC_PC_ALL, 13, 14 }
	},
	/*
	 * remainder unused
	 */
	}
};

/*
 * Row/Column/Bank address mappings for rev D/E in 128-bit mode, no interleave.
 * See BKDG 3.29 3.5.6 Table 9.
 */
static const struct _rcbmap_tbl dram_addrmap_d_e_128 = {
	MC_F_REVS_DE,
	128,
	{
	{   /* 0000 */
	    2, { 12, 13 },
	    { 20, 21, 22, 23, 24, 25, 14, 15, 16, 17, 18, 19 },
	    { 4, 5, 6, 7, 8, 9, 10, 11 }
	},
	{   /* 0001 */
	    2, { 13, 14 },
	    { 20, 21, 22, 23, 24, 25, 26, 15, 16, 17, 18, 19, 27 },
	    { 4, 5, 6, 7, 8, 9, 10, 11, 12 }
	},
	{   /* 0010 */
	    2, { 13, 14 },
	    { 20, 21, 22, 23, 24, 25, 26, 15, 16, 17, 18, 19, 27 },
	    { 4, 5, 6, 7, 8, 9, 10, 11, 12 }
	},
	{   /* 0011 */
	    2, { 14, 15 },
	    { 20, 21, 22, 23, 24, 25, 26, 27, 16, 17, 18, 19, 28, 29 },
	    { 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 }
	},
	{   /* 0100 */
	    2, { 14, 15 },
	    { 20, 21, 22, 23, 24, 25, 26, 27, 16, 17, 18, 19, 28, 29 },
	    { 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 }
	},
	{   /* 0101 */
	    2, { 14, 15 },
	    { 20, 21, 22, 23, 24, 25, 26, 27, 16, 17, 18, 19, 28, 29 },
	    { 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 }
	},
	{   /* 0110 */
	    2, { 15, 16 },
	    { 20, 21, 22, 23, 24, 25, 26, 27, 28, 17, 18, 19, 29, 30 },
	    { 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, MC_PC_ALL, 14 }
	},
	{   /* 0111 */
	    2, { 15, 16 },
	    { 20, 21, 22, 23, 24, 25, 26, 27, 28, 17, 18, 19, 29, 30 },
	    { 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, MC_PC_ALL, 14 }
	},
	{   /* 1000 */
	    2, { 15, 16 },
	    { 20, 21, 22, 23, 24, 25, 26, 27, 28, 17, 18, 19, 29, 30 },
	    { 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, MC_PC_ALL, 14 }
	},
	{   /* 1001 */
	    2, { 16, 17 },
	    { 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 18, 19, 30, 31 },
	    { 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, MC_PC_ALL, 14, 15 }
	},
	{   /* 1010 */
	    2, { 16, 17 },
	    { 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 18, 19, 30, 31 },
	    { 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, MC_PC_ALL, 14, 15 }
	},
	/*
	 * remainder unused
	 */
	}
};

/*
 * Row/Column/Bank address mappings for revs F/G in 64-bit mode, no interleave.
 */
static const struct _rcbmap_tbl dram_addrmap_f_64 = {
	MC_F_REVS_FG,
	64,
	{
	{	/* 0000 */
		2, { 12, 13 },
		{ 18, 19, 20, 21, 22, 23, 24, 25, 26, 14, 15, 16, 17 },
		{ 3, 4, 5, 6, 7, 8, 9, 10, 11 },
	},
	{	/* 0001 */
		2, { 13, 14 },
		{ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 15, 16, 17 },
		{ 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 },
	},
	{	/* 0010 */
		2, { 13, 14 },
		{ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 15, 16, 17 },
		{ 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 },
	},
	{	/* 0011 */
		2, { 14, 15 },
		{ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 16, 17 },
		{ 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, MC_PC_ALL, 13 },
	},
	{	/* 0100 */
		3, { 13, 14, 15 },
		{ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 16, 17 },
		{ 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, MC_PC_ALL, 13 },
	},
	{	/* 0101 */
		3, { 13, 14, 15 },
		{ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 16, 17 },
		{ 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }
	},
	{	/* 0110 */
		2, { 14, 15 },
		{ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 16, 17 },
		{ 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, MC_PC_ALL, 13 },
	},
	{	/* 0111 */
		3, { 13, 14, 15 },
		{ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 16, 17 },
		{ 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }
	},
	{	/* 1000 */
		3, { 14, 15, 16 },
		{ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 17 },
		{ 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, MC_PC_ALL, 13 },
	},
	{	/* 1001 */
		3, { 14, 15, 16 },
		{ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 17 },
		{ 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, MC_PC_ALL, 13 },
	},
	{	/* 1010 */
		3, { 13, 14, 15 },
		{ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
		    16, 17 },
		{ 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }
	},
	{	/* 1011 */
		3, { 14, 15, 16 },
		{ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
		    17 },
		{ 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, MC_PC_ALL, 13 },
	},
	/*
	 * remainder unused
	 */
	}
};

/*
 * Row/Column/Bank address mappings for revs F/G in 128-bit mode, no interleave.
 */
static const struct _rcbmap_tbl dram_addrmap_f_128 = {
	MC_F_REVS_FG,
	128,
	{
	{	/* 0000 */
		2, { 13, 14 },
		{ 19, 20, 21, 22, 23, 24, 25, 26, 27, 15, 16, 17, 18 },
		{ 4, 5, 6, 7, 8, 9, 10, 11, 12 },
	},
	{	/* 0001 */
		2, { 14, 15 },
		{ 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 16, 17, 18 },
		{ 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 },
	},
	{	/* 0010 */
		2, { 14, 15 },
		{ 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 16, 17, 18 },
		{ 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 },
	},
	{	/* 0011 */
		2, { 15, 16 },
		{ 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 17, 18 },
		{ 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, MC_PC_ALL, 14 },
	},
	{	/* 0100 */
		3, { 14, 15, 16 },
		{ 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 17, 18 },
		{ 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 },
	},
	{	/* 0101 */
		3, { 14, 15, 16 },
		{ 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 17, 18 },
		{ 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 },
	},
	{	/* 0110 */
		2, { 15, 16 },
		{ 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 17, 18 },
		{ 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, MC_PC_ALL, 14 },
	},
	{	/* 0111 */
		3, { 14, 15, 16 },
		{ 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
		    17, 18 },
		{ 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 },
	},
	{	/* 1000 */
		3, { 15, 16, 17 },
		{ 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
		    18 },
		{ 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, MC_PC_ALL, 14 },
	},
	{	/* 1001 */
		3, { 15, 16, 17 },
		{ 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
		    18 },
		{ 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, MC_PC_ALL, 14 },
	},
	{	/* 1010 */
		3, { 14, 15, 16 },
		{ 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
		    17, 18 },
		{ 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 },
	},
	{	/* 1011 */
		3, { 15, 16, 17 },
		{ 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
		    18 },
		{ 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, MC_PC_ALL, 14 },
	},
	/*
	 * remainder unused
	 */
	}
};

/*
 * Bank swizzling is an option in revisions E and later.  Each internal-bank-
 * select address bit is xor'd with two row address bits.  Which row
 * address bits to use is not dependent on bank address mode but on
 * revision and dram controller width alone.
 *
 * While rev E only supports 2 bank address bits, rev F supports 3 but not
 * all chip-select bank address modes use all 3.  These tables will list
 * the row bits to use in swizzling for the maximum number of supported
 * bank address bits - the consumer musr determine how many should be
 * applied (listed in the above row/col/bank tables).
 */

static const struct _bnkswzl_tbl bnswzl_info_e_64 = {
	MC_F_REV_E,
	64,
	{
	    {
		{ 17, 20 },		/* rows bits to swizzle with BA0 */
		{ 18, 21 },		/* rows bits to swizzle with BA1 */
		/* only 2 bankaddr bits on rev E */
	    }
	}
};

static const struct _bnkswzl_tbl bnswzl_info_e_128 = {
	MC_F_REV_E,
	128,
	{
	    {
		{ 18, 21 },		/* rows bits to swizzle with BA0 */
		{ 19, 22 },		/* rows bits to swizzle with BA1 */
		/* only 2 bankaddr bits on rev E */
	    }
	}
};

static const struct _bnkswzl_tbl bnswzl_info_f_64 = {
	MC_F_REVS_FG,
	64,
	{
	    {
		{ 17, 22 },		/* rows bits to swizzle with BA0 */
		{ 18, 23 },		/* rows bits to swizzle with BA1 */
		{ 19, 24 },		/* rows bits to swizzle with BA2 */
	    }
	}
};

static const struct _bnkswzl_tbl bnswzl_info_f_128 = {
	MC_F_REVS_FG,
	128,
	{
	    {
		{ 18, 23 },		/* rows bits to swizzle with BA0 */
		{ 19, 24 },		/* rows bits to swizzle with BA1 */
		{ 20, 25 },		/* rows bits to swizzle with BA2 */
	    }
	}
};

/*
 * Yet another highbit function.  This really needs to go to common source.
 * Returns range 0 to 64 inclusive;
 */
static int
topbit(uint64_t i)
{
	int h = 1;

	if (i == 0)
		return (0);

	if (i & 0xffffffff00000000ULL) {
		h += 32;
		i >>= 32;
	}

	if (i & 0xffff0000) {
		h += 16;
		i >>= 16;
	}

	if (i & 0xff00) {
		h += 8;
		i >>= 8;
	}

	if (i & 0xf0) {
		h += 4;
		i >>= 4;
	}

	if (i & 0xc) {
		h += 2;
		i >>= 2;
	}

	if (i & 0x2)
		h += 1;

	return (h);
}

/*
 * Lookup the Chip-Select Bank Address Mode Encoding table for a given
 * chip revision and chip-select mode.
 */
const struct rct_bnkaddrmode *
rct_bnkaddrmode(uint_t mcrev, uint_t csmode)
{
	int i;
	const struct _bnkaddrmode_tbldesc *bdp = bnkaddr_tbls;

	for (i = 0; i < sizeof (bnkaddr_tbls) /
	    sizeof (struct _bnkaddrmode_tbldesc);
	    i++, bdp++) {
		if (MC_REV_MATCH(mcrev, bdp->revmask) && csmode < bdp->nmodes)
			return (&bdp->modetbl[csmode]);

	}

	return (NULL);
}

/*
 * Lookup the DRAM Address Mapping table for a given chip revision, access
 * width, bank-swizzle and chip-select mode.
 */
const struct rct_rcbmap *
rct_rcbmap(uint_t mcrev, int width, uint_t csmode)
{
	const struct _rcbmap_tbl *rcbm;
	int i;

	for (i = 0; i < sizeof (rcbmap_tbls) /
	    sizeof (struct _rcbmap_tbldesc); i++) {
		rcbm = rcbmap_tbls[i].rcbmap;
		if (MC_REV_MATCH(mcrev, rcbm->mt_revmask) &&
		    rcbm->mt_width == width && csmode < rcbmap_tbls[i].nmodes)
			return (&rcbm->mt_csmap[csmode]);
	}

	return (NULL);
}

/*
 * Lookup the bank swizzling information for a given chip revision and
 * access width.
 */
const struct rct_bnkswzlinfo *
rct_bnkswzlinfo(uint_t mcrev, int width)
{
	int i;
	const struct _bnkswzl_tbl *swztp;

	for (i = 0; i < sizeof (bnkswzl_tbls) /
	    sizeof (struct rcb_bnkswzl_tbl *); i++) {
		swztp = bnkswzl_tbls[i];
		if (MC_REV_MATCH(mcrev, swztp->swzt_revmask) &&
		    swztp->swzt_width == width)
			return (&swztp->swzt_bits);
	}

	return (NULL);
}

void
rct_csintlv_bits(uint_t mcrev, int width, uint_t csmode, int factor,
    struct rct_csintlv *csid)
{
	int i, lstbnkbit;
	size_t csz;
	const struct rct_bnkaddrmode *bam;
	const struct rct_rcbmap *rcm;

	/*
	 * 8-way cs interleave for some large cs sizes in 128-bit mode is
	 * not implemented prior to rev F.
	 */
	if (factor == 8 && width == 128 &&
	    ((MC_REV_MATCH(mcrev, MC_F_REVS_BC) && csmode == 0x6) ||
	    (MC_REV_MATCH(mcrev, MC_F_REVS_DE) &&
	    (csmode == 0x9 || csmode == 0xa)))) {
		csid->csi_factor = 0;
		return;
	}

	if ((bam = rct_bnkaddrmode(mcrev, csmode)) == NULL ||
	    (rcm = rct_rcbmap(mcrev, width, csmode)) == NULL) {
		csid->csi_factor = 0;
		return;
	}

	csz = MC_CS_SIZE(bam, width);

	switch (factor) {
		case 2:
			csid->csi_nbits = 1;
			break;
		case 4:
			csid->csi_nbits = 2;
			break;
		case 8:
			csid->csi_nbits = 3;
			break;
		default:
			csid->csi_factor = 0;
			return;
	}

	csid->csi_hibit = topbit(csz) - 1;

	/*
	 * The first row bit is immediately after the last bank bit.
	 */
	lstbnkbit = 0;
	for (i = 0; i < rcm->rcb_nbankbits; i++)
		if (rcm->rcb_bankbit[i] > lstbnkbit)
			lstbnkbit = rcm->rcb_bankbit[i];

	csid->csi_lobit = lstbnkbit + 1;

	csid->csi_factor = factor;
}