summaryrefslogblamecommitdiffstats
path: root/bsps/arm/beagle/gpio/bbb-gpio.c
blob: bd081fae5af68e5cb75ce60677ca6fc207e2ea75 (plain) (tree)
















































                                                                  










































































                                                                             
                                                    












                                                   
                                                      




























                                                                          
                                                  





















































                                                                   
                                                   




                                                 
                                                                   











































































































































                                                                             
                                                    

























                                                                  
                                                  






                                
                                                   























                                                          
                      
/**
 * @file
 *
 * @ingroup arm_beagle
 *
 * @brief Support for the BeagleBone Black.
 */

/**
 * Copyright (c) 2015 Ketul Shah <ketulshah1993 at 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.
 */

/* BSP specific function definitions for BeagleBone Black.
 * It is totally beased on Generic GPIO API definition. 
 * For more details related to GPIO API please have a 
 * look at libbbsp/shared/include/gpio.h
 */

#include <bsp/beagleboneblack.h>
#include <bsp/irq-generic.h>
#include <bsp/gpio.h>
#include <bsp/bbb-gpio.h>
#include <libcpu/am335x.h>

#include <assert.h>
#include <stdlib.h>

/* Currently these definitions are for BeagleBone Black board only
 * Later on Beagle-xM board support can be added in this code.
 * After support gets added if condition should be removed
 */
#if IS_AM335X

static const uint32_t gpio_bank_addrs[] = 
  { AM335X_GPIO0_BASE,
  	AM335X_GPIO1_BASE, 
  	AM335X_GPIO2_BASE, 
  	AM335X_GPIO3_BASE };

static const rtems_vector_number gpio_bank_vector[] =
  { AM335X_INT_GPIOINT0A,
  	AM335X_INT_GPIOINT1A,
  	AM335X_INT_GPIOINT2A,
  	AM335X_INT_GPIOINT3A };

/* Get the value of Base Register + Offset */
uint32_t static inline bbb_reg(uint32_t bank, uint32_t reg)
{
  return (gpio_bank_addrs[bank] + reg);
}

static rtems_status_code bbb_select_pin_function(
  uint32_t bank,
  uint32_t pin,
  uint32_t type
) {

  if ( type == BBB_DIGITAL_IN ) {
    mmio_set(bbb_reg(bank, AM335X_GPIO_OE), BIT(pin));
  } else {
    mmio_clear(bbb_reg(bank, AM335X_GPIO_OE), BIT(pin));
  }

  return RTEMS_SUCCESSFUL;
}

rtems_status_code rtems_gpio_bsp_multi_set(uint32_t bank, uint32_t bitmask)
{
  mmio_set(bbb_reg(bank, AM335X_GPIO_SETDATAOUT), bitmask);

  return RTEMS_SUCCESSFUL;
}

rtems_status_code rtems_gpio_bsp_multi_clear(uint32_t bank, uint32_t bitmask)
{
  mmio_set(bbb_reg(bank, AM335X_GPIO_CLEARDATAOUT), bitmask);

  return RTEMS_SUCCESSFUL;
}

uint32_t rtems_gpio_bsp_multi_read(uint32_t bank, uint32_t bitmask)
{
  return (bbb_reg(bank, AM335X_GPIO_DATAIN) & bitmask);
}

rtems_status_code rtems_gpio_bsp_set(uint32_t bank, uint32_t pin)
{
  mmio_set(bbb_reg(bank, AM335X_GPIO_SETDATAOUT), BIT(pin));

  return RTEMS_SUCCESSFUL;
}

rtems_status_code rtems_gpio_bsp_clear(uint32_t bank, uint32_t pin)
{
  mmio_set(bbb_reg(bank, AM335X_GPIO_CLEARDATAOUT), BIT(pin));

  return RTEMS_SUCCESSFUL;
}

uint32_t rtems_gpio_bsp_get_value(uint32_t bank, uint32_t pin)
{
  return (mmio_read(bbb_reg(bank, AM335X_GPIO_DATAIN)) & BIT(pin));
}

rtems_status_code rtems_gpio_bsp_select_input(
  uint32_t bank,
  uint32_t pin,
  void *bsp_specific
) {
  return bbb_select_pin_function(bank, pin, BBB_DIGITAL_IN);
}

rtems_status_code rtems_gpio_bsp_select_output(
  uint32_t bank,
  uint32_t pin,
  void *bsp_specific
) {
  return bbb_select_pin_function(bank, pin, BBB_DIGITAL_OUT);
}

rtems_status_code rtems_gpio_bsp_select_specific_io(
  uint32_t bank,
  uint32_t pin,
  uint32_t function,
  void *pin_data
) {
  return RTEMS_NOT_DEFINED;
}

rtems_status_code rtems_gpio_bsp_set_resistor_mode(
  uint32_t bank,
  uint32_t pin,
  rtems_gpio_pull_mode mode
) {
  /* TODO: Add support for setting up resistor mode */
  return RTEMS_NOT_DEFINED;
}

