summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVladimir Kondratyev <wulf@FreeBSD.org>2019-11-03 20:42:04 +0000
committerVladimir Kondratyev <wulf@FreeBSD.org>2019-11-03 20:42:04 +0000
commit21e459c61b2673db69a541b10668d2e9b752685b (patch)
tree18401755a9dd97b7bd135d324dbdd4e8445a2248
parentbf9c3c58cac8447eb57f9b39fe4d55c06e42ed8a (diff)
Notes
-rw-r--r--sys/dev/ichiic/ig4_acpi.c5
-rw-r--r--sys/dev/ichiic/ig4_iic.c36
-rw-r--r--sys/dev/ichiic/ig4_var.h2
3 files changed, 20 insertions, 23 deletions
diff --git a/sys/dev/ichiic/ig4_acpi.c b/sys/dev/ichiic/ig4_acpi.c
index fad0377c72e8..e56b378f1767 100644
--- a/sys/dev/ichiic/ig4_acpi.c
+++ b/sys/dev/ichiic/ig4_acpi.c
@@ -69,18 +69,15 @@ static int
ig4iic_acpi_probe(device_t dev)
{
ig4iic_softc_t *sc;
- char *hid;
int rv;
sc = device_get_softc(dev);
if (acpi_disabled("ig4iic"))
return (ENXIO);
- rv = ACPI_ID_PROBE(device_get_parent(dev), dev, ig4iic_ids, &hid);
+ rv = ACPI_ID_PROBE(device_get_parent(dev), dev, ig4iic_ids, NULL);
if (rv > 0)
return (rv);
- if (strcmp("AMDI0010", hid) == 0)
- sc->access_intr_mask = 1;
device_set_desc(dev, "Designware I2C Controller");
return (rv);
}
diff --git a/sys/dev/ichiic/ig4_iic.c b/sys/dev/ichiic/ig4_iic.c
index 1d26dff59a7d..fcf513389be3 100644
--- a/sys/dev/ichiic/ig4_iic.c
+++ b/sys/dev/ichiic/ig4_iic.c
@@ -98,6 +98,15 @@ reg_read(ig4iic_softc_t *sc, uint32_t reg)
return (value);
}
+static void
+set_intr_mask(ig4iic_softc_t *sc, uint32_t val)
+{
+ if (sc->intr_mask != val) {
+ reg_write(sc, IG4_REG_INTR_MASK, val);
+ sc->intr_mask = val;
+ }
+}
+
/*
* Enable or disable the controller and wait for the controller to acknowledge
* the state change.
@@ -113,12 +122,9 @@ set_controller(ig4iic_softc_t *sc, uint32_t ctl)
* When the controller is enabled, interrupt on STOP detect
* or receive character ready and clear pending interrupts.
*/
- if (ctl & IG4_I2C_ENABLE) {
- reg_write(sc, IG4_REG_INTR_MASK, IG4_INTR_STOP_DET |
- IG4_INTR_RX_FULL);
+ set_intr_mask(sc, 0);
+ if (ctl & IG4_I2C_ENABLE)
reg_read(sc, IG4_REG_CLR_INTR);
- } else
- reg_write(sc, IG4_REG_INTR_MASK, 0);
reg_write(sc, IG4_REG_I2C_EN, ctl);
error = IIC_ETIMEOUT;
@@ -196,8 +202,10 @@ wait_status(ig4iic_softc_t *sc, uint32_t status)
* work, otherwise poll with the lock held.
*/
if (status & IG4_STATUS_RX_NOTEMPTY) {
+ set_intr_mask(sc, IG4_INTR_STOP_DET | IG4_INTR_RX_FULL);
mtx_sleep(sc, &sc->io_lock, 0, "i2cwait",
(hz + 99) / 100); /* sleep up to 10ms */
+ set_intr_mask(sc, 0);
count_us += 10000;
} else {
DELAY(25);
@@ -579,6 +587,10 @@ ig4iic_attach(ig4iic_softc_t *sc)
v = reg_read(sc, IG4_REG_SS_SCL_LCNT);
reg_write(sc, IG4_REG_FS_SCL_LCNT, v);
+ reg_read(sc, IG4_REG_CLR_INTR);
+ reg_write(sc, IG4_REG_INTR_MASK, 0);
+ sc->intr_mask = 0;
+
/*
* Program based on a 25000 Hz clock. This is a bit of a
* hack (obviously). The defaults are 400 and 470 for standard
@@ -725,7 +737,7 @@ ig4iic_intr(void *cookie)
uint32_t status;
mtx_lock(&sc->io_lock);
-/* reg_write(sc, IG4_REG_INTR_MASK, IG4_INTR_STOP_DET);*/
+ 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) {
@@ -735,18 +747,6 @@ ig4iic_intr(void *cookie)
status = reg_read(sc, IG4_REG_I2C_STA);
}
- /*
- * Workaround to trigger pending interrupt if IG4_REG_INTR_STAT
- * is changed after clearing it
- */
- if (sc->access_intr_mask != 0) {
- status = reg_read(sc, IG4_REG_INTR_MASK);
- if (status != 0) {
- reg_write(sc, IG4_REG_INTR_MASK, 0);
- reg_write(sc, IG4_REG_INTR_MASK, status);
- }
- }
-
wakeup(sc);
mtx_unlock(&sc->io_lock);
}
diff --git a/sys/dev/ichiic/ig4_var.h b/sys/dev/ichiic/ig4_var.h
index b679cb6db6d9..962a797a4ac1 100644
--- a/sys/dev/ichiic/ig4_var.h
+++ b/sys/dev/ichiic/ig4_var.h
@@ -65,6 +65,7 @@ struct ig4iic_softc {
int rnext;
int rpos;
char rbuf[IG4_RBUFSIZE];
+ uint32_t intr_mask;
int error;
uint8_t last_slave;
int platform_attached : 1;
@@ -72,7 +73,6 @@ struct ig4iic_softc {
int slave_valid : 1;
int read_started : 1;
int write_started : 1;
- int access_intr_mask : 1;
/*
* Locking semantics: