Example #1
0
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);
}
Example #2
0
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);
}
Example #3
0
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);
}
Example #4
0
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);
}
Example #5
0
/*
 * 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);
}
Example #6
0
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);
}