diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2022-12-06 16:06:33 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2022-12-06 16:06:33 +0000 |
commit | 2ac04ee279275eb0aeb0c23413b945a76bda2098 (patch) | |
tree | 5ba6b80b225931d4bce5e43f134dba7c8499ecc3 /sys/arch/arm64/dev | |
parent | efa7eb0aee84fb0cec9a5d73713dc29f49eb3ba9 (diff) |
For write operations, wait until the transaction completes just like we
do after sending the command for a read operation. Fixes issues with doing
multiple operations back-to-back.
ok patrick@
Diffstat (limited to 'sys/arch/arm64/dev')
-rw-r--r-- | sys/arch/arm64/dev/apliic.c | 47 |
1 files changed, 33 insertions, 14 deletions
diff --git a/sys/arch/arm64/dev/apliic.c b/sys/arch/arm64/dev/apliic.c index 59e51d2e44a..7358d669b0d 100644 --- a/sys/arch/arm64/dev/apliic.c +++ b/sys/arch/arm64/dev/apliic.c @@ -1,4 +1,4 @@ -/* $OpenBSD: apliic.c,v 1.3 2022/02/14 14:55:53 kettenis Exp $ */ +/* $OpenBSD: apliic.c,v 1.4 2022/12/06 16:06:32 kettenis Exp $ */ /* * Copyright (c) 2021 Patrick Wildt <patrick@blueri.se> * @@ -153,6 +153,29 @@ apliic_attach(struct device *parent, struct device *self, void *aux) } int +apliic_wait(struct apliic_softc *sc) +{ + uint32_t reg; + int timo; + + for (timo = 10; timo > 0; timo--) { + reg = HREAD4(sc, I2C_SMSTA); + if (reg & I2C_SMSTA_XEN) + break; + delay(1000); + } + if (reg & I2C_SMSTA_MTN) + return ENXIO; + if (timo == 0) { + HWRITE4(sc, I2C_SMSTA, reg); + return ETIMEDOUT; + } + + HWRITE4(sc, I2C_SMSTA, I2C_SMSTA_XEN); + return 0; +} + +int apliic_acquire_bus(void *cookie, int flags) { return 0; @@ -169,12 +192,13 @@ apliic_exec(void *cookie, i2c_op_t op, i2c_addr_t addr, const void *cmd, { struct apliic_softc *sc = cookie; uint32_t reg; - int i; + int error, i; if (!I2C_OP_STOP_P(op)) return EINVAL; - HWRITE4(sc, I2C_SMSTA, 0xffffffff); + reg = HREAD4(sc, I2C_SMSTA); + HWRITE4(sc, I2C_SMSTA, reg); if (cmdlen > 0) { HWRITE4(sc, I2C_MTXFIFO, I2C_MTXFIFO_START | addr << 1); @@ -191,17 +215,9 @@ apliic_exec(void *cookie, i2c_op_t op, i2c_addr_t addr, const void *cmd, HWRITE4(sc, I2C_MTXFIFO, I2C_MTXFIFO_START | addr << 1 | 1); HWRITE4(sc, I2C_MTXFIFO, I2C_MTXFIFO_READ | buflen | I2C_MTXFIFO_STOP); - for (i = 10; i > 0; i--) { - delay(1000); - reg = HREAD4(sc, I2C_SMSTA); - if (reg & I2C_SMSTA_XEN) - break; - } - if (reg & I2C_SMSTA_MTN) - return ENXIO; - if (i == 0) - return ETIMEDOUT; - HWRITE4(sc, I2C_SMSTA, I2C_SMSTA_XEN); + error = apliic_wait(sc); + if (error) + return error; for (i = 0; i < buflen; i++) { reg = HREAD4(sc, I2C_MRXFIFO); if (reg & I2C_MRXFIFO_EMPTY) @@ -215,6 +231,9 @@ apliic_exec(void *cookie, i2c_op_t op, i2c_addr_t addr, const void *cmd, HWRITE4(sc, I2C_MTXFIFO, ((uint8_t *)buf)[i]); HWRITE4(sc, I2C_MTXFIFO, ((uint8_t *)buf)[buflen - 1] | I2C_MTXFIFO_STOP); + error = apliic_wait(sc); + if (error) + return error; } return 0; |