if_eqos_pci.c revision 1.1
1/* $NetBSD: if_eqos_pci.c,v 1.1 2023/10/20 10:09:43 msaitoh Exp $ */ 2 3/*- 4 * Copyright (c) 2023 Masanobu SAITOH <msaitoh@netbsd.org> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 17 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 25 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29/* 30 * TODO: 31 * Use multi vector MSI to support multiqueue. 32 * 33 */ 34 35#include "opt_net_mpsafe.h" 36 37#include <sys/cdefs.h> 38__KERNEL_RCSID(0, "$NetBSD: if_eqos_pci.c,v 1.1 2023/10/20 10:09:43 msaitoh Exp $"); 39 40#include <sys/param.h> 41#include <sys/bus.h> 42#include <sys/device.h> 43#include <sys/rndsource.h> 44 45#include <net/if_ether.h> 46#include <net/if_media.h> 47 48#include <dev/pci/pcireg.h> 49#include <dev/pci/pcivar.h> 50#include <dev/pci/pcidevs.h> 51 52#include <dev/mii/miivar.h> 53#include <dev/ic/dwc_eqos_var.h> 54 55#define EQOS_PCI_MAX_INTR 1 56 57static int eqos_pci_match(device_t, cfdata_t, void *); 58static void eqos_pci_attach(device_t, device_t, void *); 59 60struct eqos_pci_softc { 61 struct eqos_softc sc_eqos; 62 pci_chipset_tag_t sc_pc; 63 pcitag_t sc_tag; 64 void *sc_ihs[EQOS_PCI_MAX_INTR]; 65 pci_intr_handle_t *sc_intrs; 66 uint16_t sc_pcidevid; 67}; 68 69static const struct device_compatible_entry compat_data[] = { 70 { .id = PCI_ID_CODE(PCI_VENDOR_INTEL, 71 PCI_PRODUCT_INTEL_EHL_ETH) }, 72 { .id = PCI_ID_CODE(PCI_VENDOR_INTEL, 73 PCI_PRODUCT_INTEL_EHL_PSE_ETH_0_RGMII) }, 74 { .id = PCI_ID_CODE(PCI_VENDOR_INTEL, 75 PCI_PRODUCT_INTEL_EHL_PSE_ETH_1_RGMII) }, 76 { .id = PCI_ID_CODE(PCI_VENDOR_INTEL, 77 PCI_PRODUCT_INTEL_EHL_PSE_ETH_0_SGMII_1G) }, 78 { .id = PCI_ID_CODE(PCI_VENDOR_INTEL, 79 PCI_PRODUCT_INTEL_EHL_PSE_ETH_1_SGMII_1G) }, 80 { .id = PCI_ID_CODE(PCI_VENDOR_INTEL, 81 PCI_PRODUCT_INTEL_EHL_PSE_ETH_0_SGMII_2_5G) }, 82 { .id = PCI_ID_CODE(PCI_VENDOR_INTEL, 83 PCI_PRODUCT_INTEL_EHL_PSE_ETH_1_SGMII_2_5G) }, 84 85 PCI_COMPAT_EOL 86}; 87 88CFATTACH_DECL3_NEW(eqos_pci, sizeof(struct eqos_pci_softc), 89 eqos_pci_match, eqos_pci_attach, NULL, NULL, NULL, NULL, 90 0); 91 92static int 93eqos_pci_match(device_t parent, cfdata_t match, void *aux) 94{ 95 struct pci_attach_args *pa =aux; 96 97 return pci_compatible_match(pa, compat_data); 98} 99 100static void 101eqos_pci_attach(device_t parent, device_t self, void *aux) 102{ 103 struct eqos_pci_softc * const psc = device_private(self); 104 struct eqos_softc * const sc = &psc->sc_eqos; 105 struct pci_attach_args *pa =aux; 106 const pci_chipset_tag_t pc = pa->pa_pc; 107 const pcitag_t tag = pa->pa_tag; 108 bus_space_tag_t memt; 109 bus_space_handle_t memh; 110 int counts[PCI_INTR_TYPE_SIZE]; 111 char intrbuf[PCI_INTRSTR_LEN]; 112 bus_size_t memsize; 113 pcireg_t memtype; 114 const char *intrstr; 115 116 psc->sc_pc = pc; 117 psc->sc_tag = tag; 118 psc->sc_pcidevid = PCI_PRODUCT(pa->pa_id); 119 120 memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, PCI_BAR0); 121 if (pci_mapreg_map(pa, PCI_BAR0, memtype, 0, &memt, &memh, NULL, 122 &memsize) != 0) { 123 aprint_error(": can't map mem space\n"); 124 return; 125 } 126 sc->sc_dev = self; 127 sc->sc_bst = memt; 128 sc->sc_bsh = memh; 129 130#if 0 /* I don't know why dmat64 doesn't work... */ 131 if (pci_dma64_available(pa)) { 132 aprint_verbose(", 64-bit DMA"); 133 sc->sc_dmat = pa->pa_dmat64; 134 } else { 135 aprint_verbose(", 32-bit DMA"); 136 sc->sc_dmat = pa->pa_dmat; 137 } 138#else 139 sc->sc_dmat = pa->pa_dmat; 140#endif 141 sc->sc_phy_id = MII_PHY_ANY; 142 switch (psc->sc_pcidevid) { 143 case PCI_PRODUCT_INTEL_EHL_ETH: 144 sc->sc_csr_clock = 204800000; 145 break; 146 case PCI_PRODUCT_INTEL_EHL_PSE_ETH_0_RGMII: 147 case PCI_PRODUCT_INTEL_EHL_PSE_ETH_1_RGMII: 148 case PCI_PRODUCT_INTEL_EHL_PSE_ETH_0_SGMII_1G: 149 case PCI_PRODUCT_INTEL_EHL_PSE_ETH_1_SGMII_1G: 150 case PCI_PRODUCT_INTEL_EHL_PSE_ETH_0_SGMII_2_5G: 151 case PCI_PRODUCT_INTEL_EHL_PSE_ETH_1_SGMII_2_5G: 152 sc->sc_csr_clock = 200000000; 153 break; 154 default: 155 sc->sc_csr_clock = 200000000; /* XXX */ 156 } 157 if (eqos_attach(sc) != 0) { 158 aprint_error_dev(sc->sc_dev, "failed in eqos_attach()\n"); 159 return; 160 } 161 162 /* Allocation settings */ 163 counts[PCI_INTR_TYPE_MSI] = 1; 164 counts[PCI_INTR_TYPE_INTX] = 1; 165 if (pci_intr_alloc(pa, &psc->sc_intrs, counts, PCI_INTR_TYPE_MSI) != 0) 166 { 167 aprint_error_dev(sc->sc_dev, "failed to allocate interrupt\n"); 168 return; 169 } 170 intrstr = pci_intr_string(pc, psc->sc_intrs[0], intrbuf, 171 sizeof(intrbuf)); 172 pci_intr_setattr(pc, &psc->sc_intrs[0], PCI_INTR_MPSAFE, true); 173 psc->sc_ihs[0] = pci_intr_establish_xname(pc, psc->sc_intrs[0], 174 IPL_NET, eqos_intr, sc, device_xname(self)); 175 176 aprint_normal_dev(self, "interrupting on %s\n", intrstr); 177 178 if (pmf_device_register(self, NULL, NULL)) 179 pmf_class_network_register(self, &sc->sc_ec.ec_if); 180 else 181 aprint_error_dev(self, "couldn't establish power handler\n"); 182} 183