11.4Sskrll/* $NetBSD: if_eqos_pci.c,v 1.4 2023/12/19 09:39:55 skrll Exp $ */ 21.1Smsaitoh 31.1Smsaitoh/*- 41.1Smsaitoh * Copyright (c) 2023 Masanobu SAITOH <msaitoh@netbsd.org> 51.1Smsaitoh * All rights reserved. 61.1Smsaitoh * 71.1Smsaitoh * Redistribution and use in source and binary forms, with or without 81.1Smsaitoh * modification, are permitted provided that the following conditions 91.1Smsaitoh * are met: 101.1Smsaitoh * 1. Redistributions of source code must retain the above copyright 111.1Smsaitoh * notice, this list of conditions and the following disclaimer. 121.1Smsaitoh * 2. Redistributions in binary form must reproduce the above copyright 131.1Smsaitoh * notice, this list of conditions and the following disclaimer in the 141.1Smsaitoh * documentation and/or other materials provided with the distribution. 151.1Smsaitoh * 161.1Smsaitoh * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 171.1Smsaitoh * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 181.1Smsaitoh * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 191.1Smsaitoh * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 201.1Smsaitoh * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 211.1Smsaitoh * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 221.1Smsaitoh * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 231.1Smsaitoh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 241.1Smsaitoh * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 251.1Smsaitoh * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 261.1Smsaitoh * POSSIBILITY OF SUCH DAMAGE. 271.1Smsaitoh */ 281.1Smsaitoh 291.1Smsaitoh/* 301.1Smsaitoh * TODO: 311.1Smsaitoh * Use multi vector MSI to support multiqueue. 321.1Smsaitoh * 331.1Smsaitoh */ 341.1Smsaitoh 351.1Smsaitoh#include <sys/cdefs.h> 361.4Sskrll__KERNEL_RCSID(0, "$NetBSD: if_eqos_pci.c,v 1.4 2023/12/19 09:39:55 skrll Exp $"); 371.1Smsaitoh 381.1Smsaitoh#include <sys/param.h> 391.1Smsaitoh#include <sys/bus.h> 401.1Smsaitoh#include <sys/device.h> 411.1Smsaitoh#include <sys/rndsource.h> 421.1Smsaitoh 431.1Smsaitoh#include <net/if_ether.h> 441.1Smsaitoh#include <net/if_media.h> 451.1Smsaitoh 461.1Smsaitoh#include <dev/pci/pcireg.h> 471.1Smsaitoh#include <dev/pci/pcivar.h> 481.1Smsaitoh#include <dev/pci/pcidevs.h> 491.1Smsaitoh 501.1Smsaitoh#include <dev/mii/miivar.h> 511.1Smsaitoh#include <dev/ic/dwc_eqos_var.h> 521.1Smsaitoh 531.1Smsaitoh#define EQOS_PCI_MAX_INTR 1 541.1Smsaitoh 551.1Smsaitohstatic int eqos_pci_match(device_t, cfdata_t, void *); 561.1Smsaitohstatic void eqos_pci_attach(device_t, device_t, void *); 571.1Smsaitoh 581.1Smsaitohstruct eqos_pci_softc { 591.1Smsaitoh struct eqos_softc sc_eqos; 601.1Smsaitoh pci_chipset_tag_t sc_pc; 611.1Smsaitoh pcitag_t sc_tag; 621.1Smsaitoh void *sc_ihs[EQOS_PCI_MAX_INTR]; 631.1Smsaitoh pci_intr_handle_t *sc_intrs; 641.1Smsaitoh uint16_t sc_pcidevid; 651.1Smsaitoh}; 661.1Smsaitoh 671.1Smsaitohstatic const struct device_compatible_entry compat_data[] = { 681.1Smsaitoh { .id = PCI_ID_CODE(PCI_VENDOR_INTEL, 691.1Smsaitoh PCI_PRODUCT_INTEL_EHL_ETH) }, 701.1Smsaitoh { .id = PCI_ID_CODE(PCI_VENDOR_INTEL, 711.1Smsaitoh PCI_PRODUCT_INTEL_EHL_PSE_ETH_0_RGMII) }, 721.1Smsaitoh { .id = PCI_ID_CODE(PCI_VENDOR_INTEL, 731.1Smsaitoh PCI_PRODUCT_INTEL_EHL_PSE_ETH_1_RGMII) }, 741.1Smsaitoh { .id = PCI_ID_CODE(PCI_VENDOR_INTEL, 751.1Smsaitoh PCI_PRODUCT_INTEL_EHL_PSE_ETH_0_SGMII_1G) }, 761.1Smsaitoh { .id = PCI_ID_CODE(PCI_VENDOR_INTEL, 771.1Smsaitoh PCI_PRODUCT_INTEL_EHL_PSE_ETH_1_SGMII_1G) }, 781.1Smsaitoh { .id = PCI_ID_CODE(PCI_VENDOR_INTEL, 791.1Smsaitoh PCI_PRODUCT_INTEL_EHL_PSE_ETH_0_SGMII_2_5G) }, 801.1Smsaitoh { .id = PCI_ID_CODE(PCI_VENDOR_INTEL, 811.1Smsaitoh PCI_PRODUCT_INTEL_EHL_PSE_ETH_1_SGMII_2_5G) }, 821.1Smsaitoh 831.1Smsaitoh PCI_COMPAT_EOL 841.1Smsaitoh}; 851.1Smsaitoh 861.1SmsaitohCFATTACH_DECL3_NEW(eqos_pci, sizeof(struct eqos_pci_softc), 871.1Smsaitoh eqos_pci_match, eqos_pci_attach, NULL, NULL, NULL, NULL, 881.1Smsaitoh 0); 891.1Smsaitoh 901.1Smsaitohstatic int 911.1Smsaitoheqos_pci_match(device_t parent, cfdata_t match, void *aux) 921.1Smsaitoh{ 931.1Smsaitoh struct pci_attach_args *pa =aux; 941.1Smsaitoh 951.1Smsaitoh return pci_compatible_match(pa, compat_data); 961.1Smsaitoh} 971.1Smsaitoh 981.1Smsaitohstatic void 991.1Smsaitoheqos_pci_attach(device_t parent, device_t self, void *aux) 1001.1Smsaitoh{ 1011.1Smsaitoh struct eqos_pci_softc * const psc = device_private(self); 1021.1Smsaitoh struct eqos_softc * const sc = &psc->sc_eqos; 1031.1Smsaitoh struct pci_attach_args *pa =aux; 1041.1Smsaitoh const pci_chipset_tag_t pc = pa->pa_pc; 1051.1Smsaitoh const pcitag_t tag = pa->pa_tag; 1061.2Smsaitoh prop_dictionary_t prop; 1071.1Smsaitoh bus_space_tag_t memt; 1081.1Smsaitoh bus_space_handle_t memh; 1091.1Smsaitoh int counts[PCI_INTR_TYPE_SIZE]; 1101.1Smsaitoh char intrbuf[PCI_INTRSTR_LEN]; 1111.1Smsaitoh bus_size_t memsize; 1121.1Smsaitoh pcireg_t memtype; 1131.1Smsaitoh const char *intrstr; 1141.2Smsaitoh uint32_t dma_pbl = 0; 1151.1Smsaitoh 1161.1Smsaitoh psc->sc_pc = pc; 1171.1Smsaitoh psc->sc_tag = tag; 1181.1Smsaitoh psc->sc_pcidevid = PCI_PRODUCT(pa->pa_id); 1191.1Smsaitoh 1201.1Smsaitoh memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, PCI_BAR0); 1211.1Smsaitoh if (pci_mapreg_map(pa, PCI_BAR0, memtype, 0, &memt, &memh, NULL, 1221.1Smsaitoh &memsize) != 0) { 1231.1Smsaitoh aprint_error(": can't map mem space\n"); 1241.1Smsaitoh return; 1251.1Smsaitoh } 1261.1Smsaitoh sc->sc_dev = self; 1271.1Smsaitoh sc->sc_bst = memt; 1281.1Smsaitoh sc->sc_bsh = memh; 1291.2Smsaitoh prop = device_properties(sc->sc_dev); 1301.1Smsaitoh 1311.3Smsaitoh if (pci_dma64_available(pa)) 1321.1Smsaitoh sc->sc_dmat = pa->pa_dmat64; 1331.3Smsaitoh else 1341.1Smsaitoh sc->sc_dmat = pa->pa_dmat; 1351.3Smsaitoh 1361.1Smsaitoh sc->sc_phy_id = MII_PHY_ANY; 1371.1Smsaitoh switch (psc->sc_pcidevid) { 1381.1Smsaitoh case PCI_PRODUCT_INTEL_EHL_ETH: 1391.1Smsaitoh sc->sc_csr_clock = 204800000; 1401.2Smsaitoh dma_pbl = 32; 1411.1Smsaitoh break; 1421.1Smsaitoh case PCI_PRODUCT_INTEL_EHL_PSE_ETH_0_RGMII: 1431.1Smsaitoh case PCI_PRODUCT_INTEL_EHL_PSE_ETH_1_RGMII: 1441.1Smsaitoh case PCI_PRODUCT_INTEL_EHL_PSE_ETH_0_SGMII_1G: 1451.1Smsaitoh case PCI_PRODUCT_INTEL_EHL_PSE_ETH_1_SGMII_1G: 1461.1Smsaitoh case PCI_PRODUCT_INTEL_EHL_PSE_ETH_0_SGMII_2_5G: 1471.1Smsaitoh case PCI_PRODUCT_INTEL_EHL_PSE_ETH_1_SGMII_2_5G: 1481.3Smsaitoh sc->sc_dmat = pa->pa_dmat; /* 32bit DMA only */ 1491.1Smsaitoh sc->sc_csr_clock = 200000000; 1501.2Smsaitoh dma_pbl = 32; 1511.1Smsaitoh break; 1521.2Smsaitoh#if 0 1531.2Smsaitoh case PCI_PRODUCT_INTEL_QUARTK_ETH: 1541.2Smsaitoh dma_pbl = 16; 1551.2Smsaitoh#endif 1561.1Smsaitoh default: 1571.1Smsaitoh sc->sc_csr_clock = 200000000; /* XXX */ 1581.1Smsaitoh } 1591.3Smsaitoh 1601.3Smsaitoh if (sc->sc_dmat == pa->pa_dmat64) 1611.3Smsaitoh aprint_verbose(", 64-bit DMA"); 1621.3Smsaitoh else 1631.3Smsaitoh aprint_verbose(", 32-bit DMA"); 1641.3Smsaitoh 1651.2Smsaitoh /* Defaults */ 1661.2Smsaitoh if (dma_pbl != 0) { 1671.2Smsaitoh prop = device_properties(sc->sc_dev); 1681.2Smsaitoh prop_dictionary_set_uint32(prop, "snps,pbl", dma_pbl); 1691.2Smsaitoh } 1701.2Smsaitoh 1711.1Smsaitoh if (eqos_attach(sc) != 0) { 1721.1Smsaitoh aprint_error_dev(sc->sc_dev, "failed in eqos_attach()\n"); 1731.1Smsaitoh return; 1741.1Smsaitoh } 1751.1Smsaitoh 1761.1Smsaitoh /* Allocation settings */ 1771.1Smsaitoh counts[PCI_INTR_TYPE_MSI] = 1; 1781.1Smsaitoh counts[PCI_INTR_TYPE_INTX] = 1; 1791.1Smsaitoh if (pci_intr_alloc(pa, &psc->sc_intrs, counts, PCI_INTR_TYPE_MSI) != 0) 1801.1Smsaitoh { 1811.1Smsaitoh aprint_error_dev(sc->sc_dev, "failed to allocate interrupt\n"); 1821.1Smsaitoh return; 1831.1Smsaitoh } 1841.1Smsaitoh intrstr = pci_intr_string(pc, psc->sc_intrs[0], intrbuf, 1851.1Smsaitoh sizeof(intrbuf)); 1861.1Smsaitoh pci_intr_setattr(pc, &psc->sc_intrs[0], PCI_INTR_MPSAFE, true); 1871.1Smsaitoh psc->sc_ihs[0] = pci_intr_establish_xname(pc, psc->sc_intrs[0], 1881.1Smsaitoh IPL_NET, eqos_intr, sc, device_xname(self)); 1891.1Smsaitoh 1901.1Smsaitoh aprint_normal_dev(self, "interrupting on %s\n", intrstr); 1911.1Smsaitoh 1921.1Smsaitoh if (pmf_device_register(self, NULL, NULL)) 1931.1Smsaitoh pmf_class_network_register(self, &sc->sc_ec.ec_if); 1941.1Smsaitoh else 1951.1Smsaitoh aprint_error_dev(self, "couldn't establish power handler\n"); 1961.1Smsaitoh} 197