xref: /dflybsd-src/sys/dev/misc/coremctl/coremctl.c (revision 0c1d7dca433e727c476aff53acb839b357a28ef6)
1f7409137SSepherosa Ziehau /*
2f7409137SSepherosa Ziehau  * Copyright (c) 2015 The DragonFly Project.  All rights reserved.
3f7409137SSepherosa Ziehau  *
4f7409137SSepherosa Ziehau  * This code is derived from software contributed to The DragonFly Project
5f7409137SSepherosa Ziehau  * by Sepherosa Ziehau <sepherosa@gmail.com>
6f7409137SSepherosa Ziehau  *
7f7409137SSepherosa Ziehau  * Redistribution and use in source and binary forms, with or without
8f7409137SSepherosa Ziehau  * modification, are permitted provided that the following conditions
9f7409137SSepherosa Ziehau  * are met:
10f7409137SSepherosa Ziehau  *
11f7409137SSepherosa Ziehau  * 1. Redistributions of source code must retain the above copyright
12f7409137SSepherosa Ziehau  *    notice, this list of conditions and the following disclaimer.
13f7409137SSepherosa Ziehau  * 2. Redistributions in binary form must reproduce the above copyright
14f7409137SSepherosa Ziehau  *    notice, this list of conditions and the following disclaimer in
15f7409137SSepherosa Ziehau  *    the documentation and/or other materials provided with the
16f7409137SSepherosa Ziehau  *    distribution.
17f7409137SSepherosa Ziehau  * 3. Neither the name of The DragonFly Project nor the names of its
18f7409137SSepherosa Ziehau  *    contributors may be used to endorse or promote products derived
19f7409137SSepherosa Ziehau  *    from this software without specific, prior written permission.
20f7409137SSepherosa Ziehau  *
21f7409137SSepherosa Ziehau  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22f7409137SSepherosa Ziehau  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23f7409137SSepherosa Ziehau  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24f7409137SSepherosa Ziehau  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
25f7409137SSepherosa Ziehau  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26f7409137SSepherosa Ziehau  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27f7409137SSepherosa Ziehau  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28f7409137SSepherosa Ziehau  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29f7409137SSepherosa Ziehau  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30f7409137SSepherosa Ziehau  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31f7409137SSepherosa Ziehau  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32f7409137SSepherosa Ziehau  * SUCH DAMAGE.
33f7409137SSepherosa Ziehau  */
34f7409137SSepherosa Ziehau 
35f7409137SSepherosa Ziehau #include <sys/param.h>
36f7409137SSepherosa Ziehau #include <sys/systm.h>
37f7409137SSepherosa Ziehau #include <sys/bus.h>
38f7409137SSepherosa Ziehau #include <sys/kernel.h>
39f7409137SSepherosa Ziehau #include <sys/malloc.h>
40f7409137SSepherosa Ziehau #include <sys/bitops.h>
41f7409137SSepherosa Ziehau 
42f7409137SSepherosa Ziehau #include <bus/pci/pcivar.h>
43f7409137SSepherosa Ziehau #include <bus/pci/pcireg.h>
44f7409137SSepherosa Ziehau #include <bus/pci/pci_cfgreg.h>
45f7409137SSepherosa Ziehau 
46f7409137SSepherosa Ziehau #include <vm/pmap.h>
47f7409137SSepherosa Ziehau 
48f7409137SSepherosa Ziehau #include "coremctl_if.h"
49f7409137SSepherosa Ziehau #include "pcib_if.h"
50f7409137SSepherosa Ziehau 
51f7409137SSepherosa Ziehau #include <dev/misc/coremctl/coremctl_reg.h>
52f7409137SSepherosa Ziehau 
53f7409137SSepherosa Ziehau #define COREMCTL_VER_1	1	/* Sandy Bridge */
54f7409137SSepherosa Ziehau #define COREMCTL_VER_2	2	/* Ivy Bridge */
55f7409137SSepherosa Ziehau #define COREMCTL_VER_3	3	/* Haswell */
56f7409137SSepherosa Ziehau 
57f7409137SSepherosa Ziehau struct coremctl_type {
58f7409137SSepherosa Ziehau 	uint16_t	did;
59f7409137SSepherosa Ziehau 	const char	*desc;
60f7409137SSepherosa Ziehau 	int		ver;		/* COREMCTL_VER_ */
61f7409137SSepherosa Ziehau };
62f7409137SSepherosa Ziehau 
63f7409137SSepherosa Ziehau struct coremctl_softc {
64f7409137SSepherosa Ziehau 	device_t	sc_dev;
65f7409137SSepherosa Ziehau 	int		sc_ver;	/* COREMCTL_VER_ */
66f7409137SSepherosa Ziehau 	device_t	sc_ecc;
67*d9902073SSepherosa Ziehau 	device_t	sc_temp;
68f7409137SSepherosa Ziehau 	volatile uint8_t *sc_mch;
69f7409137SSepherosa Ziehau };
70f7409137SSepherosa Ziehau 
71*d9902073SSepherosa Ziehau #define CSR_READ_4(sc, ofs)		\
72*d9902073SSepherosa Ziehau 	(*(volatile uint32_t *)((sc)->sc_mch + (ofs)))
73*d9902073SSepherosa Ziehau #define CSR_WRITE_4(sc, ofs, val)	\
74*d9902073SSepherosa Ziehau 	(*(volatile uint32_t *)((sc)->sc_mch + (ofs)) = (val))
75f7409137SSepherosa Ziehau 
76f7409137SSepherosa Ziehau static void	coremctl_identify(driver_t *, device_t);
77f7409137SSepherosa Ziehau static int	coremctl_probe(device_t);
78f7409137SSepherosa Ziehau static int	coremctl_attach(device_t);
79f7409137SSepherosa Ziehau static int	coremctl_detach(device_t);
80f7409137SSepherosa Ziehau static int	coremctl_mch_readreg(device_t, int, uint32_t *);
81*d9902073SSepherosa Ziehau static int	coremctl_mch_writereg(device_t, int, uint32_t);
82f7409137SSepherosa Ziehau static int	coremctl_pci_read_ivar(device_t, device_t, int, uintptr_t *);
83f7409137SSepherosa Ziehau static uint32_t	coremctl_pci_read_config(device_t, device_t, int, int);
84f7409137SSepherosa Ziehau static void	coremctl_pci_write_config(device_t, device_t, int, uint32_t,
85f7409137SSepherosa Ziehau 		    int);
86f7409137SSepherosa Ziehau 
87f7409137SSepherosa Ziehau static void	coremctl_chaninfo(struct coremctl_softc *, uint32_t,
88f7409137SSepherosa Ziehau 		    const char *);
89f7409137SSepherosa Ziehau 
90f7409137SSepherosa Ziehau static const struct coremctl_type coremctl_types[] = {
91f7409137SSepherosa Ziehau 	{ PCI_E3V1_MEMCTL_DID, "Intel E3 memory controller",
92f7409137SSepherosa Ziehau 	  COREMCTL_VER_1 },
93f7409137SSepherosa Ziehau 
94f7409137SSepherosa Ziehau 	{ PCI_E3V2_MEMCTL_DID, "Intel E3 v2 memory controller",
95f7409137SSepherosa Ziehau 	  COREMCTL_VER_2 },
96f7409137SSepherosa Ziehau 
97f7409137SSepherosa Ziehau 	{ PCI_E3V3_MEMCTL_DID, "Intel E3 v3 memory controller",
98f7409137SSepherosa Ziehau 	  COREMCTL_VER_3 },
99f7409137SSepherosa Ziehau 
100f7409137SSepherosa Ziehau 	{ PCI_COREV3_MEMCTL_DID, "Intel i3/i5/i7 Haswell memory controller",
101f7409137SSepherosa Ziehau 	  COREMCTL_VER_3 },
102f7409137SSepherosa Ziehau 
103f7409137SSepherosa Ziehau 	{ 0, NULL, 0 } /* required last entry */
104f7409137SSepherosa Ziehau };
105f7409137SSepherosa Ziehau 
106f7409137SSepherosa Ziehau static device_method_t coremctl_methods[] = {
107f7409137SSepherosa Ziehau 	/* Device interface */
108f7409137SSepherosa Ziehau 	DEVMETHOD(device_identify,	coremctl_identify),
109f7409137SSepherosa Ziehau 	DEVMETHOD(device_probe,		coremctl_probe),
110f7409137SSepherosa Ziehau 	DEVMETHOD(device_attach,	coremctl_attach),
111f7409137SSepherosa Ziehau 	DEVMETHOD(device_detach,	coremctl_detach),
112f7409137SSepherosa Ziehau 	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
113f7409137SSepherosa Ziehau 	DEVMETHOD(device_suspend,	bus_generic_suspend),
114f7409137SSepherosa Ziehau 	DEVMETHOD(device_resume,	bus_generic_resume),
115f7409137SSepherosa Ziehau 
116f7409137SSepherosa Ziehau 	/* Bus interface */
117f7409137SSepherosa Ziehau 	DEVMETHOD(bus_read_ivar,	coremctl_pci_read_ivar),
118f7409137SSepherosa Ziehau 
119f7409137SSepherosa Ziehau 	/* PCI interface */
120f7409137SSepherosa Ziehau 	DEVMETHOD(pci_read_config,	coremctl_pci_read_config),
121f7409137SSepherosa Ziehau 	DEVMETHOD(pci_write_config,	coremctl_pci_write_config),
122f7409137SSepherosa Ziehau 
123f7409137SSepherosa Ziehau 	/* Core memory controller interface */
124f7409137SSepherosa Ziehau 	DEVMETHOD(coremctl_mch_read,	coremctl_mch_readreg),
125*d9902073SSepherosa Ziehau 	DEVMETHOD(coremctl_mch_write,	coremctl_mch_writereg),
126f7409137SSepherosa Ziehau 
127f7409137SSepherosa Ziehau 	DEVMETHOD_END
128f7409137SSepherosa Ziehau };
129f7409137SSepherosa Ziehau 
130f7409137SSepherosa Ziehau static driver_t coremctl_driver = {
131f7409137SSepherosa Ziehau 	"coremctl",
132f7409137SSepherosa Ziehau 	coremctl_methods,
133f7409137SSepherosa Ziehau 	sizeof(struct coremctl_softc)
134f7409137SSepherosa Ziehau };
135f7409137SSepherosa Ziehau static devclass_t coremctl_devclass;
136f7409137SSepherosa Ziehau 
137f7409137SSepherosa Ziehau DRIVER_MODULE(coremctl, hostb, coremctl_driver, coremctl_devclass, NULL, NULL);
138f7409137SSepherosa Ziehau MODULE_VERSION(coremctl, 1);
139f7409137SSepherosa Ziehau MODULE_DEPEND(coremctl, pci, 1, 1, 1);
140f7409137SSepherosa Ziehau 
141f7409137SSepherosa Ziehau static void
coremctl_identify(driver_t * driver,device_t parent)142f7409137SSepherosa Ziehau coremctl_identify(driver_t *driver, device_t parent)
143f7409137SSepherosa Ziehau {
144f7409137SSepherosa Ziehau 	const struct coremctl_type *t;
145f7409137SSepherosa Ziehau 	uint16_t did;
146f7409137SSepherosa Ziehau 
147f7409137SSepherosa Ziehau 	/* Already identified */
148f7409137SSepherosa Ziehau 	if (device_find_child(parent, "coremctl", -1) != NULL)
149f7409137SSepherosa Ziehau 		return;
150f7409137SSepherosa Ziehau 
151f7409137SSepherosa Ziehau 	if (pci_get_vendor(parent) != PCI_CORE_MEMCTL_VID)
152f7409137SSepherosa Ziehau 		return;
153f7409137SSepherosa Ziehau 
154f7409137SSepherosa Ziehau 	did = pci_get_device(parent);
155f7409137SSepherosa Ziehau 	for (t = coremctl_types; t->desc != NULL; ++t) {
156f7409137SSepherosa Ziehau 		if (t->did == did) {
157f7409137SSepherosa Ziehau 			if (device_add_child(parent, "coremctl", -1) == NULL)
158f7409137SSepherosa Ziehau 				device_printf(parent, "add coremctl failed\n");
159f7409137SSepherosa Ziehau 			return;
160f7409137SSepherosa Ziehau 		}
161f7409137SSepherosa Ziehau 	}
162f7409137SSepherosa Ziehau }
163f7409137SSepherosa Ziehau 
164f7409137SSepherosa Ziehau static int
coremctl_probe(device_t dev)165f7409137SSepherosa Ziehau coremctl_probe(device_t dev)
166f7409137SSepherosa Ziehau {
167f7409137SSepherosa Ziehau 	const struct coremctl_type *t;
168f7409137SSepherosa Ziehau 	uint16_t did;
169f7409137SSepherosa Ziehau 
170f7409137SSepherosa Ziehau 	if (pci_get_vendor(dev) != PCI_CORE_MEMCTL_VID)
171f7409137SSepherosa Ziehau 		return ENXIO;
172f7409137SSepherosa Ziehau 
173f7409137SSepherosa Ziehau 	did = pci_get_device(dev);
174f7409137SSepherosa Ziehau 	for (t = coremctl_types; t->desc != NULL; ++t) {
175f7409137SSepherosa Ziehau 		if (t->did == did) {
176f7409137SSepherosa Ziehau 			struct coremctl_softc *sc = device_get_softc(dev);
177f7409137SSepherosa Ziehau 
178f7409137SSepherosa Ziehau 			device_set_desc(dev, t->desc);
179f7409137SSepherosa Ziehau 			sc->sc_ver = t->ver;
180f7409137SSepherosa Ziehau 			return 0;
181f7409137SSepherosa Ziehau 		}
182f7409137SSepherosa Ziehau 	}
183f7409137SSepherosa Ziehau 	return ENXIO;
184f7409137SSepherosa Ziehau }
185f7409137SSepherosa Ziehau 
186f7409137SSepherosa Ziehau static int
coremctl_attach(device_t dev)187f7409137SSepherosa Ziehau coremctl_attach(device_t dev)
188f7409137SSepherosa Ziehau {
189f7409137SSepherosa Ziehau 	struct coremctl_softc *sc = device_get_softc(dev);
190f7409137SSepherosa Ziehau 	uint32_t capa, dmfc, mch_barlo, mch_barhi;
191f7409137SSepherosa Ziehau 	uint64_t mch_bar;
192f7409137SSepherosa Ziehau 	int dmfc_parsed = 1;
193f7409137SSepherosa Ziehau 
194f7409137SSepherosa Ziehau 	sc->sc_dev = dev;
195f7409137SSepherosa Ziehau 
196f7409137SSepherosa Ziehau 	capa = pci_read_config(dev, PCI_CORE_CAPID0_A, 4);
197f7409137SSepherosa Ziehau 
198f7409137SSepherosa Ziehau 	if (sc->sc_ver == COREMCTL_VER_1) {
199f7409137SSepherosa Ziehau 		dmfc = __SHIFTOUT(capa, PCI_CORE_CAPID0_A_DMFC);
200f7409137SSepherosa Ziehau 	} else { /* v2/v3 */
201f7409137SSepherosa Ziehau 		uint32_t capb;
202f7409137SSepherosa Ziehau 
203f7409137SSepherosa Ziehau 		capb = pci_read_config(dev, PCI_CORE_CAPID0_B, 4);
204f7409137SSepherosa Ziehau 		dmfc = __SHIFTOUT(capb, PCI_CORE_CAPID0_B_DMFC);
205f7409137SSepherosa Ziehau 	}
206f7409137SSepherosa Ziehau 
207f7409137SSepherosa Ziehau 	if (dmfc == PCI_CORE_CAPID0_DMFC_1067) {
208f7409137SSepherosa Ziehau 		device_printf(dev, "CAP DDR3 1067 ");
209f7409137SSepherosa Ziehau 	} else if (dmfc == PCI_CORE_CAPID0_DMFC_1333) {
210f7409137SSepherosa Ziehau 		device_printf(dev, "CAP DDR3 1333 ");
211f7409137SSepherosa Ziehau 	} else {
212f7409137SSepherosa Ziehau 		if (sc->sc_ver == COREMCTL_VER_1) {
213f7409137SSepherosa Ziehau 			if (dmfc == PCI_CORE_CAPID0_DMFC_V1_ALL)
214f7409137SSepherosa Ziehau 				device_printf(dev, "no CAP ");
215f7409137SSepherosa Ziehau 			else
216f7409137SSepherosa Ziehau 				dmfc_parsed = 0;
217f7409137SSepherosa Ziehau 		} else { /* v2/v3 */
218f7409137SSepherosa Ziehau 			if (dmfc == PCI_CORE_CAPID0_DMFC_1600)
219f7409137SSepherosa Ziehau 				device_printf(dev, "CAP DDR3 1600 ");
220f7409137SSepherosa Ziehau 			else if (dmfc == PCI_CORE_CAPID0_DMFC_1867)
221f7409137SSepherosa Ziehau 				device_printf(dev, "CAP DDR3 1867 ");
222f7409137SSepherosa Ziehau 			else if (dmfc == PCI_CORE_CAPID0_DMFC_2133)
223f7409137SSepherosa Ziehau 				device_printf(dev, "CAP DDR3 2133 ");
224f7409137SSepherosa Ziehau 			else if (dmfc == PCI_CORE_CAPID0_DMFC_2400)
225f7409137SSepherosa Ziehau 				device_printf(dev, "CAP DDR3 2400 ");
226f7409137SSepherosa Ziehau 			else if (dmfc == PCI_CORE_CAPID0_DMFC_2667)
227f7409137SSepherosa Ziehau 				device_printf(dev, "CAP DDR3 2667 ");
228f7409137SSepherosa Ziehau 			else if (dmfc == PCI_CORE_CAPID0_DMFC_2933)
229f7409137SSepherosa Ziehau 				device_printf(dev, "CAP DDR3 2933 ");
230f7409137SSepherosa Ziehau 			else
231f7409137SSepherosa Ziehau 				dmfc_parsed = 0;
232f7409137SSepherosa Ziehau 		}
233f7409137SSepherosa Ziehau 	}
234f7409137SSepherosa Ziehau 	if (!dmfc_parsed) {
235f7409137SSepherosa Ziehau 		device_printf(dev, "unknown DMFC %#x\n", dmfc);
236f7409137SSepherosa Ziehau 		return 0;
237f7409137SSepherosa Ziehau 	}
238f7409137SSepherosa Ziehau 
239f7409137SSepherosa Ziehau 	if (capa & PCI_CORE_CAPID0_A_ECCDIS) {
240f7409137SSepherosa Ziehau 		kprintf("NON-ECC\n");
241f7409137SSepherosa Ziehau 	} else {
242f7409137SSepherosa Ziehau 		kprintf("ECC\n");
243f7409137SSepherosa Ziehau 		sc->sc_ecc = device_add_child(dev, "ecc", -1);
244f7409137SSepherosa Ziehau 		if (sc->sc_ecc == NULL)
245f7409137SSepherosa Ziehau 			device_printf(dev, "add ecc failed\n");
246f7409137SSepherosa Ziehau 	}
247f7409137SSepherosa Ziehau 
248f7409137SSepherosa Ziehau 	mch_barlo = pci_read_config(dev, PCI_CORE_MCHBAR_LO, 4);
249f7409137SSepherosa Ziehau 	mch_barhi = pci_read_config(dev, PCI_CORE_MCHBAR_HI, 4);
250f7409137SSepherosa Ziehau 
251f7409137SSepherosa Ziehau 	mch_bar = (uint64_t)mch_barlo | (((uint64_t)mch_barhi) << 32);
252f7409137SSepherosa Ziehau 	if (bootverbose)
253f7409137SSepherosa Ziehau 		device_printf(dev, "MCHBAR 0x%jx\n", (uintmax_t)mch_bar);
254f7409137SSepherosa Ziehau 
255f7409137SSepherosa Ziehau 	if (mch_bar & PCI_CORE_MCHBAR_LO_EN) {
256f7409137SSepherosa Ziehau 		uint64_t map_addr = mch_bar & PCI_CORE_MCHBAR_ADDRMASK;
257f7409137SSepherosa Ziehau 
258f7409137SSepherosa Ziehau 		sc->sc_mch = pmap_mapdev_uncacheable(map_addr, MCH_CORE_SIZE);
259f7409137SSepherosa Ziehau 
260f7409137SSepherosa Ziehau 		if (bootverbose) {
261f7409137SSepherosa Ziehau 			uint32_t dimm_ch0, dimm_ch1;
262f7409137SSepherosa Ziehau 
263f7409137SSepherosa Ziehau 			dimm_ch0 = CSR_READ_4(sc, MCH_CORE_DIMM_CH0);
264f7409137SSepherosa Ziehau 			dimm_ch1 = CSR_READ_4(sc, MCH_CORE_DIMM_CH1);
265f7409137SSepherosa Ziehau 
266f7409137SSepherosa Ziehau 			coremctl_chaninfo(sc, dimm_ch0, "channel0");
267f7409137SSepherosa Ziehau 			coremctl_chaninfo(sc, dimm_ch1, "channel1");
268f7409137SSepherosa Ziehau 		}
269f7409137SSepherosa Ziehau 	} else {
270f7409137SSepherosa Ziehau 		device_printf(dev, "MCHBAR is not enabled\n");
271f7409137SSepherosa Ziehau 	}
272f7409137SSepherosa Ziehau 
273*d9902073SSepherosa Ziehau 	if (sc->sc_ver == COREMCTL_VER_3 && sc->sc_mch != NULL) {
274*d9902073SSepherosa Ziehau 		uint32_t ptm_ctl;
275*d9902073SSepherosa Ziehau 
276*d9902073SSepherosa Ziehau 		/*
277*d9902073SSepherosa Ziehau 		 * XXX
278*d9902073SSepherosa Ziehau 		 * It seems that memory thermal sensor is available,
279*d9902073SSepherosa Ziehau 		 * if any of the following bits are set.
280*d9902073SSepherosa Ziehau 		 */
281*d9902073SSepherosa Ziehau 		ptm_ctl = CSR_READ_4(sc, MCH_CORE_DDR_PTM_CTL0);
282*d9902073SSepherosa Ziehau 		if (ptm_ctl & (MCH_CORE_DDR_PTM_CTL0_CLTM |
283*d9902073SSepherosa Ziehau 		    MCH_CORE_DDR_PTM_CTL0_EXTTS | MCH_CORE_DDR_PTM_CTL0_OLTM)) {
284*d9902073SSepherosa Ziehau 			sc->sc_temp = device_add_child(dev, "memtemp", -1);
285*d9902073SSepherosa Ziehau 			if (sc->sc_temp == NULL)
286*d9902073SSepherosa Ziehau 				device_printf(dev, "add memtemp failed\n");
287*d9902073SSepherosa Ziehau 		}
288*d9902073SSepherosa Ziehau 	}
289*d9902073SSepherosa Ziehau 
290f7409137SSepherosa Ziehau 	bus_generic_attach(dev);
291f7409137SSepherosa Ziehau 
292f7409137SSepherosa Ziehau 	return 0;
293f7409137SSepherosa Ziehau }
294f7409137SSepherosa Ziehau 
295f7409137SSepherosa Ziehau static void
coremctl_chaninfo(struct coremctl_softc * sc,uint32_t dimm_ch,const char * desc)296f7409137SSepherosa Ziehau coremctl_chaninfo(struct coremctl_softc *sc, uint32_t dimm_ch,
297f7409137SSepherosa Ziehau     const char *desc)
298f7409137SSepherosa Ziehau {
299f7409137SSepherosa Ziehau 	int size_a, size_b;
300f7409137SSepherosa Ziehau 	int dimma_id, dimmb_id;
301f7409137SSepherosa Ziehau 
302f7409137SSepherosa Ziehau 	dimma_id = 0;
303f7409137SSepherosa Ziehau 	dimmb_id = 1;
304f7409137SSepherosa Ziehau 	if (dimm_ch & MCH_CORE_DIMM_A_SELECT) {
305f7409137SSepherosa Ziehau 		dimma_id = 1;
306f7409137SSepherosa Ziehau 		dimmb_id = 0;
307f7409137SSepherosa Ziehau 	}
308f7409137SSepherosa Ziehau 
309f7409137SSepherosa Ziehau 	size_a = __SHIFTOUT(dimm_ch, MCH_CORE_DIMM_A_SIZE);
310f7409137SSepherosa Ziehau 	if (size_a != 0) {
311f7409137SSepherosa Ziehau 		device_printf(sc->sc_dev, "%s, DIMM%d %dMB %dx%d\n", desc,
312f7409137SSepherosa Ziehau 		    dimma_id, size_a * MCH_CORE_DIMM_SIZE_UNIT,
313f7409137SSepherosa Ziehau 		    (dimm_ch & MCH_CORE_DIMM_A_DUAL_RANK) ? 2 : 1,
314f7409137SSepherosa Ziehau 		    (dimm_ch & MCH_CORE_DIMM_A_X16) ? 16 : 8);
315f7409137SSepherosa Ziehau 	}
316f7409137SSepherosa Ziehau 
317f7409137SSepherosa Ziehau 	size_b = __SHIFTOUT(dimm_ch, MCH_CORE_DIMM_B_SIZE);
318f7409137SSepherosa Ziehau 	if (size_b != 0) {
319f7409137SSepherosa Ziehau 		device_printf(sc->sc_dev, "%s, DIMM%d %dMB %dx%d\n", desc,
320f7409137SSepherosa Ziehau 		    dimmb_id, size_b * MCH_CORE_DIMM_SIZE_UNIT,
321f7409137SSepherosa Ziehau 		    (dimm_ch & MCH_CORE_DIMM_B_DUAL_RANK) ? 2 : 1,
322f7409137SSepherosa Ziehau 		    (dimm_ch & MCH_CORE_DIMM_B_X16) ? 16 : 8);
323f7409137SSepherosa Ziehau 	}
324f7409137SSepherosa Ziehau 
325f7409137SSepherosa Ziehau 	if (size_a == 0 && size_b == 0)
326f7409137SSepherosa Ziehau 		return;
327f7409137SSepherosa Ziehau 
328f7409137SSepherosa Ziehau 	if (sc->sc_ver == COREMCTL_VER_1 || sc->sc_ver == COREMCTL_VER_2) {
329f7409137SSepherosa Ziehau 		/* This bit is v3 only */
330f7409137SSepherosa Ziehau 		dimm_ch &= ~MCH_CORE_DIMM_HORI;
331f7409137SSepherosa Ziehau 	}
332f7409137SSepherosa Ziehau 	if (dimm_ch & (MCH_CORE_DIMM_ENHI | MCH_CORE_DIMM_RI |
333f7409137SSepherosa Ziehau 	    MCH_CORE_DIMM_HORI)) {
334f7409137SSepherosa Ziehau 		device_printf(sc->sc_dev, "%s", desc);
335f7409137SSepherosa Ziehau 		if (dimm_ch & MCH_CORE_DIMM_RI)
336f7409137SSepherosa Ziehau 			kprintf(", rank interleave");
337f7409137SSepherosa Ziehau 		if (dimm_ch & MCH_CORE_DIMM_ENHI)
338f7409137SSepherosa Ziehau 			kprintf(", enhanced interleave");
339f7409137SSepherosa Ziehau 		if (dimm_ch & MCH_CORE_DIMM_HORI)
340f7409137SSepherosa Ziehau 			kprintf(", high order rank interleave");
341f7409137SSepherosa Ziehau 		kprintf("\n");
342f7409137SSepherosa Ziehau 	}
343f7409137SSepherosa Ziehau }
344f7409137SSepherosa Ziehau 
345f7409137SSepherosa Ziehau static int
coremctl_detach(device_t dev)346f7409137SSepherosa Ziehau coremctl_detach(device_t dev)
347f7409137SSepherosa Ziehau {
348f7409137SSepherosa Ziehau 	struct coremctl_softc *sc = device_get_softc(dev);
349f7409137SSepherosa Ziehau 
350f7409137SSepherosa Ziehau 	if (sc->sc_ecc != NULL)
351f7409137SSepherosa Ziehau 		device_delete_child(dev, sc->sc_ecc);
352*d9902073SSepherosa Ziehau 	if (sc->sc_temp != NULL)
353*d9902073SSepherosa Ziehau 		device_delete_child(dev, sc->sc_temp);
354f7409137SSepherosa Ziehau 	bus_generic_detach(dev);
355f7409137SSepherosa Ziehau 
356f7409137SSepherosa Ziehau 	if (sc->sc_mch != NULL)
357f7409137SSepherosa Ziehau 		pmap_unmapdev((vm_offset_t)sc->sc_mch, MCH_CORE_SIZE);
358f7409137SSepherosa Ziehau 	return 0;
359f7409137SSepherosa Ziehau }
360f7409137SSepherosa Ziehau 
361f7409137SSepherosa Ziehau static int
coremctl_mch_readreg(device_t dev,int reg,uint32_t * val)362f7409137SSepherosa Ziehau coremctl_mch_readreg(device_t dev, int reg, uint32_t *val)
363f7409137SSepherosa Ziehau {
364f7409137SSepherosa Ziehau 	struct coremctl_softc *sc = device_get_softc(dev);
365f7409137SSepherosa Ziehau 
366f7409137SSepherosa Ziehau 	if (sc->sc_mch == NULL)
367f7409137SSepherosa Ziehau 		return EOPNOTSUPP;
368f7409137SSepherosa Ziehau 
369f7409137SSepherosa Ziehau 	*val = CSR_READ_4(sc, reg);
370f7409137SSepherosa Ziehau 	return 0;
371f7409137SSepherosa Ziehau }
372f7409137SSepherosa Ziehau 
373f7409137SSepherosa Ziehau static int
coremctl_mch_writereg(device_t dev,int reg,uint32_t val)374*d9902073SSepherosa Ziehau coremctl_mch_writereg(device_t dev, int reg, uint32_t val)
375*d9902073SSepherosa Ziehau {
376*d9902073SSepherosa Ziehau 	struct coremctl_softc *sc = device_get_softc(dev);
377*d9902073SSepherosa Ziehau 
378*d9902073SSepherosa Ziehau 	if (sc->sc_mch == NULL)
379*d9902073SSepherosa Ziehau 		return EOPNOTSUPP;
380*d9902073SSepherosa Ziehau 
381*d9902073SSepherosa Ziehau 	CSR_WRITE_4(sc, reg, val);
382*d9902073SSepherosa Ziehau 	return 0;
383*d9902073SSepherosa Ziehau }
384*d9902073SSepherosa Ziehau 
385*d9902073SSepherosa Ziehau static int
coremctl_pci_read_ivar(device_t dev,device_t child,int which,uintptr_t * result)386f7409137SSepherosa Ziehau coremctl_pci_read_ivar(device_t dev, device_t child, int which,
387f7409137SSepherosa Ziehau     uintptr_t *result)
388f7409137SSepherosa Ziehau {
389f7409137SSepherosa Ziehau 	return BUS_READ_IVAR(device_get_parent(dev), dev, which, result);
390f7409137SSepherosa Ziehau }
391f7409137SSepherosa Ziehau 
392f7409137SSepherosa Ziehau static uint32_t
coremctl_pci_read_config(device_t dev,device_t child,int reg,int width)393f7409137SSepherosa Ziehau coremctl_pci_read_config(device_t dev, device_t child, int reg, int width)
394f7409137SSepherosa Ziehau {
395f7409137SSepherosa Ziehau 	return pci_read_config(dev, reg, width);
396f7409137SSepherosa Ziehau }
397f7409137SSepherosa Ziehau 
398f7409137SSepherosa Ziehau static void
coremctl_pci_write_config(device_t dev,device_t child,int reg,uint32_t val,int width)399f7409137SSepherosa Ziehau coremctl_pci_write_config(device_t dev, device_t child, int reg, uint32_t val,
400f7409137SSepherosa Ziehau     int width)
401f7409137SSepherosa Ziehau {
402f7409137SSepherosa Ziehau 	pci_write_config(dev, reg, val, width);
403f7409137SSepherosa Ziehau }
404