diff options
| author | Corvin Köhne <corvink@FreeBSD.org> | 2026-03-30 09:33:20 +0000 |
|---|---|---|
| committer | Corvin Köhne <corvink@FreeBSD.org> | 2026-04-30 09:15:18 +0000 |
| commit | 226b37dc3ad5641c18f8542c18baea3ea641c5af (patch) | |
| tree | 1593be4ede24e3fc4d45843c24ef46a3e5f4e776 /sys/dev | |
| parent | 75909086a45da3c5aeaff8152728111cf798c6bc (diff) | |
Diffstat (limited to 'sys/dev')
| -rw-r--r-- | sys/dev/ichsmb/ichsmb.c | 18 | ||||
| -rw-r--r-- | sys/dev/ichsmb/ichsmb_pci.c | 54 | ||||
| -rw-r--r-- | sys/dev/ichsmb/ichsmb_reg.h | 3 | ||||
| -rw-r--r-- | sys/dev/ichsmb/ichsmb_var.h | 3 |
4 files changed, 78 insertions, 0 deletions
diff --git a/sys/dev/ichsmb/ichsmb.c b/sys/dev/ichsmb/ichsmb.c index e40a8a8a3886..0df757d9cc0e 100644 --- a/sys/dev/ichsmb/ichsmb.c +++ b/sys/dev/ichsmb/ichsmb.c @@ -395,6 +395,15 @@ ichsmb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf) sc->block_write = true; mtx_lock(&sc->mutex); + /* + * We don't expect the block buffer to be enabled. However, BIOS code + * might enable it and doesn't restore it at any time, so we should + * ensure it's disabled before sending an SMBus command. + */ + if (sc->features & ICHSMB_FEATURE_BLOCK_BUFFER) { + bus_write_1(sc->io_res, ICH_AUX_CNT, + bus_read_1(sc->io_res, ICH_AUX_CNT) & ~ICH_AUX_CNT_E32B); + } sc->ich_cmd = ICH_HST_CNT_SMB_CMD_BLOCK; bus_write_1(sc->io_res, ICH_XMIT_SLVA, slave | ICH_XMIT_SLVA_WRITE); @@ -424,6 +433,15 @@ ichsmb_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf) sc->block_write = false; mtx_lock(&sc->mutex); + /* + * We don't expect the block buffer to be enabled. However, BIOS code + * might enable it and doesn't restore it at any time, so we should + * ensure it's disabled before sending an SMBus command. + */ + if (sc->features & ICHSMB_FEATURE_BLOCK_BUFFER) { + bus_write_1(sc->io_res, ICH_AUX_CNT, + bus_read_1(sc->io_res, ICH_AUX_CNT) & ~ICH_AUX_CNT_E32B); + } sc->ich_cmd = ICH_HST_CNT_SMB_CMD_BLOCK; bus_write_1(sc->io_res, ICH_XMIT_SLVA, slave | ICH_XMIT_SLVA_READ); diff --git a/sys/dev/ichsmb/ichsmb_pci.c b/sys/dev/ichsmb/ichsmb_pci.c index 7d6d94dbb4a4..af3e0f004b88 100644 --- a/sys/dev/ichsmb/ichsmb_pci.c +++ b/sys/dev/ichsmb/ichsmb_pci.c @@ -129,106 +129,153 @@ static const struct pci_device_table ichsmb_devices[] = { { PCI_DEV(PCI_VENDOR_INTEL, ID_82801CA), PCI_DESCR("Intel 82801CA (ICH3) SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_82801DC), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel 82801DC (ICH4) SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_82801EB), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel 82801EB (ICH5) SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_82801FB), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel 82801FB (ICH6) SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_82801GB), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel 82801GB (ICH7) SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_82801H), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel 82801H (ICH8) SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_82801I), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel 82801I (ICH9) SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_82801GB), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel 82801GB (ICH7) SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_82801H), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel 82801H (ICH8) SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_82801I), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel 82801I (ICH9) SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_EP80579), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel EP80579 SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_82801JI), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel 82801JI (ICH10) SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_82801JD), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel 82801JD (ICH10) SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_PCH), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel PCH SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_6300ESB), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel 6300ESB (ICH) SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_631xESB), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel 631xESB/6321ESB (ESB2) SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_DH89XXCC), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel DH89xxCC SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_PATSBURG), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Patsburg SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_CPT), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Cougar Point SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_PPT), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Panther Point SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_AVOTON), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Avoton SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_LPT), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Lynx Point SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_LPTLP), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Lynx Point-LP SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_WCPT), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Wildcat Point SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_WCPTLP), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Wildcat Point-LP SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_BAYTRAIL), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Baytrail SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_BRASWELL), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Braswell SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_COLETOCRK), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Coleto Creek SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_WELLSBURG), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Wellsburg SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_SRPT), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Sunrise Point-H SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_SRPTLP), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Sunrise Point-LP SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_DENVERTON), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Denverton SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_BROXTON), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Broxton SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_LEWISBURG), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Lewisburg SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_LEWISBURG2), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Lewisburg SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_KABYLAKE), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Kaby Lake SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_CANNONLAKE), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Cannon Lake SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_COMETLAKE), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Comet Lake SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_COMETLAKE2), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Comet Lake SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_TIGERLAKE), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Tiger Lake SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_TIGERLAKE2), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Tiger Lake SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_ELKHARTLAKE), PCI_DESCR("Intel Elkhart Lake SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_GEMINILAKE), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Gemini Lake SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_CEDARFORK), PCI_DESCR("Intel Cedar Fork SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_ICELAKE), PCI_DESCR("Intel Ice Lake SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_ALDERLAKE), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Alder Lake SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_ALDERLAKE2), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Alder Lake SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_ALDERLAKE3), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Alder Lake SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_RAPTORLAKE), PCI_DESCR("Intel Raptor Lake SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_METEORLAKE), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Meteor Lake SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_METEORLAKE2), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Meteor Lake SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_METEORLAKE3), + .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER, PCI_DESCR("Intel Meteor Lake SMBus controller") }, }; @@ -288,6 +335,7 @@ ichsmb_pci_probe(device_t dev) static int ichsmb_pci_attach(device_t dev) { + const struct pci_device_table *tbl; const sc_p sc = device_get_softc(dev); int error; @@ -296,6 +344,12 @@ ichsmb_pci_attach(device_t dev) sc->ich_cmd = -1; sc->dev = dev; + tbl = PCI_MATCH(dev, ichsmb_devices); + if (tbl == NULL) + return (ENXIO); + + sc->features = (uint32_t)tbl->driver_data; + /* Allocate an I/O range */ sc->io_rid = ICH_SMB_BASE; sc->io_res = bus_alloc_resource_anywhere(dev, SYS_RES_IOPORT, diff --git a/sys/dev/ichsmb/ichsmb_reg.h b/sys/dev/ichsmb/ichsmb_reg.h index 78e398a556ef..be3b9e4a899d 100644 --- a/sys/dev/ichsmb/ichsmb_reg.h +++ b/sys/dev/ichsmb/ichsmb_reg.h @@ -84,6 +84,9 @@ #define ICH_D0 0x05 /* host data 0 */ #define ICH_D1 0x06 /* host data 1 */ #define ICH_BLOCK_DB 0x07 /* block data byte */ +#define ICH_AUX_CNT 0x0d /* auxiliary control */ +#define ICH_AUX_CNT_E32B 0x02 /* enable 32 byte buffer */ +#define ICH_AUX_CNT_AAC 0x01 /* automatically append crc */ #endif /* _DEV_ICHSMB_ICHSMB_REG_H_ */ diff --git a/sys/dev/ichsmb/ichsmb_var.h b/sys/dev/ichsmb/ichsmb_var.h index 8aeaf403781b..f16a40be9777 100644 --- a/sys/dev/ichsmb/ichsmb_var.h +++ b/sys/dev/ichsmb/ichsmb_var.h @@ -41,6 +41,8 @@ #include "smbus_if.h" +#define ICHSMB_FEATURE_BLOCK_BUFFER 0x01 /* supports 32 byte block buffer */ + /* Per-device private info */ struct ichsmb_softc { @@ -52,6 +54,7 @@ struct ichsmb_softc { struct resource *irq_res; /* interrupt resource */ int irq_rid; /* interrupt bus id */ void *irq_handle; /* handle for interrupt code */ + uint32_t features; /* supported device features */ /* Device state */ int ich_cmd; /* ich command, or -1 */ |
