1*a4663606Sjsg /* $OpenBSD: ichiic.c,v 1.49 2022/06/21 04:17:21 jsg Exp $ */ 23b00bf77Sgrange 33b00bf77Sgrange /* 4a547cd46Sgrange * Copyright (c) 2005, 2006 Alexander Yurchenko <grange@openbsd.org> 53b00bf77Sgrange * 63b00bf77Sgrange * Permission to use, copy, modify, and distribute this software for any 73b00bf77Sgrange * purpose with or without fee is hereby granted, provided that the above 83b00bf77Sgrange * copyright notice and this permission notice appear in all copies. 93b00bf77Sgrange * 103b00bf77Sgrange * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 113b00bf77Sgrange * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 123b00bf77Sgrange * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 133b00bf77Sgrange * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 143b00bf77Sgrange * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 153b00bf77Sgrange * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 163b00bf77Sgrange * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 173b00bf77Sgrange */ 183b00bf77Sgrange 193b00bf77Sgrange /* 203b00bf77Sgrange * Intel ICH SMBus controller driver. 213b00bf77Sgrange */ 223b00bf77Sgrange 233b00bf77Sgrange #include <sys/param.h> 243b00bf77Sgrange #include <sys/systm.h> 253b00bf77Sgrange #include <sys/device.h> 263b00bf77Sgrange #include <sys/kernel.h> 2773550447Sdlg #include <sys/rwlock.h> 283b00bf77Sgrange 293b00bf77Sgrange #include <machine/bus.h> 303b00bf77Sgrange 313b00bf77Sgrange #include <dev/pci/pcidevs.h> 323b00bf77Sgrange #include <dev/pci/pcireg.h> 333b00bf77Sgrange #include <dev/pci/pcivar.h> 343b00bf77Sgrange 353b00bf77Sgrange #include <dev/pci/ichreg.h> 363b00bf77Sgrange 373b00bf77Sgrange #include <dev/i2c/i2cvar.h> 383b00bf77Sgrange 393b00bf77Sgrange #ifdef ICHIIC_DEBUG 403b00bf77Sgrange #define DPRINTF(x) printf x 413b00bf77Sgrange #else 423b00bf77Sgrange #define DPRINTF(x) 433b00bf77Sgrange #endif 443b00bf77Sgrange 453b00bf77Sgrange #define ICHIIC_DELAY 100 463b00bf77Sgrange #define ICHIIC_TIMEOUT 1 473b00bf77Sgrange 483b00bf77Sgrange struct ichiic_softc { 493b00bf77Sgrange struct device sc_dev; 503b00bf77Sgrange 513b00bf77Sgrange bus_space_tag_t sc_iot; 523b00bf77Sgrange bus_space_handle_t sc_ioh; 533b00bf77Sgrange void * sc_ih; 54749dbd03Sgrange int sc_poll; 553b00bf77Sgrange 563b00bf77Sgrange struct i2c_controller sc_i2c_tag; 5773550447Sdlg struct rwlock sc_i2c_lock; 58c17198b5Sgrange struct { 593b00bf77Sgrange i2c_op_t op; 603b00bf77Sgrange void * buf; 613b00bf77Sgrange size_t len; 623b00bf77Sgrange int flags; 63c17198b5Sgrange volatile int error; 643b00bf77Sgrange } sc_i2c_xfer; 653b00bf77Sgrange }; 663b00bf77Sgrange 673b00bf77Sgrange int ichiic_match(struct device *, void *, void *); 683b00bf77Sgrange void ichiic_attach(struct device *, struct device *, void *); 693b00bf77Sgrange 703b00bf77Sgrange int ichiic_i2c_acquire_bus(void *, int); 713b00bf77Sgrange void ichiic_i2c_release_bus(void *, int); 723b00bf77Sgrange int ichiic_i2c_exec(void *, i2c_op_t, i2c_addr_t, const void *, size_t, 733b00bf77Sgrange void *, size_t, int); 743b00bf77Sgrange 753b00bf77Sgrange int ichiic_intr(void *); 763b00bf77Sgrange 778d2c75e4Smpi const struct cfattach ichiic_ca = { 783b00bf77Sgrange sizeof(struct ichiic_softc), 793b00bf77Sgrange ichiic_match, 803b00bf77Sgrange ichiic_attach 813b00bf77Sgrange }; 823b00bf77Sgrange 833b00bf77Sgrange struct cfdriver ichiic_cd = { 843b00bf77Sgrange NULL, "ichiic", DV_DULL 853b00bf77Sgrange }; 863b00bf77Sgrange 873b00bf77Sgrange const struct pci_matchid ichiic_ids[] = { 888e056978Ssthen { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_3400_SMB }, 89d22bb502Sjsg { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_6SERIES_SMB }, 909eb33f7aSbrad { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_6300ESB_SMB }, 91ae7cc0c1Sbrad { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_6321ESB_SMB }, 92c9849cecSjasper { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_7SERIES_SMB }, 93aa424616Sjsg { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_8SERIES_SMB }, 94aa424616Sjsg { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_8SERIES_LP_SMB }, 95fb0880c9Sjsg { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_9SERIES_SMB }, 96fb0880c9Sjsg { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_9SERIES_LP_SMB }, 973b00bf77Sgrange { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801AA_SMB }, 983b00bf77Sgrange { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801AB_SMB }, 993b00bf77Sgrange { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801BA_SMB }, 1003b00bf77Sgrange { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801CA_SMB }, 1013b00bf77Sgrange { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801DB_SMB }, 1029eb33f7aSbrad { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801E_SMB }, 1033b00bf77Sgrange { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801EB_SMB }, 1043b00bf77Sgrange { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801FB_SMB }, 105e182382cSbrad { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801GB_SMB }, 106a2cd58f7Sbrad { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801H_SMB }, 107a54030c0Sbrad { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801I_SMB }, 1088e056978Ssthen { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801JD_SMB }, 10954d12d52Sjsg { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801JI_SMB }, 110d91cfd19Shenning { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_APOLLOLAKE_SMB }, 111acabe721Sjsg { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_ATOMC2000_PCU_SMB }, 112f00a52a0Sjsg { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_BAYTRAIL_SMB }, 113f00a52a0Sjsg { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_BRASWELL_SMB }, 114b19a9072Sjsg { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_C600_SMB }, 115cb711e62Sjsg { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_C600_SMB_IDF_1 }, 116cb711e62Sjsg { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_C600_SMB_IDF_2 }, 117cb711e62Sjsg { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_C600_SMB_IDF_3 }, 11818ec9edcSjsg { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_C610_SMB }, 11918ec9edcSjsg { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_C610_MS_SMB_1 }, 12018ec9edcSjsg { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_C610_MS_SMB_2 }, 12118ec9edcSjsg { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_C610_MS_SMB_3 }, 1228e8ebef9Sjsg { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_C620_SMB }, 123cb711e62Sjsg { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_DH8900_SMB }, 124f5c876d9Sjsg { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_EP80579_SMBUS }, 1258e8ebef9Sjsg { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_GLK_SMB }, 126266aef52Sjsg { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_100SERIES_SMB }, 127079a7ecbSjsg { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_100SERIES_LP_SMB }, 128c4dfe020Sjsg { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_200SERIES_SMB }, 129c4dfe020Sjsg { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_300SERIES_SMB }, 1308e8ebef9Sjsg { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_300SERIES_U_SMB }, 1318e8ebef9Sjsg { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_400SERIES_SMB }, 1328e8ebef9Sjsg { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_400SERIES_LP_SMB }, 1338e8ebef9Sjsg { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_400SERIES_V_SMB }, 1348e8ebef9Sjsg { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_495SERIES_LP_SMB }, 13577a9f4bbSjsg { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_500SERIES_SMB }, 1368e8ebef9Sjsg { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_500SERIES_LP_SMB }, 13761553a4eSjsg { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_600SERIES_SMB }, 138*a4663606Sjsg { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_600SERIES_LP_SMB }, 139d6969a1fSjsg { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_JSL_SMB }, 1403b00bf77Sgrange }; 1413b00bf77Sgrange 1423b00bf77Sgrange int 1433b00bf77Sgrange ichiic_match(struct device *parent, void *match, void *aux) 1443b00bf77Sgrange { 1453b00bf77Sgrange return (pci_matchbyid(aux, ichiic_ids, 1463b00bf77Sgrange sizeof(ichiic_ids) / sizeof(ichiic_ids[0]))); 1473b00bf77Sgrange } 1483b00bf77Sgrange 1493b00bf77Sgrange void 1503b00bf77Sgrange ichiic_attach(struct device *parent, struct device *self, void *aux) 1513b00bf77Sgrange { 1523b00bf77Sgrange struct ichiic_softc *sc = (struct ichiic_softc *)self; 1533b00bf77Sgrange struct pci_attach_args *pa = aux; 1543b00bf77Sgrange struct i2cbus_attach_args iba; 155749dbd03Sgrange pcireg_t conf; 1563b00bf77Sgrange bus_size_t iosize; 1573b00bf77Sgrange pci_intr_handle_t ih; 1583b00bf77Sgrange const char *intrstr = NULL; 1593b00bf77Sgrange 160d204c798Sgrange /* Read configuration */ 161d204c798Sgrange conf = pci_conf_read(pa->pa_pc, pa->pa_tag, ICH_SMB_HOSTC); 1626f23e57aSgrange DPRINTF((": conf 0x%08x", conf)); 163d204c798Sgrange 164d204c798Sgrange if ((conf & ICH_SMB_HOSTC_HSTEN) == 0) { 165d204c798Sgrange printf(": SMBus disabled\n"); 166d204c798Sgrange return; 167d204c798Sgrange } 168d204c798Sgrange 1693b00bf77Sgrange /* Map I/O space */ 1703b00bf77Sgrange if (pci_mapreg_map(pa, ICH_SMB_BASE, PCI_MAPREG_TYPE_IO, 0, 1713b00bf77Sgrange &sc->sc_iot, &sc->sc_ioh, NULL, &iosize, 0)) { 172e10c952fSsthen printf(": can't map i/o space\n"); 1733b00bf77Sgrange return; 1743b00bf77Sgrange } 1753b00bf77Sgrange 176749dbd03Sgrange sc->sc_poll = 1; 177e3269dfcSgrange if (conf & ICH_SMB_HOSTC_SMIEN) { 178e3269dfcSgrange /* No PCI IRQ */ 179e3269dfcSgrange printf(": SMI"); 180749dbd03Sgrange } else { 1813b00bf77Sgrange /* Install interrupt handler */ 182e3269dfcSgrange if (pci_intr_map(pa, &ih) == 0) { 1833b00bf77Sgrange intrstr = pci_intr_string(pa->pa_pc, ih); 184749dbd03Sgrange sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_BIO, 185749dbd03Sgrange ichiic_intr, sc, sc->sc_dev.dv_xname); 186e3269dfcSgrange if (sc->sc_ih != NULL) { 1873b00bf77Sgrange printf(": %s", intrstr); 188e3269dfcSgrange sc->sc_poll = 0; 189e3269dfcSgrange } 190e3269dfcSgrange } 191e3269dfcSgrange if (sc->sc_poll) 192e3269dfcSgrange printf(": polling"); 193749dbd03Sgrange } 1943b00bf77Sgrange 1953b00bf77Sgrange printf("\n"); 1963b00bf77Sgrange 1973b00bf77Sgrange /* Attach I2C bus */ 19873550447Sdlg rw_init(&sc->sc_i2c_lock, "iiclk"); 1993b00bf77Sgrange sc->sc_i2c_tag.ic_cookie = sc; 2003b00bf77Sgrange sc->sc_i2c_tag.ic_acquire_bus = ichiic_i2c_acquire_bus; 2013b00bf77Sgrange sc->sc_i2c_tag.ic_release_bus = ichiic_i2c_release_bus; 2023b00bf77Sgrange sc->sc_i2c_tag.ic_exec = ichiic_i2c_exec; 203a5a63700Sderaadt 204f57d9f10Sgrange bzero(&iba, sizeof(iba)); 2053b00bf77Sgrange iba.iba_name = "iic"; 2063b00bf77Sgrange iba.iba_tag = &sc->sc_i2c_tag; 2073b00bf77Sgrange config_found(self, &iba, iicbus_print); 2083b00bf77Sgrange 2093b00bf77Sgrange return; 2103b00bf77Sgrange } 2113b00bf77Sgrange 2123b00bf77Sgrange int 2133b00bf77Sgrange ichiic_i2c_acquire_bus(void *cookie, int flags) 2143b00bf77Sgrange { 2153b00bf77Sgrange struct ichiic_softc *sc = cookie; 2163b00bf77Sgrange 2177ecfa26eSgrange if (cold || sc->sc_poll || (flags & I2C_F_POLL)) 2183b00bf77Sgrange return (0); 2193b00bf77Sgrange 22073550447Sdlg return (rw_enter(&sc->sc_i2c_lock, RW_WRITE | RW_INTR)); 2213b00bf77Sgrange } 2223b00bf77Sgrange 2233b00bf77Sgrange void 2243b00bf77Sgrange ichiic_i2c_release_bus(void *cookie, int flags) 2253b00bf77Sgrange { 2263b00bf77Sgrange struct ichiic_softc *sc = cookie; 2273b00bf77Sgrange 2287ecfa26eSgrange if (cold || sc->sc_poll || (flags & I2C_F_POLL)) 2293b00bf77Sgrange return; 2303b00bf77Sgrange 23173550447Sdlg rw_exit(&sc->sc_i2c_lock); 2323b00bf77Sgrange } 2333b00bf77Sgrange 2343b00bf77Sgrange int 2353b00bf77Sgrange ichiic_i2c_exec(void *cookie, i2c_op_t op, i2c_addr_t addr, 2363b00bf77Sgrange const void *cmdbuf, size_t cmdlen, void *buf, size_t len, int flags) 2373b00bf77Sgrange { 2383b00bf77Sgrange struct ichiic_softc *sc = cookie; 2393b00bf77Sgrange u_int8_t *b; 2403b00bf77Sgrange u_int8_t ctl, st; 2413b00bf77Sgrange int retries; 2423b00bf77Sgrange 2436f23e57aSgrange DPRINTF(("%s: exec: op %d, addr 0x%02x, cmdlen %d, len %d, " 2446f23e57aSgrange "flags 0x%02x\n", sc->sc_dev.dv_xname, op, addr, cmdlen, 2456f23e57aSgrange len, flags)); 246d204c798Sgrange 247c90a9223Sgrange /* Wait for bus to be idle */ 248c90a9223Sgrange for (retries = 100; retries > 0; retries--) { 249d204c798Sgrange st = bus_space_read_1(sc->sc_iot, sc->sc_ioh, ICH_SMB_HS); 250c90a9223Sgrange if (!(st & ICH_SMB_HS_BUSY)) 251c90a9223Sgrange break; 252c90a9223Sgrange DELAY(ICHIIC_DELAY); 253c90a9223Sgrange } 254d204c798Sgrange DPRINTF(("%s: exec: st 0x%b\n", sc->sc_dev.dv_xname, st, 255d204c798Sgrange ICH_SMB_HS_BITS)); 256d204c798Sgrange if (st & ICH_SMB_HS_BUSY) 257c5eaf0b6Sgrange return (1); 258749dbd03Sgrange 2597ecfa26eSgrange if (cold || sc->sc_poll) 260749dbd03Sgrange flags |= I2C_F_POLL; 2613b00bf77Sgrange 2623b00bf77Sgrange if (!I2C_OP_STOP_P(op) || cmdlen > 1 || len > 2) 263c5eaf0b6Sgrange return (1); 2643b00bf77Sgrange 2653b00bf77Sgrange /* Setup transfer */ 2663b00bf77Sgrange sc->sc_i2c_xfer.op = op; 2673b00bf77Sgrange sc->sc_i2c_xfer.buf = buf; 2683b00bf77Sgrange sc->sc_i2c_xfer.len = len; 2693b00bf77Sgrange sc->sc_i2c_xfer.flags = flags; 2703b00bf77Sgrange sc->sc_i2c_xfer.error = 0; 2713b00bf77Sgrange 2723b00bf77Sgrange /* Set slave address and transfer direction */ 2733b00bf77Sgrange bus_space_write_1(sc->sc_iot, sc->sc_ioh, ICH_SMB_TXSLVA, 2743b00bf77Sgrange ICH_SMB_TXSLVA_ADDR(addr) | 2753b00bf77Sgrange (I2C_OP_READ_P(op) ? ICH_SMB_TXSLVA_READ : 0)); 2763b00bf77Sgrange 2773b00bf77Sgrange b = (void *)cmdbuf; 2783b00bf77Sgrange if (cmdlen > 0) 2793b00bf77Sgrange /* Set command byte */ 2803b00bf77Sgrange bus_space_write_1(sc->sc_iot, sc->sc_ioh, ICH_SMB_HCMD, b[0]); 2813b00bf77Sgrange 2823b00bf77Sgrange if (I2C_OP_WRITE_P(op)) { 2833b00bf77Sgrange /* Write data */ 2843b00bf77Sgrange b = buf; 2853b00bf77Sgrange if (len > 0) 2863b00bf77Sgrange bus_space_write_1(sc->sc_iot, sc->sc_ioh, 2873b00bf77Sgrange ICH_SMB_HD0, b[0]); 2883b00bf77Sgrange if (len > 1) 2893b00bf77Sgrange bus_space_write_1(sc->sc_iot, sc->sc_ioh, 2903b00bf77Sgrange ICH_SMB_HD1, b[1]); 2913b00bf77Sgrange } 2923b00bf77Sgrange 2933b00bf77Sgrange /* Set SMBus command */ 2943b00bf77Sgrange if (len == 0) 2953b00bf77Sgrange ctl = ICH_SMB_HC_CMD_BYTE; 2963b00bf77Sgrange else if (len == 1) 2973b00bf77Sgrange ctl = ICH_SMB_HC_CMD_BDATA; 2983b00bf77Sgrange else if (len == 2) 2993b00bf77Sgrange ctl = ICH_SMB_HC_CMD_WDATA; 300c0d07f7cShaesbaert else 301c0d07f7cShaesbaert panic("%s: unexpected len %zd", __func__, len); 3023b00bf77Sgrange 3033b00bf77Sgrange if ((flags & I2C_F_POLL) == 0) 3043b00bf77Sgrange ctl |= ICH_SMB_HC_INTREN; 3053b00bf77Sgrange 3063b00bf77Sgrange /* Start transaction */ 3073b00bf77Sgrange ctl |= ICH_SMB_HC_START; 3083b00bf77Sgrange bus_space_write_1(sc->sc_iot, sc->sc_ioh, ICH_SMB_HC, ctl); 3093b00bf77Sgrange 3103b00bf77Sgrange if (flags & I2C_F_POLL) { 3113b00bf77Sgrange /* Poll for completion */ 3123b00bf77Sgrange DELAY(ICHIIC_DELAY); 3133b00bf77Sgrange for (retries = 1000; retries > 0; retries--) { 3143b00bf77Sgrange st = bus_space_read_1(sc->sc_iot, sc->sc_ioh, 3153b00bf77Sgrange ICH_SMB_HS); 3163b00bf77Sgrange if ((st & ICH_SMB_HS_BUSY) == 0) 3173b00bf77Sgrange break; 3183b00bf77Sgrange DELAY(ICHIIC_DELAY); 3193b00bf77Sgrange } 320d204c798Sgrange if (st & ICH_SMB_HS_BUSY) 321d204c798Sgrange goto timeout; 3223b00bf77Sgrange ichiic_intr(sc); 3233b00bf77Sgrange } else { 324c17198b5Sgrange /* Wait for interrupt */ 3258544fed6Smpi if (tsleep_nsec(sc, PRIBIO, "ichiic", 3268544fed6Smpi SEC_TO_NSEC(ICHIIC_TIMEOUT))) 327d204c798Sgrange goto timeout; 3283b00bf77Sgrange } 3293b00bf77Sgrange 3303b00bf77Sgrange if (sc->sc_i2c_xfer.error) 3313b00bf77Sgrange return (1); 3323b00bf77Sgrange 3333b00bf77Sgrange return (0); 334d204c798Sgrange 335d204c798Sgrange timeout: 336d204c798Sgrange /* 337d204c798Sgrange * Transfer timeout. Kill the transaction and clear status bits. 338d204c798Sgrange */ 339d204c798Sgrange bus_space_write_1(sc->sc_iot, sc->sc_ioh, ICH_SMB_HC, 340d204c798Sgrange ICH_SMB_HC_KILL); 341d204c798Sgrange DELAY(ICHIIC_DELAY); 342d204c798Sgrange st = bus_space_read_1(sc->sc_iot, sc->sc_ioh, ICH_SMB_HS); 343d204c798Sgrange if ((st & ICH_SMB_HS_FAILED) == 0) 3446f23e57aSgrange printf("%s: abort failed, status 0x%b\n", 345d204c798Sgrange sc->sc_dev.dv_xname, st, ICH_SMB_HS_BITS); 346d204c798Sgrange bus_space_write_1(sc->sc_iot, sc->sc_ioh, ICH_SMB_HS, st); 347d204c798Sgrange return (1); 3483b00bf77Sgrange } 3493b00bf77Sgrange 3503b00bf77Sgrange int 3513b00bf77Sgrange ichiic_intr(void *arg) 3523b00bf77Sgrange { 3533b00bf77Sgrange struct ichiic_softc *sc = arg; 3543b00bf77Sgrange u_int8_t st; 3553b00bf77Sgrange u_int8_t *b; 3563b00bf77Sgrange size_t len; 3573b00bf77Sgrange 3583b00bf77Sgrange /* Read status */ 3593b00bf77Sgrange st = bus_space_read_1(sc->sc_iot, sc->sc_ioh, ICH_SMB_HS); 3600c9bc80bSstsp 3610c9bc80bSstsp /* Clear status bits */ 3620c9bc80bSstsp bus_space_write_1(sc->sc_iot, sc->sc_ioh, ICH_SMB_HS, st); 3630c9bc80bSstsp 3640c9bc80bSstsp /* XXX Ignore SMBALERT# for now */ 3653b00bf77Sgrange if ((st & ICH_SMB_HS_BUSY) != 0 || (st & (ICH_SMB_HS_INTR | 3663b00bf77Sgrange ICH_SMB_HS_DEVERR | ICH_SMB_HS_BUSERR | ICH_SMB_HS_FAILED | 3670c9bc80bSstsp ICH_SMB_HS_BDONE)) == 0) 3683b00bf77Sgrange /* Interrupt was not for us */ 3693b00bf77Sgrange return (0); 3703b00bf77Sgrange 3713b00bf77Sgrange DPRINTF(("%s: intr st 0x%b\n", sc->sc_dev.dv_xname, st, 3723b00bf77Sgrange ICH_SMB_HS_BITS)); 3733b00bf77Sgrange 3743b00bf77Sgrange /* Check for errors */ 3753b00bf77Sgrange if (st & (ICH_SMB_HS_DEVERR | ICH_SMB_HS_BUSERR | ICH_SMB_HS_FAILED)) { 3763b00bf77Sgrange sc->sc_i2c_xfer.error = 1; 3773b00bf77Sgrange goto done; 3783b00bf77Sgrange } 3793b00bf77Sgrange 3803b00bf77Sgrange if (st & ICH_SMB_HS_INTR) { 3813b00bf77Sgrange if (I2C_OP_WRITE_P(sc->sc_i2c_xfer.op)) 3823b00bf77Sgrange goto done; 3833b00bf77Sgrange 3843b00bf77Sgrange /* Read data */ 3853b00bf77Sgrange b = sc->sc_i2c_xfer.buf; 3863b00bf77Sgrange len = sc->sc_i2c_xfer.len; 3873b00bf77Sgrange if (len > 0) 3883b00bf77Sgrange b[0] = bus_space_read_1(sc->sc_iot, sc->sc_ioh, 3893b00bf77Sgrange ICH_SMB_HD0); 3903b00bf77Sgrange if (len > 1) 3913b00bf77Sgrange b[1] = bus_space_read_1(sc->sc_iot, sc->sc_ioh, 3923b00bf77Sgrange ICH_SMB_HD1); 3933b00bf77Sgrange } 3943b00bf77Sgrange 3953b00bf77Sgrange done: 3963b00bf77Sgrange if ((sc->sc_i2c_xfer.flags & I2C_F_POLL) == 0) 3973b00bf77Sgrange wakeup(sc); 3983b00bf77Sgrange return (1); 3993b00bf77Sgrange } 400