1 /* $OpenBSD: iosf_pci.c,v 1.1 2023/04/23 00:20:26 dlg 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 #include <sys/mutex.h> 23 #include <sys/rwlock.h> 24 25 #include <machine/bus.h> 26 27 #include <dev/pci/pcivar.h> 28 #include <dev/pci/pcidevs.h> 29 30 #include <dev/ic/iosfvar.h> 31 32 /* 33 * Intel OnChip System Fabric driver 34 */ 35 36 struct iosf_pci_softc { 37 struct device sc_dev; 38 39 pci_chipset_tag_t sc_pc; 40 pcitag_t sc_pcitag; 41 42 int sc_semaddr; 43 44 struct iosf_mbi sc_mbi; 45 }; 46 47 static int iosf_pci_match(struct device *, void *, void *); 48 static void iosf_pci_attach(struct device *, struct device *, void *); 49 50 static uint32_t iosf_pci_mbi_mdr_rd(struct iosf_mbi *, uint32_t, uint32_t); 51 static void iosf_pci_mbi_mdr_wr(struct iosf_mbi *, uint32_t, uint32_t, 52 uint32_t); 53 54 const struct cfattach iosf_pci_ca = { 55 sizeof(struct iosf_pci_softc), iosf_pci_match, iosf_pci_attach 56 }; 57 58 struct iosf_pci_device { 59 struct pci_matchid id_pm; 60 int id_semaddr; 61 }; 62 63 static const struct iosf_pci_device iosf_pci_devices[] = { 64 { { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_BAYTRAIL_HB }, 0x7 }, 65 { { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_BSW_HB }, 0x10e }, 66 /* Quark X1000, -1 */ 67 /* Tangier, -1 */ 68 }; 69 70 static const struct iosf_pci_device * 71 iosf_pci_device_match(struct pci_attach_args *pa) 72 { 73 pci_vendor_id_t vid = PCI_VENDOR(pa->pa_id); 74 pci_product_id_t pid = PCI_PRODUCT(pa->pa_id); 75 const struct iosf_pci_device *id; 76 size_t i; 77 78 for (i = 0; i < nitems(iosf_pci_devices); i++) { 79 id = &iosf_pci_devices[i]; 80 if (id->id_pm.pm_vid == vid && id->id_pm.pm_pid == pid) 81 return (id); 82 } 83 84 return (NULL); 85 } 86 87 static int 88 iosf_pci_match(struct device *parent, void *match, void *aux) 89 { 90 struct pci_attach_args *pa = aux; 91 92 if (iosf_pci_device_match(pa) != NULL) { 93 /* match higher than pchb(4) */ 94 return (2); 95 } 96 97 return (0); 98 } 99 100 static void 101 iosf_pci_attach(struct device *parent, struct device *self, void *aux) 102 { 103 struct iosf_pci_softc *sc = (struct iosf_pci_softc *)self; 104 struct pci_attach_args *pa = aux; 105 const struct iosf_pci_device *id = iosf_pci_device_match(pa); 106 107 sc->sc_pc = pa->pa_pc; 108 sc->sc_pcitag = pa->pa_tag; 109 110 printf(": mbi\n"); 111 112 sc->sc_mbi.mbi_dev = self; 113 sc->sc_mbi.mbi_prio = 2; /* prefer pci over acpi ops */ 114 sc->sc_mbi.mbi_semaddr = id->id_semaddr; 115 sc->sc_mbi.mbi_mdr_rd = iosf_pci_mbi_mdr_rd; 116 sc->sc_mbi.mbi_mdr_wr = iosf_pci_mbi_mdr_wr; 117 118 iosf_mbi_attach(&sc->sc_mbi); 119 } 120 121 /* 122 * mbi mdr pciconf operations 123 */ 124 125 #define IOSF_PCI_MBI_MCR 0xd0 126 #define IOSF_PCI_MBI_MDR 0xd4 127 #define IOSF_PCI_MBI_MCRX 0xd8 128 129 static uint32_t 130 iosf_pci_mbi_mdr_rd(struct iosf_mbi *mbi, uint32_t mcr, uint32_t mcrx) 131 { 132 struct iosf_pci_softc *sc = (struct iosf_pci_softc *)mbi->mbi_dev; 133 134 if (mcrx != 0) { 135 pci_conf_write(sc->sc_pc, sc->sc_pcitag, 136 IOSF_PCI_MBI_MCRX, mcrx); 137 } 138 pci_conf_write(sc->sc_pc, sc->sc_pcitag, IOSF_PCI_MBI_MCR, mcr); 139 140 return (pci_conf_read(sc->sc_pc, sc->sc_pcitag, IOSF_PCI_MBI_MDR)); 141 } 142 143 static void 144 iosf_pci_mbi_mdr_wr(struct iosf_mbi *mbi, uint32_t mcr, uint32_t mcrx, 145 uint32_t mdr) 146 { 147 struct iosf_pci_softc *sc = (struct iosf_pci_softc *)mbi->mbi_dev; 148 149 pci_conf_write(sc->sc_pc, sc->sc_pcitag, IOSF_PCI_MBI_MDR, mdr); 150 151 if (mcrx != 0) { 152 pci_conf_write(sc->sc_pc, sc->sc_pcitag, 153 IOSF_PCI_MBI_MCRX, mcrx); 154 } 155 156 pci_conf_write(sc->sc_pc, sc->sc_pcitag, IOSF_PCI_MBI_MCR, mcr); 157 } 158