summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpatrick <patrick@openbsd.org>2018-12-23 22:48:19 +0000
committerpatrick <patrick@openbsd.org>2018-12-23 22:48:19 +0000
commitede2cd4659fc7a98adf78cd8183ff942ff261f5f (patch)
treeed3a2931eb6db4d59d0486fd42a54ec29f050ade
parentFinally, stop abusing .Ss and .Sx to mark up macros, use .Ic instead (diff)
downloadwireguard-openbsd-ede2cd4659fc7a98adf78cd8183ff942ff261f5f.tar.xz
wireguard-openbsd-ede2cd4659fc7a98adf78cd8183ff942ff261f5f.zip
Add support for generating a REPEATED START on operations where we first
write the register address and then read the register data in one go. ok kettenis@
-rw-r--r--sys/dev/fdt/imxiic.c25
1 files changed, 18 insertions, 7 deletions
diff --git a/sys/dev/fdt/imxiic.c b/sys/dev/fdt/imxiic.c
index 54de59ac253..97a42f04544 100644
--- a/sys/dev/fdt/imxiic.c
+++ b/sys/dev/fdt/imxiic.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: imxiic.c,v 1.6 2018/08/20 16:48:47 patrick Exp $ */
+/* $OpenBSD: imxiic.c,v 1.7 2018/12/23 22:48:19 patrick Exp $ */
/*
* Copyright (c) 2013 Patrick Wildt <patrick@blueri.se>
*
@@ -71,7 +71,8 @@ void imxiic_setspeed(struct imxiic_softc *, u_int);
int imxiic_intr(void *);
int imxiic_wait_intr(struct imxiic_softc *, int, int);
int imxiic_wait_state(struct imxiic_softc *, uint32_t, uint32_t);
-int imxiic_read(struct imxiic_softc *, int, void *, int);
+int imxiic_read(struct imxiic_softc *, int, const void *, int,
+ void *, int);
int imxiic_write(struct imxiic_softc *, int, const void *, int,
const void *, int);
@@ -234,7 +235,6 @@ imxiic_wait_state(struct imxiic_softc *sc, uint32_t mask, uint32_t value)
{
uint32_t state;
int timeout;
- state = HREAD2(sc, I2C_I2SR);
for (timeout = 1000; timeout > 0; timeout--) {
if (((state = HREAD2(sc, I2C_I2SR)) & mask) == value)
return 0;
@@ -244,10 +244,22 @@ imxiic_wait_state(struct imxiic_softc *sc, uint32_t mask, uint32_t value)
}
int
-imxiic_read(struct imxiic_softc *sc, int addr, void *data, int len)
+imxiic_read(struct imxiic_softc *sc, int addr, const void *cmd, int cmdlen,
+ void *data, int len)
{
int i;
+ if (cmdlen > 0) {
+ if (imxiic_write(sc, addr, cmd, cmdlen, NULL, 0))
+ return (EIO);
+
+ HSET2(sc, I2C_I2CR, I2C_I2CR_RSTA);
+ delay(1);
+ if (imxiic_wait_state(sc, I2C_I2SR_IBB, I2C_I2SR_IBB))
+ return (EIO);
+ }
+
+ HCLR2(sc, I2C_I2SR, I2C_I2SR_IIF);
HWRITE2(sc, I2C_I2DR, (addr << 1) | 1);
if (imxiic_wait_state(sc, I2C_I2SR_IIF, I2C_I2SR_IIF))
@@ -287,6 +299,7 @@ imxiic_write(struct imxiic_softc *sc, int addr, const void *cmd, int cmdlen,
{
int i;
+ HCLR2(sc, I2C_I2SR, I2C_I2SR_IIF);
HWRITE2(sc, I2C_I2DR, addr << 1);
if (imxiic_wait_state(sc, I2C_I2SR_IIF, I2C_I2SR_IIF))
@@ -357,8 +370,6 @@ imxiic_i2c_exec(void *cookie, i2c_op_t op, i2c_addr_t addr,
if (!I2C_OP_STOP_P(op))
return EINVAL;
- if (I2C_OP_READ_P(op) && cmdlen > 0)
- return EINVAL;
/* start transaction */
HSET2(sc, I2C_I2CR, I2C_I2CR_MSTA);
@@ -373,7 +384,7 @@ imxiic_i2c_exec(void *cookie, i2c_op_t op, i2c_addr_t addr,
HSET2(sc, I2C_I2CR, I2C_I2CR_IIEN | I2C_I2CR_MTX | I2C_I2CR_TXAK);
if (I2C_OP_READ_P(op)) {
- ret = imxiic_read(sc, addr, buf, len);
+ ret = imxiic_read(sc, addr, cmdbuf, cmdlen, buf, len);
} else {
ret = imxiic_write(sc, addr, cmdbuf, cmdlen, buf, len);
}