Per the i2c spec, a slave device can stretch SCL idefinitely, so 25ms is
a bit arbitrary in general. smbus does specify an optional timeout
recovery mechanism to be done at about 25~35ms, but the IPMI SSIF spec
says that BMCs don't have any obligation to implement that.
The BMC on Altra seems to mostly respond within 25ms, but occasionally
will stretch SCL for ~300 msec.
Also, the count_us mechanism seems to actually timeout around 25%
earlier than it would claim (timeout really happening around 19ms
instead of 25ms).
Sponsored by: Ampere Computing LLC
Submitted by: Klara Inc.
Reviewed by: manu, imp
Differential Revision: https://reviews.freebsd.org/D28747
Use DRIVER_MODULE_ORDERED(SI_ORDER_ANY) so that ig4's ACPI attachment
happens after iicbus and acpi_iicbus drivers are registered.
I have seen a problem where iicbus attached under ig4 instead of
acpi_iicbus when ig4.ko was loaded with kldload. I believe that that
happened because ig4 driver was a first driver to register, it attached
and created an iicbus child. Then iicbus driver was registered and,
since it was the only driver that could attach to the iicbus child
device, it did exactly that. After that acpi_iicbus driver was
registered. It would be able to attach to the iicbus device, but it was
already attached, so nothing happened.
MFC after: 2 weeks
When iicbus is attached as child of Designware I2C controller it scans all
ACPI nodes for "I2C Serial Bus Connection Resource Descriptor" described
in section 19.6.57 of ACPI specs.
If such a descriptor is found, I2C child is added to iicbus, it's I2C
address, IRQ resource and ACPI handle are added to ivars. Existing
ACPI bus-hosted child is deleted afterwards.
The driver also installs so called "I2C address space handler" which is
disabled by default as nontested.
Set hw.iicbus.enable_acpi_space_handler loader tunable to 1 to enable it.
Reviewed by: markj
MFC after: 2 weeks
Differential Revision: https://reviews.freebsd.org/D22901
bus_get/set_resource methods are implemented in child device (iicbus).
As their implementation with bus_generic_rl_get/set calls do not
recurse up the tree, the versions in ig4 are never called.
Suggested by: jhb
Handle error bits of INTR_STAT and TX_ABORT registers.
Move interrupt clearing from interrupt handler to polling loop to get
common execution path with polled mode.
Do not clear interrupts with reading of IG4_REG_CLR_INTR register as
interrupts, triggered during the period from reg_read(IG4_REG_INTR_STAT)
to reg_read(IG4_REG_CLR_INTR) will be missed.
Instead, read each IG4_REG_CLR_* register separately.
INTR_STAT register exposes more useful informaton then STA register does
e.g. it exposes error and I2C bus STOP conditions. Make it a main source
of I2C transfer state.
In this mode DATA_CMD register reads and writes are performed in
TX/RX FIFO-sized bursts to increase I2C bus utilization.
That reduces read time from 60us to 30us per byte when read data is fit
in to RX FIFO buffer in FAST speed mode in my setup.
IC clock rates are varied between different controller models so we have
to adjust timing registers in each case individually. Borrow intresting
constants and formulas from Intel specs, i2c-designware and lpss_intel
drivers and apply them to FreeBSD supported controller models.
Implement fetching of timing data via ACPI methods execution if available.
as the driver is fully functional on a cold boot through utilization of
polled mode.
As a side effect, ig4 children probe and attach methods can be called
earlier in the boot sequence, so now it is up to the child drivers
to wait for a kernel initialization completion if it is required.
If controller is allocated with IIC_NOWAIT option ig4 enables polled mode
for a period of allocation that makes possible to start I2C transfers
from the contexts where sleeping is not allowed e.g. from ithreads or
callouts.
Currently ig4 internally depends on it's own interrupts and uses mtx_sleep()
to wait for them. That means it can not be used from any context where
sleeping is disallowed e.g. on cold boot, from DDB/KDB, from other device
driver's interrupt handlers and so on.
This change replaces sleeps with busy loops in cold boot and DDB cases.
Setting the IG4_REG_RX_TL register to 1 was actually generating an
interrupt after 2 bytes were available in the Rx fifo. We need to set the
register to 0 to get an interrupt for 1 byte already.
Obtained from: DragonflyBSD (02f0bf2)
Now io_lock is used as condition variable to synchronize active process with
the interrupt handler. It is not used for tasks other than waiting for
interrupt and passing parameters to and from it's handler.
Specs shows no dedicated interrupt firing on disable of the controller.
Remove io lock acquisitions around set_controller() calls as they are
not needed anymore.
There is no need to read all controller's RX FIFO data to clear RX_FULL
bit in interrupt handler as interrupts are masked permanently since
previous commit.
This avoids possible interrupt storms, depending on the state of the I2C
controller before the driver attached.
During attaching this clears the interrupt mask.
Revert r338215 as this change makes it no-op.
Obtained from: DragonflyBSD (d7c8555)
Fail the attach on controller startup errors. For some reason the
dell xps 13 says there's I2C controller, but the controller appears
to be permanente disabled and will refuse to enable.
Obtained from: DragonflyBSD (509820b)
They share common device driver code with different bus attachments
This commit starts a bunch of changes which have following properties:
Reviewed by: imp (previous version)
MFC after: 1 month
Differential Revision: https://reviews.freebsd.org/D22016
Execution of "Soft reset" command (IG4_REG_RESETS_SKL) at controller init
stage sets SDA_HOLD register value to 0x0001 which is often too low for
normal operation.
Set SDA_HOLD back to 28 after reset to restore controller functionality.
PR: 240339
Reported by: imp, GregV, et al.
MFC after: 3 days
This includes removing stray whitespace, adding a line after the
variable declaration block and removing a redundant check.
MFC after: 1 week
X-MFC with: r339754
In testing on a Dell Latitude 7480, having ig4.ko loaded during a
suspend caused the system to hang. It turns out that ig4iic_intr() was
being called after the device entered D3, and entered an infinite loop
because a read of the I2C status register returned all ones, causing us
to attempt to read a byte from the data buffer until one of the status
bits clears. This occured because ig4iic_pci0 shares an interrupt with
the VGA device on this laptop, so ig4iic_intr() gets called even when
there is no work to do. This is exactly the problem fixed by r342170,
which resolves the hang for me and allows suspend/resume to work with
ig4.ko loaded. So, re-enable autoloading of ig4.ko in the hope that
r342170 resolves the problem universally.
Reviewed by: gonzo
MFC after: 1 month (pending an MFC of r342170)
Differential Revision: https://reviews.freebsd.org/D18587
Due to hardware limitation AMD I2C controller can't trigger pending
interrupt if interrupt status has been changed after clearing
interrupt status bits. So, I2C will lose the interrupt and IO will be
timed out. Implements a workaround to disable I2C controller interrupt
and re-enable I2C interrupt before existing interrupt handler.
Submitted by: rajfbsd@gmail.com
MFC after: 2 weeks
Differential Revision: https://reviews.freebsd.org/D16720