<div dir="ltr"><div dir="ltr"><br><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Jun 25, 2019 at 1:47 AM <<a href="mailto:list@c-mauderer.de">list@c-mauderer.de</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">From: Christian Mauderer <<a href="mailto:christian.mauderer@embedded-brains.de" target="_blank">christian.mauderer@embedded-brains.de</a>><br>
<br>
The old driver worked well for EEPROMS with the RTEMS EEPROM driver. But<br>
it had problems with a lot of other situations. Although it's not a<br>
direct port, the new driver is heavily modeled after the FreeBSD ti_i2c<br>
driver.<br></blockquote><div>This is great!</div><div>I have tried this patch with the FreeBSD ported IIC bus through the rtems_i2c</div><div>adaptation layer is FreeBSD and the output MATCHES the original FreeBSD i2c</div><div>scan with the ti_i2c driver. </div><div>Would also like to add that the i2c probe and i2c md in u-boot also shows the same</div><div>results. </div><div>```</div><div>SHLL [/] # i2c -a 0x50 -w16 -mtr -c10<br>aa 55 33 ee 41 33 33 35 42 4e <br>SHLL [/] # i2c -s<br>Scanning I2C devices on /dev/iic0: Hardware may not support START/STOP scanning; trying less-reliable read method.<br>24 34 50 <br></div><div>``` </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
---<br>
bsps/arm/beagle/i2c/bbb-i2c.c | 646 ++++++++++++++++--------------<br>
bsps/arm/beagle/include/bsp/i2c.h | 84 +---<br>
bsps/arm/include/libcpu/am335x.h | 35 +-<br>
3 files changed, 370 insertions(+), 395 deletions(-)<br>
<br>
diff --git a/bsps/arm/beagle/i2c/bbb-i2c.c b/bsps/arm/beagle/i2c/bbb-i2c.c<br>
index 3a8637d457..37b88864b9 100644<br>
--- a/bsps/arm/beagle/i2c/bbb-i2c.c<br>
+++ b/bsps/arm/beagle/i2c/bbb-i2c.c<br>
@@ -9,17 +9,14 @@<br>
/*<br>
* Copyright (c) 2016 Punit Vara <<a href="mailto:punitvara@gmail.com" target="_blank">punitvara@gmail.com</a>><br>
* Copyright (c) 2017 Sichen Zhao <<a href="mailto:zsc19940506@gmail.com" target="_blank">zsc19940506@gmail.com</a>><br>
+ * Copyright (c) 2019 Christian Mauderer <<a href="mailto:christian.mauderer@embedded-brains.de" target="_blank">christian.mauderer@embedded-brains.de</a>><br>
*<br>
* The license and distribution terms for this file may be<br>
* found in the file LICENSE in this distribution or at<br>
* <a href="http://www.rtems.org/license/LICENSE" rel="noreferrer" target="_blank">http://www.rtems.org/license/LICENSE</a>.<br>
*/<br>
<br>
-/*<br>
- * Modified on Punit Vara<<a href="mailto:punitvara@gmail.com" target="_blank">punitvara@gmail.com</a>> works, currently<br>
- * the i2c file is working on the Beaglebone Black board(AM335x)<br>
- */<br>
-<br>
+#include <rtems/bspIo.h><br>
#include <stdio.h><br>
#include <bsp/i2c.h><br>
#include <libcpu/am335x.h><br>
@@ -27,26 +24,114 @@<br>
#include <rtems/counter.h><br>
#include <bsp/bbb-gpio.h><br>
#include <rtems/score/assert.h><br>
+#include <dev/i2c/i2c.h><br>
<br>
-static void am335x_i2c0_pinmux( bbb_i2c_bus *bus )<br>
+typedef struct bbb_i2c_bus {<br>
+ i2c_bus base;<br>
+ volatile bbb_i2c_regs *regs;<br>
+ struct {<br>
+ volatile uint32_t *ctrl_clkctrl;<br>
+ volatile uint32_t *i2c_clkctrl;<br>
+ volatile uint32_t *clkstctrl;<br>
+ } clkregs;<br>
+ struct {<br>
+ volatile uint32_t *conf_sda;<br>
+ uint32_t mmode_sda;<br>
+ volatile uint32_t *conf_scl;<br>
+ uint32_t mmode_scl;<br>
+ } pinregs;<br>
+ rtems_id task_id;<br>
+ rtems_vector_number irq;<br>
+ i2c_msg *buffer;<br>
+ size_t buffer_pos;<br>
+ int error;<br>
+ uint32_t con_reg;<br>
+} bbb_i2c_bus;<br>
+<br>
+#define TRANSFER_TIMEOUT_COUNT 100<br>
+#define FIFO_THRESHOLD 5<br>
+#define min(l,r) ((l) < (r) ? (l) : (r))<br>
+#if 0<br>
+#define debug_print(fmt, args...) printk("bbb-i2c: " fmt, ## args)<br>
+#else<br>
+#define debug_print(fmt, args...)<br>
+#endif<br>
+<br>
+static int am335x_i2c_fill_registers(<br>
+ bbb_i2c_bus *bus,<br>
+ uintptr_t register_base<br>
+)<br>
{<br>
- REG( bus->regs + AM335X_CONF_I2C0_SDA ) =<br>
- ( BBB_RXACTIVE | BBB_SLEWCTRL | BBB_PU_EN );<br>
+ /* FIXME: The pin handling should be replaced by a proper pin handling during<br>
+ * initialization. This one is heavily board specific. */<br>
+#if ! IS_AM335X<br>
+ printk ("The I2C driver currently only works on Beagle Bone. Please add your pin configs.")<br>
+ return EINVAL;<br>
+#endif<br>
+ bus->regs = (volatile bbb_i2c_regs *) register_base;<br>
+ switch ((intptr_t) bus->regs) {<br>
+ case AM335X_I2C0_BASE:<br>
+ bus->clkregs.ctrl_clkctrl = ®(AM335X_SOC_CM_WKUP_REGS +<br>
+ AM335X_CM_WKUP_CONTROL_CLKCTRL);<br>
+ bus->clkregs.i2c_clkctrl = ®(AM335X_SOC_CM_WKUP_REGS +<br>
+ AM335X_CM_WKUP_I2C0_CLKCTRL);<br>
+ bus->clkregs.clkstctrl = ®(AM335X_SOC_CM_WKUP_REGS +<br>
+ AM335X_CM_WKUP_CLKSTCTRL);<br>
+ bus->pinregs.conf_sda = ®(AM335X_PADCONF_BASE + AM335X_CONF_I2C0_SDA);<br>
+ bus->pinregs.mmode_sda = 0;<br>
+ bus->pinregs.conf_scl = ®(AM335X_PADCONF_BASE + AM335X_CONF_I2C0_SCL);<br>
+ bus->pinregs.mmode_scl = 0;<br>
+ break;<br>
+ case AM335X_I2C1_BASE:<br>
+ bus->clkregs.ctrl_clkctrl = ®(AM335X_SOC_CM_WKUP_REGS +<br>
+ AM335X_CM_WKUP_CONTROL_CLKCTRL);<br>
+ bus->clkregs.i2c_clkctrl = ®(AM335X_CM_PER_ADDR +<br>
+ AM335X_CM_PER_I2C1_CLKCTRL);<br>
+ bus->clkregs.clkstctrl = NULL;<br>
+ bus->pinregs.conf_sda = ®(AM335X_PADCONF_BASE + AM335X_CONF_SPI0_D1);<br>
+ bus->pinregs.mmode_sda = 2;<br>
+ bus->pinregs.conf_scl = ®(AM335X_PADCONF_BASE + AM335X_CONF_SPI0_CS0);<br>
+ bus->pinregs.mmode_scl = 2;<br>
+ break;<br>
+ case AM335X_I2C2_BASE:<br>
+ bus->clkregs.ctrl_clkctrl = ®(AM335X_SOC_CM_WKUP_REGS +<br>
+ AM335X_CM_WKUP_CONTROL_CLKCTRL);<br>
+ bus->clkregs.i2c_clkctrl = ®(AM335X_CM_PER_ADDR +<br>
+ AM335X_CM_PER_I2C2_CLKCTRL);<br>
+ bus->clkregs.clkstctrl = NULL;<br>
+ bus->pinregs.conf_sda = ®(AM335X_PADCONF_BASE + AM335X_CONF_UART1_CTSN);<br>
+ bus->pinregs.mmode_sda = 3;<br>
+ bus->pinregs.conf_scl = ®(AM335X_PADCONF_BASE + AM335X_CONF_UART1_RTSN);<br>
+ bus->pinregs.mmode_scl = 3;<br>
+ break;<br>
+ default:<br>
+ return EINVAL;<br>
+ }<br>
+ return 0;<br>
+}<br>
<br>
- REG( bus->regs + AM335X_CONF_I2C0_SCL ) =<br>
- ( BBB_RXACTIVE | BBB_SLEWCTRL | BBB_PU_EN );<br>
+static void am335x_i2c_pinmux( bbb_i2c_bus *bus )<br>
+{<br>
+ *bus->pinregs.conf_sda =<br>
+ ( BBB_RXACTIVE | BBB_SLEWCTRL | bus->pinregs.mmode_sda);<br>
+<br>
+ *bus->pinregs.conf_scl =<br>
+ ( BBB_RXACTIVE | BBB_SLEWCTRL | bus->pinregs.mmode_scl);<br>
}<br>
<br>
-static void I2C0ModuleClkConfig( void )<br>
+static void am335x_i2c_module_clk_enable( bbb_i2c_bus *bus )<br>
{<br>
+ volatile uint32_t *ctrl_clkctrl = bus->clkregs.ctrl_clkctrl;<br>
+ volatile uint32_t *i2c_clkctrl = bus->clkregs.i2c_clkctrl;<br>
+ volatile uint32_t *clkstctrl = bus->clkregs.clkstctrl;<br>
+<br>
/* Writing to MODULEMODE field of AM335X_CM_WKUP_I2C0_CLKCTRL register. */<br>
- REG( AM335X_SOC_CM_WKUP_REGS + AM335X_CM_WKUP_I2C0_CLKCTRL ) |=<br>
- AM335X_CM_WKUP_I2C0_CLKCTRL_MODULEMODE_ENABLE;<br>
+ *i2c_clkctrl |= AM335X_CM_WKUP_I2C0_CLKCTRL_MODULEMODE_ENABLE;<br>
<br>
/* Waiting for MODULEMODE field to reflect the written value. */<br>
while ( AM335X_CM_WKUP_I2C0_CLKCTRL_MODULEMODE_ENABLE !=<br>
- ( REG( AM335X_SOC_CM_WKUP_REGS + AM335X_CM_WKUP_I2C0_CLKCTRL ) &<br>
- AM335X_CM_WKUP_I2C0_CLKCTRL_MODULEMODE ) ) ;<br>
+ ( *i2c_clkctrl & AM335X_CM_WKUP_I2C0_CLKCTRL_MODULEMODE ) )<br>
+ { /* busy wait */ }<br>
<br>
/*<br>
* Waiting for IDLEST field in AM335X_CM_WKUP_CONTROL_CLKCTRL<br>
@@ -54,16 +139,18 @@ static void I2C0ModuleClkConfig( void )<br>
*/<br>
while ( ( AM335X_CM_WKUP_CONTROL_CLKCTRL_IDLEST_FUNC <<<br>
AM335X_CM_WKUP_CONTROL_CLKCTRL_IDLEST_SHIFT ) !=<br>
- ( REG( AM335X_SOC_CM_WKUP_REGS + AM335X_CM_WKUP_CONTROL_CLKCTRL ) &<br>
- AM335X_CM_WKUP_CONTROL_CLKCTRL_IDLEST ) ) ;<br>
-<br>
- /*<br>
- * Waiting for CLKACTIVITY_I2C0_GFCLK field in AM335X_CM_WKUP_CLKSTCTRL<br>
- * register to attain desired value.<br>
- */<br>
- while ( AM335X_CM_WKUP_CLKSTCTRL_CLKACTIVITY_I2C0_GFCLK !=<br>
- ( REG( AM335X_SOC_CM_WKUP_REGS + AM335X_CM_WKUP_CLKSTCTRL ) &<br>
- AM335X_CM_WKUP_CLKSTCTRL_CLKACTIVITY_I2C0_GFCLK ) ) ;<br>
+ ( *ctrl_clkctrl & AM335X_CM_WKUP_I2C0_CLKCTRL_IDLEST ) )<br>
+ { /* busy wait */ }<br>
+<br>
+ if ( clkstctrl != NULL ) {<br>
+ /*<br>
+ * Waiting for CLKACTIVITY_I2C0_GFCLK field in AM335X_CM_WKUP_CLKSTCTRL<br>
+ * register to attain desired value.<br>
+ */<br>
+ while ( AM335X_CM_WKUP_CLKSTCTRL_CLKACTIVITY_I2C0_GFCLK !=<br>
+ ( *clkstctrl & AM335X_CM_WKUP_CLKSTCTRL_CLKACTIVITY_I2C0_GFCLK ) )<br>
+ { /* busy wait */ }<br>
+ }<br>
<br>
/*<br>
* Waiting for IDLEST field in AM335X_CM_WKUP_I2C0_CLKCTRL register to attain<br>
@@ -71,333 +158,286 @@ static void I2C0ModuleClkConfig( void )<br>
*/<br>
while ( ( AM335X_CM_WKUP_I2C0_CLKCTRL_IDLEST_FUNC <<<br>
AM335X_CM_WKUP_I2C0_CLKCTRL_IDLEST_SHIFT ) !=<br>
- ( REG( AM335X_SOC_CM_WKUP_REGS + AM335X_CM_WKUP_I2C0_CLKCTRL ) &<br>
- AM335X_CM_WKUP_I2C0_CLKCTRL_IDLEST ) ) ;<br>
-}<br>
-<br>
-static void am335x_i2c_reset( bbb_i2c_bus *bus )<br>
-{<br>
- volatile bbb_i2c_regs *regs = bus->regs;<br>
- int timeout = I2C_TIMEOUT;<br>
-<br>
- if ( REG( ®s->BBB_I2C_CON ) & BBB_I2C_CON_EN ) {<br>
- REG( ®s->BBB_I2C_CON ) = BBB_I2C_CON_CLR;<br>
- udelay( 50000 );<br>
- }<br>
-<br>
- REG( ®s->BBB_I2C_SYSC ) = BBB_I2C_SYSC_SRST; /* for ES2 after soft reset */<br>
- udelay( 1000 );<br>
- REG( ®s->BBB_I2C_CON ) = BBB_I2C_CON_EN;<br>
-<br>
- while ( !( REG( ®s->BBB_I2C_SYSS ) & BBB_I2C_SYSS_RDONE ) && timeout-- ) {<br>
- if ( timeout <= 0 ) {<br>
- puts( "ERROR: Timeout in soft-reset\n" );<br>
-<br>
- return;<br>
- }<br>
-<br>
- udelay( 1000 );<br>
- }<br>
+ ( *i2c_clkctrl & AM335X_CM_WKUP_I2C0_CLKCTRL_IDLEST ) ) ;<br>
}<br>
-/*<br>
- * Possible values for msg->flag<br>
- * - @ref I2C_M_TEN,<br>
- * - @ref I2C_M_RD,<br>
- * - @ref I2C_M_STOP,<br>
- * - @ref I2C_M_NOSTART,<br>
- * - @ref I2C_M_REV_DIR_ADDR,<br>
- * - @ref I2C_M_IGNORE_NAK,<br>
- * - @ref I2C_M_NO_RD_ACK, and<br>
- * - @ref I2C_M_RECV_LEN.<br>
- */<br>
<br>
-static void am335x_i2c_set_address_size(<br>
- const i2c_msg *msgs,<br>
- volatile bbb_i2c_regs *regs<br>
+static int am335x_i2c_set_clock(<br>
+ i2c_bus *base,<br>
+ unsigned long clock<br>
)<br>
{<br>
- /*<br>
- * Can be configured multiple modes here.<br>
- * Need to think about own address modes<br>
- */<br>
- if ( ( msgs->flags & I2C_M_TEN ) == 0 ) {<br>
- /* 7-bit mode slave address mode */<br>
- REG( ®s->BBB_I2C_CON ) = AM335X_I2C_CFG_7BIT_SLAVE_ADDR;<br>
- } else {<br>
- /* 10-bit slave address mode */<br>
- REG( ®s->BBB_I2C_CON ) = AM335X_I2C_CFG_10BIT_SLAVE_ADDR;<br>
- }<br>
-}<br>
-<br>
-static void am335x_i2c_next_byte( bbb_i2c_bus *bus )<br>
-{<br>
- i2c_msg *msg;<br>
+ bbb_i2c_bus *bus = (bbb_i2c_bus *) base;<br>
+ uint32_t prescaler, divider;<br>
<br>
- ++bus->msgs;<br>
- --bus->msg_todo;<br>
- msg = &bus->msgs[ 0 ];<br>
- bus->current_msg_todo = msg->len;<br>
- bus->current_msg_byte = msg->buf;<br>
-}<br>
+ prescaler = ( BBB_I2C_SYSCLK / BBB_I2C_INTERNAL_CLK ) - 1;<br>
+ bus->regs->BBB_I2C_PSC = prescaler;<br>
+ divider = BBB_I2C_INTERNAL_CLK / ( 2 * clock );<br>
+ bus->regs->BBB_I2C_SCLL = ( divider - 7 );<br>
+ bus->regs->BBB_I2C_SCLH = ( divider - 5 );<br>
<br>
-static void am335x_i2c_masterint_enable(<br>
- volatile bbb_i2c_regs *regs,<br>
- unsigned int flag<br>
-)<br>
-{<br>
- REG( ®s->BBB_I2C_IRQENABLE_SET ) |= flag;<br>
+ return 0;<br>
}<br>
<br>
-static void am335x_i2c_masterint_disable(<br>
- volatile bbb_i2c_regs *regs,<br>
- unsigned int flag<br>
-)<br>
+static int am335x_i2c_reset( bbb_i2c_bus *bus )<br>
{<br>
- REG( ®s->BBB_I2C_IRQENABLE_CLR ) = flag;<br>
-}<br>
+ volatile bbb_i2c_regs *regs = bus->regs;<br>
+ int timeout = 100;<br>
+ int err;<br>
<br>
-static void am335x_int_clear(<br>
- volatile bbb_i2c_regs *regs,<br>
- unsigned int flag<br>
-)<br>
-{<br>
- REG( ®s->BBB_I2C_IRQSTATUS ) = flag;<br>
-}<br>
+ bus->con_reg = 0;<br>
+ regs->BBB_I2C_CON = bus->con_reg;<br>
+ udelay( 50000 );<br>
<br>
-static void am335x_clean_interrupts( volatile bbb_i2c_regs *regs )<br>
-{<br>
- am335x_i2c_masterint_enable( regs, BBB_I2C_ALL_FLAGS );<br>
- am335x_int_clear( regs, BBB_I2C_ALL_FLAGS );<br>
- am335x_i2c_masterint_disable( regs, BBB_I2C_ALL_FLAGS );<br>
-}<br>
-<br>
-static void am335x_i2c_setup_read_transfer(<br>
- bbb_i2c_bus *bus,<br>
- volatile bbb_i2c_regs *regs,<br>
- const i2c_msg *msgs,<br>
- bool send_stop<br>
-)<br>
-{<br>
- REG( ®s->BBB_I2C_CNT ) = bus->current_msg_todo;<br>
+ regs->BBB_I2C_SYSC = AM335X_I2C_SYSC_SRST;<br>
+ udelay( 1000 );<br>
+ regs->BBB_I2C_CON = AM335X_I2C_CON_I2C_EN;<br>
<br>
- REG( ®s->BBB_I2C_CON ) = AM335X_I2C_CFG_MST_RX | AM335X_I2C_CON_I2C_EN;<br>
+ while ( !( regs->BBB_I2C_SYSS & AM335X_I2C_SYSS_RDONE )<br>
+ && timeout >= 0 ) {<br>
+ --timeout;<br>
+ udelay( 100 );<br>
+ }<br>
<br>
- if ( send_stop ) {<br>
- REG( ®s->BBB_I2C_CON ) |= AM335X_I2C_CON_START | AM335X_I2C_CON_STOP;<br>
- } else {<br>
- REG( ®s->BBB_I2C_CON ) |= AM335X_I2C_CON_START;<br>
+ if ( timeout <= 0 ) {<br>
+ puts( "ERROR: Timeout in soft-reset\n" );<br>
+ return ETIMEDOUT;<br>
}<br>
<br>
- am335x_i2c_masterint_enable( regs, AM335X_I2C_INT_RECV_READY |<br>
- AM335X_I2C_IRQSTATUS_ARDY );<br>
-}<br>
+ /* Disable again after reset */<br>
+ regs->BBB_I2C_CON = bus->con_reg;<br>
<br>
-static void am335x_i2c_continue_read_transfer(<br>
- bbb_i2c_bus *bus,<br>
- volatile bbb_i2c_regs *regs<br>
-)<br>
-{<br>
- bus->current_msg_byte[ bus->already_transferred ] =<br>
- REG( ®s->BBB_I2C_DATA );<br>
+ err = am335x_i2c_set_clock( &bus->base, I2C_BUS_CLOCK_DEFAULT );<br>
+ if (err) {<br>
+ return err;<br>
+ }<br>
<br>
- bus->already_transferred++;<br>
+ regs->BBB_I2C_BUF = AM335X_I2C_BUF_TXTRSH(FIFO_THRESHOLD) |<br>
+ AM335X_I2C_BUF_RXTRSH(FIFO_THRESHOLD);<br>
<br>
- REG( ®s->BBB_I2C_IRQSTATUS ) = AM335X_I2C_INT_RECV_READY;<br>
+ /* Enable the I2C controller in master mode. */<br>
+ bus->con_reg |= AM335X_I2C_CON_I2C_EN | AM335X_I2C_CON_MST;<br>
+ regs->BBB_I2C_CON = bus->con_reg;<br>
<br>
- if ( bus->already_transferred == bus->current_msg_todo - 1 ) {<br>
- REG( ®s->BBB_I2C_CON ) |= AM335X_I2C_CON_STOP;<br>
- }<br>
-}<br>
+ regs->BBB_I2C_IRQENABLE_SET =<br>
+ AM335X_I2C_IRQSTATUS_XDR | AM335X_I2C_IRQSTATUS_XRDY |<br>
+ AM335X_I2C_IRQSTATUS_RDR | AM335X_I2C_IRQSTATUS_RRDY |<br>
+ AM335X_I2C_IRQSTATUS_ARDY | AM335X_I2C_IRQSTATUS_NACK |<br>
+ AM335X_I2C_IRQSTATUS_AL;<br>
<br>
-static void am335x_i2c_continue_write(<br>
- bbb_i2c_bus *bus,<br>
- volatile bbb_i2c_regs *regs<br>
-)<br>
-{<br>
- if ( bus->already_transferred == bus->msg_todo ) {<br>
- REG( ®s->BBB_I2C_DATA ) =<br>
- bus->current_msg_byte[ bus->already_transferred ];<br>
- REG( ®s->BBB_I2C_IRQSTATUS ) = AM335X_I2C_IRQSTATUS_XRDY;<br>
- am335x_i2c_masterint_disable( regs, AM335X_I2C_IRQSTATUS_XRDY );<br>
- REG( ®s->BBB_I2C_CON ) |= AM335X_I2C_CON_STOP;<br>
- } else {<br>
- writeb( bus->current_msg_byte[ bus->already_transferred ],<br>
- ®s->BBB_I2C_DATA );<br>
- REG( ®s->BBB_I2C_IRQSTATUS ) = AM335X_I2C_IRQSTATUS_XRDY;<br>
- bus->already_transferred++;<br>
- }<br>
-}<br>
-<br>
-static void am335x_i2c_setup_write_transfer(<br>
- bbb_i2c_bus *bus,<br>
- volatile bbb_i2c_regs *regs,<br>
- const i2c_msg *msgs<br>
-)<br>
-{<br>
- volatile unsigned int no_bytes;<br>
-<br>
- REG( ®s->BBB_I2C_CNT ) = bus->current_msg_todo;<br>
- no_bytes = REG( ®s->BBB_I2C_CNT );<br>
- (void) no_bytes; /* indicate we know that no_bytes is not referenced again */<br>
- REG( ®s->BBB_I2C_SA ) = msgs->addr;<br>
- REG( ®s->BBB_I2C_CON ) = AM335X_I2C_CFG_MST_TX | AM335X_I2C_CON_I2C_EN;<br>
- am335x_clean_interrupts( regs );<br>
- am335x_i2c_masterint_enable( regs, AM335X_I2C_IRQSTATUS_XRDY );<br>
- REG( ®s->BBB_I2C_CON ) |= AM335X_I2C_CON_START | AM335X_I2C_CON_STOP;<br>
+ return 0;<br>
}<br>
<br>
-static void am335x_i2c_setup_transfer(<br>
- bbb_i2c_bus *bus,<br>
- volatile bbb_i2c_regs *regs<br>
-)<br>
+/* Return true if done. */<br>
+static bool am335x_i2c_transfer_intr(bbb_i2c_bus *bus, uint32_t status)<br>
{<br>
- const i2c_msg *msgs = bus->msgs;<br>
- uint32_t msg_todo = bus->msg_todo;<br>
- bool send_stop = false;<br>
- uint32_t i;<br>
+ size_t i;<br>
+ size_t amount = 0;<br>
+ volatile bbb_i2c_regs *regs = bus->regs;<br>
<br>
- bus->current_todo = msgs[ 0 ].len;<br>
+ /* Handle errors */<br>
+ if ((status & AM335X_I2C_IRQSTATUS_NACK) != 0) {<br>
+ debug_print("NACK\n");<br>
+ regs->BBB_I2C_IRQSTATUS = AM335X_I2C_IRQSTATUS_NACK;<br>
+ bus->error = ENXIO;<br>
+ } else if ((status & AM335X_I2C_IRQSTATUS_AL) != 0) {<br>
+ debug_print("Arbitration lost\n");<br>
+ regs->BBB_I2C_IRQSTATUS = AM335X_I2C_IRQSTATUS_AL;<br>
+ bus->error = ENXIO;<br>
+ }<br>
<br>
- for ( i = 1; i < msg_todo && ( msgs[ i ].flags & I2C_M_NOSTART ) != 0;<br>
- ++i ) {<br>
- bus->current_todo += msgs[ i ].len;<br>
+ /* Transfer finished? */<br>
+ if ((status & AM335X_I2C_IRQSTATUS_ARDY) != 0) {<br>
+ debug_print("ARDY transaction complete\n");<br>
+ if (bus->error != 0 && (bus->buffer->flags & I2C_M_STOP) == 0) {<br>
+ regs->BBB_I2C_CON = bus->con_reg | AM335X_I2C_CON_STOP;<br>
+ }<br>
+ regs->BBB_I2C_IRQSTATUS = AM335X_I2C_IRQSTATUS_ARDY |<br>
+ AM335X_I2C_IRQSTATUS_RDR |<br>
+ AM335X_I2C_IRQSTATUS_RRDY |<br>
+ AM335X_I2C_IRQSTATUS_XDR |<br>
+ AM335X_I2C_IRQSTATUS_XRDY;<br>
+ return true;<br>
}<br>
<br>
- regs = bus->regs;<br>
- REG( &bus->regs->BBB_I2C_BUF ) |= AM335X_I2C_BUF_TXFIFO_CLR;<br>
- REG( &bus->regs->BBB_I2C_BUF ) |= AM335X_I2C_BUF_RXFIFO_CLR;<br>
- am335x_i2c_set_address_size( msgs, regs );<br>
- bus->read = ( msgs->flags & I2C_M_RD ) != 0;<br>
- bus->already_transferred = ( bus->read == true ) ? 0 : 1;<br>
+ if (bus->buffer->flags & I2C_M_RD) {<br>
+ if (status & AM335X_I2C_IRQSTATUS_RDR) {<br>
+ debug_print("RDR\n");<br>
+ /* last data received */<br>
+ amount = bus->buffer->len - bus->buffer_pos;<br>
+ } else if (status & AM335X_I2C_IRQSTATUS_RRDY) {<br>
+ debug_print("RRDY\n");<br>
+ /* FIFO threshold reached */<br>
+ amount = min(FIFO_THRESHOLD, bus->buffer->len - bus->buffer_pos);<br>
+ }<br>
<br>
- if ( bus->read ) {<br>
- if ( bus->current_msg_todo == 1 ) {<br>
- send_stop = true;<br>
+ debug_print("Read %d bytes\n", amount);<br>
+ for (i = 0; i < amount; i++) {<br>
+ bus->buffer->buf[bus->buffer_pos] = (uint8_t)(regs->BBB_I2C_DATA);<br>
+ ++bus->buffer_pos;<br>
}<br>
<br>
- am335x_i2c_setup_read_transfer( bus, regs, msgs, send_stop );<br>
+ if (status & AM335X_I2C_IRQSTATUS_RDR) {<br>
+ regs->BBB_I2C_IRQSTATUS =AM335X_I2C_IRQSTATUS_RDR;<br>
+ }<br>
+ if (status & AM335X_I2C_IRQSTATUS_RRDY) {<br>
+ regs->BBB_I2C_IRQSTATUS =AM335X_I2C_IRQSTATUS_RRDY;<br>
+ }<br>
} else {<br>
- am335x_i2c_setup_write_transfer( bus, regs, msgs );<br>
+ if (status & AM335X_I2C_IRQSTATUS_XDR) {<br>
+ debug_print("XDR\n");<br>
+ /* Remaining TX data won't reach the FIFO threshold. */<br>
+ amount = bus->buffer->len - bus->buffer_pos;<br>
+ } else if (status & AM335X_I2C_IRQSTATUS_XRDY) {<br>
+ debug_print("XRDY\n");<br>
+ /* FIFO threshold reached */<br>
+ amount = min(FIFO_THRESHOLD, bus->buffer->len - bus->buffer_pos);<br>
+ }<br>
+<br>
+ debug_print("Write %d bytes\n", amount);<br>
+ for (i = 0; i < amount; i++) {<br>
+ regs->BBB_I2C_DATA = bus->buffer->buf[bus->buffer_pos];<br>
+ ++bus->buffer_pos;<br>
+ }<br>
+<br>
+ if (status & AM335X_I2C_IRQSTATUS_XDR) {<br>
+ regs->BBB_I2C_IRQSTATUS = AM335X_I2C_IRQSTATUS_XDR;<br>
+ }<br>
+ if (status & AM335X_I2C_IRQSTATUS_XRDY) {<br>
+ regs->BBB_I2C_IRQSTATUS = AM335X_I2C_IRQSTATUS_XRDY;<br>
+ }<br>
}<br>
+<br>
+ return false;<br>
}<br>
<br>
static void am335x_i2c_interrupt( void *arg )<br>
{<br>
- bbb_i2c_bus *bus = arg;<br>
+ bbb_i2c_bus *bus = arg;<br>
volatile bbb_i2c_regs *regs = bus->regs;<br>
- /* Get status of enabled interrupts */<br>
- uint32_t irqstatus = REG( ®s->BBB_I2C_IRQSTATUS );<br>
- bool done = false;<br>
+ uint32_t status;<br>
<br>
- /*<br>
- * Clear all enabled interrupt except receive ready<br>
- * and transmit ready interrupt in status register<br>
- */<br>
- REG( ®s->BBB_I2C_IRQSTATUS ) =<br>
- ( irqstatus & ~( AM335X_I2C_IRQSTATUS_RRDY |<br>
- AM335X_I2C_IRQSTATUS_XRDY ) );<br>
+ status = regs->BBB_I2C_IRQSTATUS;<br>
<br>
- if ( irqstatus & AM335X_I2C_INT_RECV_READY ) {<br>
- am335x_i2c_continue_read_transfer( bus, regs );<br>
- }<br>
-<br>
- if ( irqstatus & AM335X_I2C_IRQSTATUS_XRDY ) {<br>
- am335x_i2c_continue_write( bus, regs );<br>
- }<br>
+ debug_print("interrupt: %08x\n", status);<br>
<br>
- if ( irqstatus & AM335X_I2C_IRQSTATUS_NACK ) {<br>
- done = true;<br>
- am335x_i2c_masterint_disable( regs, AM335X_I2C_IRQSTATUS_NACK );<br>
+ if (status == 0) {<br>
+ /* Why can this even happen? */<br>
+ return;<br>
}<br>
<br>
- if ( irqstatus & AM335X_I2C_IRQSTATUS_ARDY ) {<br>
- done = true;<br>
- REG( ®s->BBB_I2C_IRQSTATUS ) = BBB_I2C_STAT_ARDY;<br>
+ if (bus->buffer == NULL) {<br>
+ debug_print("Buffer is NULL\n");<br>
+ bus->error = EINVAL;<br>
}<br>
<br>
- if ( irqstatus & AM335X_I2C_IRQSTATUS_BF ) {<br>
- REG( ®s->BBB_I2C_IRQSTATUS ) = AM335X_I2C_IRQSTATUS_BF;<br>
- }<br>
-<br>
- if ( done ) {<br>
- uint32_t err = irqstatus & BBB_I2C_IRQ_ERROR;<br>
- am335x_i2c_next_byte( bus );<br>
-<br>
- if ( bus->msg_todo == 0 ) {<br>
- rtems_status_code sc;<br>
- am335x_i2c_masterint_disable( regs, ( AM335X_I2C_IRQSTATUS_RRDY |<br>
- AM335X_I2C_IRQSTATUS_XRDY |<br>
- AM335X_I2C_IRQSTATUS_BF ) );<br>
- REG( ®s->BBB_I2C_IRQSTATUS ) = err;<br>
-<br>
- sc = rtems_event_transient_send( bus->task_id );<br>
- _Assert( sc == RTEMS_SUCCESSFUL );<br>
- (void) sc;<br>
- } else {<br>
- am335x_i2c_setup_transfer( bus, regs );<br>
- }<br>
+ if (bus->buffer == NULL || am335x_i2c_transfer_intr(bus, status)) {<br>
+ rtems_status_code sc;<br>
+ sc = rtems_event_transient_send( bus->task_id );<br>
+ _Assert( sc == RTEMS_SUCCESSFUL );<br>
+ (void) sc; /* suppress warning in case of no assert */<br>
}<br>
}<br>
<br>
static int am335x_i2c_transfer(<br>
i2c_bus *base,<br>
i2c_msg *msgs,<br>
- uint32_t msg_count<br>
+ uint32_t nmsgs<br>
)<br>
{<br>
- rtems_status_code sc;<br>
- bbb_i2c_bus *bus = (bbb_i2c_bus *) base;<br>
- volatile bbb_i2c_regs *regs;<br>
- uint32_t i;<br>
+ size_t i;<br>
+ int err = 0;<br>
+ bool repstart = false;<br>
+ int timeout = 0;<br>
+ bbb_i2c_bus *bus = (bbb_i2c_bus *) base;<br>
+ volatile bbb_i2c_regs *regs = bus->regs;<br>
+ uint32_t reg;<br>
+ rtems_status_code sc;<br>
+<br>
+ bus->task_id = rtems_task_self();<br>
<br>
- rtems_task_wake_after( 1 );<br>
+ for (i = 0; i < nmsgs; i++) {<br>
+ bus->buffer = &msgs[i];<br>
+ bus->buffer_pos = 0;<br>
+ bus->error = 0;<br>
<br>
- if ( msg_count < 1 ) {<br>
- return 1;<br>
- }<br>
+ debug_print("processing %2d/%d: addr: 0x%04x, flags: 0x%04x, len: %d, buf: %p\n",<br>
+ i, nmsgs, msgs[i].addr, msgs[i].flags, msgs[i].len, msgs[i].buf);<br>
<br>
- for ( i = 0; i < msg_count; ++i ) {<br>
- if ( ( msgs[ i ].flags & I2C_M_RECV_LEN ) != 0 ) {<br>
- return -EINVAL;<br>
+ if (bus->buffer == NULL || bus->buffer->buf == NULL ||<br>
+ bus->buffer->len == 0) {<br>
+ err = EINVAL;<br>
+ break;<br>
}<br>
- }<br>
<br>
- bus->msgs = &msgs[ 0 ];<br>
- bus->msg_todo = msg_count;<br>
- bus->current_msg_todo = msgs[ 0 ].len;<br>
- bus->current_msg_byte = msgs[ 0 ].buf;<br>
- bus->task_id = rtems_task_self();<br>
- regs = bus->regs;<br>
- am335x_i2c_setup_transfer( bus, regs );<br>
- REG( ®s->BBB_I2C_IRQENABLE_SET ) = BBB_I2C_IRQ_USED;<br>
+ /*<br>
+ * Send START when bus is busy on repeated starts.<br>
+ * Otherwise wait some time.<br>
+ */<br>
+ if (!repstart) {<br>
+ timeout = 0;<br>
+ while ((regs->BBB_I2C_IRQSTATUS_RAW & AM335X_I2C_IRQSTATUS_BB) != 0<br>
+ && timeout <= TRANSFER_TIMEOUT_COUNT) {<br>
+ ++timeout;<br>
+ rtems_task_wake_after(RTEMS_MICROSECONDS_TO_TICKS(1000));<br>
+ }<br>
+ if (timeout > TRANSFER_TIMEOUT_COUNT) {<br>
+ err = EBUSY;<br>
+ break;<br>
+ }<br>
+ timeout = 0;<br>
+ } else {<br>
+ repstart = false;<br>
+ }<br>
+<br>
+ if ((bus->buffer->flags & I2C_M_STOP) == 0) {<br>
+ repstart = true;<br>
+ }<br>
<br>
- sc = rtems_event_transient_receive( RTEMS_WAIT, bus->base.timeout );<br>
+ regs->BBB_I2C_SA = bus->buffer->addr;<br>
+ regs->BBB_I2C_CNT = bus->buffer->len;<br>
<br>
- if ( sc != RTEMS_SUCCESSFUL ) {<br>
- am335x_i2c_reset( bus );<br>
- rtems_event_transient_clear();<br>
+ regs->BBB_I2C_BUF |= AM335X_I2C_BUF_RXFIFO_CLR | AM335X_I2C_BUF_TXFIFO_CLR;<br>
<br>
- return -ETIMEDOUT;<br>
+ reg = bus->con_reg | AM335X_I2C_CON_START;<br>
+ if (!repstart) {<br>
+ reg |= AM335X_I2C_CON_STOP;<br>
+ }<br>
+ if ((bus->buffer->flags & I2C_M_RD) == 0) {<br>
+ reg |= AM335X_I2C_CON_TRX;<br>
+ }<br>
+ /* Implicit stop on last message. */<br>
+ if (i == nmsgs - 1) {<br>
+ reg |= AM335X_I2C_CON_STOP;<br>
+ }<br>
+ regs->BBB_I2C_CON = reg;<br>
+<br>
+ sc = rtems_event_transient_receive( RTEMS_WAIT, bus->base.timeout );<br>
+ if ( sc != RTEMS_SUCCESSFUL ) {<br>
+ rtems_event_transient_clear();<br>
+ err = ETIMEDOUT;<br>
+ break;<br>
+ }<br>
+ if (bus->error) {<br>
+ err = bus->error;<br>
+ break;<br>
+ }<br>
}<br>
<br>
- return 0;<br>
-}<br>
+ if (timeout == 0) {<br>
+ while ((regs->BBB_I2C_IRQSTATUS_RAW & AM335X_I2C_IRQSTATUS_BB) != 0<br>
+ && timeout <= TRANSFER_TIMEOUT_COUNT) {<br>
+ ++timeout;<br>
+ rtems_task_wake_after(RTEMS_MICROSECONDS_TO_TICKS(1000));<br>
+ }<br>
+ }<br>
<br>
-static int am335x_i2c_set_clock(<br>
- i2c_bus *base,<br>
- unsigned long clock<br>
-)<br>
-{<br>
- bbb_i2c_bus *bus = (bbb_i2c_bus *) base;<br>
- uint32_t prescaler, divider;<br>
+ if ((regs->BBB_I2C_CON & AM335X_I2C_CON_MST) == 0) {<br>
+ regs->BBB_I2C_CON = bus->con_reg;<br>
+ }<br>
<br>
- prescaler = ( BBB_I2C_SYSCLK / BBB_I2C_INTERNAL_CLK ) - 1;<br>
- REG( &bus->regs->BBB_I2C_PSC ) = prescaler;<br>
- divider = BBB_I2C_INTERNAL_CLK / ( 2 * clock );<br>
- REG( &bus->regs->BBB_I2C_SCLL ) = ( divider - 7 );<br>
- REG( &bus->regs->BBB_I2C_SCLH ) = ( divider - 5 );<br>
+ bus->buffer = NULL;<br>
<br>
- return 0;<br>
+ return -err;<br>
}<br>
<br>
static void am335x_i2c_destroy( i2c_bus *base )<br>
@@ -405,6 +445,8 @@ static void am335x_i2c_destroy( i2c_bus *base )<br>
bbb_i2c_bus *bus = (bbb_i2c_bus *) base;<br>
rtems_status_code sc;<br>
<br>
+ bus->regs->BBB_I2C_IRQENABLE_CLR = 0xFFFF;<br>
+ bus->regs->BBB_I2C_CON = 0;<br>
sc = rtems_interrupt_handler_remove( bus->irq, am335x_i2c_interrupt, bus );<br>
_Assert( sc == RTEMS_SUCCESSFUL );<br>
(void) sc;<br>
@@ -422,36 +464,36 @@ int am335x_i2c_bus_register(<br>
rtems_status_code sc;<br>
int err;<br>
<br>
- /* Check bus number is >0 & <MAX */<br>
+ (void) input_clock; /* FIXME: Unused. Left for compatibility. */<br>
+<br>
bus = (bbb_i2c_bus *) i2c_bus_alloc_and_init( sizeof( *bus ) );<br>
<br>
if ( bus == NULL ) {<br>
return -1;<br>
}<br>
<br>
- bus->regs = (volatile bbb_i2c_regs *) register_base;<br>
-<br>
- I2C0ModuleClkConfig();<br>
- am335x_i2c0_pinmux( bus );<br>
- am335x_i2c_reset( bus );<br>
- bus->input_clock = input_clock;<br>
- err = am335x_i2c_set_clock( &bus->base, I2C_BUS_CLOCK_DEFAULT );<br>
+ bus->irq = irq;<br>
<br>
- if ( err != 0 ) {<br>
+ err = am335x_i2c_fill_registers(bus, register_base);<br>
+ if (err != 0) {<br>
( *bus->base.destroy )( &bus->base );<br>
- rtems_set_errno_and_return_minus_one( -err );<br>
+ rtems_set_errno_and_return_minus_one( err );<br>
+ }<br>
+ am335x_i2c_module_clk_enable(bus);<br>
+ am335x_i2c_pinmux( bus );<br>
+ err = am335x_i2c_reset( bus );<br>
+ if (err != 0) {<br>
+ ( *bus->base.destroy )( &bus->base );<br>
+ rtems_set_errno_and_return_minus_one( err );<br>
}<br>
-<br>
- bus->irq = irq;<br>
- REG( &bus->regs->BBB_I2C_IRQSTATUS ) = BBB_I2C_ALL_IRQ_FLAGS;<br>
<br>
sc = rtems_interrupt_handler_install(<br>
- irq,<br>
+ bus->irq,<br>
"BBB_I2C",<br>
RTEMS_INTERRUPT_UNIQUE,<br>
(rtems_interrupt_handler) am335x_i2c_interrupt,<br>
bus<br>
- );<br>
+ );<br>
<br>
if ( sc != RTEMS_SUCCESSFUL ) {<br>
( *bus->base.destroy )( &bus->base );<br>
diff --git a/bsps/arm/beagle/include/bsp/i2c.h b/bsps/arm/beagle/include/bsp/i2c.h<br>
index 3ada3c4b0d..9d253406bf 100644<br>
--- a/bsps/arm/beagle/include/bsp/i2c.h<br>
+++ b/bsps/arm/beagle/include/bsp/i2c.h<br>
@@ -24,76 +24,15 @@<br>
#define LIBBSP_ARM_BEAGLE_I2C_H<br>
<br>
#include <rtems.h><br>
-#include <dev/i2c/i2c.h><br>
#include <bsp.h><br>
+#include <dev/i2c/i2c.h><br>
<br>
#ifdef __cplusplus<br>
extern "C" {<br>
#endif /* __cplusplus */<br>
<br>
-<br>
-/* I2C Configuration Register (I2C_CON): */<br>
-<br>
-#define BBB_I2C_CON_EN (1 << 15) /* I2C module enable */<br>
-#define BBB_I2C_CON_BE (1 << 14) /* Big endian mode */<br>
-#define BBB_I2C_CON_STB (1 << 11) /* Start byte mode (master mode only) */<br>
-#define BBB_I2C_CON_MST (1 << 10) /* Master/slave mode */<br>
-#define BBB_I2C_CON_TRX (1 << 9) /* Transmitter/receiver mode */<br>
- /* (master mode only) */<br>
-#define BBB_I2C_CON_XA (1 << 8) /* Expand address */<br>
-#define BBB_I2C_CON_STP (1 << 1) /* Stop condition (master mode only) */<br>
-#define BBB_I2C_CON_STT (1 << 0) /* Start condition (master mode only) */<br>
-#define BBB_I2C_CON_CLR 0x0 /* Clear configuration register */<br>
-/* I2C Status Register (I2C_STAT): */<br>
-<br>
-#define BBB_I2C_STAT_SBD (1 << 15) /* Single byte data */<br>
-#define BBB_I2C_STAT_BB (1 << 12) /* Bus busy */<br>
-#define BBB_I2C_STAT_ROVR (1 << 11) /* Receive overrun */<br>
-#define BBB_I2C_STAT_XUDF (1 << 10) /* Transmit underflow */<br>
-#define BBB_I2C_STAT_AAS (1 << 9) /* Address as slave */<br>
-#define BBB_I2C_STAT_GC (1 << 5)<br>
-#define BBB_I2C_STAT_XRDY (1 << 4) /* Transmit data ready */<br>
-#define BBB_I2C_STAT_RRDY (1 << 3) /* Receive data ready */<br>
-#define BBB_I2C_STAT_ARDY (1 << 2) /* Register access ready */<br>
-#define BBB_I2C_STAT_NACK (1 << 1) /* No acknowledgment interrupt enable */<br>
-#define BBB_I2C_STAT_AL (1 << 0) /* Arbitration lost interrupt enable */<br>
-<br>
-/* I2C Interrupt Enable Register (I2C_IE): */<br>
-#define BBB_I2C_IE_GC_IE (1 << 5)<br>
-#define BBB_I2C_IE_XRDY_IE (1 << 4) /* Transmit data ready interrupt enable */<br>
-#define BBB_I2C_IE_RRDY_IE (1 << 3) /* Receive data ready interrupt enable */<br>
-#define BBB_I2C_IE_ARDY_IE (1 << 2) /* Register access ready interrupt enable */<br>
-#define BBB_I2C_IE_NACK_IE (1 << 1) /* No acknowledgment interrupt enable */<br>
-#define BBB_I2C_IE_AL_IE (1 << 0) /* Arbitration lost interrupt enable */<br>
-<br>
-/* I2C SYSC Register (I2C_SYSC): */<br>
-#define BBB_I2C_SYSC_SRST (1 << 1)<br>
-<br>
-#define BBB_I2C_TIMEOUT 1000<br>
-<br>
-#define BBB_I2C_SYSS_RDONE (1 << 0) /* Internel reset monitoring */<br>
-<br>
-#define BBB_CONFIG_SYS_I2C_SPEED 100000<br>
-#define BBB_CONFIG_SYS_I2C_SLAVE 1<br>
-#define BBB_I2C_ALL_FLAGS 0x7FFF<br>
-#define BBB_I2C_ALL_IRQ_FLAGS 0xFFFF<br>
-<br>
#define BBB_I2C_SYSCLK 48000000<br>
#define BBB_I2C_INTERNAL_CLK 12000000<br>
-#define BBB_I2C_SPEED_CLK 100000<br>
-<br>
-#define BBB_I2C_IRQ_ERROR \<br>
- ( AM335X_I2C_IRQSTATUS_NACK \<br>
- | AM335X_I2C_IRQSTATUS_ROVR \<br>
- | AM335X_I2C_IRQSTATUS_AL \<br>
- | AM335X_I2C_IRQSTATUS_ARDY \<br>
- | AM335X_I2C_IRQSTATUS_RRDY \<br>
- | AM335X_I2C_IRQSTATUS_XRDY \<br>
- | AM335X_I2C_IRQSTATUS_XUDF )<br>
-<br>
-#define BBB_I2C_IRQ_USED \<br>
- ( AM335X_I2C_IRQSTATUS_ARDY \<br>
- | AM335X_I2C_IRQSTATUS_XRDY )<br>
<br>
#define BBB_I2C_0_BUS_PATH "/dev/i2c-0"<br>
#define BBB_I2C_1_BUS_PATH "/dev/i2c-1"<br>
@@ -103,9 +42,6 @@ extern "C" {<br>
#define BBB_I2C1_IRQ 71<br>
#define BBB_I2C2_IRQ 30<br>
<br>
-#define BBB_MODE2 2<br>
-#define BBB_MODE3 3<br>
-<br>
typedef enum {<br>
I2C0,<br>
I2C1,<br>
@@ -151,26 +87,10 @@ typedef struct i2c_regs {<br>
uint32_t BBB_I2C_SBLOCK;<br>
} bbb_i2c_regs;<br>
<br>
-typedef struct bbb_i2c_bus {<br>
- i2c_bus base;<br>
- volatile bbb_i2c_regs *regs;<br>
- i2c_msg *msgs;<br>
- uint32_t msg_todo;<br>
- uint32_t current_msg_todo;<br>
- uint8_t *current_msg_byte;<br>
- uint32_t current_todo;<br>
- bool read;<br>
- bool hold;<br>
- rtems_id task_id;<br>
- rtems_vector_number irq;<br>
- uint32_t input_clock;<br>
- uint32_t already_transferred;<br>
-} bbb_i2c_bus;<br>
-<br>
int am335x_i2c_bus_register(<br>
const char *bus_path,<br>
uintptr_t register_base,<br>
- uint32_t input_clock,<br>
+ uint32_t input_clock, /* FIXME: Unused. Left for compatibility. */<br>
rtems_vector_number irq<br>
);<br>
<br>
diff --git a/bsps/arm/include/libcpu/am335x.h b/bsps/arm/include/libcpu/am335x.h<br>
index a78cbd028d..b69c822d62 100644<br>
--- a/bsps/arm/include/libcpu/am335x.h<br>
+++ b/bsps/arm/include/libcpu/am335x.h<br>
@@ -664,6 +664,9 @@<br>
#define AM335X_I2C_CON_MST (0x00000400u)<br>
#define AM335X_I2C_CON_STB (0x00000800u)<br>
#define AM335X_I2C_SYSC_AUTOIDLE (0x00000001u)<br>
+#define AM335X_I2C_SYSC_SRST (0x00000002u)<br>
+#define AM335X_I2C_SYSC_ENAWAKEUP (0x00000004u)<br>
+#define AM335X_I2C_SYSS_RDONE (0x00000001u)<br>
<br>
/*I2C0 module clock registers*/<br>
#define AM335X_CM_WKUP_CONTROL_CLKCTRL (0x4)<br>
@@ -686,29 +689,39 @@<br>
#define AM335X_CM_PER_CONTROL_CLKCTRL_IDLEST (0x00030000u)<br>
<br>
<br>
+#define AM335X_I2C_BUF_TXTRSH_SHIFT (0)<br>
+#define AM335X_I2C_BUF_TXTRSH_MASK (0x0000003Fu)<br>
+#define AM335X_I2C_BUF_TXTRSH(X) (((X) << AM335X_I2C_BUF_TXTRSH_SHIFT) \<br>
+ & AM335X_I2C_BUF_TXTRSH_MASK)<br>
+#define AM335X_I2C_BUF_TXFIFO_CLR (0x00000040u)<br>
+#define AM335X_I2C_BUF_RXTRSH_SHIFT (8)<br>
+#define AM335X_I2C_BUF_RXTRSH_MASK (0x00003F00u)<br>
+#define AM335X_I2C_BUF_RXTRSH(X) (((X) << AM335X_I2C_BUF_RXTRSH_SHIFT) \<br>
+ & AM335X_I2C_BUF_RXTRSH_MASK)<br>
+#define AM335X_I2C_BUF_RXFIFO_CLR (0x00004000u)<br>
+<br>
/* I2C status Register */<br>
+#define AM335X_I2C_IRQSTATUS_AL (1 << 0)<br>
#define AM335X_I2C_IRQSTATUS_NACK (1 << 1)<br>
-#define AM335X_I2C_IRQSTATUS_ROVR (1 << 11)<br>
-#define AM335X_I2C_IRQSTATUS_AL (1<<0)<br>
#define AM335X_I2C_IRQSTATUS_ARDY (1 << 2)<br>
#define AM335X_I2C_IRQSTATUS_RRDY (1 << 3)<br>
#define AM335X_I2C_IRQSTATUS_XRDY (1 << 4)<br>
-#define AM335X_I2C_IRQSTATUS_XUDF (1 << 10)<br>
-#define AM335X_I2C_BUF_TXFIFO_CLR (0x00000040u)<br>
-#define AM335X_I2C_BUF_RXFIFO_CLR (0x00004000u)<br>
-#define AM335X_I2C_IRQSTATUS_AAS (1 << 9)<br>
-#define AM335X_I2C_IRQSTATUS_BF (1 << 8)<br>
+#define AM335X_I2C_IRQSTATUS_GC (1 << 5)<br>
#define AM335X_I2C_IRQSTATUS_STC (1 << 6)<br>
-#define AM335X_I2C_IRQSTATUS_GC (1 << 5)<br>
-#define AM335X_I2C_IRQSTATUS_XDR (1 << 14)<br>
-#define AM335X_I2C_IRQSTATUS_RDR (1 << 13)<br>
+#define AM335X_I2C_IRQSTATUS_AERR (1 << 7)<br>
+#define AM335X_I2C_IRQSTATUS_BF (1 << 8)<br>
+#define AM335X_I2C_IRQSTATUS_AAS (1 << 9)<br>
+#define AM335X_I2C_IRQSTATUS_XUDF (1 << 10)<br>
+#define AM335X_I2C_IRQSTATUS_ROVR (1 << 11)<br>
+#define AM335X_I2C_IRQSTATUS_BB (1 << 12)<br>
+#define AM335X_I2C_IRQSTATUS_RDR (1 << 13)<br>
+#define AM335X_I2C_IRQSTATUS_XDR (1 << 14)<br>
<br>
#define AM335X_I2C_INT_RECV_READY AM335X_I2C_IRQSTATUS_RRDY<br>
#define AM335X_I2C_CON_STOP (0x00000002u)<br>
#define AM335X_I2C_CON_START (0x00000001u)<br>
#define AM335X_I2C_CFG_MST_RX AM335X_I2C_CON_MST<br>
#define AM335X_I2C_CFG_MST_TX (AM335X_I2C_CON_TRX | AM335X_I2C_CON_MST)<br>
-#define AM335X_I2C_IRQSTATUS_RAW_BB (0x00001000u)<br>
#define AM335X_CM_PER_OCPWP_L3_CLKSTCTRL_CLKACTIVITY_OCPWP_L4_GCLK (0x00000020u)<br>
#define AM335X_I2C_INT_STOP_CONDITION AM335X_I2C_IRQSTATUS_BF<br>
<br>
-- <br>
2.21.0<br>
<br>
</blockquote></div></div>