Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F133109254
D44021.id135445.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
8 KB
Referenced Files
None
Subscribers
None
D44021.id135445.diff
View Options
diff --git a/sys/dev/iicbus/controller/vybrid/vf_i2c.h b/sys/dev/iicbus/controller/vybrid/vf_i2c.h
--- a/sys/dev/iicbus/controller/vybrid/vf_i2c.h
+++ b/sys/dev/iicbus/controller/vybrid/vf_i2c.h
@@ -28,7 +28,8 @@
/*
* Vybrid Family Inter-Integrated Circuit (I2C)
- * Chapter 48, Vybrid Reference Manual, Rev. 5, 07/2013
+ * Originally based on Chapter 48, Vybrid Reference Manual, Rev. 5, 07/2013
+ * Currently based on Chapter 21, LX2160A Reference Manual, Rev. 1, 10/2021
*
* The current implementation is based on the original driver by Ruslan Bukin,
* later modified by Dawid Górecki, and split into FDT and ACPI drivers by Val
diff --git a/sys/dev/iicbus/controller/vybrid/vf_i2c.c b/sys/dev/iicbus/controller/vybrid/vf_i2c.c
--- a/sys/dev/iicbus/controller/vybrid/vf_i2c.c
+++ b/sys/dev/iicbus/controller/vybrid/vf_i2c.c
@@ -28,7 +28,8 @@
/*
* Vybrid Family Inter-Integrated Circuit (I2C)
- * Chapter 48, Vybrid Reference Manual, Rev. 5, 07/2013
+ * Originally based on Chapter 48, Vybrid Reference Manual, Rev. 5, 07/2013
+ * Currently based on Chapter 21, LX2160A Reference Manual, Rev. 1, 10/2021
*
* The current implementation is based on the original driver by Ruslan Bukin,
* later modified by Dawid Górecki, and split into FDT and ACPI drivers by Val
@@ -175,8 +176,8 @@
device_printf(dev, "Bus frequency divider value appears unset, defaulting to low I2C bus speed.\n");
}
}
-
sc->iicbus = device_add_child(dev, "iicbus", -1);
+
if (sc->iicbus == NULL) {
device_printf(dev, "could not add iicbus child");
bus_release_resources(dev, i2c_spec, sc->res);
@@ -225,24 +226,6 @@
return (0);
}
-/* Wait for transfer interrupt flag */
-static int
-wait_for_iif(struct vf_i2c_softc *sc)
-{
- int retry;
-
- retry = 1000;
- while (retry --) {
- if (READ1(sc, I2C_IBSR) & IBSR_IBIF) {
- WRITE1(sc, I2C_IBSR, IBSR_IBIF);
- return (IIC_NOERR);
- }
- DELAY(10);
- }
-
- return (IIC_ETIMEOUT);
-}
-
/* Wait for free bus */
static int
wait_for_nibb(struct vf_i2c_softc *sc)
@@ -264,14 +247,24 @@
wait_for_icf(struct vf_i2c_softc *sc)
{
int retry;
+ uint8_t ibsr;
+
+ vf_i2c_dbg(sc, "i2c wait for transfer complete + interrupt flag\n");
retry = 1000;
while (retry --) {
- if (READ1(sc, I2C_IBSR) & IBSR_TCF) {
- if (READ1(sc, I2C_IBSR) & IBSR_IBIF) {
- WRITE1(sc, I2C_IBSR, IBSR_IBIF);
- return (IIC_NOERR);
+ ibsr = READ1(sc, I2C_IBSR);
+
+ if (ibsr & IBSR_IBIF) {
+ WRITE1(sc, I2C_IBSR, IBSR_IBIF);
+
+ if (ibsr & IBSR_IBAL) {
+ WRITE1(sc, I2C_IBSR, IBSR_IBAL);
+ return (IIC_EBUSBSY);
}
+
+ if (ibsr & IBSR_TCF)
+ return (IIC_NOERR);
}
DELAY(10);
}
@@ -301,30 +294,24 @@
mtx_lock(&sc->mutex);
- WRITE1(sc, I2C_IBAD, slave);
-
if ((READ1(sc, I2C_IBSR) & IBSR_IBB) == 0) {
+ vf_i2c_dbg(sc, "cant i2c repeat start: bus is no longer busy\n");
mtx_unlock(&sc->mutex);
return (IIC_EBUSERR);
}
- /* Set repeated start condition */
- DELAY(10);
-
reg = READ1(sc, I2C_IBCR);
reg |= (IBCR_RSTA | IBCR_IBIE);
WRITE1(sc, I2C_IBCR, reg);
- DELAY(10);
-
/* Write target address - LSB is R/W bit */
WRITE1(sc, I2C_IBDR, slave);
- error = wait_for_iif(sc);
+ error = wait_for_icf(sc);
if (!tx_acked(sc)) {
- vf_i2c_dbg(sc,
- "cant i2c start: missing ACK after slave addres\n");
+ mtx_unlock(&sc->mutex);
+ vf_i2c_dbg(sc, "cant i2c repeat start: missing ACK after slave address\n");
return (IIC_ENOACK);
}
@@ -349,27 +336,32 @@
mtx_lock(&sc->mutex);
- WRITE1(sc, I2C_IBAD, slave);
+ error = wait_for_nibb(sc);
+
+ /* Reset controller if bus is still busy. */
+ if (error == IIC_ETIMEOUT) {
+ WRITE1(sc, I2C_IBCR, IBCR_MDIS);
+ DELAY(1000);
+ WRITE1(sc, I2C_IBCR, IBCR_NOACK);
+ error = wait_for_nibb(sc);
+ }
- if (READ1(sc, I2C_IBSR) & IBSR_IBB) {
+ if (error != 0) {
mtx_unlock(&sc->mutex);
- vf_i2c_dbg(sc, "cant i2c start: IIC_EBUSBSY\n");
- return (IIC_EBUSERR);
+ vf_i2c_dbg(sc, "cant i2c start: %i\n", error);
+ return (error);
}
/* Set start condition */
- reg = (IBCR_MSSL | IBCR_NOACK | IBCR_IBIE);
+ reg = (IBCR_MSSL | IBCR_NOACK | IBCR_IBIE | IBCR_TXRX);
WRITE1(sc, I2C_IBCR, reg);
- DELAY(100);
-
- reg |= (IBCR_TXRX);
- WRITE1(sc, I2C_IBCR, reg);
+ WRITE1(sc, I2C_IBSR, IBSR_IBIF);
/* Write target address - LSB is R/W bit */
WRITE1(sc, I2C_IBDR, slave);
- error = wait_for_iif(sc);
+ error = wait_for_icf(sc);
if (error != 0) {
mtx_unlock(&sc->mutex);
vf_i2c_dbg(sc, "cant i2c start: iif error\n");
@@ -378,8 +370,7 @@
mtx_unlock(&sc->mutex);
if (!tx_acked(sc)) {
- vf_i2c_dbg(sc,
- "cant i2c start: missing QACK after slave addres\n");
+ vf_i2c_dbg(sc, "cant i2c start: missing ACK after slave address\n");
return (IIC_ENOACK);
}
@@ -397,16 +388,9 @@
mtx_lock(&sc->mutex);
- WRITE1(sc, I2C_IBCR, IBCR_NOACK | IBCR_IBIE);
+ if ((READ1(sc, I2C_IBCR) & IBCR_MSSL) != 0)
+ WRITE1(sc, I2C_IBCR, IBCR_NOACK | IBCR_IBIE);
- DELAY(100);
-
- /* Reset controller if bus still busy after STOP */
- if (wait_for_nibb(sc) == IIC_ETIMEOUT) {
- WRITE1(sc, I2C_IBCR, IBCR_MDIS);
- DELAY(1000);
- WRITE1(sc, I2C_IBCR, IBCR_NOACK);
- }
mtx_unlock(&sc->mutex);
return (IIC_NOERR);
@@ -461,27 +445,14 @@
div_reg = i2c_get_div_val(dev);
vf_i2c_dbg(sc, "i2c reset\n");
- switch (speed) {
- case IIC_FAST:
- case IIC_SLOW:
- case IIC_UNKNOWN:
- case IIC_FASTEST:
- default:
- break;
- }
-
mtx_lock(&sc->mutex);
WRITE1(sc, I2C_IBCR, IBCR_MDIS);
- DELAY(1000);
-
if(div_reg != DIV_REG_UNSET)
WRITE1(sc, I2C_IBFD, div_reg);
WRITE1(sc, I2C_IBCR, 0x0); /* Enable i2c */
- DELAY(1000);
-
mtx_unlock(&sc->mutex);
return (IIC_NOERR);
@@ -503,36 +474,34 @@
if (len) {
if (len == 1)
- WRITE1(sc, I2C_IBCR, IBCR_IBIE | IBCR_MSSL | \
- IBCR_NOACK);
+ WRITE1(sc, I2C_IBCR, IBCR_IBIE | IBCR_MSSL | IBCR_NOACK);
else
WRITE1(sc, I2C_IBCR, IBCR_IBIE | IBCR_MSSL);
/* dummy read */
READ1(sc, I2C_IBDR);
- DELAY(1000);
- }
- while (*read < len) {
- error = wait_for_icf(sc);
- if (error != 0) {
- mtx_unlock(&sc->mutex);
- return (error);
- }
+ while (*read < len) {
+ error = wait_for_icf(sc);
+ if (error != 0) {
+ mtx_unlock(&sc->mutex);
+ return (error);
+ }
- if ((*read == len - 2) && last) {
- /* NO ACK on last byte */
- WRITE1(sc, I2C_IBCR, IBCR_IBIE | IBCR_MSSL | \
- IBCR_NOACK);
- }
+ if (last) {
+ if (*read == len - 2) {
+ /* NO ACK on last byte */
+ WRITE1(sc, I2C_IBCR, IBCR_IBIE | IBCR_MSSL | IBCR_NOACK);
- if ((*read == len - 1) && last) {
- /* Transfer done, remove master bit */
- WRITE1(sc, I2C_IBCR, IBCR_IBIE | IBCR_NOACK);
- }
+ } else if (*read == len - 1) {
+ /* Transfer done, remove master bit */
+ WRITE1(sc, I2C_IBCR, IBCR_IBIE | IBCR_NOACK);
+ }
+ }
- *buf++ = READ1(sc, I2C_IBDR);
- (*read)++;
+ *buf++ = READ1(sc, I2C_IBDR);
+ (*read)++;
+ }
}
mtx_unlock(&sc->mutex);
@@ -555,7 +524,7 @@
while (*sent < len) {
WRITE1(sc, I2C_IBDR, *buf++);
- error = wait_for_iif(sc);
+ error = wait_for_icf(sc);
if (error != 0) {
mtx_unlock(&sc->mutex);
return (error);
diff --git a/sys/dev/iicbus/controller/vybrid/vf_i2c_acpi.c b/sys/dev/iicbus/controller/vybrid/vf_i2c_acpi.c
--- a/sys/dev/iicbus/controller/vybrid/vf_i2c_acpi.c
+++ b/sys/dev/iicbus/controller/vybrid/vf_i2c_acpi.c
@@ -27,7 +27,8 @@
/*
* Vybrid Family Inter-Integrated Circuit (I2C)
- * Chapter 48, Vybrid Reference Manual, Rev. 5, 07/2013
+ * Originally based on Chapter 48, Vybrid Reference Manual, Rev. 5, 07/2013
+ * Currently based on Chapter 21, LX2160A Reference Manual, Rev. 1, 10/2021
*
* The current implementation is based on the original driver by Ruslan Bukin,
* later modified by Dawid Górecki, and split into FDT and ACPI drivers by Val
diff --git a/sys/dev/iicbus/controller/vybrid/vf_i2c_fdt.c b/sys/dev/iicbus/controller/vybrid/vf_i2c_fdt.c
--- a/sys/dev/iicbus/controller/vybrid/vf_i2c_fdt.c
+++ b/sys/dev/iicbus/controller/vybrid/vf_i2c_fdt.c
@@ -28,7 +28,8 @@
/*
* Vybrid Family Inter-Integrated Circuit (I2C)
- * Chapter 48, Vybrid Reference Manual, Rev. 5, 07/2013
+ * Originally based on Chapter 48, Vybrid Reference Manual, Rev. 5, 07/2013
+ * Currently based on Chapter 21, LX2160A Reference Manual, Rev. 1, 10/2021
*
* The current implementation is based on the original driver by Ruslan Bukin,
* later modified by Dawid Górecki, and split into FDT and ACPI drivers by Val
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Oct 24, 1:33 AM (5 h, 47 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
24111936
Default Alt Text
D44021.id135445.diff (8 KB)
Attached To
Mode
D44021: Revamping the existing Vybrid I2C Controller Driver to Include Support for the QorIQ LX2160A Controller
Attached
Detach File
Event Timeline
Log In to Comment