if_eqos_pci.c revision 1.2
1/* $NetBSD: if_eqos_pci.c,v 1.2 2023/10/26 18:02:51 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.2 2023/10/26 18:02:51 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 prop_dictionary_t prop; 109 bus_space_tag_t memt; 110 bus_space_handle_t memh; 111 int counts[PCI_INTR_TYPE_SIZE]; 112 char intrbuf[PCI_INTRSTR_LEN]; 113 bus_size_t memsize; 114 pcireg_t memtype; 115 const char *intrstr; 116 uint32_t dma_pbl = 0; 117 118 psc->sc_pc = pc; 119 psc->sc_tag = tag; 120 psc->sc_pcidevid = PCI_PRODUCT(pa->pa_id); 121 122 memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, PCI_BAR0); 123 if (pci_mapreg_map(pa, PCI_BAR0, memtype, 0, &memt, &memh, NULL, 124 &memsize) != 0) { 125 aprint_error(": can't map mem space\n"); 126 return; 127 } 128 sc->sc_dev = self; 129 sc->sc_bst = memt; 130 sc->sc_bsh = memh; 131 prop = device_properties(sc->sc_dev); 132 133#if 0 /* I don't know why dmat64 doesn't work... */ 134 if (pci_dma64_available(pa)) { 135 aprint_verbose(", 64-bit DMA"); 136 sc->sc_dmat = pa->pa_dmat64; 137 } else { 138 aprint_verbose(", 32-bit DMA"); 139 sc->sc_dmat = pa->pa_dmat; 140 } 141#else 142 sc->sc_dmat = pa->pa_dmat; 143#endif 144 sc->sc_phy_id = MII_PHY_ANY; 145 switch (psc->sc_pcidevid) { 146 case PCI_PRODUCT_INTEL_EHL_ETH: 147 sc->sc_csr_clock = 204800000; 148 dma_pbl = 32; 149 break; 150 case PCI_PRODUCT_INTEL_EHL_PSE_ETH_0_RGMII: 151 case PCI_PRODUCT_INTEL_EHL_PSE_ETH_1_RGMII: 152 case PCI_PRODUCT_INTEL_EHL_PSE_ETH_0_SGMII_1G: 153 case PCI_PRODUCT_INTEL_EHL_PSE_ETH_1_SGMII_1G: 154 case PCI_PRODUCT_INTEL_EHL_PSE_ETH_0_SGMII_2_5G: 155 case PCI_PRODUCT_INTEL_EHL_PSE_ETH_1_SGMII_2_5G: 156 sc->sc_csr_clock = 200000000; 157 dma_pbl = 32; 158 break; 159#if 0 160 case PCI_PRODUCT_INTEL_QUARTK_ETH: 161 dma_pbl = 16; 162#endif 163 default: 164 sc->sc_csr_clock = 200000000; /* XXX */ 165 } 166 /* Defaults */ 167 if (dma_pbl != 0) { 168 prop = device_properties(sc->sc_dev); 169 prop_dictionary_set_uint32(prop, "snps,pbl", dma_pbl); 170 } 171 172 if (eqos_attach(sc) != 0) { 173 aprint_error_dev(sc->sc_dev, "failed in eqos_attach()\n"); 174 return; 175 } 176 177 /* Allocation settings */ 178 counts[PCI_INTR_TYPE_MSI] = 1; 179 counts[PCI_INTR_TYPE_INTX] = 1; 180 if (pci_intr_alloc(pa, &psc->sc_intrs, counts, PCI_INTR_TYPE_MSI) != 0) 181 { 182 aprint_error_dev(sc->sc_dev, "failed to allocate interrupt\n"); 183 return; 184 } 185 intrstr = pci_intr_string(pc, psc->sc_intrs[0], intrbuf, 186 sizeof(intrbuf)); 187 pci_intr_setattr(pc, &psc->sc_intrs[0], PCI_INTR_MPSAFE, true); 188 psc->sc_ihs[0] = pci_intr_establish_xname(pc, psc->sc_intrs[0], 189 IPL_NET, eqos_intr, sc, device_xname(self)); 190 191 aprint_normal_dev(self, "interrupting on %s\n", intrstr); 192 193 if (pmf_device_register(self, NULL, NULL)) 194 pmf_class_network_register(self, &sc->sc_ec.ec_if); 195 else 196 aprint_error_dev(self, "couldn't establish power handler\n"); 197} 198