]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/commit
MFC r351885, r351887
authorIan Lepore <ian@FreeBSD.org>
Sat, 14 Sep 2019 20:26:50 +0000 (20:26 +0000)
committerIan Lepore <ian@FreeBSD.org>
Sat, 14 Sep 2019 20:26:50 +0000 (20:26 +0000)
commit7b3e00f6aca83f9615fc5ca618807f04be785e1d
tree45263b59029718897ada6ef1be73421df67b3710
parentbfcea5b8ab44a12f9077019bea16cbdae79e928d
MFC r351885, r351887

r351885:
Ensure a measurement is complete before reading the result in ads111x.
Also, disable the comparator by default; it's not used for anything.

The previous logic would start a measurement, and then pause_sbt() for the
averaging time currently configured in the chip.  After waiting that long,
the code would blindly read the measurement register and return its value.
The problem is that the chip's idea of averaging time is based on its
internal free-running 1MHz oscillator, which may be running at a wildly
different rate than the kernel clock.  If the chip's internal timer was
running slower than the kernel clock, we'd end up grabbing a stale result
from an old measurement.

The driver now still uses pause_sbt() to yield the cpu while waiting for
the measurement to complete, but after sleeping it checks the chip's status
register to ensure the measurement engine is idle.  If it's not, the driver
uses a retry loop to wait a bit (5% of the original wait time) then check
again for completion.

r351887:
Use a single write of 3 bytes instead of iicdev_writeto() in ads111x.

The iicdev_writeto() function basically does scatter-gather IO by filling
in a pair of iic_msg structs to write the register address then the data
from different locations but with a single bus START/xfer/STOP sequence.
It turns out several low-level i2c controller drivers do not honor the
IIC_NOSTART flag, so the second piece of the write gets a new START on
the bus, and that confuses the ads111x chips which expect a continuous
write of 3 bytes to set a register.

A proper fix for this is to track down all the misbehaving controllers
drivers and fix them.  For now this change makes this driver work again.
sys/dev/iicbus/ads111x.c