1 /* $OpenBSD: iosf_pci.c,v 1.2 2024/05/24 06:02:57 jsg Exp $ */ 2 3 /* 4 * Copyright (c) 2023 David Gwynne <dlg@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/param.h> 20 #include <sys/systm.h> 21 #include <sys/device.h> 22 23 #include <machine/bus.h> 24 25 #include <dev/pci/pcivar.h> 26 #include <dev/pci/pcidevs.h> 27 28 #include <dev/ic/iosfvar.h> 29 30 /* 31 * Intel OnChip System Fabric driver 32 */ 33 34 struct iosf_pci_softc { 35 struct device sc_dev; 36 37 pci_chipset_tag_t sc_pc; 38 pcitag_t sc_pcitag; 39 40 int sc_semaddr; 41 42 struct iosf_mbi sc_mbi; 43 }; 44 45 static int iosf_pci_match(struct device *, void *, void *); 46 static void iosf_pci_attach(struct device *, struct device *, void *); 47 48 static uint32_t iosf_pci_mbi_mdr_rd(struct iosf_mbi *, uint32_t, uint32_t); 49 static void iosf_pci_mbi_mdr_wr(struct iosf_mbi *, uint32_t, uint32_t, 50 uint32_t); 51 52 const struct cfattach iosf_pci_ca = { 53 sizeof(struct iosf_pci_softc), iosf_pci_match, iosf_pci_attach 54 }; 55 56 struct iosf_pci_device { 57 struct pci_matchid id_pm; 58 int id_semaddr; 59 }; 60 61 static const struct iosf_pci_device iosf_pci_devices[] = { 62 { { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_BAYTRAIL_HB }, 0x7 }, 63 { { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_BSW_HB }, 0x10e }, 64 /* Quark X1000, -1 */ 65 /* Tangier, -1 */ 66 }; 67 68 static const struct iosf_pci_device * 69 iosf_pci_device_match(struct pci_attach_args *pa) 70 { 71 pci_vendor_id_t vid = PCI_VENDOR(pa->pa_id); 72 pci_product_id_t pid = PCI_PRODUCT(pa->pa_id); 73 const struct iosf_pci_device *id; 74 size_t i; 75 76 for (i = 0; i < nitems(iosf_pci_devices); i++) { 77 id = &iosf_pci_devices[i]; 78 if (id->id_pm.pm_vid == vid && id->id_pm.pm_pid == pid) 79 return (id); 80 } 81 82 return (NULL); 83 } 84 85 static int 86 iosf_pci_match(struct device *parent, void *match, void *aux) 87 { 88 struct pci_attach_args *pa = aux; 89 90 if (iosf_pci_device_match(pa) != NULL) { 91 /* match higher than pchb(4) */ 92 return (2); 93 } 94 95 return (0); 96 } 97 98 static void 99 iosf_pci_attach(struct device *parent, struct device *self, void *aux) 100 { 101 struct iosf_pci_softc *sc = (struct iosf_pci_softc *)self; 102 struct pci_attach_args *pa = aux; 103 const struct iosf_pci_device *id = iosf_pci_device_match(pa); 104 105 sc->sc_pc = pa->pa_pc; 106 sc->sc_pcitag = pa->pa_tag; 107 108 printf(": mbi\n"); 109 110 sc->sc_mbi.mbi_dev = self; 111 sc->sc_mbi.mbi_prio = 2; /* prefer pci over acpi ops */ 112 sc->sc_mbi.mbi_semaddr = id->id_semaddr; 113 sc->sc_mbi.mbi_mdr_rd = iosf_pci_mbi_mdr_rd; 114 sc->sc_mbi.mbi_mdr_wr = iosf_pci_mbi_mdr_wr; 115 116 iosf_mbi_attach(&sc->sc_mbi); 117 } 118 119 /* 120 * mbi mdr pciconf operations 121 */ 122 123 #define IOSF_PCI_MBI_MCR 0xd0 124 #define IOSF_PCI_MBI_MDR 0xd4 125 #define IOSF_PCI_MBI_MCRX 0xd8 126 127 static uint32_t 128 iosf_pci_mbi_mdr_rd(struct iosf_mbi *mbi, uint32_t mcr, uint32_t mcrx) 129 { 130 struct iosf_pci_softc *sc = (struct iosf_pci_softc *)mbi->mbi_dev; 131 132 if (mcrx != 0) { 133 pci_conf_write(sc->sc_pc, sc->sc_pcitag, 134 IOSF_PCI_MBI_MCRX, mcrx); 135 } 136 pci_conf_write(sc->sc_pc, sc->sc_pcitag, IOSF_PCI_MBI_MCR, mcr); 137 138 return (pci_conf_read(sc->sc_pc, sc->sc_pcitag, IOSF_PCI_MBI_MDR)); 139 } 140 141 static void 142 iosf_pci_mbi_mdr_wr(struct iosf_mbi *mbi, uint32_t mcr, uint32_t mcrx, 143 uint32_t mdr) 144 { 145 struct iosf_pci_softc *sc = (struct iosf_pci_softc *)mbi->mbi_dev; 146 147 pci_conf_write(sc->sc_pc, sc->sc_pcitag, IOSF_PCI_MBI_MDR, mdr); 148 149 if (mcrx != 0) { 150 pci_conf_write(sc->sc_pc, sc->sc_pcitag, 151 IOSF_PCI_MBI_MCRX, mcrx); 152 } 153 154 pci_conf_write(sc->sc_pc, sc->sc_pcitag, IOSF_PCI_MBI_MCR, mcr); 155 } 156