aboutsummaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorCorvin Köhne <corvink@FreeBSD.org>2026-03-30 09:33:20 +0000
committerCorvin Köhne <corvink@FreeBSD.org>2026-04-30 09:15:18 +0000
commit226b37dc3ad5641c18f8542c18baea3ea641c5af (patch)
tree1593be4ede24e3fc4d45843c24ef46a3e5f4e776 /sys/dev
parent75909086a45da3c5aeaff8152728111cf798c6bc (diff)
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/ichsmb/ichsmb.c18
-rw-r--r--sys/dev/ichsmb/ichsmb_pci.c54
-rw-r--r--sys/dev/ichsmb/ichsmb_reg.h3
-rw-r--r--sys/dev/ichsmb/ichsmb_var.h3
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 */