/** * @file * * @ingroup arm_beagle * * @brief Support for the BeagleBone Black. */ /** * Copyright (c) 2015 Ketul Shah * * 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 #include #include #include #include #include #include /* 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 */