Commit 95563d34 authored by Jordan Crouse's avatar Jordan Crouse Committed by Greg Kroah-Hartman

[PATCH] scx200_acb: Fix for the CS5535 errata

This is a fix for the CS5535 errata 111:

When the SMBus controller tries to access a non-existing device, it sets
the NEGACK bit, SMBus I/O offset 01h[4], to 1 after it detects no
acknowledge at the ninth clock.  The specification states that the bit
can be cleared by writing a 1 to it, but under certain circumstances it
is possible for this bit to not clear.

Writing a 0 to the bit resets the internal state machine and clears the
issue.

Since all writable bits in ACBST are W1C bits (write-one-to-clear) the
second write doesn't affect any other logic except the buggy NEGACK
state machine. The second write clears an internal register which is
responsible for "overwriting" the NEGACK bit in ACBST.
Signed-off-by: default avatarJordan Crouse <jordan.crouse@amd.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarJean Delvare <khali@linux-fr.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent b33d0798
...@@ -133,6 +133,9 @@ static void scx200_acb_machine(struct scx200_acb_iface *iface, u8 status) ...@@ -133,6 +133,9 @@ static void scx200_acb_machine(struct scx200_acb_iface *iface, u8 status)
outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1); outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1);
outb(ACBST_STASTR | ACBST_NEGACK, ACBST); outb(ACBST_STASTR | ACBST_NEGACK, ACBST);
/* Reset the status register */
outb(0, ACBST);
return; return;
} }
...@@ -228,6 +231,10 @@ static void scx200_acb_poll(struct scx200_acb_iface *iface) ...@@ -228,6 +231,10 @@ static void scx200_acb_poll(struct scx200_acb_iface *iface)
timeout = jiffies + POLL_TIMEOUT; timeout = jiffies + POLL_TIMEOUT;
while (time_before(jiffies, timeout)) { while (time_before(jiffies, timeout)) {
status = inb(ACBST); status = inb(ACBST);
/* Reset the status register to avoid the hang */
outb(0, ACBST);
if ((status & (ACBST_SDAST|ACBST_BER|ACBST_NEGACK)) != 0) { if ((status & (ACBST_SDAST|ACBST_BER|ACBST_NEGACK)) != 0) {
scx200_acb_machine(iface, status); scx200_acb_machine(iface, status);
return; return;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment