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 *
iosf_pci_device_match(struct pci_attach_args * pa)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
iosf_pci_match(struct device * parent,void * match,void * aux)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
iosf_pci_attach(struct device * parent,struct device * self,void * aux)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
iosf_pci_mbi_mdr_rd(struct iosf_mbi * mbi,uint32_t mcr,uint32_t mcrx)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
iosf_pci_mbi_mdr_wr(struct iosf_mbi * mbi,uint32_t mcr,uint32_t mcrx,uint32_t mdr)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