1*a72a7a26Sdlg /* $OpenBSD: iosf_acpi.c,v 1.1 2023/04/23 00:20:26 dlg Exp $ */
2*a72a7a26Sdlg /*
3*a72a7a26Sdlg * Copyright (c) 2023 David Gwynne <dlg@openbsd.org>
4*a72a7a26Sdlg *
5*a72a7a26Sdlg * Permission to use, copy, modify, and distribute this software for any
6*a72a7a26Sdlg * purpose with or without fee is hereby granted, provided that the above
7*a72a7a26Sdlg * copyright notice and this permission notice appear in all copies.
8*a72a7a26Sdlg *
9*a72a7a26Sdlg * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10*a72a7a26Sdlg * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11*a72a7a26Sdlg * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12*a72a7a26Sdlg * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13*a72a7a26Sdlg * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14*a72a7a26Sdlg * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15*a72a7a26Sdlg * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16*a72a7a26Sdlg */
17*a72a7a26Sdlg
18*a72a7a26Sdlg #include <sys/param.h>
19*a72a7a26Sdlg #include <sys/systm.h>
20*a72a7a26Sdlg #include <sys/device.h>
21*a72a7a26Sdlg
22*a72a7a26Sdlg #include <machine/bus.h>
23*a72a7a26Sdlg #include <machine/intr.h>
24*a72a7a26Sdlg
25*a72a7a26Sdlg #include <dev/acpi/acpireg.h>
26*a72a7a26Sdlg #include <dev/acpi/acpivar.h>
27*a72a7a26Sdlg #include <dev/acpi/acpidev.h>
28*a72a7a26Sdlg #include <dev/acpi/amltypes.h>
29*a72a7a26Sdlg #include <dev/acpi/dsdt.h>
30*a72a7a26Sdlg
31*a72a7a26Sdlg #include <dev/ic/iosfvar.h>
32*a72a7a26Sdlg
33*a72a7a26Sdlg struct iosf_acpi_softc {
34*a72a7a26Sdlg struct device sc_dev;
35*a72a7a26Sdlg struct acpi_softc *sc_acpi;
36*a72a7a26Sdlg struct aml_node *sc_node;
37*a72a7a26Sdlg
38*a72a7a26Sdlg bus_space_tag_t sc_iot;
39*a72a7a26Sdlg bus_space_handle_t sc_ioh;
40*a72a7a26Sdlg bus_size_t sc_ios;
41*a72a7a26Sdlg
42*a72a7a26Sdlg struct iosf_mbi sc_mbi;
43*a72a7a26Sdlg };
44*a72a7a26Sdlg
45*a72a7a26Sdlg static int iosf_acpi_match(struct device *, void *, void *);
46*a72a7a26Sdlg static void iosf_acpi_attach(struct device *, struct device *, void *);
47*a72a7a26Sdlg
48*a72a7a26Sdlg static uint32_t iosf_acpi_mbi_mdr_rd(struct iosf_mbi *, uint32_t, uint32_t);
49*a72a7a26Sdlg static void iosf_acpi_mbi_mdr_wr(struct iosf_mbi *, uint32_t, uint32_t,
50*a72a7a26Sdlg uint32_t);
51*a72a7a26Sdlg
52*a72a7a26Sdlg const struct cfattach iosf_acpi_ca = {
53*a72a7a26Sdlg sizeof(struct iosf_acpi_softc), iosf_acpi_match, iosf_acpi_attach
54*a72a7a26Sdlg };
55*a72a7a26Sdlg
56*a72a7a26Sdlg static const char *iosf_hids[] = {
57*a72a7a26Sdlg "INT33BD",
58*a72a7a26Sdlg NULL
59*a72a7a26Sdlg };
60*a72a7a26Sdlg
61*a72a7a26Sdlg static int
iosf_acpi_match(struct device * parent,void * match,void * aux)62*a72a7a26Sdlg iosf_acpi_match(struct device *parent, void *match, void *aux)
63*a72a7a26Sdlg {
64*a72a7a26Sdlg struct acpi_attach_args *aaa = aux;
65*a72a7a26Sdlg struct cfdata *cf = match;
66*a72a7a26Sdlg
67*a72a7a26Sdlg if (aaa->aaa_naddr < 1)
68*a72a7a26Sdlg return 0;
69*a72a7a26Sdlg
70*a72a7a26Sdlg return (acpi_matchhids(aaa, iosf_hids, cf->cf_driver->cd_name));
71*a72a7a26Sdlg }
72*a72a7a26Sdlg
73*a72a7a26Sdlg static void
iosf_acpi_attach(struct device * parent,struct device * self,void * aux)74*a72a7a26Sdlg iosf_acpi_attach(struct device *parent, struct device *self, void *aux)
75*a72a7a26Sdlg {
76*a72a7a26Sdlg struct iosf_acpi_softc *sc = (struct iosf_acpi_softc *)self;
77*a72a7a26Sdlg struct acpi_attach_args *aaa = aux;
78*a72a7a26Sdlg struct cpu_info *ci;
79*a72a7a26Sdlg int semaddr = -1;
80*a72a7a26Sdlg
81*a72a7a26Sdlg sc->sc_acpi = (struct acpi_softc *)parent;
82*a72a7a26Sdlg sc->sc_node = aaa->aaa_node;
83*a72a7a26Sdlg printf(" %s", sc->sc_node->name);
84*a72a7a26Sdlg
85*a72a7a26Sdlg sc->sc_iot = aaa->aaa_bst[0];
86*a72a7a26Sdlg sc->sc_ios = aaa->aaa_size[0];
87*a72a7a26Sdlg
88*a72a7a26Sdlg if (bus_space_map(sc->sc_iot, aaa->aaa_addr[0], aaa->aaa_size[0], 0,
89*a72a7a26Sdlg &sc->sc_ioh)) {
90*a72a7a26Sdlg printf(": can't map registers\n");
91*a72a7a26Sdlg return;
92*a72a7a26Sdlg }
93*a72a7a26Sdlg
94*a72a7a26Sdlg ci = curcpu();
95*a72a7a26Sdlg if (strcmp(cpu_vendor, "GenuineIntel") == 0 &&
96*a72a7a26Sdlg ci->ci_family == 0x06 && ci->ci_model == 0x4c) {
97*a72a7a26Sdlg /* cherry trail, braswell */
98*a72a7a26Sdlg semaddr = 0x10e;
99*a72a7a26Sdlg }
100*a72a7a26Sdlg
101*a72a7a26Sdlg if (semaddr != -1) {
102*a72a7a26Sdlg printf(": mbi");
103*a72a7a26Sdlg
104*a72a7a26Sdlg sc->sc_mbi.mbi_dev = self;
105*a72a7a26Sdlg sc->sc_mbi.mbi_prio = 1; /* lower prio than iosf_pci ops */
106*a72a7a26Sdlg sc->sc_mbi.mbi_semaddr = semaddr;
107*a72a7a26Sdlg sc->sc_mbi.mbi_mdr_rd = iosf_acpi_mbi_mdr_rd;
108*a72a7a26Sdlg sc->sc_mbi.mbi_mdr_wr = iosf_acpi_mbi_mdr_wr;
109*a72a7a26Sdlg }
110*a72a7a26Sdlg
111*a72a7a26Sdlg printf("\n");
112*a72a7a26Sdlg }
113*a72a7a26Sdlg
114*a72a7a26Sdlg /*
115*a72a7a26Sdlg * mbi mdr ACPI operations
116*a72a7a26Sdlg */
117*a72a7a26Sdlg
118*a72a7a26Sdlg #define IOSF_ACPI_MBI_MCR 0x0
119*a72a7a26Sdlg #define IOSF_ACPI_MBI_MDR 0x4
120*a72a7a26Sdlg #define IOSF_ACPI_MBI_MCRX 0x8
121*a72a7a26Sdlg
122*a72a7a26Sdlg static uint32_t
iosf_acpi_mbi_mdr_rd(struct iosf_mbi * mbi,uint32_t mcr,uint32_t mcrx)123*a72a7a26Sdlg iosf_acpi_mbi_mdr_rd(struct iosf_mbi *mbi, uint32_t mcr, uint32_t mcrx)
124*a72a7a26Sdlg {
125*a72a7a26Sdlg struct iosf_acpi_softc *sc = (struct iosf_acpi_softc *)mbi->mbi_dev;
126*a72a7a26Sdlg
127*a72a7a26Sdlg if (mcrx != 0) {
128*a72a7a26Sdlg bus_space_write_4(sc->sc_iot, sc->sc_ioh,
129*a72a7a26Sdlg IOSF_ACPI_MBI_MCRX, mcrx);
130*a72a7a26Sdlg }
131*a72a7a26Sdlg bus_space_write_4(sc->sc_iot, sc->sc_ioh, IOSF_ACPI_MBI_MCR, mcr);
132*a72a7a26Sdlg
133*a72a7a26Sdlg return (bus_space_read_4(sc->sc_iot, sc->sc_ioh, IOSF_ACPI_MBI_MDR));
134*a72a7a26Sdlg }
135*a72a7a26Sdlg
136*a72a7a26Sdlg static void
iosf_acpi_mbi_mdr_wr(struct iosf_mbi * mbi,uint32_t mcr,uint32_t mcrx,uint32_t mdr)137*a72a7a26Sdlg iosf_acpi_mbi_mdr_wr(struct iosf_mbi *mbi, uint32_t mcr, uint32_t mcrx,
138*a72a7a26Sdlg uint32_t mdr)
139*a72a7a26Sdlg {
140*a72a7a26Sdlg struct iosf_acpi_softc *sc = (struct iosf_acpi_softc *)mbi->mbi_dev;
141*a72a7a26Sdlg
142*a72a7a26Sdlg bus_space_write_4(sc->sc_iot, sc->sc_ioh, IOSF_ACPI_MBI_MDR, mdr);
143*a72a7a26Sdlg if (mcrx != 0) {
144*a72a7a26Sdlg bus_space_write_4(sc->sc_iot, sc->sc_ioh,
145*a72a7a26Sdlg IOSF_ACPI_MBI_MCRX, mcrx);
146*a72a7a26Sdlg }
147*a72a7a26Sdlg
148*a72a7a26Sdlg bus_space_write_4(sc->sc_iot, sc->sc_ioh, IOSF_ACPI_MBI_MCR, mcr);
149*a72a7a26Sdlg }
150