diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-04-23 09:45:28 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-04-23 15:18:43 +0200 |
commit | a2dad96ab736f66ed54421cad53caf31f250e181 (patch) | |
tree | 1935320b5b52276ed2e52741cdae71637f209f77 /c/src/lib/libbsp/arm/beagle | |
parent | bsps/arm: Remove unused stm32f* files (diff) | |
download | rtems-a2dad96ab736f66ed54421cad53caf31f250e181.tar.bz2 |
bsps: Move I2C drivers to bsps
This patch is a part of the BSP source reorganization.
Update #3285.
Diffstat (limited to 'c/src/lib/libbsp/arm/beagle')
-rw-r--r-- | c/src/lib/libbsp/arm/beagle/Makefile.am | 2 | ||||
-rw-r--r-- | c/src/lib/libbsp/arm/beagle/i2c/bbb-i2c.c | 466 |
2 files changed, 1 insertions, 467 deletions
diff --git a/c/src/lib/libbsp/arm/beagle/Makefile.am b/c/src/lib/libbsp/arm/beagle/Makefile.am index 9da9278220..72a80b0b35 100644 --- a/c/src/lib/libbsp/arm/beagle/Makefile.am +++ b/c/src/lib/libbsp/arm/beagle/Makefile.am @@ -68,7 +68,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/serial/legacy-console librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/beagle/console/console-config.c # I2C -librtemsbsp_a_SOURCES += i2c/bbb-i2c.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/beagle/i2c/bbb-i2c.c # GPIO librtemsbsp_a_SOURCES += gpio/bbb-gpio.c diff --git a/c/src/lib/libbsp/arm/beagle/i2c/bbb-i2c.c b/c/src/lib/libbsp/arm/beagle/i2c/bbb-i2c.c deleted file mode 100644 index 3a8637d457..0000000000 --- a/c/src/lib/libbsp/arm/beagle/i2c/bbb-i2c.c +++ /dev/null @@ -1,466 +0,0 @@ -/** - * @file - * - * @ingroup arm_beagle - * - * @brief BeagleBoard I2C bus initialization and API Support. - */ - -/* - * Copyright (c) 2016 Punit Vara <punitvara@gmail.com> - * Copyright (c) 2017 Sichen Zhao <zsc19940506@gmail.com> - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -/* - * Modified on Punit Vara<punitvara@gmail.com> works, currently - * the i2c file is working on the Beaglebone Black board(AM335x) - */ - -#include <stdio.h> -#include <bsp/i2c.h> -#include <libcpu/am335x.h> -#include <rtems/irq-extension.h> -#include <rtems/counter.h> -#include <bsp/bbb-gpio.h> -#include <rtems/score/assert.h> - -static void am335x_i2c0_pinmux( bbb_i2c_bus *bus ) -{ - REG( bus->regs + AM335X_CONF_I2C0_SDA ) = - ( BBB_RXACTIVE | BBB_SLEWCTRL | BBB_PU_EN ); - - REG( bus->regs + AM335X_CONF_I2C0_SCL ) = - ( BBB_RXACTIVE | BBB_SLEWCTRL | BBB_PU_EN ); -} - -static void I2C0ModuleClkConfig( void ) -{ - /* Writing to MODULEMODE field of AM335X_CM_WKUP_I2C0_CLKCTRL register. */ - REG( AM335X_SOC_CM_WKUP_REGS + AM335X_CM_WKUP_I2C0_CLKCTRL ) |= - AM335X_CM_WKUP_I2C0_CLKCTRL_MODULEMODE_ENABLE; - - /* Waiting for MODULEMODE field to reflect the written value. */ - while ( AM335X_CM_WKUP_I2C0_CLKCTRL_MODULEMODE_ENABLE != - ( REG( AM335X_SOC_CM_WKUP_REGS + AM335X_CM_WKUP_I2C0_CLKCTRL ) & - AM335X_CM_WKUP_I2C0_CLKCTRL_MODULEMODE ) ) ; - - /* - * Waiting for IDLEST field in AM335X_CM_WKUP_CONTROL_CLKCTRL - * register to attain desired value. - */ - while ( ( AM335X_CM_WKUP_CONTROL_CLKCTRL_IDLEST_FUNC << - AM335X_CM_WKUP_CONTROL_CLKCTRL_IDLEST_SHIFT ) != - ( REG( AM335X_SOC_CM_WKUP_REGS + AM335X_CM_WKUP_CONTROL_CLKCTRL ) & - AM335X_CM_WKUP_CONTROL_CLKCTRL_IDLEST ) ) ; - - /* - * Waiting for CLKACTIVITY_I2C0_GFCLK field in AM335X_CM_WKUP_CLKSTCTRL - * register to attain desired value. - */ - while ( AM335X_CM_WKUP_CLKSTCTRL_CLKACTIVITY_I2C0_GFCLK != - ( REG( AM335X_SOC_CM_WKUP_REGS + AM335X_CM_WKUP_CLKSTCTRL ) & - AM335X_CM_WKUP_CLKSTCTRL_CLKACTIVITY_I2C0_GFCLK ) ) ; - - /* - * Waiting for IDLEST field in AM335X_CM_WKUP_I2C0_CLKCTRL register to attain - * desired value. - */ - while ( ( AM335X_CM_WKUP_I2C0_CLKCTRL_IDLEST_FUNC << - AM335X_CM_WKUP_I2C0_CLKCTRL_IDLEST_SHIFT ) != - ( REG( AM335X_SOC_CM_WKUP_REGS + AM335X_CM_WKUP_I2C0_CLKCTRL ) & - AM335X_CM_WKUP_I2C0_CLKCTRL_IDLEST ) ) ; -} - -static void am335x_i2c_reset( bbb_i2c_bus *bus ) -{ - volatile bbb_i2c_regs *regs = bus->regs; - int timeout = I2C_TIMEOUT; - - if ( REG( ®s->BBB_I2C_CON ) & BBB_I2C_CON_EN ) { - REG( ®s->BBB_I2C_CON ) = BBB_I2C_CON_CLR; - udelay( 50000 ); - } - - REG( ®s->BBB_I2C_SYSC ) = BBB_I2C_SYSC_SRST; /* for ES2 after soft reset */ - udelay( 1000 ); - REG( ®s->BBB_I2C_CON ) = BBB_I2C_CON_EN; - - while ( !( REG( ®s->BBB_I2C_SYSS ) & BBB_I2C_SYSS_RDONE ) && timeout-- ) { - if ( timeout <= 0 ) { - puts( "ERROR: Timeout in soft-reset\n" ); - - return; - } - - udelay( 1000 ); - } -} -/* - * Possible values for msg->flag - * - @ref I2C_M_TEN, - * - @ref I2C_M_RD, - * - @ref I2C_M_STOP, - * - @ref I2C_M_NOSTART, - * - @ref I2C_M_REV_DIR_ADDR, - * - @ref I2C_M_IGNORE_NAK, - * - @ref I2C_M_NO_RD_ACK, and - * - @ref I2C_M_RECV_LEN. - */ - -static void am335x_i2c_set_address_size( - const i2c_msg *msgs, - volatile bbb_i2c_regs *regs -) -{ - /* - * Can be configured multiple modes here. - * Need to think about own address modes - */ - if ( ( msgs->flags & I2C_M_TEN ) == 0 ) { - /* 7-bit mode slave address mode */ - REG( ®s->BBB_I2C_CON ) = AM335X_I2C_CFG_7BIT_SLAVE_ADDR; - } else { - /* 10-bit slave address mode */ - REG( ®s->BBB_I2C_CON ) = AM335X_I2C_CFG_10BIT_SLAVE_ADDR; - } -} - -static void am335x_i2c_next_byte( bbb_i2c_bus *bus ) -{ - i2c_msg *msg; - - ++bus->msgs; - --bus->msg_todo; - msg = &bus->msgs[ 0 ]; - bus->current_msg_todo = msg->len; - bus->current_msg_byte = msg->buf; -} - -static void am335x_i2c_masterint_enable( - volatile bbb_i2c_regs *regs, - unsigned int flag -) -{ - REG( ®s->BBB_I2C_IRQENABLE_SET ) |= flag; -} - -static void am335x_i2c_masterint_disable( - volatile bbb_i2c_regs *regs, - unsigned int flag -) -{ - REG( ®s->BBB_I2C_IRQENABLE_CLR ) = flag; -} - -static void am335x_int_clear( - volatile bbb_i2c_regs *regs, - unsigned int flag -) -{ - REG( ®s->BBB_I2C_IRQSTATUS ) = flag; -} - -static void am335x_clean_interrupts( volatile bbb_i2c_regs *regs ) -{ - am335x_i2c_masterint_enable( regs, BBB_I2C_ALL_FLAGS ); - am335x_int_clear( regs, BBB_I2C_ALL_FLAGS ); - am335x_i2c_masterint_disable( regs, BBB_I2C_ALL_FLAGS ); -} - -static void am335x_i2c_setup_read_transfer( - bbb_i2c_bus *bus, - volatile bbb_i2c_regs *regs, - const i2c_msg *msgs, - bool send_stop -) -{ - REG( ®s->BBB_I2C_CNT ) = bus->current_msg_todo; - - REG( ®s->BBB_I2C_CON ) = AM335X_I2C_CFG_MST_RX | AM335X_I2C_CON_I2C_EN; - - if ( send_stop ) { - REG( ®s->BBB_I2C_CON ) |= AM335X_I2C_CON_START | AM335X_I2C_CON_STOP; - } else { - REG( ®s->BBB_I2C_CON ) |= AM335X_I2C_CON_START; - } - - am335x_i2c_masterint_enable( regs, AM335X_I2C_INT_RECV_READY | - AM335X_I2C_IRQSTATUS_ARDY ); -} - -static void am335x_i2c_continue_read_transfer( - bbb_i2c_bus *bus, - volatile bbb_i2c_regs *regs -) -{ - bus->current_msg_byte[ bus->already_transferred ] = - REG( ®s->BBB_I2C_DATA ); - - bus->already_transferred++; - - REG( ®s->BBB_I2C_IRQSTATUS ) = AM335X_I2C_INT_RECV_READY; - - if ( bus->already_transferred == bus->current_msg_todo - 1 ) { - REG( ®s->BBB_I2C_CON ) |= AM335X_I2C_CON_STOP; - } -} - -static void am335x_i2c_continue_write( - bbb_i2c_bus *bus, - volatile bbb_i2c_regs *regs -) -{ - if ( bus->already_transferred == bus->msg_todo ) { - REG( ®s->BBB_I2C_DATA ) = - bus->current_msg_byte[ bus->already_transferred ]; - REG( ®s->BBB_I2C_IRQSTATUS ) = AM335X_I2C_IRQSTATUS_XRDY; - am335x_i2c_masterint_disable( regs, AM335X_I2C_IRQSTATUS_XRDY ); - REG( ®s->BBB_I2C_CON ) |= AM335X_I2C_CON_STOP; - } else { - writeb( bus->current_msg_byte[ bus->already_transferred ], - ®s->BBB_I2C_DATA ); - REG( ®s->BBB_I2C_IRQSTATUS ) = AM335X_I2C_IRQSTATUS_XRDY; - bus->already_transferred++; - } -} - -static void am335x_i2c_setup_write_transfer( - bbb_i2c_bus *bus, - volatile bbb_i2c_regs *regs, - const i2c_msg *msgs -) -{ - volatile unsigned int no_bytes; - - REG( ®s->BBB_I2C_CNT ) = bus->current_msg_todo; - no_bytes = REG( ®s->BBB_I2C_CNT ); - (void) no_bytes; /* indicate we know that no_bytes is not referenced again */ - REG( ®s->BBB_I2C_SA ) = msgs->addr; - REG( ®s->BBB_I2C_CON ) = AM335X_I2C_CFG_MST_TX | AM335X_I2C_CON_I2C_EN; - am335x_clean_interrupts( regs ); - am335x_i2c_masterint_enable( regs, AM335X_I2C_IRQSTATUS_XRDY ); - REG( ®s->BBB_I2C_CON ) |= AM335X_I2C_CON_START | AM335X_I2C_CON_STOP; -} - -static void am335x_i2c_setup_transfer( - bbb_i2c_bus *bus, - volatile bbb_i2c_regs *regs -) -{ - const i2c_msg *msgs = bus->msgs; - uint32_t msg_todo = bus->msg_todo; - bool send_stop = false; - uint32_t i; - - bus->current_todo = msgs[ 0 ].len; - - for ( i = 1; i < msg_todo && ( msgs[ i ].flags & I2C_M_NOSTART ) != 0; - ++i ) { - bus->current_todo += msgs[ i ].len; - } - - regs = bus->regs; - REG( &bus->regs->BBB_I2C_BUF ) |= AM335X_I2C_BUF_TXFIFO_CLR; - REG( &bus->regs->BBB_I2C_BUF ) |= AM335X_I2C_BUF_RXFIFO_CLR; - am335x_i2c_set_address_size( msgs, regs ); - bus->read = ( msgs->flags & I2C_M_RD ) != 0; - bus->already_transferred = ( bus->read == true ) ? 0 : 1; - - if ( bus->read ) { - if ( bus->current_msg_todo == 1 ) { - send_stop = true; - } - - am335x_i2c_setup_read_transfer( bus, regs, msgs, send_stop ); - } else { - am335x_i2c_setup_write_transfer( bus, regs, msgs ); - } -} - -static void am335x_i2c_interrupt( void *arg ) -{ - bbb_i2c_bus *bus = arg; - volatile bbb_i2c_regs *regs = bus->regs; - /* Get status of enabled interrupts */ - uint32_t irqstatus = REG( ®s->BBB_I2C_IRQSTATUS ); - bool done = false; - - /* - * Clear all enabled interrupt except receive ready - * and transmit ready interrupt in status register - */ - REG( ®s->BBB_I2C_IRQSTATUS ) = - ( irqstatus & ~( AM335X_I2C_IRQSTATUS_RRDY | - AM335X_I2C_IRQSTATUS_XRDY ) ); - - if ( irqstatus & AM335X_I2C_INT_RECV_READY ) { - am335x_i2c_continue_read_transfer( bus, regs ); - } - - if ( irqstatus & AM335X_I2C_IRQSTATUS_XRDY ) { - am335x_i2c_continue_write( bus, regs ); - } - - if ( irqstatus & AM335X_I2C_IRQSTATUS_NACK ) { - done = true; - am335x_i2c_masterint_disable( regs, AM335X_I2C_IRQSTATUS_NACK ); - } - - if ( irqstatus & AM335X_I2C_IRQSTATUS_ARDY ) { - done = true; - REG( ®s->BBB_I2C_IRQSTATUS ) = BBB_I2C_STAT_ARDY; - } - - if ( irqstatus & AM335X_I2C_IRQSTATUS_BF ) { - REG( ®s->BBB_I2C_IRQSTATUS ) = AM335X_I2C_IRQSTATUS_BF; - } - - if ( done ) { - uint32_t err = irqstatus & BBB_I2C_IRQ_ERROR; - am335x_i2c_next_byte( bus ); - - if ( bus->msg_todo == 0 ) { - rtems_status_code sc; - am335x_i2c_masterint_disable( regs, ( AM335X_I2C_IRQSTATUS_RRDY | - AM335X_I2C_IRQSTATUS_XRDY | - AM335X_I2C_IRQSTATUS_BF ) ); - REG( ®s->BBB_I2C_IRQSTATUS ) = err; - - sc = rtems_event_transient_send( bus->task_id ); - _Assert( sc == RTEMS_SUCCESSFUL ); - (void) sc; - } else { - am335x_i2c_setup_transfer( bus, regs ); - } - } -} - -static int am335x_i2c_transfer( - i2c_bus *base, - i2c_msg *msgs, - uint32_t msg_count -) -{ - rtems_status_code sc; - bbb_i2c_bus *bus = (bbb_i2c_bus *) base; - volatile bbb_i2c_regs *regs; - uint32_t i; - - rtems_task_wake_after( 1 ); - - if ( msg_count < 1 ) { - return 1; - } - - for ( i = 0; i < msg_count; ++i ) { - if ( ( msgs[ i ].flags & I2C_M_RECV_LEN ) != 0 ) { - return -EINVAL; - } - } - - bus->msgs = &msgs[ 0 ]; - bus->msg_todo = msg_count; - bus->current_msg_todo = msgs[ 0 ].len; - bus->current_msg_byte = msgs[ 0 ].buf; - bus->task_id = rtems_task_self(); - regs = bus->regs; - am335x_i2c_setup_transfer( bus, regs ); - REG( ®s->BBB_I2C_IRQENABLE_SET ) = BBB_I2C_IRQ_USED; - - sc = rtems_event_transient_receive( RTEMS_WAIT, bus->base.timeout ); - - if ( sc != RTEMS_SUCCESSFUL ) { - am335x_i2c_reset( bus ); - rtems_event_transient_clear(); - - return -ETIMEDOUT; - } - - return 0; -} - -static int am335x_i2c_set_clock( - i2c_bus *base, - unsigned long clock -) -{ - bbb_i2c_bus *bus = (bbb_i2c_bus *) base; - uint32_t prescaler, divider; - - prescaler = ( BBB_I2C_SYSCLK / BBB_I2C_INTERNAL_CLK ) - 1; - REG( &bus->regs->BBB_I2C_PSC ) = prescaler; - divider = BBB_I2C_INTERNAL_CLK / ( 2 * clock ); - REG( &bus->regs->BBB_I2C_SCLL ) = ( divider - 7 ); - REG( &bus->regs->BBB_I2C_SCLH ) = ( divider - 5 ); - - return 0; -} - -static void am335x_i2c_destroy( i2c_bus *base ) -{ - bbb_i2c_bus *bus = (bbb_i2c_bus *) base; - rtems_status_code sc; - - sc = rtems_interrupt_handler_remove( bus->irq, am335x_i2c_interrupt, bus ); - _Assert( sc == RTEMS_SUCCESSFUL ); - (void) sc; - i2c_bus_destroy_and_free( &bus->base ); -} - -int am335x_i2c_bus_register( - const char *bus_path, - uintptr_t register_base, - uint32_t input_clock, - rtems_vector_number irq -) -{ - bbb_i2c_bus *bus; - rtems_status_code sc; - int err; - - /* Check bus number is >0 & <MAX */ - bus = (bbb_i2c_bus *) i2c_bus_alloc_and_init( sizeof( *bus ) ); - - if ( bus == NULL ) { - return -1; - } - - bus->regs = (volatile bbb_i2c_regs *) register_base; - - I2C0ModuleClkConfig(); - am335x_i2c0_pinmux( bus ); - am335x_i2c_reset( bus ); - bus->input_clock = input_clock; - err = am335x_i2c_set_clock( &bus->base, I2C_BUS_CLOCK_DEFAULT ); - - if ( err != 0 ) { - ( *bus->base.destroy )( &bus->base ); - rtems_set_errno_and_return_minus_one( -err ); - } - - bus->irq = irq; - REG( &bus->regs->BBB_I2C_IRQSTATUS ) = BBB_I2C_ALL_IRQ_FLAGS; - - sc = rtems_interrupt_handler_install( - irq, - "BBB_I2C", - RTEMS_INTERRUPT_UNIQUE, - (rtems_interrupt_handler) am335x_i2c_interrupt, - bus - ); - - if ( sc != RTEMS_SUCCESSFUL ) { - ( *bus->base.destroy )( &bus->base ); - rtems_set_errno_and_return_minus_one( EIO ); - } - - bus->base.transfer = am335x_i2c_transfer; - bus->base.set_clock = am335x_i2c_set_clock; - bus->base.destroy = am335x_i2c_destroy; - - return i2c_bus_register( &bus->base, bus_path ); -} |