Index: arch/amd64/conf/GENERIC =================================================================== RCS file: /cvs/src/sys/arch/amd64/conf/GENERIC,v retrieving revision 1.514 diff -u -p -r1.514 GENERIC --- arch/amd64/conf/GENERIC 11 Nov 2022 15:27:39 -0000 1.514 +++ arch/amd64/conf/GENERIC 1 Mar 2023 01:55:14 -0000 @@ -159,6 +159,8 @@ iic* at amdpm? dwiic* at acpi? # DesignWare Synopsys i2c controller dwiic* at pci? iic* at dwiic? +iosf* at acpi? # Intel OnChip System Fabric +iosf* at pci? itherm* at pci? # Intel 3400 Thermal Sensor adc* at iic? # Analog Devices AD7416/AD7417/7418 Index: conf/files =================================================================== RCS file: /cvs/src/sys/conf/files,v retrieving revision 1.722 diff -u -p -r1.722 files --- conf/files 13 Feb 2023 19:18:53 -0000 1.722 +++ conf/files 1 Mar 2023 01:55:16 -0000 @@ -424,6 +424,10 @@ file dev/ic/malo.c malo device bwi: ether, ifnet, ifmedia, firmload, wlan file dev/ic/bwi.c bwi +# Intel OnChip System Fabric +device iosf +file dev/ic/iosf.c iosf needs-flag + # Attributes which machine-independent bus support can be attached to. # These should be defined here, because some of these busses can have # devices which provide these attributes, and we'd like to avoid hairy Index: dev/acpi/dwiic_acpi.c =================================================================== RCS file: /cvs/src/sys/dev/acpi/dwiic_acpi.c,v retrieving revision 1.20 diff -u -p -r1.20 dwiic_acpi.c --- dev/acpi/dwiic_acpi.c 31 Aug 2022 15:14:01 -0000 1.20 +++ dev/acpi/dwiic_acpi.c 1 Mar 2023 01:55:16 -0000 @@ -17,6 +17,8 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include "iosf.h" + #include #include #include @@ -28,6 +30,7 @@ #include #include +#include struct dwiic_crs { int irq_int; @@ -53,6 +56,9 @@ void dwiic_acpi_power(struct dwiic_soft void dwiic_acpi_bus_scan(struct device *, struct i2cbus_attach_args *, void *); +static int dwiic_acpi_acquire_bus(void *, int); +static void dwiic_acpi_release_bus(void *, int); + const struct cfattach dwiic_acpi_ca = { sizeof(struct dwiic_softc), dwiic_acpi_match, @@ -103,6 +109,7 @@ dwiic_acpi_attach(struct device *parent, struct acpi_attach_args *aaa = aux; struct aml_value res; struct dwiic_crs crs; + uint64_t sem; sc->sc_acpi = (struct acpi_softc *)parent; sc->sc_devnode = aaa->aaa_node; @@ -163,14 +170,31 @@ dwiic_acpi_attach(struct device *parent, printf(": can't establish interrupt"); } + if (aml_evalinteger(sc->sc_acpi, sc->sc_devnode, + "_SEM", 0, NULL, &sem)) + sem = 0; + + if (sem) { + printf(" sem"); +#if NIOSF > 0 + if (!iosf_mbi_available()) +#endif + printf(", iosf-mbi not available"); + } + printf("\n"); rw_init(&sc->sc_i2c_lock, "iiclk"); /* setup and attach iic bus */ sc->sc_i2c_tag.ic_cookie = sc; - sc->sc_i2c_tag.ic_acquire_bus = dwiic_i2c_acquire_bus; - sc->sc_i2c_tag.ic_release_bus = dwiic_i2c_release_bus; + if (sem) { + sc->sc_i2c_tag.ic_acquire_bus = dwiic_acpi_acquire_bus; + sc->sc_i2c_tag.ic_release_bus = dwiic_acpi_release_bus; + } else { + sc->sc_i2c_tag.ic_acquire_bus = dwiic_i2c_acquire_bus; + sc->sc_i2c_tag.ic_release_bus = dwiic_i2c_release_bus; + } sc->sc_i2c_tag.ic_exec = dwiic_i2c_exec; sc->sc_i2c_tag.ic_intr_establish = dwiic_i2c_intr_establish; sc->sc_i2c_tag.ic_intr_disestablish = dwiic_i2c_intr_disestablish; @@ -546,4 +570,26 @@ dwiic_acpi_power(struct dwiic_softc *sc, */ dwiic_write(sc, 0x800, 1); } +} + +int iosf_i2c_acquire(int); +void iosf_i2c_release(int); + +static int +dwiic_acpi_acquire_bus(void *cookie, int flags) +{ + int rv; + + rv = dwiic_i2c_acquire_bus(cookie, flags); + if (rv != 0) + return (rv); + + return (iosf_i2c_acquire(flags)); +} + +static void +dwiic_acpi_release_bus(void *cookie, int flags) +{ + iosf_i2c_release(flags); + dwiic_i2c_release_bus(cookie, flags); } Index: dev/acpi/files.acpi =================================================================== RCS file: /cvs/src/sys/dev/acpi/files.acpi,v retrieving revision 1.68 diff -u -p -r1.68 files.acpi --- dev/acpi/files.acpi 4 Feb 2023 23:11:59 -0000 1.68 +++ dev/acpi/files.acpi 1 Mar 2023 01:55:16 -0000 @@ -275,3 +275,7 @@ file dev/acpi/qciic.c qciic # UFS HC attach ufshci at acpi with ufshci_acpi file dev/acpi/ufshci_acpi.c ufshci_acpi + +# Intel OnChip System Fabric +attach iosf at acpi with iosf_acpi +file dev/acpi/iosf_acpi.c iosf_acpi Index: dev/acpi/iosf_acpi.c =================================================================== RCS file: dev/acpi/iosf_acpi.c diff -N dev/acpi/iosf_acpi.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ dev/acpi/iosf_acpi.c 1 Mar 2023 01:55:16 -0000 @@ -0,0 +1,136 @@ +/* $OpenBSD$ */ +/* + * Copyright (c) 2023 David Gwynne + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include + +struct iosf_acpi_softc { + struct device sc_dev; + struct acpi_softc *sc_acpi; + struct aml_node *sc_node; + + bus_space_tag_t sc_iot; + bus_space_handle_t sc_ioh; + bus_size_t sc_ios; + + struct iosf_mbi sc_mbi; +}; + +static int iosf_acpi_match(struct device *, void *, void *); +static void iosf_acpi_attach(struct device *, struct device *, void *); + +static uint32_t iosf_acpi_mbi_mdr_rd(struct iosf_mbi *, uint32_t, uint32_t); +static void iosf_acpi_mbi_mdr_wr(struct iosf_mbi *, uint32_t, uint32_t, + uint32_t); + +const struct cfattach iosf_acpi_ca = { + sizeof(struct iosf_acpi_softc), iosf_acpi_match, iosf_acpi_attach +}; + +static const char *iosf_hids[] = { + "INT33BD", + NULL +}; + +static int +iosf_acpi_match(struct device *parent, void *match, void *aux) +{ + struct acpi_attach_args *aaa = aux; + struct cfdata *cf = match; + + if (aaa->aaa_naddr < 1) + return 0; + + return (acpi_matchhids(aaa, iosf_hids, cf->cf_driver->cd_name)); +} + +static void +iosf_acpi_attach(struct device *parent, struct device *self, void *aux) +{ + struct iosf_acpi_softc *sc = (struct iosf_acpi_softc *)self; + struct acpi_attach_args *aaa = aux; + + sc->sc_acpi = (struct acpi_softc *)parent; + sc->sc_node = aaa->aaa_node; + printf(" %s", sc->sc_node->name); + + sc->sc_iot = aaa->aaa_bst[0]; + sc->sc_ios = aaa->aaa_size[0]; + + if (bus_space_map(sc->sc_iot, aaa->aaa_addr[0], aaa->aaa_size[0], 0, + &sc->sc_ioh)) { + printf(": can't map registers\n"); + return; + } + + sc->sc_mbi.mbi_dev = self; + sc->sc_mbi.mbi_prio = 1; /* lower prio than iosf_pci ops */ + sc->sc_mbi.mbi_semaddr = 0x10e; /* XXX */ + sc->sc_mbi.mbi_mdr_rd = iosf_acpi_mbi_mdr_rd; + sc->sc_mbi.mbi_mdr_wr = iosf_acpi_mbi_mdr_wr; + + printf("\n"); +} + +/* + * mbi mdr ACPI operations + */ + +#define IOSF_ACPI_MBI_MCR 0x0 +#define IOSF_ACPI_MBI_MDR 0x4 +#define IOSF_ACPI_MBI_MCRX 0x8 + +static uint32_t +iosf_acpi_mbi_mdr_rd(struct iosf_mbi *mbi, uint32_t mcr, uint32_t mcrx) +{ + struct iosf_acpi_softc *sc = (struct iosf_acpi_softc *)mbi->mbi_dev; + + if (mcrx != 0) { + bus_space_write_4(sc->sc_iot, sc->sc_ioh, + IOSF_ACPI_MBI_MCRX, mcrx); + } + bus_space_write_4(sc->sc_iot, sc->sc_ioh, IOSF_ACPI_MBI_MCR, mcr); + + return (bus_space_read_4(sc->sc_iot, sc->sc_ioh, IOSF_ACPI_MBI_MDR)); +} + +static void +iosf_acpi_mbi_mdr_wr(struct iosf_mbi *mbi, uint32_t mcr, uint32_t mcrx, + uint32_t mdr) +{ + struct iosf_acpi_softc *sc = (struct iosf_acpi_softc *)mbi->mbi_dev; + + bus_space_write_4(sc->sc_iot, sc->sc_ioh, IOSF_ACPI_MBI_MDR, mdr); + if (mcrx != 0) { + bus_space_write_4(sc->sc_iot, sc->sc_ioh, + IOSF_ACPI_MBI_MCRX, mcrx); + } + + bus_space_write_4(sc->sc_iot, sc->sc_ioh, IOSF_ACPI_MBI_MCR, mcr); +} Index: dev/acpi/tipmic.c =================================================================== RCS file: /cvs/src/sys/dev/acpi/tipmic.c,v retrieving revision 1.7 diff -u -p -r1.7 tipmic.c --- dev/acpi/tipmic.c 6 Apr 2022 18:59:27 -0000 1.7 +++ dev/acpi/tipmic.c 1 Mar 2023 01:55:16 -0000 @@ -276,6 +276,25 @@ struct tipmic_regmap tipmic_thermal_regm { 0x18, TIPMIC_SYSTEMP_HI, TIPMIC_SYSTEMP_LO } }; +static int +tipmic_wait_adc(struct tipmic_softc *sc) +{ + int i; + + if (!cold) { + return (tsleep_nsec(&sc->sc_stat_adc, PRIBIO, "tipmic", + SEC_TO_NSEC(1))); + } + + for (i = 0; i < 1000; i++) { + delay(1000); + if (tipmic_intr(sc) == 1) + return (0); + } + + return (EWOULDBLOCK); +} + int tipmic_thermal_opreg_handler(void *cookie, int iodir, uint64_t address, int size, uint64_t *value) @@ -333,8 +352,7 @@ tipmic_thermal_opreg_handler(void *cooki splx(s); while (sc->sc_stat_adc == 0) { - if (tsleep_nsec(&sc->sc_stat_adc, PRIBIO, "tipmic", - SEC_TO_NSEC(1))) { + if (tipmic_wait_adc(sc)) { printf("%s: ADC timeout\n", sc->sc_dev.dv_xname); break; } Index: dev/ic/iosf.c =================================================================== RCS file: dev/ic/iosf.c diff -N dev/ic/iosf.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ dev/ic/iosf.c 1 Mar 2023 01:55:16 -0000 @@ -0,0 +1,336 @@ +/* $OpenBSD$ */ + +/* + * Copyright (c) 2023 David Gwynne + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include + +#include + +#include + +#define IOSF_MBI_MASK_HI 0xffffff00 +#define IOSF_MBI_MASK_LO 0x000000ff +#define IOSF_MBI_ENABLE 0x000000f0 + +#define IOSF_MBI_MCR_OP_SHIFT 24 +#define IOSF_MBI_MCR_PORT_SHIFT 16 +#define IOSF_MBI_MCR_OFFSET_SHIFT 8 + +/* IOSF sideband read/write opcodes */ +#define IOSF_MBI_OP_MMIO_READ 0x00 +#define IOSF_MBI_OP_MMIO_WRITE 0x01 +#define IOSF_MBI_OP_CFG_READ 0x04 +#define IOSF_MBI_OP_CFG_WRITE 0x05 +#define IOSF_MBI_OP_CR_READ 0x06 +#define IOSF_MBI_OP_CR_WRITE 0x07 +#define IOSF_MBI_OP_REG_READ 0x10 +#define IOSF_MBI_OP_REG_WRITE 0x11 +#define IOSF_MBI_OP_ESRAM_READ 0x12 +#define IOSF_MBI_OP_ESRAM_WRITE 0x13 + +/* Baytrail */ +#define IOSF_BT_MBI_UNIT_AUNIT 0x00 +#define IOSF_BT_MBI_UNIT_SMC 0x01 +#define IOSF_BT_MBI_UNIT_CPU 0x02 +#define IOSF_BT_MBI_UNIT_BUNIT 0x03 +#define IOSF_BT_MBI_UNIT_PMC 0x04 +#define IOSF_BT_MBI_UNIT_GFX 0x06 +#define IOSF_BT_MBI_UNIT_SMI 0x0C +#define IOSF_BT_MBI_UNIT_CCK 0x14 +#define IOSF_BT_MBI_UNIT_USB 0x43 +#define IOSF_BT_MBI_UNIT_SATA 0xA3 +#define IOSF_BT_MBI_UNIT_PCIE 0xA6 + +/* semaphore bits */ +#define IOSF_PUNIT_SEM_BIT (1 << 0) +#define IOSF_PUNIT_SEM_ACQUIRE (1 << 1) + +struct cfdriver iosf_cd = { + NULL, "iosf", DV_DULL +}; + +/* + * serialise register ops + */ +static struct mutex iosf_mbi_mtx = MUTEX_INITIALIZER(IPL_HIGH); + +/* + * rwlock for kernel to coordinate access to the mbi with + */ +static struct rwlock iosf_lock = RWLOCK_INITIALIZER("iosf"); + +/* + * drivers provide an iosf_mbi that acts as a backend for the code below. + */ +static struct iosf_mbi *iosf_mbi; + +void +iosf_mbi_attach(struct iosf_mbi *mbi) +{ + /* + * assume this is serialised by autoconf being run sequentially + * during boot. + */ + + if (iosf_mbi == NULL || iosf_mbi->mbi_prio < mbi->mbi_prio) + iosf_mbi = mbi; +} + +static inline uint32_t +iosf_mbi_mcr(uint8_t op, uint8_t port, uint32_t offset) +{ + uint32_t rv = IOSF_MBI_ENABLE; + rv |= op << IOSF_MBI_MCR_OP_SHIFT; + rv |= port << IOSF_MBI_MCR_PORT_SHIFT; + rv |= (offset & IOSF_MBI_MASK_LO) << IOSF_MBI_MCR_OFFSET_SHIFT; + return (rv); +} + +static inline uint32_t +iosf_mbi_mcrx(uint32_t offset) +{ + return (offset & IOSF_MBI_MASK_HI); +} + +/* + * serialised mbi mdr operations + */ + +static uint32_t +iosf_mbi_mdr_read(struct iosf_mbi *mbi, uint8_t port, uint8_t op, + uint32_t offset) +{ + uint32_t mcr, mcrx, mdr; + + mcr = iosf_mbi_mcr(op, port, offset); + mcrx = iosf_mbi_mcrx(offset); + + mtx_enter(&iosf_mbi_mtx); + mdr = (*mbi->mbi_mdr_rd)(mbi, mcr, mcrx); + mtx_leave(&iosf_mbi_mtx); + + return (mdr); +} + +static void +iosf_mbi_mdr_write(struct iosf_mbi *mbi, uint8_t port, uint8_t op, + uint32_t offset, uint32_t mdr) +{ + uint32_t mcr, mcrx; + + mcr = iosf_mbi_mcr(op, port, offset); + mcrx = iosf_mbi_mcrx(offset); + + mtx_enter(&iosf_mbi_mtx); + (*mbi->mbi_mdr_wr)(mbi, mcr, mcrx, mdr); + mtx_leave(&iosf_mbi_mtx); +} + +static void +iosf_mbi_mdr_modify(struct iosf_mbi *mbi, uint8_t port, uint8_t op, + uint32_t offset, uint32_t bits, uint32_t mask) +{ + uint32_t mcr, mcrx, mdr; + + mcr = iosf_mbi_mcr(op, port, offset); + mcrx = iosf_mbi_mcrx(offset); + + mtx_enter(&iosf_mbi_mtx); + mdr = (*mbi->mbi_mdr_rd)(mbi, mcr, mcrx); + + CLR(mdr, mask); + SET(mdr, bits & mask); + + (*mbi->mbi_mdr_wr)(mbi, mcr, mcrx, mdr); + mtx_leave(&iosf_mbi_mtx); +} + +/* + * linux compat api + */ + +int +iosf_mbi_read(uint8_t port, uint8_t opcode, uint32_t offset, uint32_t *mdrp) +{ + struct iosf_mbi *mbi; + + mbi = iosf_mbi; + if (mbi == NULL) + return (ENODEV); + + /* check port != BT_MBI_UNIT_GFX? */ + + *mdrp = iosf_mbi_mdr_read(mbi, port, opcode, offset); + + return (0); +} + +int +iosf_mbi_write(uint8_t port, uint8_t opcode, uint32_t offset, uint32_t mdr) +{ + struct iosf_mbi *mbi; + + mbi = iosf_mbi; + if (mbi == NULL) + return (ENODEV); + + /* check port != BT_MBI_UNIT_GFX? */ + + iosf_mbi_mdr_write(mbi, port, opcode, offset, mdr); + + return (0); +} + +int +iosf_mbi_modify(uint8_t port, uint8_t opcode, uint32_t offset, + uint32_t bits, uint32_t mask) +{ + struct iosf_mbi *mbi; + + mbi = iosf_mbi; + if (mbi == NULL) + return (ENODEV); + + /* check port != BT_MBI_UNIT_GFX? */ + + iosf_mbi_mdr_modify(mbi, port, opcode, offset, bits, mask); + + return (0); +} + +int +iosf_mbi_available(void) +{ + return (iosf_mbi != NULL); +} + +static uint32_t +iosf_mbi_sem_get(struct iosf_mbi *mbi) +{ + uint32_t sem; + + sem = iosf_mbi_mdr_read(mbi, + IOSF_BT_MBI_UNIT_PMC, IOSF_MBI_OP_REG_READ, mbi->mbi_semaddr); + + return (ISSET(sem, IOSF_PUNIT_SEM_BIT)); +} + +static void +iosf_mbi_sem_reset(struct iosf_mbi *mbi) +{ + iosf_mbi_mdr_modify(mbi, + IOSF_BT_MBI_UNIT_PMC, IOSF_MBI_OP_REG_READ, mbi->mbi_semaddr, + 0, IOSF_PUNIT_SEM_BIT); +} + +void +iosf_mbi_punit_acquire(void) +{ + rw_enter_write(&iosf_lock); +} + +void +iosf_mbi_punit_release(void) +{ + rw_exit_write(&iosf_lock); +} + +void iosf_mbi_assert_punit_acquired(void) +{ + int s; + + if (splassert_ctl == 0) + return; + + s = rw_status(&iosf_lock); + if (s != RW_WRITE) + splassert_fail(RW_WRITE, s, __func__); +} + +static void +iosf_sem_wait(uint64_t usec, int waitok) +{ + if (waitok) + tsleep_nsec(&nowake, PRIBIO, "iosfsem", USEC_TO_NSEC(usec)); + else + delay(usec); +} + +#include + +int +iosf_i2c_acquire(int flags) +{ + struct iosf_mbi *mbi; + int waitok = !cold && !ISSET(flags, I2C_F_POLL); + unsigned int i; + + mbi = iosf_mbi; + if (mbi == NULL) + return (0); + + if (waitok) + rw_enter_write(&iosf_lock); + else if (iosf_lock.rwl_owner != 0) + panic("%s", __func__); + + /* XXX disable C6 and C7 states */ + + iosf_mbi_mdr_write(mbi, IOSF_BT_MBI_UNIT_PMC, IOSF_MBI_OP_REG_WRITE, + mbi->mbi_semaddr, IOSF_PUNIT_SEM_ACQUIRE); + + for (i = 0; i < 50; i++) { + if (iosf_mbi_sem_get(mbi)) { + /* success! */ + //printf("%s: %s!\n", sc->sc_dev.dv_xname, __func__); + return (0); + } + + iosf_sem_wait(10000, waitok); + } + + iosf_mbi_sem_reset(mbi); + + if (waitok) + rw_exit_write(&iosf_lock); + else if (iosf_lock.rwl_owner != 0) + panic("%s", __func__); + + return (EWOULDBLOCK); +} + +void +iosf_i2c_release(int flags) +{ + struct iosf_mbi *mbi; + int waitok = !cold && !ISSET(flags, I2C_F_POLL); + + mbi = iosf_mbi; + if (mbi == NULL) + return; + + iosf_mbi_sem_reset(mbi); + + if (waitok) + rw_exit_write(&iosf_lock); + else if (iosf_lock.rwl_owner != 0) + panic("%s", __func__); +} Index: dev/ic/iosfvar.h =================================================================== RCS file: dev/ic/iosfvar.h diff -N dev/ic/iosfvar.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ dev/ic/iosfvar.h 1 Mar 2023 01:55:16 -0000 @@ -0,0 +1,59 @@ +/* $OpenBSD$ */ + +/* + * Copyright (c) 2023 David Gwynne + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _DEV_IC_IOSFVAR_H_ +#define _DEV_IC_IOSFVAR_H_ + +/* + * iosf provider api + */ + +struct iosf_mbi { + struct device *mbi_dev; + int mbi_prio; + int mbi_semaddr; + + uint32_t (*mbi_mdr_rd)(struct iosf_mbi *sc, uint32_t, uint32_t); + void (*mbi_mdr_wr)(struct iosf_mbi *sc, uint32_t, uint32_t, + uint32_t); +}; + +void iosf_mbi_attach(struct iosf_mbi *); + +/* + * iosf consumer apis + */ + +int iosf_mbi_available(void); + +/* for i2c */ +int iosf_i2c_acquire(int); +void iosf_i2c_relese(int); + +/* for drm to coordinate with the rest of the kernel */ +void iosf_mbi_punit_acquire(void); +void iosf_mbi_punit_release(void); +void iosf_mbi_assert_punit_acquired(void); + +#ifdef nyetyet +int iosf_mbi_read(uint8_t, uint8_t, uint32_t, uint32_t *); +int iosf_mbi_write(uint8_t, uint8_t, uint32_t, uint32_t); +int iosf_mbi_modify(uint8_t, uint8_t, uint32_t, uint32_t, uint32_t); +#endif + +#endif /* _DEV_IC_IOSFVAR_H_ */ Index: dev/pci/files.pci =================================================================== RCS file: /cvs/src/sys/dev/pci/files.pci,v retrieving revision 1.359 diff -u -p -r1.359 files.pci --- dev/pci/files.pci 31 Mar 2022 21:41:17 -0000 1.359 +++ dev/pci/files.pci 1 Mar 2023 01:55:16 -0000 @@ -771,6 +771,10 @@ device gcu attach gcu at pci file dev/pci/gcu.c gcu needs-flag +# Intel OnChip System Fabric +attach iosf at pci with iosf_pci +file dev/pci/iosf_pci.c iosf_pci + # AMD Geode CS5536 Audio device auglx: audio, ac97 attach auglx at pci Index: dev/pci/iosf_pci.c =================================================================== RCS file: dev/pci/iosf_pci.c diff -N dev/pci/iosf_pci.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ dev/pci/iosf_pci.c 1 Mar 2023 01:55:16 -0000 @@ -0,0 +1,156 @@ +/* $OpenBSD$ */ + +/* + * Copyright (c) 2023 David Gwynne + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include + +/* + * Intel OnChip System Fabric driver + */ + +struct iosf_pci_softc { + struct device sc_dev; + + pci_chipset_tag_t sc_pc; + pcitag_t sc_pcitag; + + int sc_semaddr; + + struct iosf_mbi sc_mbi; +}; + +static int iosf_pci_match(struct device *, void *, void *); +static void iosf_pci_attach(struct device *, struct device *, void *); + +static uint32_t iosf_pci_mbi_mdr_rd(struct iosf_mbi *, uint32_t, uint32_t); +static void iosf_pci_mbi_mdr_wr(struct iosf_mbi *, uint32_t, uint32_t, + uint32_t); + +const struct cfattach iosf_pci_ca = { + sizeof(struct iosf_pci_softc), iosf_pci_match, iosf_pci_attach +}; + +struct iosf_pci_device { + struct pci_matchid id_pm; + int id_semaddr; +}; + +static const struct iosf_pci_device iosf_pci_devices[] = { + { { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_BAYTRAIL_HB }, 0x7 }, + { { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_BSW_HB }, 0x10e }, + /* Quark X1000, -1 */ + /* Tangier, -1 */ +}; + +static const struct iosf_pci_device * +iosf_pci_device_match(struct pci_attach_args *pa) +{ + pci_vendor_id_t vid = PCI_VENDOR(pa->pa_id); + pci_product_id_t pid = PCI_PRODUCT(pa->pa_id); + const struct iosf_pci_device *id; + size_t i; + + for (i = 0; i < nitems(iosf_pci_devices); i++) { + id = &iosf_pci_devices[i]; + if (id->id_pm.pm_vid == vid && id->id_pm.pm_pid == pid) + return (id); + } + + return (NULL); +} + +static int +iosf_pci_match(struct device *parent, void *match, void *aux) +{ + struct pci_attach_args *pa = aux; + + if (iosf_pci_device_match(pa) != NULL) { + /* match higher than pchb(4) */ + return (2); + } + + return (0); +} + +static void +iosf_pci_attach(struct device *parent, struct device *self, void *aux) +{ + struct iosf_pci_softc *sc = (struct iosf_pci_softc *)self; + struct pci_attach_args *pa = aux; + const struct iosf_pci_device *id = iosf_pci_device_match(pa); + + sc->sc_pc = pa->pa_pc; + sc->sc_pcitag = pa->pa_tag; + + sc->sc_mbi.mbi_dev = self; + sc->sc_mbi.mbi_prio = 2; /* prefer pci over acpi ops */ + sc->sc_mbi.mbi_semaddr = id->id_semaddr; + sc->sc_mbi.mbi_mdr_rd = iosf_pci_mbi_mdr_rd; + sc->sc_mbi.mbi_mdr_wr = iosf_pci_mbi_mdr_wr; + + iosf_mbi_attach(&sc->sc_mbi); + printf("\n"); +} + +/* + * mbi mdr pciconf operations + */ + +#define IOSF_PCI_MBI_MCR 0xd0 +#define IOSF_PCI_MBI_MDR 0xd4 +#define IOSF_PCI_MBI_MCRX 0xd8 + +static uint32_t +iosf_pci_mbi_mdr_rd(struct iosf_mbi *mbi, uint32_t mcr, uint32_t mcrx) +{ + struct iosf_pci_softc *sc = (struct iosf_pci_softc *)mbi->mbi_dev; + + if (mcrx != 0) { + pci_conf_write(sc->sc_pc, sc->sc_pcitag, + IOSF_PCI_MBI_MCRX, mcrx); + } + pci_conf_write(sc->sc_pc, sc->sc_pcitag, IOSF_PCI_MBI_MCR, mcr); + + return (pci_conf_read(sc->sc_pc, sc->sc_pcitag, IOSF_PCI_MBI_MDR)); +} + +static void +iosf_pci_mbi_mdr_wr(struct iosf_mbi *mbi, uint32_t mcr, uint32_t mcrx, + uint32_t mdr) +{ + struct iosf_pci_softc *sc = (struct iosf_pci_softc *)mbi->mbi_dev; + + pci_conf_write(sc->sc_pc, sc->sc_pcitag, IOSF_PCI_MBI_MDR, mdr); + + if (mcrx != 0) { + pci_conf_write(sc->sc_pc, sc->sc_pcitag, + IOSF_PCI_MBI_MCRX, mcrx); + } + + pci_conf_write(sc->sc_pc, sc->sc_pcitag, IOSF_PCI_MBI_MCR, mcr); +} Index: dev/pci/drm/include/asm/iosf_mbi.h =================================================================== RCS file: /cvs/src/sys/dev/pci/drm/include/asm/iosf_mbi.h,v retrieving revision 1.2 diff -u -p -r1.2 iosf_mbi.h --- dev/pci/drm/include/asm/iosf_mbi.h 1 Mar 2022 04:08:04 -0000 1.2 +++ dev/pci/drm/include/asm/iosf_mbi.h 1 Mar 2023 01:55:17 -0000 @@ -3,10 +3,11 @@ #ifndef _ASM_IOSF_MBI_H #define _ASM_IOSF_MBI_H -struct notifier_block; +#include "iosf.h" -#define MBI_PMIC_BUS_ACCESS_BEGIN 1 -#define MBI_PMIC_BUS_ACCESS_END 2 +#if NIOSF > 0 +#include +#else static inline void iosf_mbi_assert_punit_acquired(void) @@ -22,6 +23,13 @@ static inline void iosf_mbi_punit_release(void) { } + +#endif + +struct notifier_block; + +#define MBI_PMIC_BUS_ACCESS_BEGIN 1 +#define MBI_PMIC_BUS_ACCESS_END 2 static inline int iosf_mbi_register_pmic_bus_access_notifier(struct notifier_block *nb)