xref: /openbsd-src/sys/dev/pci/iosf_pci.c (revision 1ad61ae0a79a724d2d3ec69e69c8e1d1ff6b53a0)
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