1e3d60c9bSAdrian Frost /*
2e3d60c9bSAdrian Frost  * CDDL HEADER START
3e3d60c9bSAdrian Frost  *
4e3d60c9bSAdrian Frost  * The contents of this file are subject to the terms of the
5e3d60c9bSAdrian Frost  * Common Development and Distribution License (the "License").
6e3d60c9bSAdrian Frost  * You may not use this file except in compliance with the License.
7e3d60c9bSAdrian Frost  *
8e3d60c9bSAdrian Frost  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9e3d60c9bSAdrian Frost  * or http://www.opensolaris.org/os/licensing.
10e3d60c9bSAdrian Frost  * See the License for the specific language governing permissions
11e3d60c9bSAdrian Frost  * and limitations under the License.
12e3d60c9bSAdrian Frost  *
13e3d60c9bSAdrian Frost  * When distributing Covered Code, include this CDDL HEADER in each
14e3d60c9bSAdrian Frost  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15e3d60c9bSAdrian Frost  * If applicable, add the following below this CDDL HEADER, with the
16e3d60c9bSAdrian Frost  * fields enclosed by brackets "[]" replaced with your own identifying
17e3d60c9bSAdrian Frost  * information: Portions Copyright [yyyy] [name of copyright owner]
18e3d60c9bSAdrian Frost  *
19e3d60c9bSAdrian Frost  * CDDL HEADER END
20e3d60c9bSAdrian Frost  */
21e3d60c9bSAdrian Frost 
22e3d60c9bSAdrian Frost /*
23f657cd55SCheng Sean Ye  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24e3d60c9bSAdrian Frost  * Use is subject to license terms.
25e3d60c9bSAdrian Frost  */
26e3d60c9bSAdrian Frost 
27e3d60c9bSAdrian Frost #include <sys/types.h>
28e3d60c9bSAdrian Frost #include <sys/cmn_err.h>
29e3d60c9bSAdrian Frost #include <sys/errno.h>
30e3d60c9bSAdrian Frost #include <sys/log.h>
31e3d60c9bSAdrian Frost #include <sys/systm.h>
32e3d60c9bSAdrian Frost #include <sys/modctl.h>
33e3d60c9bSAdrian Frost #include <sys/errorq.h>
34e3d60c9bSAdrian Frost #include <sys/controlregs.h>
35e3d60c9bSAdrian Frost #include <sys/fm/util.h>
36e3d60c9bSAdrian Frost #include <sys/fm/protocol.h>
37e3d60c9bSAdrian Frost #include <sys/sysevent.h>
38e3d60c9bSAdrian Frost #include <sys/pghw.h>
39e3d60c9bSAdrian Frost #include <sys/cyclic.h>
40e3d60c9bSAdrian Frost #include <sys/pci_cfgspace.h>
41e3d60c9bSAdrian Frost #include <sys/mc_intel.h>
42e3d60c9bSAdrian Frost #include <sys/cpu_module_impl.h>
43e3d60c9bSAdrian Frost #include <sys/smbios.h>
44e3d60c9bSAdrian Frost #include <sys/pci.h>
45e3d60c9bSAdrian Frost #include "intel_nhm.h"
46e3d60c9bSAdrian Frost #include "nhm_log.h"
47e3d60c9bSAdrian Frost 
48e3d60c9bSAdrian Frost errorq_t *nhm_queue;
49e3d60c9bSAdrian Frost kmutex_t nhm_mutex;
50e3d60c9bSAdrian Frost uint32_t nhm_chipset;
51e3d60c9bSAdrian Frost 
52e3d60c9bSAdrian Frost nhm_dimm_t **nhm_dimms;
53e3d60c9bSAdrian Frost 
54e3d60c9bSAdrian Frost uint64_t nhm_memory_on_ctl[MAX_MEMORY_CONTROLLERS];
55e3d60c9bSAdrian Frost int nhm_patrol_scrub;
56e3d60c9bSAdrian Frost int nhm_demand_scrub;
57e3d60c9bSAdrian Frost int nhm_no_smbios;
58e3d60c9bSAdrian Frost int nhm_smbios_serial;
59e3d60c9bSAdrian Frost int nhm_smbios_manufacturer;
60e3d60c9bSAdrian Frost int nhm_smbios_part_number;
61e3d60c9bSAdrian Frost int nhm_smbios_version;
62e3d60c9bSAdrian Frost int nhm_smbios_label;
63e3d60c9bSAdrian Frost 
64e3d60c9bSAdrian Frost extern char ecc_enabled;
65e3d60c9bSAdrian Frost extern void mem_reg_init(void);
66e3d60c9bSAdrian Frost 
67e3d60c9bSAdrian Frost static void
check_serial_number()68e3d60c9bSAdrian Frost check_serial_number()
69e3d60c9bSAdrian Frost {
70e3d60c9bSAdrian Frost 	nhm_dimm_t *dimmp, *tp;
71e3d60c9bSAdrian Frost 	nhm_dimm_t **dimmpp, **tpp;
72e3d60c9bSAdrian Frost 	nhm_dimm_t **end;
73e3d60c9bSAdrian Frost 	int not_unique;
74e3d60c9bSAdrian Frost 
75e3d60c9bSAdrian Frost 	end = &nhm_dimms[MAX_MEMORY_CONTROLLERS *
76e3d60c9bSAdrian Frost 	    CHANNELS_PER_MEMORY_CONTROLLER * MAX_DIMMS_PER_CHANNEL];
77e3d60c9bSAdrian Frost 	for (dimmpp = nhm_dimms; dimmpp < end; dimmpp++) {
78e3d60c9bSAdrian Frost 		dimmp = *dimmpp;
79e3d60c9bSAdrian Frost 		if (dimmp == NULL)
80e3d60c9bSAdrian Frost 			continue;
81e3d60c9bSAdrian Frost 		not_unique = 0;
82e3d60c9bSAdrian Frost 		for (tpp = dimmpp + 1; tpp < end; tpp++) {
83e3d60c9bSAdrian Frost 			tp = *tpp;
84e3d60c9bSAdrian Frost 			if (tp == NULL)
85e3d60c9bSAdrian Frost 				continue;
86e3d60c9bSAdrian Frost 			if (strncmp(dimmp->serial_number, tp->serial_number,
87e3d60c9bSAdrian Frost 			    sizeof (dimmp->serial_number)) == 0) {
88e3d60c9bSAdrian Frost 				not_unique = 1;
89e3d60c9bSAdrian Frost 				tp->serial_number[0] = 0;
90e3d60c9bSAdrian Frost 			}
91e3d60c9bSAdrian Frost 		}
92e3d60c9bSAdrian Frost 		if (not_unique)
93e3d60c9bSAdrian Frost 			dimmp->serial_number[0] = 0;
94e3d60c9bSAdrian Frost 	}
95e3d60c9bSAdrian Frost }
96e3d60c9bSAdrian Frost 
97e3d60c9bSAdrian Frost static void
dimm_manufacture_data(smbios_hdl_t * shp,id_t id,nhm_dimm_t * dimmp)98e3d60c9bSAdrian Frost dimm_manufacture_data(smbios_hdl_t *shp, id_t id, nhm_dimm_t *dimmp)
99e3d60c9bSAdrian Frost {
100e3d60c9bSAdrian Frost 	smbios_info_t cd;
101e3d60c9bSAdrian Frost 
102e3d60c9bSAdrian Frost 	if (smbios_info_common(shp, id, &cd) == 0) {
103e3d60c9bSAdrian Frost 		if (cd.smbi_serial && nhm_smbios_serial) {
104e3d60c9bSAdrian Frost 			(void) strncpy(dimmp->serial_number, cd.smbi_serial,
105e3d60c9bSAdrian Frost 			    sizeof (dimmp->serial_number));
106e3d60c9bSAdrian Frost 		}
107e3d60c9bSAdrian Frost 		if (cd.smbi_manufacturer && nhm_smbios_manufacturer) {
108e3d60c9bSAdrian Frost 			(void) strncpy(dimmp->manufacturer,
109e3d60c9bSAdrian Frost 			    cd.smbi_manufacturer,
110e3d60c9bSAdrian Frost 			    sizeof (dimmp->manufacturer));
111e3d60c9bSAdrian Frost 		}
112e3d60c9bSAdrian Frost 		if (cd.smbi_part && nhm_smbios_part_number) {
113e3d60c9bSAdrian Frost 			(void) strncpy(dimmp->part_number, cd.smbi_part,
114e3d60c9bSAdrian Frost 			    sizeof (dimmp->part_number));
115e3d60c9bSAdrian Frost 		}
116e3d60c9bSAdrian Frost 		if (cd.smbi_version && nhm_smbios_version) {
117e3d60c9bSAdrian Frost 			(void) strncpy(dimmp->revision, cd.smbi_version,
118e3d60c9bSAdrian Frost 			    sizeof (dimmp->revision));
119e3d60c9bSAdrian Frost 		}
120e3d60c9bSAdrian Frost 	}
121e3d60c9bSAdrian Frost }
122e3d60c9bSAdrian Frost 
123e3d60c9bSAdrian Frost struct dimm_slot {
124e3d60c9bSAdrian Frost 	int controller;
125e3d60c9bSAdrian Frost 	int channel;
126e3d60c9bSAdrian Frost 	int dimm;
127e3d60c9bSAdrian Frost 	int max_dimm;
128e3d60c9bSAdrian Frost };
129e3d60c9bSAdrian Frost 
130e3d60c9bSAdrian Frost static int
dimm_label(smbios_hdl_t * shp,const smbios_struct_t * sp,void * arg)131e3d60c9bSAdrian Frost dimm_label(smbios_hdl_t *shp, const smbios_struct_t *sp, void *arg)
132e3d60c9bSAdrian Frost {
133e3d60c9bSAdrian Frost 	nhm_dimm_t *dimmp;
134e3d60c9bSAdrian Frost 	smbios_memdevice_t md;
135e3d60c9bSAdrian Frost 	int slot;
136e3d60c9bSAdrian Frost 	int last_slot;
137e3d60c9bSAdrian Frost 	struct dimm_slot *dsp = (struct dimm_slot *)arg;
138e3d60c9bSAdrian Frost 
139e3d60c9bSAdrian Frost 	slot = (dsp->controller * CHANNELS_PER_MEMORY_CONTROLLER *
140e3d60c9bSAdrian Frost 	    MAX_DIMMS_PER_CHANNEL) + (dsp->channel * MAX_DIMMS_PER_CHANNEL) +
141e3d60c9bSAdrian Frost 	    dsp->dimm;
142e3d60c9bSAdrian Frost 	last_slot = MAX_MEMORY_CONTROLLERS * CHANNELS_PER_MEMORY_CONTROLLER *
143e3d60c9bSAdrian Frost 	    MAX_DIMMS_PER_CHANNEL;
144e3d60c9bSAdrian Frost 	if (slot >= last_slot)
145e3d60c9bSAdrian Frost 		return (0);
146e3d60c9bSAdrian Frost 	dimmp = nhm_dimms[slot];
147e3d60c9bSAdrian Frost 	if (sp->smbstr_type == SMB_TYPE_MEMDEVICE) {
148e3d60c9bSAdrian Frost 		if (smbios_info_memdevice(shp, sp->smbstr_id,
149e3d60c9bSAdrian Frost 		    &md) == 0 && md.smbmd_dloc != NULL) {
150e3d60c9bSAdrian Frost 			if (dimmp == NULL && md.smbmd_size) {
151e3d60c9bSAdrian Frost 				/* skip non existent slot */
152e3d60c9bSAdrian Frost 				dsp->channel++;
153e3d60c9bSAdrian Frost 				if (dsp->dimm == 2)
154e3d60c9bSAdrian Frost 					dsp->max_dimm = 2;
155e3d60c9bSAdrian Frost 				dsp->dimm = 0;
156e3d60c9bSAdrian Frost 				slot = (dsp->controller *
157e3d60c9bSAdrian Frost 				    CHANNELS_PER_MEMORY_CONTROLLER *
158e3d60c9bSAdrian Frost 				    MAX_DIMMS_PER_CHANNEL) +
159e3d60c9bSAdrian Frost 				    (dsp->channel * MAX_DIMMS_PER_CHANNEL);
160e3d60c9bSAdrian Frost 				if (slot >= last_slot)
161e3d60c9bSAdrian Frost 					return (0);
162e3d60c9bSAdrian Frost 
163e3d60c9bSAdrian Frost 				dimmp = nhm_dimms[slot];
164e3d60c9bSAdrian Frost 
165e3d60c9bSAdrian Frost 				if (dimmp == NULL) {
166e3d60c9bSAdrian Frost 					dsp->channel++;
167e3d60c9bSAdrian Frost 					if (dsp->channel ==
168e3d60c9bSAdrian Frost 					    CHANNELS_PER_MEMORY_CONTROLLER) {
169e3d60c9bSAdrian Frost 						dsp->channel = 0;
170e3d60c9bSAdrian Frost 						dsp->controller++;
171e3d60c9bSAdrian Frost 					}
172e3d60c9bSAdrian Frost 					slot = (dsp->controller *
173e3d60c9bSAdrian Frost 					    CHANNELS_PER_MEMORY_CONTROLLER *
174e3d60c9bSAdrian Frost 					    MAX_DIMMS_PER_CHANNEL) +
175e3d60c9bSAdrian Frost 					    (dsp->channel *
176e3d60c9bSAdrian Frost 					    MAX_DIMMS_PER_CHANNEL);
177e3d60c9bSAdrian Frost 					if (slot >= last_slot)
178e3d60c9bSAdrian Frost 						return (0);
179e3d60c9bSAdrian Frost 					dimmp = nhm_dimms[slot];
180e3d60c9bSAdrian Frost 				}
181e3d60c9bSAdrian Frost 			}
182e3d60c9bSAdrian Frost 			if (dimmp) {
183e3d60c9bSAdrian Frost 				if (nhm_smbios_label)
184e3d60c9bSAdrian Frost 					(void) snprintf(dimmp->label,
185e3d60c9bSAdrian Frost 					    sizeof (dimmp->label), "%s",
186e3d60c9bSAdrian Frost 					    md.smbmd_dloc);
187e3d60c9bSAdrian Frost 				dimm_manufacture_data(shp, sp->smbstr_id,
188e3d60c9bSAdrian Frost 				    dimmp);
189e3d60c9bSAdrian Frost 			}
190e3d60c9bSAdrian Frost 		}
191e3d60c9bSAdrian Frost 		dsp->dimm++;
192e3d60c9bSAdrian Frost 		if (dsp->dimm == dsp->max_dimm) {
193e3d60c9bSAdrian Frost 			dsp->dimm = 0;
194e3d60c9bSAdrian Frost 			dsp->channel++;
195e3d60c9bSAdrian Frost 			if (dsp->channel == CHANNELS_PER_MEMORY_CONTROLLER) {
196e3d60c9bSAdrian Frost 				dsp->channel = 0;
197e3d60c9bSAdrian Frost 				dsp->controller++;
198e3d60c9bSAdrian Frost 			}
199e3d60c9bSAdrian Frost 		}
200e3d60c9bSAdrian Frost 	}
201e3d60c9bSAdrian Frost 	return (0);
202e3d60c9bSAdrian Frost }
203e3d60c9bSAdrian Frost 
204e3d60c9bSAdrian Frost void
nhm_smbios()205e3d60c9bSAdrian Frost nhm_smbios()
206e3d60c9bSAdrian Frost {
207e3d60c9bSAdrian Frost 	struct dimm_slot ds;
208e3d60c9bSAdrian Frost 
209e3d60c9bSAdrian Frost 	if (ksmbios != NULL && nhm_no_smbios == 0) {
210e3d60c9bSAdrian Frost 		ds.dimm = 0;
211e3d60c9bSAdrian Frost 		ds.channel = 0;
212e3d60c9bSAdrian Frost 		ds.controller = 0;
213e3d60c9bSAdrian Frost 		ds.max_dimm = MAX_DIMMS_PER_CHANNEL;
214e3d60c9bSAdrian Frost 		(void) smbios_iter(ksmbios, dimm_label, &ds);
215e3d60c9bSAdrian Frost 		check_serial_number();
216e3d60c9bSAdrian Frost 	}
217e3d60c9bSAdrian Frost }
218e3d60c9bSAdrian Frost 
219e3d60c9bSAdrian Frost static void
dimm_prop(nhm_dimm_t * dimmp,uint32_t dod)220e3d60c9bSAdrian Frost dimm_prop(nhm_dimm_t *dimmp, uint32_t dod)
221e3d60c9bSAdrian Frost {
222e3d60c9bSAdrian Frost 	dimmp->dimm_size = DIMMSIZE(dod);
223e3d60c9bSAdrian Frost 	dimmp->nranks = NUMRANK(dod);
224e3d60c9bSAdrian Frost 	dimmp->nbanks = NUMBANK(dod);
225e3d60c9bSAdrian Frost 	dimmp->ncolumn = NUMCOL(dod);
226e3d60c9bSAdrian Frost 	dimmp->nrow = NUMROW(dod);
227e3d60c9bSAdrian Frost 	dimmp->width = DIMMWIDTH;
228e3d60c9bSAdrian Frost }
229e3d60c9bSAdrian Frost 
230e3d60c9bSAdrian Frost void
nhm_scrubber_enable()231e3d60c9bSAdrian Frost nhm_scrubber_enable()
232e3d60c9bSAdrian Frost {
233e3d60c9bSAdrian Frost 	uint32_t mc_ssrcontrol;
234e3d60c9bSAdrian Frost 	uint32_t mc_dimm_clk_ratio_status;
235e3d60c9bSAdrian Frost 	uint64_t cycle_time;
236e3d60c9bSAdrian Frost 	uint32_t interval;
237*35366b93SAdrian Frost 	uint32_t id;
238e3d60c9bSAdrian Frost 	int i;
239e3d60c9bSAdrian Frost 	int hw_scrub = 0;
240e3d60c9bSAdrian Frost 
241e3d60c9bSAdrian Frost 	if (ecc_enabled && (nhm_patrol_scrub || nhm_demand_scrub)) {
242e3d60c9bSAdrian Frost 		for (i = 0; i < MAX_MEMORY_CONTROLLERS; i++) {
243*35366b93SAdrian Frost 			id = MC_CPU_RAS_RD(i);
244*35366b93SAdrian Frost 			if ((id != NHM_CPU_RAS && id != NHM_JF_CPU_RAS &&
245*35366b93SAdrian Frost 			    id != NHM_WM_CPU_RAS) || nhm_memory_on_ctl[i] == 0)
246e3d60c9bSAdrian Frost 				continue;
247e3d60c9bSAdrian Frost 			mc_ssrcontrol = MC_SSR_CONTROL_RD(i);
248e3d60c9bSAdrian Frost 			if (nhm_demand_scrub &&
249e3d60c9bSAdrian Frost 			    (mc_ssrcontrol & DEMAND_SCRUB_ENABLE) == 0) {
250e3d60c9bSAdrian Frost 				mc_ssrcontrol |= DEMAND_SCRUB_ENABLE;
251e3d60c9bSAdrian Frost 				MC_SSR_CONTROL_WR(i, mc_ssrcontrol);
252e3d60c9bSAdrian Frost 			}
253e3d60c9bSAdrian Frost 			if (nhm_patrol_scrub == 0)
254e3d60c9bSAdrian Frost 				continue;
255e3d60c9bSAdrian Frost 			if (SSR_MODE(mc_ssrcontrol) == SSR_IDLE) {
256e3d60c9bSAdrian Frost 				mc_dimm_clk_ratio_status =
257e3d60c9bSAdrian Frost 				    MC_DIMM_CLK_RATIO_STATUS(i);
258e3d60c9bSAdrian Frost 				cycle_time =
259e3d60c9bSAdrian Frost 				    MAX_DIMM_CLK_RATIO(mc_dimm_clk_ratio_status)
260e3d60c9bSAdrian Frost 				    * 80000000;
261e3d60c9bSAdrian Frost 				interval = (uint32_t)((36400ULL * cycle_time) /
262e3d60c9bSAdrian Frost 				    (nhm_memory_on_ctl[i]/64));
263e3d60c9bSAdrian Frost 				MC_SCRUB_CONTROL_WR(i, STARTSCRUB | interval);
264e3d60c9bSAdrian Frost 				MC_SSR_CONTROL_WR(i, mc_ssrcontrol | SSR_SCRUB);
265e3d60c9bSAdrian Frost 			} else if (SSR_MODE(mc_ssrcontrol) == SSR_SPARE) {
266e3d60c9bSAdrian Frost 				hw_scrub = 0;
267e3d60c9bSAdrian Frost 				break;
268e3d60c9bSAdrian Frost 			}
269e3d60c9bSAdrian Frost 			hw_scrub = 1;
270e3d60c9bSAdrian Frost 		}
271e3d60c9bSAdrian Frost 		if (hw_scrub)
272f657cd55SCheng Sean Ye 			cmi_mc_sw_memscrub_disable();
273e3d60c9bSAdrian Frost 	}
274e3d60c9bSAdrian Frost }
275e3d60c9bSAdrian Frost 
276e3d60c9bSAdrian Frost void
init_dimms()277e3d60c9bSAdrian Frost init_dimms()
278e3d60c9bSAdrian Frost {
279e3d60c9bSAdrian Frost 	int i, j, k;
280e3d60c9bSAdrian Frost 	nhm_dimm_t **dimmpp;
281e3d60c9bSAdrian Frost 	nhm_dimm_t *dimmp;
282e3d60c9bSAdrian Frost 	uint32_t dod;
283ee9ef9e5SAdrian Frost 	uint32_t did;
284e3d60c9bSAdrian Frost 
285e3d60c9bSAdrian Frost 	nhm_dimms = (nhm_dimm_t **)kmem_zalloc(sizeof (nhm_dimm_t *) *
286e3d60c9bSAdrian Frost 	    MAX_MEMORY_CONTROLLERS * CHANNELS_PER_MEMORY_CONTROLLER *
287e3d60c9bSAdrian Frost 	    MAX_DIMMS_PER_CHANNEL, KM_SLEEP);
288e3d60c9bSAdrian Frost 	dimmpp = nhm_dimms;
289e3d60c9bSAdrian Frost 	for (i = 0; i < MAX_MEMORY_CONTROLLERS; i++) {
290ee9ef9e5SAdrian Frost 		did = CPU_ID_RD(i);
291*35366b93SAdrian Frost 		if (did != NHM_EP_CPU && did != NHM_WS_CPU &&
292*35366b93SAdrian Frost 		    did != NHM_JF_CPU && did != NHM_WM_CPU) {
293e3d60c9bSAdrian Frost 			dimmpp += CHANNELS_PER_MEMORY_CONTROLLER *
294e3d60c9bSAdrian Frost 			    MAX_DIMMS_PER_CHANNEL;
295e3d60c9bSAdrian Frost 			continue;
296e3d60c9bSAdrian Frost 		}
297e3d60c9bSAdrian Frost 		for (j = 0; j < CHANNELS_PER_MEMORY_CONTROLLER; j++) {
298e3d60c9bSAdrian Frost 			for (k = 0; k < MAX_DIMMS_PER_CHANNEL; k++) {
299e3d60c9bSAdrian Frost 				dod = MC_DOD_RD(i, j, k);
300e3d60c9bSAdrian Frost 				if (DIMMPRESENT(dod)) {
301e3d60c9bSAdrian Frost 					dimmp = (nhm_dimm_t *)
302e3d60c9bSAdrian Frost 					    kmem_zalloc(sizeof (nhm_dimm_t),
303e3d60c9bSAdrian Frost 					    KM_SLEEP);
304e3d60c9bSAdrian Frost 					dimm_prop(dimmp, dod);
305e3d60c9bSAdrian Frost 					(void) snprintf(dimmp->label,
306e3d60c9bSAdrian Frost 					    sizeof (dimmp->label),
307e3d60c9bSAdrian Frost 					    "Socket %d channel %d dimm %d",
308e3d60c9bSAdrian Frost 					    i, j, k);
309e3d60c9bSAdrian Frost 					*dimmpp = dimmp;
310e3d60c9bSAdrian Frost 					nhm_memory_on_ctl[i] +=
311e3d60c9bSAdrian Frost 					    dimmp->dimm_size;
312e3d60c9bSAdrian Frost 				}
313e3d60c9bSAdrian Frost 				dimmpp++;
314e3d60c9bSAdrian Frost 			}
315e3d60c9bSAdrian Frost 		}
316e3d60c9bSAdrian Frost 	}
317e3d60c9bSAdrian Frost }
318e3d60c9bSAdrian Frost 
319e3d60c9bSAdrian Frost 
320e3d60c9bSAdrian Frost int
nhm_init(void)321e3d60c9bSAdrian Frost nhm_init(void)
322e3d60c9bSAdrian Frost {
323e3d60c9bSAdrian Frost 	int slot;
324e3d60c9bSAdrian Frost 
325e3d60c9bSAdrian Frost 	/* return ENOTSUP if there is no PCI config space support. */
326e3d60c9bSAdrian Frost 	if (pci_getl_func == NULL)
327e3d60c9bSAdrian Frost 		return (ENOTSUP);
328e3d60c9bSAdrian Frost 	for (slot = 0; slot < MAX_CPU_NODES; slot++) {
329e3d60c9bSAdrian Frost 		nhm_chipset = CPU_ID_RD(slot);
330*35366b93SAdrian Frost 		if (nhm_chipset == NHM_EP_CPU || nhm_chipset == NHM_WS_CPU ||
331*35366b93SAdrian Frost 		    nhm_chipset == NHM_JF_CPU || nhm_chipset == NHM_WM_CPU)
332e3d60c9bSAdrian Frost 			break;
333e3d60c9bSAdrian Frost 	}
334*35366b93SAdrian Frost 	if (slot == MAX_CPU_NODES) {
335e3d60c9bSAdrian Frost 		return (ENOTSUP);
336e3d60c9bSAdrian Frost 	}
337e3d60c9bSAdrian Frost 	mem_reg_init();
338e3d60c9bSAdrian Frost 	return (0);
339e3d60c9bSAdrian Frost }
340e3d60c9bSAdrian Frost 
341e3d60c9bSAdrian Frost int
nhm_reinit(void)342e3d60c9bSAdrian Frost nhm_reinit(void)
343e3d60c9bSAdrian Frost {
344e3d60c9bSAdrian Frost 	mem_reg_init();
345e3d60c9bSAdrian Frost 	return (0);
346e3d60c9bSAdrian Frost }
347e3d60c9bSAdrian Frost 
348e3d60c9bSAdrian Frost int
nhm_dev_init()349e3d60c9bSAdrian Frost nhm_dev_init()
350e3d60c9bSAdrian Frost {
351e3d60c9bSAdrian Frost 	return (0);
352e3d60c9bSAdrian Frost }
353e3d60c9bSAdrian Frost 
354e3d60c9bSAdrian Frost void
nhm_dev_reinit()355e3d60c9bSAdrian Frost nhm_dev_reinit()
356e3d60c9bSAdrian Frost {
357e3d60c9bSAdrian Frost }
358e3d60c9bSAdrian Frost 
359e3d60c9bSAdrian Frost void
nhm_unload()360e3d60c9bSAdrian Frost nhm_unload()
361e3d60c9bSAdrian Frost {
362e3d60c9bSAdrian Frost }
363