rtems_vector_number rtems_gpio_bsp_get_vector(uint32_t bank)
{
  return gpio_bank_vector[bank];
}

uint32_t rtems_gpio_bsp_interrupt_line(rtems_vector_number vector)
{
  uint32_t event_status;
  uint8_t bank_nr = 0;

  /* Following loop will get the bank number from vector number */
  while (bank_nr < GPIO_BANK_COUNT && vector != gpio_bank_vector[bank_nr])
  {
  	bank_nr++;
  }

  /* Retrieve the interrupt event status. */
  event_status = mmio_read(bbb_reg(bank_nr, AM335X_GPIO_IRQSTATUS_0));

  /* Clear the interrupt line. */
  mmio_write(
    (bbb_reg(bank_nr, AM335X_GPIO_IRQSTATUS_0)), event_status);
  
  return event_status;
}

rtems_status_code rtems_gpio_bsp_enable_interrupt(
  uint32_t bank,
  uint32_t pin,
  rtems_gpio_interrupt interrupt
) {
  
  /* Enable IRQ generation for the specific pin */
  mmio_set(bbb_reg(bank, AM335X_GPIO_IRQSTATUS_SET_0), BIT(pin));
  
  switch ( interrupt ) {
    case FALLING_EDGE:
      /* Enables asynchronous falling edge detection. */
      mmio_set(bbb_reg(bank, AM335X_GPIO_FALLINGDETECT), BIT(pin));
      break;
    case RISING_EDGE:
      /* Enables asynchronous rising edge detection. */
      mmio_set(bbb_reg(bank, AM335X_GPIO_RISINGDETECT), BIT(pin));
      break;
    case BOTH_EDGES:
      /* Enables asynchronous falling edge detection. */
      mmio_set(bbb_reg(bank, AM335X_GPIO_FALLINGDETECT), BIT(pin));

      /* Enables asynchronous rising edge detection. */
      mmio_set(bbb_reg(bank, AM335X_GPIO_RISINGDETECT), BIT(pin));
      break;
    case LOW_LEVEL:
      /* Enables pin low level detection. */
      mmio_set(bbb_reg(bank, AM335X_GPIO_LEVELDETECT0), BIT(pin));
      break;
    case HIGH_LEVEL:
       /* Enables pin high level detection. */
      mmio_set(bbb_reg(bank, AM335X_GPIO_LEVELDETECT1), BIT(pin));
      break;
    case BOTH_LEVELS:
      /* Enables pin low level detection. */
      mmio_set(bbb_reg(bank, AM335X_GPIO_LEVELDETECT0), BIT(pin));

      /* Enables pin high level detection. */
      mmio_set(bbb_reg(bank, AM335X_GPIO_LEVELDETECT1), BIT(pin));
      break;
    case NONE:
    default:
      return RTEMS_UNSATISFIED;
  }

  /* The detection starts after 5 clock cycles as per AM335X TRM
   * This period is required to clean the synchronization edge/
   * level detection pipeline
   */
  asm volatile("nop"); asm volatile("nop"); asm volatile("nop");
  asm volatile("nop"); asm volatile("nop");
  
  return RTEMS_SUCCESSFUL;
}

rtems_status_code rtems_gpio_bsp_disable_interrupt(
  uint32_t bank,
  uint32_t pin,
  rtems_gpio_interrupt interrupt
) {
  /* Clear IRQ generation for the specific pin */
  mmio_write(bbb_reg(bank, AM335X_GPIO_IRQSTATUS_CLR_0), BIT(pin));

  switch ( interrupt ) {
    case FALLING_EDGE:
      /* Disables asynchronous falling edge detection. */
      mmio_clear(bbb_reg(bank, AM335X_GPIO_FALLINGDETECT), BIT(pin));
      break;
    case RISING_EDGE:
      /* Disables asynchronous rising edge detection. */
      mmio_clear(bbb_reg(bank, AM335X_GPIO_RISINGDETECT), BIT(pin));
      break;
    case BOTH_EDGES:
      /* Disables asynchronous falling edge detection. */
      mmio_clear(bbb_reg(bank, AM335X_GPIO_FALLINGDETECT), BIT(pin));

      /* Disables asynchronous rising edge detection. */
      mmio_clear(bbb_reg(bank, AM335X_GPIO_RISINGDETECT), BIT(pin));
      break;
    case LOW_LEVEL:
      /* Disables pin low level detection. */
      mmio_clear(bbb_reg(bank, AM335X_GPIO_LEVELDETECT0), BIT(pin));
      break;
    case HIGH_LEVEL:
      /* Disables pin high level detection. */
       mmio_clear(bbb_reg(bank, AM335X_GPIO_LEVELDETECT1), BIT(pin));
      break;
    case BOTH_LEVELS:
      /* Disables pin low level detection. */
      mmio_clear(bbb_reg(bank, AM335X_GPIO_LEVELDETECT0), BIT(pin));

      /* Disables pin high level detection. */
      mmio_clear(bbb_reg(bank, AM335X_GPIO_LEVELDETECT1), BIT(pin));
      break;
    case NONE:
    default:
      return RTEMS_UNSATISFIED;
  }

  /* The detection starts after 5 clock cycles as per AM335X TRM
   * This period is required to clean the synchronization edge/
   * level detection pipeline
   */
  asm volatile("nop"); asm volatile("nop"); asm volatile("nop");
  asm volatile("nop"); asm volatile("nop");

  return RTEMS_SUCCESSFUL;
}

