xref: /netbsd-src/sys/arch/x86/pci/amdsmn.c (revision ea402bb65ef70807d534b78fbbffe39fa4b36007)
1*ea402bb6Smsaitoh /*	$NetBSD: amdsmn.c,v 1.18 2024/10/17 14:02:40 msaitoh Exp $	*/
23a74451dSchristos 
33a74451dSchristos /*-
4f90792d2Ssimonb  * Copyright (c) 2017, 2019 Conrad Meyer <cem@FreeBSD.org>
53a74451dSchristos  * All rights reserved.
63a74451dSchristos  *
73a74451dSchristos  * NetBSD port by Ian Clark <mrrooster@gmail.com>
83a74451dSchristos  *
93a74451dSchristos  * Redistribution and use in source and binary forms, with or without
103a74451dSchristos  * modification, are permitted provided that the following conditions
113a74451dSchristos  * are met:
123a74451dSchristos  * 1. Redistributions of source code must retain the above copyright
133a74451dSchristos  *    notice, this list of conditions and the following disclaimer.
143a74451dSchristos  * 2. Redistributions in binary form must reproduce the above copyright
153a74451dSchristos  *    notice, this list of conditions and the following disclaimer in the
163a74451dSchristos  *    documentation and/or other materials provided with the distribution.
173a74451dSchristos  *
183a74451dSchristos  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
193a74451dSchristos  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
203a74451dSchristos  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
213a74451dSchristos  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
223a74451dSchristos  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
233a74451dSchristos  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
243a74451dSchristos  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
253a74451dSchristos  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
263a74451dSchristos  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
273a74451dSchristos  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
283a74451dSchristos  * POSSIBILITY OF SUCH DAMAGE.
293a74451dSchristos  */
303a74451dSchristos 
313a74451dSchristos #include <sys/cdefs.h>
32*ea402bb6Smsaitoh __KERNEL_RCSID(0, "$NetBSD: amdsmn.c,v 1.18 2024/10/17 14:02:40 msaitoh Exp $ ");
333a74451dSchristos 
343a74451dSchristos /*
35f90792d2Ssimonb  * Driver for the AMD Family 15h (model 60+) and 17h CPU
36f90792d2Ssimonb  * System Management Network.
373a74451dSchristos  */
383a74451dSchristos 
393a74451dSchristos #include <sys/param.h>
403a74451dSchristos #include <sys/device.h>
413a74451dSchristos #include <sys/errno.h>
423a74451dSchristos #include <sys/mutex.h>
433a74451dSchristos #include <sys/systm.h>
443a74451dSchristos #include <sys/cpu.h>
45a63689b9Spgoyette #include <sys/module.h>
463a74451dSchristos 
473a74451dSchristos #include <machine/specialreg.h>
483a74451dSchristos 
493a74451dSchristos #include <dev/pci/pcireg.h>
503a74451dSchristos #include <dev/pci/pcivar.h>
513a74451dSchristos #include <dev/pci/pcidevs.h>
523a74451dSchristos 
533a74451dSchristos #include "amdsmn.h"
54a63689b9Spgoyette #include "ioconf.h"
553a74451dSchristos 
56f90792d2Ssimonb #define	F15H_SMN_ADDR_REG	0xb8
57f90792d2Ssimonb #define	F15H_SMN_DATA_REG	0xbc
58f90792d2Ssimonb #define	F17H_SMN_ADDR_REG	0x60
59f90792d2Ssimonb #define	F17H_SMN_DATA_REG	0x64
603a74451dSchristos 
613a74451dSchristos struct amdsmn_softc {
623a74451dSchristos 	kmutex_t smn_lock;
63f90792d2Ssimonb 	uint8_t smn_addr_reg;
64f90792d2Ssimonb 	uint8_t smn_data_reg;
653a74451dSchristos 	struct pci_attach_args pa;
663a74451dSchristos 	pci_chipset_tag_t pc;
673a74451dSchristos 	pcitag_t pcitag;
683a74451dSchristos };
693a74451dSchristos 
7036bfd4aaSmsaitoh static const struct pciid {
7136bfd4aaSmsaitoh 	uint16_t	amdsmn_deviceid;
72f90792d2Ssimonb 	uint8_t		amdsmn_addr_reg;
73f90792d2Ssimonb 	uint8_t		amdsmn_data_reg;
7436bfd4aaSmsaitoh } amdsmn_ids[] = {
75f90792d2Ssimonb 	{
76da271569Smsaitoh 		.amdsmn_deviceid = PCI_PRODUCT_AMD_F15_6X_RC,
77f90792d2Ssimonb 		.amdsmn_addr_reg = F15H_SMN_ADDR_REG,
78f90792d2Ssimonb 		.amdsmn_data_reg = F15H_SMN_DATA_REG,
79f90792d2Ssimonb 	},
80f90792d2Ssimonb 	{
81f90792d2Ssimonb 		.amdsmn_deviceid = PCI_PRODUCT_AMD_F17_RC,
82f90792d2Ssimonb 		.amdsmn_addr_reg = F17H_SMN_ADDR_REG,
83f90792d2Ssimonb 		.amdsmn_data_reg = F17H_SMN_DATA_REG,
84f90792d2Ssimonb 	},
85f90792d2Ssimonb 	{
86f90792d2Ssimonb 		.amdsmn_deviceid = PCI_PRODUCT_AMD_F17_1X_RC,
87f90792d2Ssimonb 		.amdsmn_addr_reg = F17H_SMN_ADDR_REG,
88f90792d2Ssimonb 		.amdsmn_data_reg = F17H_SMN_DATA_REG,
89f90792d2Ssimonb 	},
90f90792d2Ssimonb 	{
9108e27227Smsaitoh 		.amdsmn_deviceid = PCI_PRODUCT_AMD_F17_6X_RC,
9208e27227Smsaitoh 		.amdsmn_addr_reg = F17H_SMN_ADDR_REG,
9308e27227Smsaitoh 		.amdsmn_data_reg = F17H_SMN_DATA_REG,
9408e27227Smsaitoh 	},
9508e27227Smsaitoh 	{
9697018bdaSmsaitoh 		.amdsmn_deviceid = PCI_PRODUCT_AMD_F17_7X_RC, /* or F19_0X */
9797018bdaSmsaitoh 		.amdsmn_addr_reg = F17H_SMN_ADDR_REG,
9897018bdaSmsaitoh 		.amdsmn_data_reg = F17H_SMN_DATA_REG,
9997018bdaSmsaitoh 	},
10097018bdaSmsaitoh 	{
10197018bdaSmsaitoh 		.amdsmn_deviceid = PCI_PRODUCT_AMD_F17_AX_RC, /* or F19_4X */
10297018bdaSmsaitoh 		.amdsmn_addr_reg = F17H_SMN_ADDR_REG,
10397018bdaSmsaitoh 		.amdsmn_data_reg = F17H_SMN_DATA_REG,
10497018bdaSmsaitoh 	},
10597018bdaSmsaitoh 	{
10697018bdaSmsaitoh 		.amdsmn_deviceid = PCI_PRODUCT_AMD_F19_1X_RC,
107f90792d2Ssimonb 		.amdsmn_addr_reg = F17H_SMN_ADDR_REG,
108f90792d2Ssimonb 		.amdsmn_data_reg = F17H_SMN_DATA_REG,
109f90792d2Ssimonb 	},
11008e27227Smsaitoh 	{
11108e27227Smsaitoh 		.amdsmn_deviceid = PCI_PRODUCT_AMD_F19_6X_RC,
11208e27227Smsaitoh 		.amdsmn_addr_reg = F17H_SMN_ADDR_REG,
11308e27227Smsaitoh 		.amdsmn_data_reg = F17H_SMN_DATA_REG,
11408e27227Smsaitoh 	},
1151b9c9e4eSmsaitoh 	{
1161b9c9e4eSmsaitoh 		.amdsmn_deviceid = PCI_PRODUCT_AMD_F19_7X_RC,
1171b9c9e4eSmsaitoh 		.amdsmn_addr_reg = F17H_SMN_ADDR_REG,
1181b9c9e4eSmsaitoh 		.amdsmn_data_reg = F17H_SMN_DATA_REG,
1191b9c9e4eSmsaitoh 	},
120*ea402bb6Smsaitoh 	{
121*ea402bb6Smsaitoh 		.amdsmn_deviceid = PCI_PRODUCT_AMD_F1A_0X_RC,
122*ea402bb6Smsaitoh 		.amdsmn_addr_reg = F17H_SMN_ADDR_REG,
123*ea402bb6Smsaitoh 		.amdsmn_data_reg = F17H_SMN_DATA_REG,
124*ea402bb6Smsaitoh 	},
12536bfd4aaSmsaitoh };
12636bfd4aaSmsaitoh 
1273a74451dSchristos static int amdsmn_match(device_t, cfdata_t, void *);
1283a74451dSchristos static void amdsmn_attach(device_t, device_t, void *);
129a63689b9Spgoyette static int amdsmn_rescan(device_t, const char *, const int *);
1303a74451dSchristos static int amdsmn_detach(device_t, int);
1313a74451dSchristos static int amdsmn_misc_search(device_t, cfdata_t, const int *, void *);
1323a74451dSchristos 
133a63689b9Spgoyette CFATTACH_DECL3_NEW(amdsmn, sizeof(struct amdsmn_softc), amdsmn_match,
134a63689b9Spgoyette     amdsmn_attach, amdsmn_detach, NULL, amdsmn_rescan, NULL, 0);
1353a74451dSchristos 
1363a74451dSchristos static int
1373a74451dSchristos amdsmn_match(device_t parent, cfdata_t match, void *aux)
1383a74451dSchristos {
1393a74451dSchristos 	struct pci_attach_args *pa = aux;
1406a4a55b0Ssimonb 	size_t i;
1413a74451dSchristos 
14236bfd4aaSmsaitoh 	if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_AMD)
14336bfd4aaSmsaitoh 		return 0;
14436bfd4aaSmsaitoh 
14536bfd4aaSmsaitoh 	for (i = 0; i < __arraycount(amdsmn_ids); i++)
14636bfd4aaSmsaitoh 		if (PCI_PRODUCT(pa->pa_id) == amdsmn_ids[i].amdsmn_deviceid)
14736bfd4aaSmsaitoh 			return 2;
14836bfd4aaSmsaitoh 
14936bfd4aaSmsaitoh 	return 0;
1503a74451dSchristos }
1513a74451dSchristos 
1523a74451dSchristos static int
1533a74451dSchristos amdsmn_misc_search(device_t parent, cfdata_t cf, const int *locs, void *aux)
1543a74451dSchristos {
1552685996bSthorpej 	if (config_probe(parent, cf, aux))
1562685996bSthorpej 		config_attach(parent, cf, aux, NULL,
157c7fb772bSthorpej 		    CFARGS(.locators = locs));
1583a74451dSchristos 
1593a74451dSchristos 	return 0;
1603a74451dSchristos }
1613a74451dSchristos 
1623a74451dSchristos static void
1633a74451dSchristos amdsmn_attach(device_t parent, device_t self, void *aux)
1643a74451dSchristos {
1653a74451dSchristos 	struct amdsmn_softc *sc = device_private(self);
1663a74451dSchristos 	struct pci_attach_args *pa = aux;
167991d71a7Sjoerg 	size_t i;
1683a74451dSchristos 
1693a74451dSchristos 	mutex_init(&sc->smn_lock, MUTEX_DEFAULT, IPL_NONE);
1703a74451dSchristos 	sc->pa = *pa;
1713a74451dSchristos 	sc->pc = pa->pa_pc;
1723a74451dSchristos 	sc->pcitag = pa->pa_tag;
173f90792d2Ssimonb 
174f90792d2Ssimonb 	for (i = 0; i < __arraycount(amdsmn_ids); i++)
175f90792d2Ssimonb 		if (PCI_PRODUCT(pa->pa_id) == amdsmn_ids[i].amdsmn_deviceid) {
176f90792d2Ssimonb 			sc->smn_addr_reg = amdsmn_ids[i].amdsmn_addr_reg;
177f90792d2Ssimonb 			sc->smn_data_reg = amdsmn_ids[i].amdsmn_data_reg;
178f90792d2Ssimonb 		}
179f90792d2Ssimonb 
180f90792d2Ssimonb 	// aprint_normal(": AMD Family 17h System Management Network\n");
181f90792d2Ssimonb 	aprint_normal(": AMD System Management Network\n");
18222a97c46Sreinoud 
18322a97c46Sreinoud 	pmf_device_register(self, NULL, NULL);
1842685996bSthorpej 	amdsmn_rescan(self, NULL, NULL);
185a63689b9Spgoyette }
186a63689b9Spgoyette 
187a63689b9Spgoyette static int
1882685996bSthorpej amdsmn_rescan(device_t self, const char *ifattr, const int *locators)
189a63689b9Spgoyette {
190a63689b9Spgoyette 	struct amdsmn_softc *sc = device_private(self);
191a63689b9Spgoyette 
1922685996bSthorpej 	config_search(self, &sc->pa,
193c7fb772bSthorpej 	    CFARGS(.search = amdsmn_misc_search));
194a63689b9Spgoyette 
195a63689b9Spgoyette 	return 0;
1963a74451dSchristos }
1973a74451dSchristos 
1983a74451dSchristos static int
1993a74451dSchristos amdsmn_detach(device_t self, int flags)
2003a74451dSchristos {
2013a74451dSchristos 	struct amdsmn_softc *sc = device_private(self);
2023a74451dSchristos 
20322a97c46Sreinoud 	pmf_device_deregister(self);
20422a97c46Sreinoud 
2053a74451dSchristos 	mutex_destroy(&sc->smn_lock);
2063a74451dSchristos 	aprint_normal_dev(self,"detach!\n");
2073a74451dSchristos 
2083a74451dSchristos 	return 0;
2093a74451dSchristos }
2103a74451dSchristos 
2113a74451dSchristos int
2123a74451dSchristos amdsmn_read(device_t dev, uint32_t addr, uint32_t *value)
2133a74451dSchristos {
2143a74451dSchristos 	struct amdsmn_softc *sc = device_private(dev);
2153a74451dSchristos 
2163a74451dSchristos 	mutex_enter(&sc->smn_lock);
217f90792d2Ssimonb 	pci_conf_write(sc->pc, sc->pcitag, sc->smn_addr_reg, addr);
218f90792d2Ssimonb 	*value = pci_conf_read(sc->pc, sc->pcitag, sc->smn_data_reg);
2193a74451dSchristos 	mutex_exit(&sc->smn_lock);
2203a74451dSchristos 
2213a74451dSchristos 	return 0;
2223a74451dSchristos }
2233a74451dSchristos 
2243a74451dSchristos int
2253a74451dSchristos amdsmn_write(device_t dev, uint32_t addr, uint32_t value)
2263a74451dSchristos {
2273a74451dSchristos 	struct amdsmn_softc *sc = device_private(dev);
2283a74451dSchristos 
2293a74451dSchristos 	mutex_enter(&sc->smn_lock);
230f90792d2Ssimonb 	pci_conf_write(sc->pc, sc->pcitag, sc->smn_addr_reg, addr);
231f90792d2Ssimonb 	pci_conf_write(sc->pc, sc->pcitag, sc->smn_data_reg, value);
2323a74451dSchristos 	mutex_exit(&sc->smn_lock);
2333a74451dSchristos 
2343a74451dSchristos 	return 0;
2353a74451dSchristos }
236a63689b9Spgoyette 
237a63689b9Spgoyette MODULE(MODULE_CLASS_DRIVER, amdsmn, "pci");
238a63689b9Spgoyette 
239a63689b9Spgoyette #ifdef _MODULE
240a63689b9Spgoyette #include "ioconf.c"
241a63689b9Spgoyette #endif
242a63689b9Spgoyette 
243a63689b9Spgoyette static int
244a63689b9Spgoyette amdsmn_modcmd(modcmd_t cmd, void *opaque)
245a63689b9Spgoyette {
246a63689b9Spgoyette 	int error = 0;
247a63689b9Spgoyette 
248a63689b9Spgoyette #ifdef _MODULE
249a63689b9Spgoyette 	switch (cmd) {
250a63689b9Spgoyette 	case MODULE_CMD_INIT:
251a63689b9Spgoyette 		error = config_init_component(cfdriver_ioconf_amdsmn,
252a63689b9Spgoyette 		    cfattach_ioconf_amdsmn, cfdata_ioconf_amdsmn);
253a63689b9Spgoyette 		break;
254a63689b9Spgoyette 	case MODULE_CMD_FINI:
255a63689b9Spgoyette 		error = config_fini_component(cfdriver_ioconf_amdsmn,
256a63689b9Spgoyette 		    cfattach_ioconf_amdsmn, cfdata_ioconf_amdsmn);
257a63689b9Spgoyette 		break;
258a63689b9Spgoyette 	default:
259a63689b9Spgoyette 		error = ENOTTY;
260a63689b9Spgoyette 		break;
261a63689b9Spgoyette 	}
262a63689b9Spgoyette #endif
263a63689b9Spgoyette 
264a63689b9Spgoyette 	return error;
265a63689b9Spgoyette }
266a63689b9Spgoyette 
267