[ig4] Drop driver's internal RX FIFO
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 commit is contained in:
parent
912a626e3e
commit
0f93ec164a
@ -167,17 +167,6 @@ wait_status(ig4iic_softc_t *sc, uint32_t status)
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* When waiting for receive data break-out if the interrupt
|
||||
* loaded data into the FIFO.
|
||||
*/
|
||||
if (status & IG4_STATUS_RX_NOTEMPTY) {
|
||||
if (sc->rpos != sc->rnext) {
|
||||
error = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* When waiting for the transmit FIFO to become empty,
|
||||
* reset the timeout if we see a change in the transmit
|
||||
@ -216,25 +205,6 @@ wait_status(ig4iic_softc_t *sc, uint32_t status)
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read I2C data. The data might have already been read by
|
||||
* the interrupt code, otherwise it is sitting in the data
|
||||
* register.
|
||||
*/
|
||||
static uint8_t
|
||||
data_read(ig4iic_softc_t *sc)
|
||||
{
|
||||
uint8_t c;
|
||||
|
||||
if (sc->rpos == sc->rnext) {
|
||||
c = (uint8_t)reg_read(sc, IG4_REG_DATA_CMD);
|
||||
} else {
|
||||
c = sc->rbuf[sc->rpos & IG4_RBUFMASK];
|
||||
++sc->rpos;
|
||||
}
|
||||
return (c);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the slave address. The controller must be disabled when
|
||||
* changing the address.
|
||||
@ -334,7 +304,7 @@ ig4iic_read(ig4iic_softc_t *sc, uint8_t *buf, uint16_t len,
|
||||
error = wait_status(sc, IG4_STATUS_RX_NOTEMPTY);
|
||||
if (error)
|
||||
break;
|
||||
buf[i] = data_read(sc);
|
||||
buf[i] = (uint8_t)reg_read(sc, IG4_REG_DATA_CMD);
|
||||
}
|
||||
|
||||
(void)reg_read(sc, IG4_REG_TX_ABRT_SOURCE);
|
||||
@ -455,16 +425,6 @@ ig4iic_transfer(device_t dev, struct iic_msg *msgs, uint32_t nmsgs)
|
||||
*/
|
||||
reg_read(sc, IG4_REG_CLR_TX_ABORT);
|
||||
|
||||
/*
|
||||
* Clean out any previously received data.
|
||||
*/
|
||||
if (sc->rpos != sc->rnext && bootverbose) {
|
||||
device_printf(sc->dev, "discarding %d bytes of spurious data\n",
|
||||
sc->rnext - sc->rpos);
|
||||
}
|
||||
sc->rpos = 0;
|
||||
sc->rnext = 0;
|
||||
|
||||
rpstart = false;
|
||||
error = 0;
|
||||
for (i = 0; i < nmsgs; i++) {
|
||||
@ -734,19 +694,10 @@ static void
|
||||
ig4iic_intr(void *cookie)
|
||||
{
|
||||
ig4iic_softc_t *sc = cookie;
|
||||
uint32_t status;
|
||||
|
||||
mtx_lock(&sc->io_lock);
|
||||
set_intr_mask(sc, 0);
|
||||
reg_read(sc, IG4_REG_CLR_INTR);
|
||||
status = reg_read(sc, IG4_REG_I2C_STA);
|
||||
while (status & IG4_STATUS_RX_NOTEMPTY) {
|
||||
sc->rbuf[sc->rnext & IG4_RBUFMASK] =
|
||||
(uint8_t)reg_read(sc, IG4_REG_DATA_CMD);
|
||||
++sc->rnext;
|
||||
status = reg_read(sc, IG4_REG_I2C_STA);
|
||||
}
|
||||
|
||||
wakeup(sc);
|
||||
mtx_unlock(&sc->io_lock);
|
||||
}
|
||||
|
@ -43,9 +43,6 @@
|
||||
#include "pci_if.h"
|
||||
#include "iicbus_if.h"
|
||||
|
||||
#define IG4_RBUFSIZE 128
|
||||
#define IG4_RBUFMASK (IG4_RBUFSIZE - 1)
|
||||
|
||||
enum ig4_op { IG4_IDLE, IG4_READ, IG4_WRITE };
|
||||
enum ig4_vers { IG4_HASWELL, IG4_ATOM, IG4_SKYLAKE, IG4_APL };
|
||||
|
||||
@ -62,9 +59,6 @@ struct ig4iic_softc {
|
||||
enum ig4_vers version;
|
||||
enum ig4_op op;
|
||||
int cmd;
|
||||
int rnext;
|
||||
int rpos;
|
||||
char rbuf[IG4_RBUFSIZE];
|
||||
uint32_t intr_mask;
|
||||
int error;
|
||||
uint8_t last_slave;
|
||||
@ -81,19 +75,6 @@ struct ig4iic_softc {
|
||||
* with the controller acquire an exclusive lock on call_lock
|
||||
* to prevent interleaving of calls to the interface and a lock on
|
||||
* io_lock right afterwards, to synchronize controller I/O activity.
|
||||
*
|
||||
* The interrupt handler can only read data while no iicbus call
|
||||
* is in progress or while io_lock is dropped during mtx_sleep in
|
||||
* wait_status and set_controller. It is safe to drop io_lock in those
|
||||
* places, because the interrupt handler only accesses those registers:
|
||||
*
|
||||
* - IG4_REG_I2C_STA (I2C Status)
|
||||
* - IG4_REG_DATA_CMD (Data Buffer and Command)
|
||||
* - IG4_REG_CLR_INTR (Clear Interrupt)
|
||||
*
|
||||
* Locking outside of those places is required to make the content
|
||||
* of rpos/rnext predictable (e.g. whenever data_read is called and in
|
||||
* ig4iic_transfer).
|
||||
*/
|
||||
struct sx call_lock;
|
||||
struct mtx io_lock;
|
||||
|
Loading…
Reference in New Issue
Block a user