static int amdpm_sendb(device_t dev, u_char slave, char byte) { struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev); int error; u_short l; AMDPM_LOCK(sc); amdpm_clear(sc); if (!amdpm_idle(sc)) { AMDPM_UNLOCK(sc); return (SMB_EBUSY); } AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB); AMDPM_SMBOUTW(sc, AMDSMB_HSTDATA, byte); l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE); AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_BYTE | AMDSMB_GE_HOST_STC); error = amdpm_wait(sc); AMDPM_DEBUG(kprintf("amdpm: SENDB to 0x%x, byte=0x%x, error=0x%x\n", slave, byte, error)); AMDPM_UNLOCK(sc); return (error); }
static int amdpm_readw(device_t dev, u_char slave, char cmd, short *word) { struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev); int error; u_short l; AMDPM_LOCK(sc); amdpm_clear(sc); if (!amdpm_idle(sc)) { AMDPM_UNLOCK(sc); return (SMB_EBUSY); } AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB); AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd); l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE); AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_WDATA | AMDSMB_GE_HOST_STC); if ((error = amdpm_wait(sc)) == SMB_ENOERR) *word = AMDPM_SMBINW(sc, AMDSMB_HSTDATA); AMDPM_DEBUG(printf("amdpm: READW from 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, *word, error)); AMDPM_UNLOCK(sc); return (error); }
static int amdpm_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf) { struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev); u_char data, len, i; int error; u_short l; if (*count < 1 || *count > 32) return (SMB_EINVAL); AMDPM_LOCK(sc); amdpm_clear(sc); if (!amdpm_idle(sc)) { AMDPM_UNLOCK(sc); return (SMB_EBUSY); } AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB); AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd); l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE); AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_BLOCK | AMDSMB_GE_HOST_STC); if ((error = amdpm_wait(sc)) != SMB_ENOERR) goto error; len = AMDPM_SMBINW(sc, AMDSMB_HSTDATA); /* Read the 32-byte internal buffer */ for (i = 0; i < len; i++) { data = AMDPM_SMBINB(sc, AMDSMB_HSTDFIFO); if (i < *count) buf[i] = data; DELAY(2); } *count = len; error: AMDPM_DEBUG(printf("amdpm: READBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, *count, cmd, error)); AMDPM_UNLOCK(sc); return (error); }
static int amdpm_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf) { struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev); u_char i; int error; u_short l; if (count < 1 || count > 32) return (SMB_EINVAL); AMDPM_LOCK(sc); amdpm_clear(sc); if (!amdpm_idle(sc)) { AMDPM_UNLOCK(sc); return (SMB_EBUSY); } AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB); /* * Do we have to reset the internal 32-byte buffer? * Can't see how to do this from the data sheet. */ AMDPM_SMBOUTW(sc, AMDSMB_HSTDATA, count); /* Fill the 32-byte internal buffer */ for (i = 0; i < count; i++) { AMDPM_SMBOUTB(sc, AMDSMB_HSTDFIFO, buf[i]); DELAY(2); } AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd); l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE); AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_BLOCK | AMDSMB_GE_HOST_STC); error = amdpm_wait(sc); AMDPM_DEBUG(printf("amdpm: WRITEBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, count, cmd, error)); AMDPM_UNLOCK(sc); return (error); }
/* * Poll the SMBus controller */ static int amdpm_wait(struct amdpm_softc *sc) { int count = 10000; u_short sts = 0; int error; AMDPM_LOCK_ASSERT(sc); /* Wait for command to complete (SMBus controller is idle) */ while(count--) { DELAY(10); sts = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_STATUS); if (!(sts & AMDSMB_GS_HST_STS)) break; } AMDPM_DEBUG(printf("amdpm: STS=0x%x (count=%d)\n", sts, count)); error = SMB_ENOERR; if (!count) error |= SMB_ETIMEOUT; if (sts & AMDSMB_GS_ABRT_STS) error |= SMB_EABORT; if (sts & AMDSMB_GS_COL_STS) error |= SMB_ENOACK; if (sts & AMDSMB_GS_PRERR_STS) error |= SMB_EBUSERR; if (error != SMB_ENOERR) amdpm_clear(sc); return (error); }
static int amdpm_quick(device_t dev, u_char slave, int how) { struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev); int error; u_short l; AMDPM_LOCK(sc); amdpm_clear(sc); if (!amdpm_idle(sc)) { AMDPM_UNLOCK(sc); return (EBUSY); } switch (how) { case SMB_QWRITE: AMDPM_DEBUG(printf("amdpm: QWRITE to 0x%x", slave)); AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB); break; case SMB_QREAD: AMDPM_DEBUG(printf("amdpm: QREAD to 0x%x", slave)); AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB); break; default: panic("%s: unknown QUICK command (%x)!", __func__, how); } l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE); AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_QUICK | AMDSMB_GE_HOST_STC); error = amdpm_wait(sc); AMDPM_DEBUG(printf(", error=0x%x\n", error)); AMDPM_UNLOCK(sc); return (error); }