11.5Sthorpej/* $NetBSD: amdnb_misc.c,v 1.5 2021/08/07 16:19:07 thorpej Exp $ */ 21.1Scegger/* 31.1Scegger * Copyright (c) 2012 The NetBSD Foundation, Inc. 41.1Scegger * All rights reserved. 51.1Scegger * 61.1Scegger * This code is derived from software contributed to The NetBSD Foundation 71.1Scegger * by Christoph Egger. 81.1Scegger * 91.1Scegger * Redistribution and use in source and binary forms, with or without 101.1Scegger * modification, are permitted provided that the following conditions 111.1Scegger * are met: 121.1Scegger * 1. Redistributions of source code must retain the above copyright 131.1Scegger * notice, this list of conditions and the following disclaimer. 141.1Scegger * 2. Redistributions in binary form must reproduce the above copyright 151.1Scegger * notice, this list of conditions and the following disclaimer in the 161.1Scegger * documentation and/or other materials provided with the distribution. 171.1Scegger * 181.1Scegger * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 191.1Scegger * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 201.1Scegger * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 211.1Scegger * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 221.1Scegger * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 231.1Scegger * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 241.1Scegger * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 251.1Scegger * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 261.1Scegger * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 271.1Scegger * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 281.1Scegger * POSSIBILITY OF SUCH DAMAGE. 291.1Scegger */ 301.1Scegger 311.1Scegger#include <sys/cdefs.h> 321.5Sthorpej__KERNEL_RCSID(0, "$NetBSD: amdnb_misc.c,v 1.5 2021/08/07 16:19:07 thorpej Exp $"); 331.1Scegger 341.1Scegger#include <sys/param.h> 351.1Scegger#include <sys/device.h> 361.1Scegger 371.1Scegger#include <dev/pci/pcireg.h> 381.1Scegger#include <dev/pci/pcivar.h> 391.1Scegger#include <dev/pci/pcidevs.h> 401.1Scegger 411.1Sceggerstatic int amdnb_misc_match(device_t, cfdata_t match, void *); 421.1Sceggerstatic void amdnb_misc_attach(device_t, device_t, void *); 431.1Sceggerstatic int amdnb_misc_detach(device_t, int); 441.2Sceggerstatic int amdnb_misc_rescan(device_t, const char *, const int *); 451.2Sceggerstatic void amdnb_misc_childdet(device_t, device_t); 461.1Scegger 471.2Sceggerstruct amdnb_misc_softc { 481.2Scegger struct pci_attach_args sc_pa; 491.2Scegger}; 501.2Scegger 511.2SceggerCFATTACH_DECL3_NEW(amdnb_misc, sizeof(struct amdnb_misc_softc), 521.2Scegger amdnb_misc_match, amdnb_misc_attach, amdnb_misc_detach, NULL, 531.2Scegger amdnb_misc_rescan, amdnb_misc_childdet, DVF_DETACH_SHUTDOWN); 541.1Scegger 551.1Scegger 561.1Sceggerstatic int 571.1Sceggeramdnb_misc_match(device_t parent, cfdata_t match, void *aux) 581.1Scegger{ 591.1Scegger struct pci_attach_args *pa = aux; 601.1Scegger 611.1Scegger if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_AMD) 621.1Scegger return 0; 631.1Scegger 641.1Scegger switch (PCI_PRODUCT(pa->pa_id)) { 651.1Scegger case PCI_PRODUCT_AMD_AMD64_MISC: 661.1Scegger case PCI_PRODUCT_AMD_AMD64_F10_MISC: 671.1Scegger case PCI_PRODUCT_AMD_AMD64_F11_MISC: 681.1Scegger case PCI_PRODUCT_AMD_F14_NB: /* Family 12h, too */ 691.1Scegger case PCI_PRODUCT_AMD_F15_MISC: 701.3Sis case PCI_PRODUCT_AMD_F16_NB: 711.3Sis case PCI_PRODUCT_AMD_F16_30_NB: 721.1Scegger break; 731.1Scegger default: 741.1Scegger return 0; 751.1Scegger } 761.1Scegger 771.1Scegger return 2; /* supercede pchb(4) */ 781.1Scegger} 791.1Scegger 801.1Sceggerstatic int 811.1Sceggeramdnb_misc_search(device_t parent, cfdata_t cf, const int *locs, void *aux) 821.1Scegger{ 831.2Scegger device_t dev; 841.2Scegger deviter_t di; 851.2Scegger bool attach; 861.2Scegger 871.4Sthorpej if (!config_probe(parent, cf, aux)) 881.2Scegger return 0; 891.2Scegger 901.2Scegger attach = true; 911.2Scegger 921.2Scegger /* Figure out if found child 'cf' is already attached. 931.2Scegger * No need to attach it twice. 941.2Scegger */ 951.2Scegger 961.2Scegger /* XXX: I only want to iterate over the children of *this* device. 971.2Scegger * Can we introduce a 981.2Scegger * deviter_first_child(&di, parent, DEVITER_F_LEAVES_ONLY) 991.2Scegger * or even better, can we introduce a query function that returns 1001.2Scegger * if a child is already attached? 1011.2Scegger */ 1021.2Scegger for (dev = deviter_first(&di, DEVITER_F_LEAVES_FIRST); dev != NULL; 1031.2Scegger dev = deviter_next(&di)) 1041.2Scegger { 1051.2Scegger if (device_parent(dev) != parent) 1061.2Scegger continue; 1071.2Scegger if (device_is_a(dev, cf->cf_name)) { 1081.2Scegger attach = false; 1091.2Scegger break; 1101.2Scegger } 1111.2Scegger } 1121.2Scegger deviter_release(&di); 1131.2Scegger 1141.2Scegger if (!attach) 1151.2Scegger return 0; 1161.2Scegger 1171.5Sthorpej config_attach(parent, cf, aux, NULL, CFARGS_NONE); 1181.1Scegger 1191.1Scegger return 0; 1201.1Scegger} 1211.1Scegger 1221.1Sceggerstatic void 1231.1Sceggeramdnb_misc_attach(device_t parent, device_t self, void *aux) 1241.1Scegger{ 1251.2Scegger struct amdnb_misc_softc *sc = device_private(self); 1261.2Scegger struct pci_attach_args *pa = aux; 1271.2Scegger 1281.2Scegger sc->sc_pa = *pa; 1291.2Scegger 1301.1Scegger aprint_naive("\n"); 1311.1Scegger aprint_normal(": AMD NB Misc Configuration\n"); 1321.1Scegger 1331.1Scegger if (!pmf_device_register(self, NULL, NULL)) 1341.1Scegger aprint_error_dev(self, "couldn't establish power handler\n"); 1351.1Scegger 1361.4Sthorpej config_search(self, &sc->sc_pa, 1371.5Sthorpej CFARGS(.search = amdnb_misc_search)); 1381.2Scegger 1391.1Scegger return; 1401.1Scegger} 1411.1Scegger 1421.1Sceggerstatic int 1431.1Sceggeramdnb_misc_detach(device_t self, int flags) 1441.1Scegger{ 1451.1Scegger int rv; 1461.1Scegger 1471.1Scegger rv = config_detach_children(self, flags); 1481.1Scegger if (rv != 0) 1491.1Scegger return rv; 1501.1Scegger 1511.1Scegger pmf_device_deregister(self); 1521.1Scegger return rv; 1531.1Scegger} 1541.2Scegger 1551.2Sceggerstatic int 1561.2Sceggeramdnb_misc_rescan(device_t self, const char *ifattr, const int *locators) 1571.2Scegger{ 1581.2Scegger struct amdnb_misc_softc *sc = device_private(self); 1591.2Scegger 1601.4Sthorpej config_search(self, &sc->sc_pa, 1611.5Sthorpej CFARGS(.search = amdnb_misc_search)); 1621.2Scegger 1631.2Scegger return 0; 1641.2Scegger} 1651.2Scegger 1661.2Sceggerstatic void 1671.2Sceggeramdnb_misc_childdet(device_t self, device_t child) 1681.2Scegger{ 1691.2Scegger return; 1701.2Scegger} 171