rtems_status_code rtems_gpio_bsp_multi_select(
  rtems_gpio_multiple_pin_select *pins,
  uint32_t pin_count,
  uint32_t select_bank
) {
  uint32_t register_address;
  uint32_t select_register;
  uint8_t i;

  register_address = gpio_bank_addrs[select_bank] + AM335X_GPIO_OE;

  select_register = REG(register_address);

  for ( i = 0; i < pin_count; ++i ) {
    if ( pins[i].function == DIGITAL_INPUT ) {
      select_register |= BIT(pins[i].pin_number);
    } else if ( pins[i].function == DIGITAL_OUTPUT ) {
      select_register &= ~BIT(pins[i].pin_number);
    } else { /* BSP_SPECIFIC function. */
      return RTEMS_NOT_DEFINED;
    }
  }

  REG(register_address) = select_register;

  return RTEMS_SUCCESSFUL;
}

rtems_status_code rtems_gpio_bsp_specific_group_operation(
  uint32_t bank,
  uint32_t *pins,
  uint32_t pin_count,
  void *arg
) {
  return RTEMS_NOT_DEFINED;
}

#endif /* IS_AM335X */

/* For support of BeagleboardxM */
#if IS_DM3730

/* Currently this section is just to satisfy
 * GPIO API and to make the build successful.
 * Later on support can be added here.
 */

rtems_status_code rtems_gpio_bsp_multi_set(uint32_t bank, uint32_t bitmask)
{
  return RTEMS_NOT_DEFINED;
}

rtems_status_code rtems_gpio_bsp_multi_clear(uint32_t bank, uint32_t bitmask)
{
  return RTEMS_NOT_DEFINED;
}

uint32_t rtems_gpio_bsp_multi_read(uint32_t bank, uint32_t bitmask)
{
  return -1;
}

rtems_status_code rtems_gpio_bsp_set(uint32_t bank, uint32_t pin)
{
  return RTEMS_NOT_DEFINED;
}

rtems_status_code rtems_gpio_bsp_clear(uint32_t bank, uint32_t pin)
{
  return RTEMS_NOT_DEFINED;
}

uint32_t rtems_gpio_bsp_get_value(uint32_t bank, uint32_t pin)
{
  return -1;
}

rtems_status_code rtems_gpio_bsp_select_input(
  uint32_t bank,
  uint32_t pin,
  void *bsp_specific
) {
  return RTEMS_NOT_DEFINED;
}

rtems_status_code rtems_gpio_bsp_select_output(
  uint32_t bank,
  uint32_t pin,
  void *bsp_specific
) {
  return RTEMS_NOT_DEFINED;
}

rtems_status_code rtems_gpio_bsp_select_specific_io(
  uint32_t bank,
  uint32_t pin,
  uint32_t function,
  void *pin_data
) {
  return RTEMS_NOT_DEFINED;
}

rtems_status_code rtems_gpio_bsp_set_resistor_mode(
  uint32_t bank,
  uint32_t pin,
  rtems_gpio_pull_mode mode
) {
  return RTEMS_NOT_DEFINED;
}

rtems_vector_number rtems_gpio_bsp_get_vector(uint32_t bank)
{
  return -1;
}

uint32_t rtems_gpio_bsp_interrupt_line(rtems_vector_number vector)
{
  return -1;
}

rtems_status_code rtems_gpio_bsp_enable_interrupt(
  uint32_t bank,
  uint32_t pin,
  rtems_gpio_interrupt interrupt
) {
  return RTEMS_NOT_DEFINED;
}

rtems_status_code rtems_gpio_bsp_disable_interrupt(
  uint32_t bank,
  uint32_t pin,
  rtems_gpio_interrupt interrupt
) {
  return RTEMS_NOT_DEFINED;
}

rtems_status_code rtems_gpio_bsp_multi_select(
  rtems_gpio_multiple_pin_select *pins,
  uint32_t pin_count,
  uint32_t select_bank
) {
  return RTEMS_NOT_DEFINED;
}

rtems_status_code rtems_gpio_bsp_specific_group_operation(
  uint32_t bank,
  uint32_t *pins,
  uint32_t pin_count,
  void *arg
) {
  return RTEMS_NOT_DEFINED;
}

#endif /* IS_DM3730 */