aboutsummaryrefslogtreecommitdiffstats
path: root/cvmx-twsi.c
diff options
context:
space:
mode:
Diffstat (limited to 'cvmx-twsi.c')
-rw-r--r--cvmx-twsi.c87
1 files changed, 69 insertions, 18 deletions
diff --git a/cvmx-twsi.c b/cvmx-twsi.c
index 30e8081858a3..4b41ace6f99e 100644
--- a/cvmx-twsi.c
+++ b/cvmx-twsi.c
@@ -1,5 +1,5 @@
/***********************license start***************
- * Copyright (c) 2003-2010 Cavium Networks (support@cavium.com). All rights
+ * Copyright (c) 2003-2010 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
@@ -15,7 +15,7 @@
* disclaimer in the documentation and/or other materials provided
* with the distribution.
- * * Neither the name of Cavium Networks nor the names of
+ * * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
@@ -26,7 +26,7 @@
* countries.
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
- * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR
+ * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
* THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR
* DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM
@@ -48,7 +48,7 @@
*
* Interface to the TWSI / I2C bus
*
- * <hr>$Revision: 49448 $<hr>
+ * <hr>$Revision: 70030 $<hr>
*
*/
#ifdef CVMX_BUILD_FOR_LINUX_KERNEL
@@ -71,9 +71,9 @@
#endif
#ifdef CVMX_BUILD_FOR_LINUX_KERNEL
+# if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
static struct i2c_adapter *__cvmx_twsix_get_adapter(int twsi_id)
{
-# if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
struct octeon_i2c {
wait_queue_head_t queue;
struct i2c_adapter adap;
@@ -94,11 +94,9 @@ static struct i2c_adapter *__cvmx_twsix_get_adapter(int twsi_id)
return NULL;
i2c = container_of(adapter, struct octeon_i2c, adap);
return &i2c[twsi_id].adap;
-#else
- return NULL;
-#endif
}
#endif
+#endif
/**
@@ -171,10 +169,11 @@ int cvmx_twsix_read_ia(int twsi_id, uint8_t dev_addr, uint16_t internal_addr, in
#else
cvmx_mio_twsx_sw_twsi_t sw_twsi_val;
cvmx_mio_twsx_sw_twsi_ext_t twsi_ext;
+ int retry_limit = 5;
if (num_bytes < 1 || num_bytes > 8 || !data || ia_width_bytes < 0 || ia_width_bytes > 2)
return -1;
-
+retry:
twsi_ext.u64 = 0;
sw_twsi_val.u64 = 0;
sw_twsi_val.s.v = 1;
@@ -197,11 +196,36 @@ int cvmx_twsix_read_ia(int twsi_id, uint8_t dev_addr, uint16_t internal_addr, in
cvmx_csr_db_decode(cvmx_get_proc_id(), CVMX_MIO_TWSX_SW_TWSI(twsi_id), sw_twsi_val.u64);
cvmx_write_csr(CVMX_MIO_TWSX_SW_TWSI(twsi_id), sw_twsi_val.u64);
while (((cvmx_mio_twsx_sw_twsi_t)(sw_twsi_val.u64 = cvmx_read_csr(CVMX_MIO_TWSX_SW_TWSI(twsi_id)))).s.v)
- ;
+ cvmx_wait(1000);
twsi_printf("Results:\n");
cvmx_csr_db_decode(cvmx_get_proc_id(), CVMX_MIO_TWSX_SW_TWSI(twsi_id), sw_twsi_val.u64);
if (!sw_twsi_val.s.r)
- return -1;
+ {
+ /* Check the reason for the failure. We may need to retry to handle multi-master
+ ** configurations.
+ ** Lost arbitration : 0x38, 0x68, 0xB0, 0x78
+ ** Core busy as slave: 0x80, 0x88, 0xA0, 0xA8, 0xB8, 0xC0, 0xC8
+ */
+ if (sw_twsi_val.s.d == 0x38
+ || sw_twsi_val.s.d == 0x68
+ || sw_twsi_val.s.d == 0xB0
+ || sw_twsi_val.s.d == 0x78
+ || sw_twsi_val.s.d == 0x80
+ || sw_twsi_val.s.d == 0x88
+ || sw_twsi_val.s.d == 0xA0
+ || sw_twsi_val.s.d == 0xA8
+ || sw_twsi_val.s.d == 0xB8
+ || sw_twsi_val.s.d == 0xC8)
+ {
+ if (retry_limit-- > 0)
+ {
+ cvmx_wait_usec(100);
+ goto retry;
+ }
+ }
+ /* For all other errors, return an error code */
+ return -1;
+ }
*data = (sw_twsi_val.s.d & (0xFFFFFFFF >> (32 - num_bytes*8)));
if (num_bytes > 4) {
@@ -265,10 +289,11 @@ int cvmx_twsix_read(int twsi_id, uint8_t dev_addr, int num_bytes, uint64_t *data
#else
cvmx_mio_twsx_sw_twsi_t sw_twsi_val;
cvmx_mio_twsx_sw_twsi_ext_t twsi_ext;
+ int retry_limit = 5;
if (num_bytes > 8 || num_bytes < 1)
return -1;
-
+retry:
sw_twsi_val.u64 = 0;
sw_twsi_val.s.v = 1;
sw_twsi_val.s.r = 1;
@@ -279,11 +304,37 @@ int cvmx_twsix_read(int twsi_id, uint8_t dev_addr, int num_bytes, uint64_t *data
cvmx_csr_db_decode(cvmx_get_proc_id(), CVMX_MIO_TWSX_SW_TWSI(twsi_id), sw_twsi_val.u64);
cvmx_write_csr(CVMX_MIO_TWSX_SW_TWSI(twsi_id), sw_twsi_val.u64);
while (((cvmx_mio_twsx_sw_twsi_t)(sw_twsi_val.u64 = cvmx_read_csr(CVMX_MIO_TWSX_SW_TWSI(twsi_id)))).s.v)
- ;
+ cvmx_wait(1000);
twsi_printf("Results:\n");
cvmx_csr_db_decode(cvmx_get_proc_id(), CVMX_MIO_TWSX_SW_TWSI(twsi_id), sw_twsi_val.u64);
if (!sw_twsi_val.s.r)
- return -1;
+ if (!sw_twsi_val.s.r)
+ {
+ /* Check the reason for the failure. We may need to retry to handle multi-master
+ ** configurations.
+ ** Lost arbitration : 0x38, 0x68, 0xB0, 0x78
+ ** Core busy as slave: 0x80, 0x88, 0xA0, 0xA8, 0xB8, 0xC0, 0xC8
+ */
+ if (sw_twsi_val.s.d == 0x38
+ || sw_twsi_val.s.d == 0x68
+ || sw_twsi_val.s.d == 0xB0
+ || sw_twsi_val.s.d == 0x78
+ || sw_twsi_val.s.d == 0x80
+ || sw_twsi_val.s.d == 0x88
+ || sw_twsi_val.s.d == 0xA0
+ || sw_twsi_val.s.d == 0xA8
+ || sw_twsi_val.s.d == 0xB8
+ || sw_twsi_val.s.d == 0xC8)
+ {
+ if (retry_limit-- > 0)
+ {
+ cvmx_wait_usec(100);
+ goto retry;
+ }
+ }
+ /* For all other errors, return an error code */
+ return -1;
+ }
*data = (sw_twsi_val.s.d & (0xFFFFFFFF >> (32 - num_bytes*8)));
if (num_bytes > 4) {
@@ -328,10 +379,10 @@ int cvmx_twsix_write(int twsi_id, uint8_t dev_addr, int num_bytes, uint64_t data
for (j = 0, i = num_bytes - 1; i >= 0; i--, j++)
data_buf[j] = (u8)(data >> (i * 8));
- msg[1].addr = dev_addr;
- msg[1].flags = 0;
- msg[1].len = num_bytes;
- msg[1].buf = data_buf;
+ msg[0].addr = dev_addr;
+ msg[0].flags = 0;
+ msg[0].len = num_bytes;
+ msg[0].buf = data_buf;
i = i2c_transfer(adapter, msg, 1);