17aec1d6eScindi /* 27aec1d6eScindi * CDDL HEADER START 37aec1d6eScindi * 47aec1d6eScindi * The contents of this file are subject to the terms of the 58a40a695Sgavinm * Common Development and Distribution License (the "License"). 68a40a695Sgavinm * You may not use this file except in compliance with the License. 77aec1d6eScindi * 87aec1d6eScindi * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97aec1d6eScindi * or http://www.opensolaris.org/os/licensing. 107aec1d6eScindi * See the License for the specific language governing permissions 117aec1d6eScindi * and limitations under the License. 127aec1d6eScindi * 137aec1d6eScindi * When distributing Covered Code, include this CDDL HEADER in each 147aec1d6eScindi * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157aec1d6eScindi * If applicable, add the following below this CDDL HEADER, with the 167aec1d6eScindi * fields enclosed by brackets "[]" replaced with your own identifying 177aec1d6eScindi * information: Portions Copyright [yyyy] [name of copyright owner] 187aec1d6eScindi * 197aec1d6eScindi * CDDL HEADER END 207aec1d6eScindi */ 217aec1d6eScindi 227aec1d6eScindi /* 23*074bb90dSTom Pothier * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 247aec1d6eScindi * Use is subject to license terms. 257aec1d6eScindi */ 267aec1d6eScindi 277aec1d6eScindi #ifndef _MCAMD_H 287aec1d6eScindi #define _MCAMD_H 297aec1d6eScindi 30bb86c342Sgavinm /* 31bb86c342Sgavinm * Header file for the mc-amd AMD memory-controller driver. This should be 32bb86c342Sgavinm * included from that driver source alone - any more-widely useful definitions 33bb86c342Sgavinm * belong in mc_amd.h. 34bb86c342Sgavinm */ 35bb86c342Sgavinm 367aec1d6eScindi #include <sys/types.h> 377aec1d6eScindi #include <sys/ddi.h> 387aec1d6eScindi #include <sys/sunddi.h> 397aec1d6eScindi #include <sys/ksynch.h> 407aec1d6eScindi #include <sys/mc_amd.h> 4120c794b3Sgavinm #include <sys/cpu_module.h> 427aec1d6eScindi #include <mcamd_api.h> 4320c794b3Sgavinm #include <mcamd_err.h> 448a40a695Sgavinm #include <mcamd_dimmcfg.h> 457aec1d6eScindi 467aec1d6eScindi #ifdef __cplusplus 477aec1d6eScindi extern "C" { 487aec1d6eScindi #endif 497aec1d6eScindi 50bb86c342Sgavinm #if MC_CHIP_DIMMPERCS > MC_UNUM_NDIMM 51bb86c342Sgavinm #error "MC_CHIP_DIMMPERCS exceeds MC_UNUM_NDIMM" 52bb86c342Sgavinm #endif 53bb86c342Sgavinm 547aec1d6eScindi /* 55bb86c342Sgavinm * The memory controller configuration registers are accessed via PCI bus 0, 56bb86c342Sgavinm * device 0x18 + nodeid, functions 0 to 3. The function numbers are 57bb86c342Sgavinm * MC_FUNC_*, defined in mc_amd.h. 58bb86c342Sgavinm * 59bb86c342Sgavinm * We do not attach to function 3 "Miscellaneous Control" pci1022,1103 608a40a695Sgavinm * since the agpgart driver already attaches to that function; instead we 618a40a695Sgavinm * retrieve what function 3 parameters we require via direct PCI Mechanism 1 62bb86c342Sgavinm * accesses 63bb86c342Sgavinm * 64bb86c342Sgavinm * The memory controller driver attaches to these device nodes, but publishes 657aec1d6eScindi * a single minor node. We need to ensure that the minor node can be 66bb86c342Sgavinm * consistently mapped back to a single (and the same) device node, so we 67bb86c342Sgavinm * need to pick one to be used. We'll use the dram address map device node, 68bb86c342Sgavinm * as it'll be the last to be attached. 697aec1d6eScindi */ 707aec1d6eScindi #define MC_FUNC_DEVIMAP MC_FUNC_DRAMCTL 71bb86c342Sgavinm #define MC_FUNC_NUM (MC_FUNC_MISCCTL + 1) 727aec1d6eScindi 73bb86c342Sgavinm #define MC_FUNC_HTCONFIG_BINDNM "pci1022,1100" 74bb86c342Sgavinm #define MC_FUNC_ADDRMAP_BINDNM "pci1022,1101" 75bb86c342Sgavinm #define MC_FUNC_DRAMCTL_BINDNM "pci1022,1102" 767aec1d6eScindi 777aec1d6eScindi typedef struct mc_func { 787aec1d6eScindi uint_t mcf_instance; 797aec1d6eScindi dev_info_t *mcf_devi; 807aec1d6eScindi } mc_func_t; 817aec1d6eScindi 827aec1d6eScindi typedef struct mc_dimm mc_dimm_t; 837aec1d6eScindi typedef struct mc_cs mc_cs_t; 847aec1d6eScindi typedef struct mc mc_t; 857aec1d6eScindi 867aec1d6eScindi /* 877aec1d6eScindi * Node types for mch_type below. These are used in array indexing. 887aec1d6eScindi */ 897aec1d6eScindi #define MC_NT_MC 0 907aec1d6eScindi #define MC_NT_CS 1 917aec1d6eScindi #define MC_NT_DIMM 2 927aec1d6eScindi #define MC_NT_NTYPES 3 937aec1d6eScindi 947aec1d6eScindi typedef struct mc_hdr { 957aec1d6eScindi uint_t mch_type; 967aec1d6eScindi union { 977aec1d6eScindi mc_t *_mch_mc; 987aec1d6eScindi mc_cs_t *_mch_cs; 997aec1d6eScindi } _mch_ptr; 1007aec1d6eScindi } mc_hdr_t; 1017aec1d6eScindi 1027aec1d6eScindi #define mch_mc _mch_ptr._mch_mc 1037aec1d6eScindi 1047aec1d6eScindi struct mc_dimm { 1057aec1d6eScindi mc_hdr_t mcd_hdr; /* id, pointer to parent */ 1067aec1d6eScindi mc_dimm_t *mcd_next; /* next dimm for this MC */ 1077aec1d6eScindi mc_cs_t *mcd_cs[MC_CHIP_DIMMRANKMAX]; /* associated chip-selects */ 1088a40a695Sgavinm const mcdcfg_csl_t *mcd_csl[MC_CHIP_DIMMRANKMAX]; /* cs lines */ 1098a40a695Sgavinm mcamd_prop_t mcd_num; /* dimm number */ 1108a40a695Sgavinm mcamd_prop_t mcd_size; /* dimm size in bytes */ 1117aec1d6eScindi }; 1127aec1d6eScindi 1137aec1d6eScindi #define mcd_mc mcd_hdr.mch_mc 1147aec1d6eScindi 1158a40a695Sgavinm /* 1168a40a695Sgavinm * Chip-select properties. If a chip-select is associated with just one 1178a40a695Sgavinm * dimm (whether it be on the A or B dram channel) that number will be 1188a40a695Sgavinm * in csp_dimmnums[0]; if the chip-select is associated with two dimms 1198a40a695Sgavinm * then csp_dimmnums[0] has the dimm from channel A and csp_dimmnums[1] has 1208a40a695Sgavinm * the partner dimm from channel B. 1218a40a695Sgavinm */ 1228a40a695Sgavinm typedef struct mccs_props { 1238a40a695Sgavinm mcamd_prop_t csp_num; /* Chip-select number */ 1248a40a695Sgavinm mcamd_prop_t csp_base; /* DRAM CS Base */ 1258a40a695Sgavinm mcamd_prop_t csp_mask; /* DRAM CS Mask */ 1268a40a695Sgavinm mcamd_prop_t csp_size; /* Chip-select bank size */ 1278a40a695Sgavinm mcamd_prop_t csp_csbe; /* Chip-select bank enable */ 1288a40a695Sgavinm mcamd_prop_t csp_spare; /* Spare */ 1298a40a695Sgavinm mcamd_prop_t csp_testfail; /* TestFail */ 1308a40a695Sgavinm mcamd_prop_t csp_dimmnums[MC_CHIP_DIMMPERCS]; /* dimm(s) in cs */ 1318a40a695Sgavinm mcamd_prop_t csp_dimmrank; /* rank # on dimms */ 1328a40a695Sgavinm } mccs_props_t; 1338a40a695Sgavinm 1348a40a695Sgavinm /* 1358a40a695Sgavinm * Chip-select config register values 1368a40a695Sgavinm */ 1378a40a695Sgavinm typedef struct mccs_cfgrefs { 1388a40a695Sgavinm mcamd_cfgreg_t csr_csbase; /* Raw CS base reg */ 1398a40a695Sgavinm mcamd_cfgreg_t csr_csmask; /* Raw CS mask reg */ 1408a40a695Sgavinm } mccs_cfgregs_t; 1418a40a695Sgavinm 1427aec1d6eScindi struct mc_cs { 1437aec1d6eScindi mc_hdr_t mccs_hdr; /* id, pointer to parent */ 1447aec1d6eScindi mc_cs_t *mccs_next; /* Next chip-select of MC */ 1457aec1d6eScindi mc_dimm_t *mccs_dimm[MC_CHIP_DIMMPERCS]; /* dimms for this cs */ 1468a40a695Sgavinm const mcdcfg_csl_t *mccs_csl[MC_CHIP_DIMMPERCS]; /* cs lines */ 1478a40a695Sgavinm mccs_props_t mccs_props; /* Properties */ 1488a40a695Sgavinm mccs_cfgregs_t mccs_cfgregs; /* Raw config values */ 1497aec1d6eScindi }; 1507aec1d6eScindi 1517aec1d6eScindi #define mccs_mc mccs_hdr.mch_mc 1527aec1d6eScindi 1538a40a695Sgavinm /* 1548a40a695Sgavinm * Memory controller properties. 1558a40a695Sgavinm */ 1567aec1d6eScindi typedef struct mc_props { 1578a40a695Sgavinm mcamd_prop_t mcp_num; /* Associated *chip* number */ 1588a40a695Sgavinm mcamd_prop_t mcp_rev; /* Chip revision (MC_REV_*) */ 1598a40a695Sgavinm mcamd_prop_t mcp_base; /* base address for mc's drams */ 1608a40a695Sgavinm mcamd_prop_t mcp_lim; /* limit address for mc's drams */ 1618a40a695Sgavinm mcamd_prop_t mcp_ilen; /* interleave enable */ 1628a40a695Sgavinm mcamd_prop_t mcp_ilsel; /* interleave select */ 1638a40a695Sgavinm mcamd_prop_t mcp_csintlvfctr; /* cs bank interleave factor */ 1648a40a695Sgavinm mcamd_prop_t mcp_dramhole_size; /* DRAM Hole Size */ 1658a40a695Sgavinm mcamd_prop_t mcp_accwidth; /* dram access width (64 or 128) */ 1668a40a695Sgavinm mcamd_prop_t mcp_csbankmapreg; /* chip-select bank mapping reg */ 1678a40a695Sgavinm mcamd_prop_t mcp_bnkswzl; /* BankSwizzle enabled */ 1688a40a695Sgavinm mcamd_prop_t mcp_mod64mux; /* Mismtached DIMMs support enabled */ 1698a40a695Sgavinm mcamd_prop_t mcp_sparecs; /* cs# replaced by online spare */ 1708a40a695Sgavinm mcamd_prop_t mcp_badcs; /* cs# replaced by online spare */ 1717aec1d6eScindi } mc_props_t; 1727aec1d6eScindi 1738a40a695Sgavinm /* 1748a40a695Sgavinm * Memory controller config register values 1758a40a695Sgavinm */ 1768a40a695Sgavinm typedef struct mc_cfgregs { 1779dd0f810Scindi mcamd_cfgreg_t mcr_htroute[MC_CHIP_MAXNODES]; 1789dd0f810Scindi mcamd_cfgreg_t mcr_htnodeid; 1799dd0f810Scindi mcamd_cfgreg_t mcr_htunitid; 1808a40a695Sgavinm mcamd_cfgreg_t mcr_drambase; 1818a40a695Sgavinm mcamd_cfgreg_t mcr_dramlimit; 1828a40a695Sgavinm mcamd_cfgreg_t mcr_dramhole; 1838a40a695Sgavinm mcamd_cfgreg_t mcr_dramcfglo; 1848a40a695Sgavinm mcamd_cfgreg_t mcr_dramcfghi; 1858a40a695Sgavinm mcamd_cfgreg_t mcr_drammisc; 1868a40a695Sgavinm mcamd_cfgreg_t mcr_nbcfg; 1878a40a695Sgavinm mcamd_cfgreg_t mcr_sparectl; 18820c794b3Sgavinm mcamd_cfgreg_t mcr_scrubctl; 18920c794b3Sgavinm mcamd_cfgreg_t mcr_scrubaddrlo; 19020c794b3Sgavinm mcamd_cfgreg_t mcr_scrubaddrhi; 1918a40a695Sgavinm } mc_cfgregs_t; 1928a40a695Sgavinm 1937aec1d6eScindi struct mc { 1947aec1d6eScindi mc_hdr_t mc_hdr; /* id */ 19520c794b3Sgavinm struct mc *mc_next; /* next MC instance */ 1967aec1d6eScindi const char *mc_revname; /* revision name string */ 1978a40a695Sgavinm uint32_t mc_socket; /* Package type */ 1987aec1d6eScindi uint_t mc_ref; /* reference (attach) count */ 1997aec1d6eScindi mc_func_t mc_funcs[MC_FUNC_NUM]; /* Instance, devinfo, ... */ 2007aec1d6eScindi mc_cs_t *mc_cslist; /* All active chip-selects */ 2017aec1d6eScindi mc_cs_t *mc_cslast; /* End of chip-select list */ 2028a40a695Sgavinm mc_dimm_t *mc_dimmlist; /* List of all logical DIMMs, */ 2038a40a695Sgavinm mc_dimm_t *mc_dimmlast; /* linked via mcd_mcnext */ 2047aec1d6eScindi mc_props_t mc_props; /* Properties */ 2058a40a695Sgavinm mc_cfgregs_t mc_cfgregs; /* Raw config values */ 2068a40a695Sgavinm hrtime_t mc_spareswaptime; /* If initiated by us */ 2077aec1d6eScindi nvlist_t *mc_nvl; /* nvlist for export */ 2087aec1d6eScindi char *mc_snapshot; /* packed nvlist for libmc */ 2097aec1d6eScindi size_t mc_snapshotsz; /* packed nvlist buffer size */ 2107aec1d6eScindi uint_t mc_snapshotgen; /* snapshot generation number */ 2118a40a695Sgavinm int mc_csdiscontig; /* chip-selects discontiguous */ 212*074bb90dSTom Pothier uint_t smb_chipid; /* smbios chip instance */ 213*074bb90dSTom Pothier nvlist_t *smb_bboard; /* smbios chip's parent */ 2147aec1d6eScindi }; 2157aec1d6eScindi 2167aec1d6eScindi typedef struct mcamd_hdl { 2177aec1d6eScindi int mcamd_errno; 2187aec1d6eScindi int mcamd_debug; 2197aec1d6eScindi } mcamd_hdl_t; 2207aec1d6eScindi 2217aec1d6eScindi extern mc_t *mc_list; 2227aec1d6eScindi extern krwlock_t mc_lock; 2237aec1d6eScindi 2247aec1d6eScindi extern void mcamd_mkhdl(mcamd_hdl_t *); 22520c794b3Sgavinm extern void mcamd_mc_register(cmi_hdl_t, mc_t *); 2268a40a695Sgavinm extern void mcamd_ereport_post(mc_t *, const char *, mc_unum_t *, uint64_t); 2277aec1d6eScindi 22820c794b3Sgavinm /* 22920c794b3Sgavinm * mcamd_mc_ops prototypes 23020c794b3Sgavinm */ 23120c794b3Sgavinm extern cmi_errno_t mcamd_patounum_wrap(void *, uint64_t, uint8_t, uint8_t, 23220c794b3Sgavinm uint32_t, int, mc_unum_t *); 23320c794b3Sgavinm extern cmi_errno_t mcamd_unumtopa_wrap(void *, mc_unum_t *, nvlist_t *, 23420c794b3Sgavinm uint64_t *); 23520c794b3Sgavinm 23620c794b3Sgavinm /* 23720c794b3Sgavinm * Internal functions 23820c794b3Sgavinm */ 23920c794b3Sgavinm cmi_errno_t mcamd_cmierr(int, mcamd_hdl_t *); 24020c794b3Sgavinm 2417aec1d6eScindi #ifdef __cplusplus 2427aec1d6eScindi } 2437aec1d6eScindi #endif 2447aec1d6eScindi 2457aec1d6eScindi #endif /* _MCAMD_H */ 246