summaryrefslogtreecommitdiffstats
path: root/bsps
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2018-04-25 10:50:12 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2018-04-25 14:31:33 +0200
commit531d160672f2829350138a8ac990de7d78c01ddf (patch)
treed01ff5254642d98b1a8788d3ef559582d9af2943 /bsps
parentbsp/gumstix: Move fb.c to bsps (diff)
downloadrtems-531d160672f2829350138a8ac990de7d78c01ddf.tar.bz2
bsp/beagle: Move source files to bsps
This patch is a part of the BSP source reorganization. Update #3285.
Diffstat (limited to 'bsps')
-rw-r--r--bsps/arm/beagle/clock/clock.c323
-rw-r--r--bsps/arm/beagle/gpio/bbb-gpio.c564
-rw-r--r--bsps/arm/beagle/pwm/pwm.c454
-rw-r--r--bsps/arm/beagle/rtc/rtc.c276
4 files changed, 1617 insertions, 0 deletions
diff --git a/bsps/arm/beagle/clock/clock.c b/bsps/arm/beagle/clock/clock.c
new file mode 100644
index 0000000000..d8b2062e80
--- /dev/null
+++ b/bsps/arm/beagle/clock/clock.c
@@ -0,0 +1,323 @@
+/**
+ * @file
+ *
+ * @ingroup arm_beagle
+ *
+ * @brief Clock driver configuration.
+ */
+
+/*
+ * Copyright (c) 2014 Ben Gras <beng@shrike-systems.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.
+ */
+
+#include <rtems.h>
+#include <rtems/timecounter.h>
+#include <bsp.h>
+
+#include <libcpu/omap_timer.h>
+
+static struct timecounter beagle_clock_tc;
+
+static omap_timer_registers_t regs_v1 = {
+ .TIDR = OMAP3_TIMER_TIDR,
+ .TIOCP_CFG = OMAP3_TIMER_TIOCP_CFG,
+ .TISTAT = OMAP3_TIMER_TISTAT,
+ .TISR = OMAP3_TIMER_TISR,
+ .TIER = OMAP3_TIMER_TIER,
+ .TWER = OMAP3_TIMER_TWER,
+ .TCLR = OMAP3_TIMER_TCLR,
+ .TCRR = OMAP3_TIMER_TCRR,
+ .TLDR = OMAP3_TIMER_TLDR,
+ .TTGR = OMAP3_TIMER_TTGR,
+ .TWPS = OMAP3_TIMER_TWPS,
+ .TMAR = OMAP3_TIMER_TMAR,
+ .TCAR1 = OMAP3_TIMER_TCAR1,
+ .TSICR = OMAP3_TIMER_TSICR,
+ .TCAR2 = OMAP3_TIMER_TCAR2,
+ .TPIR = OMAP3_TIMER_TPIR,
+ .TNIR = OMAP3_TIMER_TNIR,
+ .TCVR = OMAP3_TIMER_TCVR,
+ .TOCR = OMAP3_TIMER_TOCR,
+ .TOWR = OMAP3_TIMER_TOWR,
+};
+
+#if IS_AM335X
+/* AM335X has a different ip block for the non 1ms timers */
+static omap_timer_registers_t regs_v2 = {
+ .TIDR = AM335X_TIMER_TIDR,
+ .TIOCP_CFG = AM335X_TIMER_TIOCP_CFG,
+ .TISTAT = AM335X_TIMER_IRQSTATUS_RAW,
+ .TISR = AM335X_TIMER_IRQSTATUS,
+ .TIER = AM335X_TIMER_IRQENABLE_SET,
+ .TWER = AM335X_TIMER_IRQWAKEEN,
+ .TCLR = AM335X_TIMER_TCLR,
+ .TCRR = AM335X_TIMER_TCRR,
+ .TLDR = AM335X_TIMER_TLDR,
+ .TTGR = AM335X_TIMER_TTGR,
+ .TWPS = AM335X_TIMER_TWPS,
+ .TMAR = AM335X_TIMER_TMAR,
+ .TCAR1 = AM335X_TIMER_TCAR1,
+ .TSICR = AM335X_TIMER_TSICR,
+ .TCAR2 = AM335X_TIMER_TCAR2,
+ .TPIR = -1, /* UNDEF */
+ .TNIR = -1, /* UNDEF */
+ .TCVR = -1, /* UNDEF */
+ .TOCR = -1, /* UNDEF */
+ .TOWR = -1 /* UNDEF */
+};
+#endif
+
+/* which timers are in use? target-dependent.
+ * initialize at compile time.
+ */
+
+#if IS_DM3730
+
+static omap_timer_t dm37xx_timer = {
+ .base = OMAP3_GPTIMER1_BASE,
+ .irq_nr = OMAP3_GPT1_IRQ,
+ .regs = &regs_v1
+};
+
+/* free running timer */
+static omap_timer_t dm37xx_fr_timer = {
+ .base = OMAP3_GPTIMER10_BASE,
+ .irq_nr = OMAP3_GPT10_IRQ,
+ .regs = &regs_v1
+};
+
+static struct omap_timer *fr_timer = &dm37xx_fr_timer;
+static struct omap_timer *timer = &dm37xx_timer;
+
+#endif
+
+#if IS_AM335X
+
+/* normal timer */
+static omap_timer_t am335x_timer = {
+ .base = AM335X_DMTIMER1_1MS_BASE,
+ .irq_nr = AM335X_INT_TINT1_1MS,
+ .regs = &regs_v1
+};
+
+/* free running timer */
+static omap_timer_t am335x_fr_timer = {
+ .base = AM335X_DMTIMER7_BASE,
+ .irq_nr = AM335X_INT_TINT7,
+ .regs = &regs_v2
+};
+
+static struct omap_timer *fr_timer = &am335x_fr_timer;
+static struct omap_timer *timer = &am335x_timer;
+
+#endif
+
+#if IS_AM335X
+#define FRCLOCK_HZ (16*1500000)
+#endif
+
+#if IS_DM3730
+#define FRCLOCK_HZ (8*1625000)
+#endif
+
+#ifndef FRCLOCK_HZ
+#error expected IS_AM335X or IS_DM3730 to be defined.
+#endif
+
+static void
+omap3_frclock_init(void)
+{
+ uint32_t tisr;
+
+#if IS_DM3730
+ /* Stop timer */
+ mmio_clear(fr_timer->base + fr_timer->regs->TCLR,
+ OMAP3_TCLR_ST);
+
+ /* Use functional clock source for GPTIMER10 */
+ mmio_set(OMAP3_CM_CLKSEL_CORE, OMAP3_CLKSEL_GPT10);
+#endif
+
+#if IS_AM335X
+ /* Disable the module and wait for the module to be disabled */
+ set32(CM_PER_TIMER7_CLKCTRL, CM_MODULEMODE_MASK,
+ CM_MODULEMODE_DISABLED);
+ while ((mmio_read(CM_PER_TIMER7_CLKCTRL) & CM_CLKCTRL_IDLEST)
+ != CM_CLKCTRL_IDLEST_DISABLE);
+
+ set32(CLKSEL_TIMER7_CLK, CLKSEL_TIMER7_CLK_SEL_MASK,
+ CLKSEL_TIMER7_CLK_SEL_SEL2);
+ while ((read32(CLKSEL_TIMER7_CLK) & CLKSEL_TIMER7_CLK_SEL_MASK)
+ != CLKSEL_TIMER7_CLK_SEL_SEL2);
+
+ /* enable the module and wait for the module to be ready */
+ set32(CM_PER_TIMER7_CLKCTRL, CM_MODULEMODE_MASK,
+ CM_MODULEMODE_ENABLE);
+ while ((mmio_read(CM_PER_TIMER7_CLKCTRL) & CM_CLKCTRL_IDLEST)
+ != CM_CLKCTRL_IDLEST_FUNC);
+
+ /* Stop timer */
+ mmio_clear(fr_timer->base + fr_timer->regs->TCLR,
+ OMAP3_TCLR_ST);
+#endif
+
+ /* Start and auto-reload at 0 */
+ mmio_write(fr_timer->base + fr_timer->regs->TLDR, 0x0);
+ mmio_write(fr_timer->base + fr_timer->regs->TCRR, 0x0);
+
+ /* Set up overflow interrupt */
+ tisr = OMAP3_TISR_MAT_IT_FLAG | OMAP3_TISR_OVF_IT_FLAG |
+ OMAP3_TISR_TCAR_IT_FLAG;
+ /* Clear interrupt status */
+ mmio_write(fr_timer->base + fr_timer->regs->TISR, tisr);
+ mmio_write(fr_timer->base + fr_timer->regs->TIER,
+ OMAP3_TIER_OVF_IT_ENA);
+
+ /* Start timer, without prescaler */
+ mmio_set(fr_timer->base + fr_timer->regs->TCLR,
+ OMAP3_TCLR_OVF_TRG | OMAP3_TCLR_AR | OMAP3_TCLR_ST);
+}
+
+static uint32_t
+beagle_clock_get_timecount(struct timecounter *tc)
+{
+ return mmio_read(fr_timer->base + fr_timer->regs->TCRR);
+}
+
+static void
+beagle_clock_initialize(void)
+{
+ uint32_t freq = 1000000UL/rtems_configuration_get_microseconds_per_tick();
+
+ /* we only support 1ms resolution */
+ uint32_t tisr;
+#if IS_DM3730
+ /* Stop timer */
+ mmio_clear(timer->base + timer->regs->TCLR, OMAP3_TCLR_ST);
+
+ /* Use 32 KHz clock source for GPTIMER1 */
+ mmio_clear(OMAP3_CM_CLKSEL_WKUP, OMAP3_CLKSEL_GPT1);
+#endif
+
+#if IS_AM335X
+ /* disable the module and wait for the module to be disabled */
+ set32(CM_WKUP_TIMER1_CLKCTRL, CM_MODULEMODE_MASK,
+ CM_MODULEMODE_DISABLED);
+ while ((mmio_read(CM_WKUP_TIMER1_CLKCTRL) & CM_CLKCTRL_IDLEST)
+ != CM_CLKCTRL_IDLEST_DISABLE);
+
+ set32(CLKSEL_TIMER1MS_CLK, CLKSEL_TIMER1MS_CLK_SEL_MASK,
+ CLKSEL_TIMER1MS_CLK_SEL_SEL2);
+ while ((read32(CLKSEL_TIMER1MS_CLK) &
+ CLKSEL_TIMER1MS_CLK_SEL_MASK) !=
+ CLKSEL_TIMER1MS_CLK_SEL_SEL2);
+
+ /* enable the module and wait for the module to be ready */
+ set32(CM_WKUP_TIMER1_CLKCTRL, CM_MODULEMODE_MASK,
+ CM_MODULEMODE_ENABLE);
+ while ((mmio_read(CM_WKUP_TIMER1_CLKCTRL) & CM_CLKCTRL_IDLEST)
+ != CM_CLKCTRL_IDLEST_FUNC);
+
+ /* Stop timer */
+ mmio_clear(timer->base + timer->regs->TCLR, OMAP3_TCLR_ST);
+#endif
+
+ /* Use 1-ms tick mode for GPTIMER1 TRM 16.2.4.2.1 */
+ mmio_write(timer->base + timer->regs->TPIR, 232000);
+ mmio_write(timer->base + timer->regs->TNIR, -768000);
+ mmio_write(timer->base + timer->regs->TLDR,
+ 0xffffffff - (32768 / freq) + 1);
+ mmio_write(timer->base + timer->regs->TCRR,
+ 0xffffffff - (32768 / freq) + 1);
+
+ /* Set up overflow interrupt */
+ tisr = OMAP3_TISR_MAT_IT_FLAG | OMAP3_TISR_OVF_IT_FLAG |
+ OMAP3_TISR_TCAR_IT_FLAG;
+ /* Clear interrupt status */
+ mmio_write(timer->base + timer->regs->TISR, tisr);
+ mmio_write(timer->base + timer->regs->TIER, OMAP3_TIER_OVF_IT_ENA);
+
+ /* Start timer */
+ mmio_set(timer->base + timer->regs->TCLR,
+ OMAP3_TCLR_OVF_TRG | OMAP3_TCLR_AR | OMAP3_TCLR_ST);
+ /* also initilize the free runnning timer */
+ omap3_frclock_init();
+
+#if IS_AM335X
+ /* Disable AM335X watchdog */
+ mmio_write(AM335X_WDT_BASE+AM335X_WDT_WSPR, 0xAAAA);
+ while(mmio_read(AM335X_WDT_BASE+AM335X_WDT_WWPS) != 0) ;
+ mmio_write(AM335X_WDT_BASE+AM335X_WDT_WSPR, 0x5555);
+ while(mmio_read(AM335X_WDT_BASE+AM335X_WDT_WWPS) != 0) ;
+#endif
+
+ /* Install timecounter */ \
+ beagle_clock_tc.tc_get_timecount = beagle_clock_get_timecount;
+ beagle_clock_tc.tc_counter_mask = 0xffffffff;
+ beagle_clock_tc.tc_frequency = FRCLOCK_HZ;
+ beagle_clock_tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
+ rtems_timecounter_install(&beagle_clock_tc);
+}
+
+static void beagle_clock_at_tick(void)
+{
+ mmio_write(timer->base + timer->regs->TISR,
+ OMAP3_TISR_MAT_IT_FLAG | OMAP3_TISR_OVF_IT_FLAG |
+ OMAP3_TISR_TCAR_IT_FLAG);
+}
+
+static rtems_interrupt_handler clock_isr = NULL;
+
+static void beagle_clock_handler_install(rtems_interrupt_handler isr)
+{
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+
+ sc = rtems_interrupt_handler_install(
+ timer->irq_nr,
+ "Clock",
+ RTEMS_INTERRUPT_UNIQUE,
+ isr,
+ NULL
+ );
+
+ if (sc != RTEMS_SUCCESSFUL) {
+ rtems_fatal_error_occurred(0xdeadbeef);
+ }
+ clock_isr = isr;
+}
+
+static void beagle_clock_cleanup(void)
+{
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+
+ /* Disable timer */
+ mmio_clear(timer->base + timer->regs->TCLR, OMAP3_TCLR_ST);
+
+ /* Remove interrupt handler */
+ sc = rtems_interrupt_handler_remove(
+ timer->irq_nr,
+ clock_isr,
+ NULL
+ );
+ if (sc != RTEMS_SUCCESSFUL) {
+ rtems_fatal_error_occurred(0xdeadbeef);
+ }
+ clock_isr = NULL;
+
+ /* stop frclock */
+ mmio_clear(fr_timer->base + fr_timer->regs->TCLR, OMAP3_TCLR_ST);
+}
+
+#define Clock_driver_support_at_tick() beagle_clock_at_tick()
+#define Clock_driver_support_initialize_hardware() beagle_clock_initialize()
+#define Clock_driver_support_install_isr(isr) \
+ beagle_clock_handler_install(isr)
+
+#define Clock_driver_support_shutdown_hardware() beagle_clock_cleanup()
+
+/* Include shared source clock driver code */
+#include "../../shared/dev/clock/clockimpl.h"
diff --git a/bsps/arm/beagle/gpio/bbb-gpio.c b/bsps/arm/beagle/gpio/bbb-gpio.c
new file mode 100644
index 0000000000..8532f544ab
--- /dev/null
+++ b/bsps/arm/beagle/gpio/bbb-gpio.c
@@ -0,0 +1,564 @@
+/**
+ * @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 };
+
+/* Macro for the gpio pin not having control module offset mapping */
+#define CONF_NOT_DEFINED 0x00000000
+
+/* Mapping of gpio pin nuber to the Control module mapped register offset */
+static const uint32_t gpio_pad_conf[GPIO_BANK_COUNT][BSP_GPIO_PINS_PER_BANK] =
+{
+ /* GPIO Module 0 */
+ { CONF_NOT_DEFINED, /* GPIO0[0] */
+ CONF_NOT_DEFINED, /* GPIO0[1] */
+ AM335X_CONF_SPI0_SCLK, /* GPIO0[2] */
+ AM335X_CONF_SPI0_D0, /* GPIO0[3] */
+ AM335X_CONF_SPI0_D1, /* GPIO0[4] */
+ AM335X_CONF_SPI0_CS0, /* GPIO0[5] */
+ CONF_NOT_DEFINED, /* GPIO0[6] */
+ CONF_NOT_DEFINED, /* GPIO0[7] */
+ AM335X_CONF_LCD_DATA12, /* GPIO0[8] */
+ AM335X_CONF_LCD_DATA13, /* GPIO0[9] */
+ AM335X_CONF_LCD_DATA14, /* GPIO0[10] */
+ AM335X_CONF_LCD_DATA15, /* GPIO0[11] */
+ AM335X_CONF_UART1_CTSN, /* GPIO0[12] */
+ AM335X_CONF_UART1_RTSN, /* GPIO0[13] */
+ AM335X_CONF_UART1_RXD, /* GPIO0[14] */
+ AM335X_CONF_UART1_TXD, /* GPIO0[15] */
+ CONF_NOT_DEFINED, /* GPIO0[16] */
+ CONF_NOT_DEFINED, /* GPIO0[17] */
+ CONF_NOT_DEFINED, /* GPIO0[18] */
+ CONF_NOT_DEFINED, /* GPIO0[19] */
+ CONF_NOT_DEFINED, /* GPIO0[20] */
+ CONF_NOT_DEFINED, /* GPIO0[21] */
+ AM335X_CONF_GPMC_AD8, /* GPIO0[22] */
+ AM335X_CONF_GPMC_AD9, /* GPIO0[23] */
+ CONF_NOT_DEFINED, /* GPIO0[24] */
+ CONF_NOT_DEFINED, /* GPIO0[25] */
+ AM335X_CONF_GPMC_AD10, /* GPIO0[26] */
+ AM335X_CONF_GPMC_AD11, /* GPIO0[27] */
+ CONF_NOT_DEFINED, /* GPIO0[28] */
+ CONF_NOT_DEFINED, /* GPIO0[29] */
+ AM335X_CONF_GPMC_WAIT0, /* GPIO0[30] */
+ AM335X_CONF_GPMC_WPN /* GPIO0[31] */ },
+
+ /* GPIO Module 1 */
+ { AM335X_CONF_GPMC_AD0, /* GPIO1[0] */
+ AM335X_CONF_GPMC_AD1, /* GPIO1[1] */
+ AM335X_CONF_GPMC_AD2, /* GPIO1[2] */
+ AM335X_CONF_GPMC_AD3, /* GPIO1[3] */
+ AM335X_CONF_GPMC_AD4, /* GPIO1[4] */
+ AM335X_CONF_GPMC_AD5, /* GPIO1[5] */
+ AM335X_CONF_GPMC_AD6, /* GPIO1[6] */
+ AM335X_CONF_GPMC_AD7, /* GPIO1[7] */
+ CONF_NOT_DEFINED, /* GPIO1[8] */
+ CONF_NOT_DEFINED, /* GPIO1[9] */
+ CONF_NOT_DEFINED, /* GPIO1[10] */
+ CONF_NOT_DEFINED, /* GPIO1[11] */
+ AM335X_CONF_GPMC_AD12, /* GPIO1[12] */
+ AM335X_CONF_GPMC_AD13, /* GPIO1[13] */
+ AM335X_CONF_GPMC_AD14, /* GPIO1[14] */
+ AM335X_CONF_GPMC_AD15, /* GPIO1[15] */
+ AM335X_CONF_GPMC_A0, /* GPIO1[16] */
+ AM335X_CONF_GPMC_A1, /* GPIO1[17] */
+ AM335X_CONF_GPMC_A2, /* GPIO1[18] */
+ AM335X_CONF_GPMC_A3, /* GPIO1[19] */
+ CONF_NOT_DEFINED, /* GPIO1[20] */
+ CONF_NOT_DEFINED, /* GPIO1[21] */
+ CONF_NOT_DEFINED, /* GPIO1[22] */
+ CONF_NOT_DEFINED, /* GPIO1[23] */
+ CONF_NOT_DEFINED, /* GPIO1[24] */
+ CONF_NOT_DEFINED, /* GPIO1[25] */
+ CONF_NOT_DEFINED, /* GPIO1[26] */
+ CONF_NOT_DEFINED, /* GPIO1[27] */
+ AM335X_CONF_GPMC_BEN1, /* GPIO1[28] */
+ AM335X_CONF_GPMC_CSN0, /* GPIO1[29] */
+ AM335X_CONF_GPMC_CSN1, /* GPIO1[30] */
+ AM335X_CONF_GPMC_CSN2 /* GPIO1[31] */ },
+
+ /* GPIO Module 2 */
+ { CONF_NOT_DEFINED, /* GPIO2[0] */
+ AM335X_CONF_GPMC_CLK, /* GPIO2[1] */
+ AM335X_CONF_GPMC_ADVN_ALE, /* GPIO2[2] */
+ AM335X_CONF_GPMC_OEN_REN, /* GPIO2[3] */
+ AM335X_CONF_GPMC_WEN, /* GPIO2[4] */
+ AM335X_CONF_GPMC_BEN0_CLE, /* GPIO2[5] */
+ AM335X_CONF_LCD_DATA0, /* GPIO2[6] */
+ AM335X_CONF_LCD_DATA1, /* GPIO2[7] */
+ AM335X_CONF_LCD_DATA2, /* GPIO2[8] */
+ AM335X_CONF_LCD_DATA3, /* GPIO2[9] */
+ AM335X_CONF_LCD_DATA4, /* GPIO2[10] */
+ AM335X_CONF_LCD_DATA5, /* GPIO2[11] */
+ AM335X_CONF_LCD_DATA6, /* GPIO2[12] */
+ AM335X_CONF_LCD_DATA7, /* GPIO2[13] */
+ AM335X_CONF_LCD_DATA8, /* GPIO2[14] */
+ AM335X_CONF_LCD_DATA9, /* GPIO2[15] */
+ AM335X_CONF_LCD_DATA10, /* GPIO2[16] */
+ AM335X_CONF_LCD_DATA11, /* GPIO2[17] */
+ CONF_NOT_DEFINED, /* GPIO2[18] */
+ CONF_NOT_DEFINED, /* GPIO2[19] */
+ CONF_NOT_DEFINED, /* GPIO2[20] */
+ CONF_NOT_DEFINED, /* GPIO2[21] */
+ AM335X_CONF_LCD_VSYNC, /* GPIO2[22] */
+ AM335X_CONF_LCD_HSYNC, /* GPIO2[23] */
+ AM335X_CONF_LCD_PCLK, /* GPIO2[24] */
+ AM335X_CONF_LCD_AC_BIAS_EN /* GPIO2[25] */ },
+
+ /* GPIO Module 3 */
+ { CONF_NOT_DEFINED, /* GPIO3[0] */
+ CONF_NOT_DEFINED, /* GPIO3[1] */
+ CONF_NOT_DEFINED, /* GPIO3[2] */
+ CONF_NOT_DEFINED, /* GPIO3[3] */
+ CONF_NOT_DEFINED, /* GPIO3[4] */
+ CONF_NOT_DEFINED, /* GPIO3[5] */
+ CONF_NOT_DEFINED, /* GPIO3[6] */
+ CONF_NOT_DEFINED, /* GPIO3[7] */
+ CONF_NOT_DEFINED, /* GPIO3[8] */
+ CONF_NOT_DEFINED, /* GPIO3[9] */
+ CONF_NOT_DEFINED, /* GPIO3[10] */
+ CONF_NOT_DEFINED, /* GPIO3[11] */
+ CONF_NOT_DEFINED, /* GPIO3[12] */
+ CONF_NOT_DEFINED, /* GPIO3[13] */
+ AM335X_CONF_MCASP0_ACLKX, /* GPIO3[14] */
+ AM335X_CONF_MCASP0_FSX, /* GPIO3[15] */
+ AM335X_CONF_MCASP0_AXR0, /* GPIO3[16] */
+ AM335X_CONF_MCASP0_AHCLKR, /* GPIO3[17] */
+ CONF_NOT_DEFINED, /* GPIO3[18] */
+ AM335X_CONF_MCASP0_FSR, /* GPIO3[19] */
+ CONF_NOT_DEFINED, /* GPIO3[20] */
+ AM335X_CONF_MCASP0_AHCLKX /* GPIO3[21] */ }
+};
+
+/* Get the address of Base Register + Offset for pad config */
+uint32_t static inline bbb_conf_reg(uint32_t bank, uint32_t pin)
+{
+ return (AM335X_PADCONF_BASE + gpio_pad_conf[bank][pin]);
+}
+
+/* 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 */
diff --git a/bsps/arm/beagle/pwm/pwm.c b/bsps/arm/beagle/pwm/pwm.c
new file mode 100644
index 0000000000..0bc5d125bf
--- /dev/null
+++ b/bsps/arm/beagle/pwm/pwm.c
@@ -0,0 +1,454 @@
+/**
+ * @file
+ *
+ * @ingroup arm_beagle
+ *
+ * @brief Support for PWM for the BeagleBone Black.
+ */
+
+/**
+ * Copyright (c) 2016 Punit Vara <punitvara@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.
+ */
+
+/** This file is based on
+ * https://github.com/VegetableAvenger/BBBIOlib/blob/master/BBBio_lib/BBBiolib_PWMSS.c
+ */
+
+#include <libcpu/am335x.h>
+#include <stdio.h>
+#include <bsp/gpio.h>
+#include <bsp/bbb-gpio.h>
+#include <bsp.h>
+#include <bsp/bbb-pwm.h>
+#include <bsp/beagleboneblack.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
+
+/*
+ * @brief This function selects EPWM module to be enabled
+ *
+ * @param pwm_id It is the instance number of EPWM of pwm sub system.
+ *
+ * @return Base Address of respective pwm instant.
+*/
+static uint32_t select_pwm(BBB_PWMSS pwm_id)
+{
+ uint32_t baseAddr=0;
+
+ if (pwm_id == BBB_PWMSS0) {
+ baseAddr = AM335X_EPWM_0_REGS;
+ } else if (pwm_id == BBB_PWMSS1) {
+ baseAddr = AM335X_EPWM_1_REGS;
+ } else if (pwm_id == BBB_PWMSS2) {
+ baseAddr = AM335X_EPWM_2_REGS;
+ } else {
+ baseAddr = 0;
+ }
+ return baseAddr;
+}
+
+/*
+ * @brief This function selects PWM Sub system to be enabled
+ *
+ * @param pwmss_id The instance number of ePWMSS whose system clocks
+ * have to be configured.
+ *
+ * @return Base Address of respective pwmss instant.
+*/
+static uint32_t select_pwmss(BBB_PWMSS pwmss_id)
+{
+ uint32_t baseAddr=0;
+
+ if (pwmss_id == BBB_PWMSS0) {
+ baseAddr = AM335X_PWMSS0_MMAP_ADDR;
+ } else if (pwmss_id == BBB_PWMSS1) {
+ baseAddr = AM335X_PWMSS1_MMAP_ADDR;
+ } else if (pwmss_id == BBB_PWMSS2) {
+ baseAddr = AM335X_PWMSS2_MMAP_ADDR;
+ } else {
+ baseAddr = 0;
+ }
+ return baseAddr;
+}
+
+bool beagle_pwm_pinmux_setup(bbb_pwm_pin_t pin_no, BBB_PWMSS pwm_id)
+{
+ bool is_valid = true;
+
+ if(pwm_id == BBB_PWMSS0) {
+ if (pin_no == BBB_P9_21_0B) {
+ REG(AM335X_PADCONF_BASE + AM335X_CONF_SPI0_D0) = BBB_MUXMODE(BBB_P9_21_MUX_PWM);
+ } else if (pin_no == BBB_P9_22_0A) {
+ REG(AM335X_PADCONF_BASE + AM335X_CONF_SPI0_SCLK) = BBB_MUXMODE(BBB_P9_22_MUX_PWM);
+ } else if (pin_no == BBB_P9_29_0B) {
+ REG(AM335X_PADCONF_BASE + AM335X_CONF_MCASP0_FSX) = BBB_MUXMODE(BBB_P9_29_MUX_PWM);
+ } else if (pin_no == BBB_P9_31_0A) {
+ REG(AM335X_PADCONF_BASE + AM335X_CONF_MCASP0_ACLKX) = BBB_MUXMODE(BBB_P9_31_MUX_PWM);
+ } else {
+ is_valid = false;
+ }
+
+ } else if (pwm_id == BBB_PWMSS1) {
+ if (pin_no == BBB_P8_34_1B) {
+ REG(AM335X_PADCONF_BASE + BBB_CONTROL_CONF_LCD_DATA(11)) = BBB_MUXMODE(BBB_P8_34_MUX_PWM);
+ } else if (pin_no == BBB_P8_36_1A) {
+ REG(AM335X_PADCONF_BASE + BBB_CONTROL_CONF_LCD_DATA(10)) = BBB_MUXMODE(BBB_P8_36_MUX_PWM);
+ } else if (pin_no == BBB_P9_14_1A) {
+ REG(AM335X_PADCONF_BASE + BBB_CONTROL_CONF_GPMC_AD(2)) = BBB_MUXMODE(BBB_P9_14_MUX_PWM);
+ } else if (pin_no == BBB_P9_16_1B) {
+ REG(AM335X_PADCONF_BASE + BBB_CONTROL_CONF_GPMC_AD(3)) = BBB_MUXMODE(BBB_P9_16_MUX_PWM);
+ } else {
+ is_valid = false;
+ }
+ } else if (pwm_id == BBB_PWMSS2) {
+ if (pin_no == BBB_P8_13_2B) {
+ REG(AM335X_PADCONF_BASE + BBB_CONTROL_CONF_GPMC_AD(9)) = BBB_MUXMODE(BBB_P8_13_MUX_PWM);
+ } else if (pin_no == BBB_P8_19_2A) {
+ REG(AM335X_PADCONF_BASE + BBB_CONTROL_CONF_GPMC_AD(8)) = BBB_MUXMODE(BBB_P8_19_MUX_PWM);
+ } else if (pin_no == BBB_P8_45_2A) {
+ REG(AM335X_PADCONF_BASE + BBB_CONTROL_CONF_LCD_DATA(0)) = BBB_MUXMODE(BBB_P8_45_MUX_PWM);
+ } else if (pin_no == BBB_P8_46_2B) {
+ REG(AM335X_PADCONF_BASE + BBB_CONTROL_CONF_LCD_DATA(1)) = BBB_MUXMODE(BBB_P8_46_MUX_PWM);
+ } else {
+ is_valid = false;
+ }
+ } else {
+ is_valid = false;
+ }
+ return is_valid;
+}
+
+/**
+ * @brief This function Enables TBCLK(Time Base Clock) for specific
+ * EPWM instance of pwmsubsystem.
+ *
+ * @param instance It is the instance number of EPWM of pwmsubsystem.
+ *
+ * @return true if successful
+ * false if unsuccessful
+ **/
+static bool pwmss_tbclk_enable(BBB_PWMSS instance)
+{
+ uint32_t enable_bit;
+ bool is_valid = true;
+
+ if (instance == BBB_PWMSS0) {
+ enable_bit = AM335X_PWMSS_CTRL_PWMSS0_TBCLKEN;
+ } else if (instance == BBB_PWMSS1) {
+ enable_bit = AM335X_PWMSS_CTRL_PWMSS1_TBCLKEN;
+ } else if (instance == BBB_PWMSS2) {
+ enable_bit = AM335X_PWMSS_CTRL_PWMSS2_TBCLKEN;
+ } else {
+ is_valid = false;
+ }
+
+ if (is_valid)
+ {
+ REG(AM335X_PADCONF_BASE + AM335X_PWMSS_CTRL) |= enable_bit;
+ }
+
+ return is_valid;
+ }
+
+/**
+ * @brief This functions enables clock for EHRPWM module in PWMSS subsystem.
+ *
+ * @param pwm_id It is the instance number of EPWM of pwm sub system.
+ *
+ * @return true if successful
+ * false if unsuccessful
+ *
+ **/
+static bool pwm_clock_enable(BBB_PWMSS pwm_id)
+{
+ const bool id_is_valid = pwm_id < BBB_PWMSS_COUNT;
+ bool status = true;
+
+ if (id_is_valid) {
+ const uint32_t baseAddr = select_pwmss(pwm_id);
+ REG(baseAddr + AM335X_PWMSS_CLKCONFIG) |= AM335X_PWMSS_CLK_EN_ACK;
+ } else {
+ status = false;
+ }
+ return status;
+}
+
+/**
+ * @brief This function configures the L3 and L4_PER system clocks.
+ * It also configures the system clocks for the specified ePWMSS
+ * instance.
+ *
+ * @param pwmss_id The instance number of ePWMSS whose system clocks
+ * have to be configured.
+ *
+ * 'pwmss_id' can take one of the following values:
+ * (0 <= pwmss_id <= 2)
+ *
+ * @return True if successful
+ * False if Unsuccessful
+ */
+static bool pwmss_module_clk_config(BBB_PWMSS pwmss_id)
+{
+ bool is_valid = true;
+
+ if(pwmss_id == BBB_PWMSS0) {
+ const uint32_t is_functional = AM335X_CM_PER_EPWMSS0_CLKCTRL_IDLEST_FUNC <<
+ AM335X_CM_PER_EPWMSS0_CLKCTRL_IDLEST_SHIFT;
+ const uint32_t clkctrl = AM335X_CM_PER_ADDR + AM335X_CM_PER_EPWMSS0_CLKCTRL;
+ const uint32_t idle_bits = AM335X_CM_PER_EPWMSS0_CLKCTRL_IDLEST;
+ const uint32_t is_enable = AM335X_CM_PER_EPWMSS0_CLKCTRL_MODULEMODE_ENABLE;
+ const uint32_t module_mode = AM335X_CM_PER_EPWMSS0_CLKCTRL_MODULEMODE;
+
+ REG(clkctrl) |= is_enable;
+ while((REG(clkctrl) & module_mode) != is_enable);
+ while((REG(clkctrl) & idle_bits) != is_functional);
+ }
+ else if(pwmss_id == BBB_PWMSS1) {
+ const uint32_t is_functional = AM335X_CM_PER_EPWMSS1_CLKCTRL_IDLEST_FUNC <<
+ AM335X_CM_PER_EPWMSS1_CLKCTRL_IDLEST_SHIFT;
+ const uint32_t clkctrl = AM335X_CM_PER_ADDR + AM335X_CM_PER_EPWMSS1_CLKCTRL;
+ const uint32_t idle_bits = AM335X_CM_PER_EPWMSS1_CLKCTRL_IDLEST;
+ const uint32_t is_enable = AM335X_CM_PER_EPWMSS1_CLKCTRL_MODULEMODE_ENABLE;
+ const uint32_t module_mode = AM335X_CM_PER_EPWMSS1_CLKCTRL_MODULEMODE;
+
+ REG(clkctrl) |= is_enable;
+ while((REG(clkctrl) & module_mode) != is_enable);
+ while((REG(clkctrl) & idle_bits) != is_functional);
+ } else if(pwmss_id == BBB_PWMSS2) {
+ const uint32_t is_functional = AM335X_CM_PER_EPWMSS2_CLKCTRL_IDLEST_FUNC <<
+ AM335X_CM_PER_EPWMSS2_CLKCTRL_IDLEST_SHIFT;
+ const uint32_t clkctrl = AM335X_CM_PER_ADDR + AM335X_CM_PER_EPWMSS2_CLKCTRL;
+ const uint32_t idle_bits = AM335X_CM_PER_EPWMSS2_CLKCTRL_IDLEST;
+ const uint32_t is_enable = AM335X_CM_PER_EPWMSS2_CLKCTRL_MODULEMODE_ENABLE;
+ const uint32_t module_mode = AM335X_CM_PER_EPWMSS2_CLKCTRL_MODULEMODE;
+
+ REG(clkctrl) |= is_enable;
+ while((REG(clkctrl) & module_mode) != is_enable);
+ while((REG(clkctrl) & idle_bits) != is_functional);
+ } else
+ is_valid = false;
+ return is_valid;
+}
+
+bool beagle_pwm_init(BBB_PWMSS pwmss_id)
+{
+ const bool id_is_valid = pwmss_id < BBB_PWMSS_COUNT;
+ bool status = true;
+
+ if(id_is_valid) {
+ pwmss_module_clk_config(pwmss_id);
+ pwm_clock_enable(pwmss_id);
+ pwmss_tbclk_enable(pwmss_id);
+ } else {
+ status =false;
+ }
+ return status;
+}
+
+int beagle_pwm_configure(BBB_PWMSS pwm_id, float pwm_freq, float duty_a, float duty_b)
+{
+ uint32_t baseAddr;
+ int status = 1;
+ float cycle = 0.0f,divisor = 0;
+ unsigned int i,j;
+ const float CLKDIV_div[] = {1.0,2.0,4.0,8.0,16.0,32.0,64.0,128.0};
+ const float HSPCLKDIV_div[] = {1.0, 2.0, 4.0, 6.0, 8.0, 10.0,12.0, 14.0};
+ int NearCLKDIV =7,NearHSPCLKDIV =7,NearTBPRD =0;
+
+ if (pwm_freq <= BBB_PWM_FREQ_THRESHOLD) {
+ status =0;
+ }
+
+ if (duty_a < 0.0f || duty_a > 100.0f || duty_b < 0.0f || duty_b > 100.0f) {
+ status = 0;
+ }
+ duty_a /= 100.0f;
+ duty_b /= 100.0f;
+
+ /** 10^9 /Hz compute time per cycle (ns) */
+ cycle = 1000000000.0f / pwm_freq;
+
+ /** am335x provide (128* 14) divider and per TBPRD means 10ns when divider
+ * and max TBPRD is 65535 so max cycle is 128 * 8 * 14 * 65535 * 10ns */
+ divisor = (cycle / 655350.0f);
+ if (divisor > (128 * 14)) {
+ return 0;
+ }
+ else {
+ for (i=0;i<8;i++) {
+ for(j=0 ; j<8; j++) {
+ if((CLKDIV_div[i] * HSPCLKDIV_div[j]) < (CLKDIV_div[NearCLKDIV]
+ * HSPCLKDIV_div[NearHSPCLKDIV]) && (CLKDIV_div[i] * HSPCLKDIV_div[j] > divisor)) {
+ NearCLKDIV = i;
+ NearHSPCLKDIV = j;
+ }
+ }
+ }
+
+ baseAddr = select_pwm(pwm_id);
+
+ REG16(baseAddr + AM335X_EPWM_TBCTL) &= ~(AM335X_TBCTL_CLKDIV_MASK | AM335X_TBCTL_HSPCLKDIV_MASK);
+ const uint16_t clkdiv_clear = (REG16(baseAddr + AM335X_EPWM_TBCTL) &
+ (~AM335X_EPWM_TBCTL_CLKDIV));
+ const uint16_t clkdiv_write = ((NearCLKDIV
+ << AM335X_EPWM_TBCTL_CLKDIV_SHIFT) & AM335X_EPWM_TBCTL_CLKDIV);
+ REG16(baseAddr + AM335X_EPWM_TBCTL) = clkdiv_clear | clkdiv_write;
+ const uint16_t hspclkdiv_clear = (REG16(baseAddr + AM335X_EPWM_TBCTL) &
+ (~AM335X_EPWM_TBCTL_HSPCLKDIV));
+ const uint16_t hspclkdiv_write = ((NearHSPCLKDIV <<
+ AM335X_EPWM_TBCTL_HSPCLKDIV_SHIFT) & AM335X_EPWM_TBCTL_HSPCLKDIV);
+ REG16(baseAddr + AM335X_EPWM_TBCTL) = hspclkdiv_clear | hspclkdiv_write;
+ NearTBPRD = (cycle / (10.0 * CLKDIV_div[NearCLKDIV] * HSPCLKDIV_div[NearHSPCLKDIV]));
+ const uint16_t shadow_mask = (REG16(baseAddr + AM335X_EPWM_TBCTL) &
+ (~AM335X_EPWM_PRD_LOAD_SHADOW_MASK));
+ const uint16_t shadow_disable = (((bool)AM335X_EPWM_SHADOW_WRITE_DISABLE <<
+ AM335X_EPWM_TBCTL_PRDLD_SHIFT) & AM335X_EPWM_PRD_LOAD_SHADOW_MASK);
+ REG16(baseAddr + AM335X_EPWM_TBCTL) = shadow_mask | shadow_disable;
+ const uint16_t counter_mask = (REG16(baseAddr + AM335X_EPWM_TBCTL) &
+ (~AM335X_EPWM_COUNTER_MODE_MASK));
+ const uint16_t counter_shift = (((unsigned int)AM335X_EPWM_COUNT_UP <<
+ AM335X_TBCTL_CTRMODE_SHIFT) & AM335X_EPWM_COUNTER_MODE_MASK);
+ REG16(baseAddr + AM335X_EPWM_TBCTL) = counter_mask | counter_shift;
+ /*setting clock divider and freeze time base*/
+ REG16(baseAddr + AM335X_EPWM_CMPB) = (unsigned short)((float)(NearTBPRD) * duty_b);
+ REG16(baseAddr + AM335X_EPWM_CMPA) = (unsigned short)((float)(NearTBPRD) * duty_a);
+ REG16(baseAddr + AM335X_EPWM_TBPRD) = (unsigned short)NearTBPRD;
+ REG16(baseAddr + AM335X_EPWM_TBCNT) = 0;
+ }
+ return status;
+}
+
+bool beagle_pwm_enable(BBB_PWMSS pwmid)
+{
+ const bool id_is_valid = pwmid < BBB_PWMSS_COUNT;
+ bool status = true;
+
+ if (id_is_valid) {
+ const uint32_t baseAddr = select_pwm(pwmid);
+ /* Initially set EPWMxA o/p high , when increasing counter = CMPA toggle o/p of EPWMxA */
+ REG16(baseAddr + AM335X_EPWM_AQCTLA) = AM335X_EPWM_AQCTLA_ZRO_XAHIGH | (AM335X_EPWM_AQCTLA_CAU_EPWMXATOGGLE << AM335X_EPWM_AQCTLA_CAU_SHIFT);
+ /* Initially set EPWMxB o/p high , when increasing counter = CMPA toggle o/p of EPWMxB */
+ REG16(baseAddr + AM335X_EPWM_AQCTLB) = AM335X_EPWM_AQCTLB_ZRO_XBHIGH | (AM335X_EPWM_AQCTLB_CBU_EPWMXBTOGGLE << AM335X_EPWM_AQCTLB_CBU_SHIFT);
+ REG16(baseAddr + AM335X_EPWM_TBCNT) = 0;
+ /* Set counter mode : Up-count mode */
+ REG16(baseAddr + AM335X_EPWM_TBCTL) |= AM335X_TBCTL_FREERUN | AM335X_TBCTL_CTRMODE_UP;
+ } else {
+ status =false;
+ }
+ return status;
+}
+
+bool beagle_pwm_disable(BBB_PWMSS pwmid)
+{
+ const bool id_is_valid = pwmid < BBB_PWMSS_COUNT;
+ bool status = true;
+
+ if (id_is_valid) {
+ const uint32_t baseAddr = select_pwm(pwmid);
+ REG16(baseAddr + AM335X_EPWM_TBCTL) = AM335X_EPWM_TBCTL_CTRMODE_STOPFREEZE;
+ REG16(baseAddr + AM335X_EPWM_AQCTLA) = AM335X_EPWM_AQCTLA_ZRO_XALOW | (AM335X_EPWM_AQCTLA_CAU_EPWMXATOGGLE << AM335X_EPWM_AQCTLA_CAU_SHIFT);
+ REG16(baseAddr + AM335X_EPWM_AQCTLB) = AM335X_EPWM_AQCTLA_ZRO_XBLOW | (AM335X_EPWM_AQCTLB_CBU_EPWMXBTOGGLE << AM335X_EPWM_AQCTLB_CBU_SHIFT);
+ REG16(baseAddr + AM335X_EPWM_TBCNT) = 0;
+ } else {
+ status = false;
+ }
+ return status;
+}
+
+/**
+ * @brief This functions determines whether time base clock is enabled for EPWMSS
+ *
+ * @param pwmss_id The instance number of ePWMSS whose time base clock need to
+ * be checked
+ *
+ * @return returns 4 for PWMSS_ID = 2
+ * returns 2 for PWMSS_ID = 1
+ * returns 1 for PWMSS_ID = 0
+ **/
+static int pwmss_tb_clock_check(unsigned int pwmss_id)
+{
+ unsigned int reg_value;
+
+ /*control module check*/
+ reg_value = REG(AM335X_CONTROL_MODULE + AM335X_PWMSS_CTRL);
+ return (reg_value & (1 << pwmss_id));
+}
+
+/**
+ * @brief This functions determines whether clock for EPWMSS is enabled or not.
+ *
+ * @param It is the Memory address of the PWMSS instance used.
+ *
+ * @return
+ *
+ **/
+static unsigned int pwmss_clock_en_status(unsigned int pwmid)
+{
+ unsigned int status;
+ const uint32_t baseAddr = select_pwmss(pwmid);
+
+ status = REG(baseAddr + AM335X_PWMSS_CLKSTATUS);
+ status = status >> 8 & 0x1;
+ return status;
+}
+
+bool beagle_pwmss_is_running(unsigned int pwmss_id)
+{
+ const bool id_is_valid = pwmss_id < BBB_PWMSS_COUNT;
+ bool status=true;
+
+ if (id_is_valid) {
+ status = pwmss_clock_en_status(pwmss_id);
+ if(status){
+ status = pwmss_tb_clock_check(pwmss_id);
+ } else {
+ status = false;
+ }
+ } else {
+ status = false;
+ }
+ return status;
+}
+
+#endif
+
+/* 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.
+ */
+bool beagle_pwm_init(BBB_PWMSS pwmss_id)
+{
+ return false;
+}
+bool beagle_pwm_disable(BBB_PWMSS pwmid)
+{
+ return false;
+}
+bool beagle_pwm_enable(BBB_PWMSS pwmid)
+{
+ return false;
+}
+int beagle_pwm_configure(BBB_PWMSS pwm_id, float pwm_freq, float duty_a, float duty_b)
+{
+ return -1;
+}
+bool beagle_pwm_pinmux_setup(bbb_pwm_pin_t pin_no, BBB_PWMSS pwm_id)
+{
+ return false;
+}
+bool beagle_pwmss_is_running(unsigned int pwmss_id)
+{
+return false;
+}
+#endif
diff --git a/bsps/arm/beagle/rtc/rtc.c b/bsps/arm/beagle/rtc/rtc.c
new file mode 100644
index 0000000000..abce5df1ab
--- /dev/null
+++ b/bsps/arm/beagle/rtc/rtc.c
@@ -0,0 +1,276 @@
+/**
+ * @file
+ *
+ * @ingroup arm_beagle
+ *
+ * @brief RTC driver for AM335x SoC.
+ *
+ */
+
+/*
+ * Copyright (c) 2015 Ragunath <ragunath3252@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.com/license/LICENSE.
+ */
+
+#include <bspopts.h>
+
+#if IS_AM335X
+#include <rtems.h>
+#include <bsp.h>
+#include <time.h>
+#include <libchip/rtc.h>
+#include <libcpu/omap3.h>
+
+#define setbit(a,x) (a | (1<<x))
+#define bcd(a) ((a & 0x0f)+ (((a & 0xf0) >> 4 )*10))
+#define dec(a) (((a / 10) << 4) | (a % 10))
+#define WRITE_WAIT_MAX_COUNT 10000
+
+size_t RTC_Count = 1;
+
+static void rtc_write_enable(void);
+static void rtc_write_disable(void);
+static int rtc_write_wait(void);
+static void rtc_clk_init(void);
+void rtc_init(int minor);
+void print_time(void);
+int am335x_rtc_gettime(int minor,rtems_time_of_day *t);
+int am335x_rtc_settime(int minor, const rtems_time_of_day *t);
+void am335x_rtc_debug(void);
+
+/*
+ * probe for a rtc. we always claim to have one.
+ */
+static bool am335x_rtc_probe (int minor)
+{
+ return true;
+}
+
+/*
+ * Write key values to kick0 and kick1 registers to enable write access
+ */
+static void rtc_write_enable(void)
+{
+ mmio_write(AM335X_RTC_BASE+AM335X_RTC_KICK0,AM335X_RTC_KICK0_KEY);
+ mmio_write(AM335X_RTC_BASE+AM335X_RTC_KICK1,AM335X_RTC_KICK1_KEY);
+}
+
+/*
+ * Write random (0x11111111) value to kick0 and kick1 registers to disable write access
+ */
+static void rtc_write_disable(void)
+{
+ /* Write some random value other than key to disable*/
+ mmio_write(AM335X_RTC_BASE+AM335X_RTC_KICK0,0x11111111);
+ mmio_write(AM335X_RTC_BASE+AM335X_RTC_KICK1,0x11111111);
+}
+
+/*
+ * Wait till busy bit is reset
+ */
+static int rtc_write_wait(void)
+{
+ int i = WRITE_WAIT_MAX_COUNT;
+ while((mmio_read(AM335X_RTC_BASE+AM335X_RTC_STATUS_REG) & 0x1) && (i--));
+
+ if(i == 0)
+ return RTEMS_RESOURCE_IN_USE;
+ else
+ return RTEMS_SUCCESSFUL;
+}
+
+
+/*
+ * Initialize RTC clock
+ */
+static void rtc_clk_init(void)
+{
+ uint32_t a = 0x0;
+
+ a = setbit(a,1);
+ /* IDLEST = 0x0 & MODULEMODE = 0x1*/
+ mmio_write(CM_RTC_BASE+CM_RTC_RTC_CLKCTRL,a);
+ a = 0x0;
+
+ /*32K rtc clock active*/
+ a = setbit(a,9);
+ a = setbit(a,8);
+ mmio_write(CM_RTC_BASE+CM_RTC_CLKSTCTRL,a);
+}
+
+void rtc_init(int minor)
+{
+ uint32_t a = 0x0;
+
+ rtc_clk_init();
+ /*
+ * Steps to enable RTC
+ * 1. Enable the module clock domains (rtc_clk_init).
+ * 2. Enable the RTC module using CTRL_REG.RTC_disable. (Default enabled. Nothing done)
+ * 3. Enable the 32K clock from PER PLL, if using the internal RTC oscillator.
+ * 4. Write to the kick registers (KICK0R, KICK1R) in the RTC.
+ * 5. Configure the timer in RTCSS for desired application (set time and date, alarm wakeup, and so on).
+ * 6. Start the RTC (in CTRL_REG.STOP_RTC).
+ */
+ rtc_write_enable();
+ a = setbit(a,0);
+ mmio_write(AM335X_RTC_BASE+AM335X_RTC_SYSCONFIG,a);
+ a = mmio_read(AM335X_RTC_BASE+AM335X_RTC_OSC_CLOCK);
+ a = setbit(a,6);
+ mmio_write(AM335X_RTC_BASE+AM335X_RTC_OSC_CLOCK,a);
+ a = mmio_read(AM335X_RTC_BASE+AM335X_RTC_CTRL_REG);
+ a = setbit(a,0);
+ mmio_write(AM335X_RTC_BASE+AM335X_RTC_CTRL_REG,a);
+
+ rtc_write_disable();
+}
+
+int am335x_rtc_gettime(int minor,rtems_time_of_day *t)
+{
+ uint32_t a = 0x0;
+
+ if(minor != 0)
+ return RTEMS_INVALID_NUMBER;
+
+ a = mmio_read(AM335X_RTC_BASE+AM335X_RTC_SECS);
+ t->second = bcd(a);
+ a = mmio_read(AM335X_RTC_BASE+AM335X_RTC_MINS);
+ t->minute = bcd(a);
+ a = mmio_read(AM335X_RTC_BASE+AM335X_RTC_HOURS);
+ t->hour = bcd(a);
+ a = mmio_read(AM335X_RTC_BASE+AM335X_RTC_DAYS);
+ t->day = bcd(a);
+ a = mmio_read(AM335X_RTC_BASE+AM335X_RTC_MONTHS);
+ t->month = bcd(a);
+ a = mmio_read(AM335X_RTC_BASE+AM335X_RTC_YEARS);
+ t->year = bcd(a)+2000;
+ t->ticks=0;
+ return RTEMS_SUCCESSFUL;
+}
+
+int am335x_rtc_settime(int minor,const rtems_time_of_day *t)
+{
+ uint32_t a=0x0;
+ int rv;
+
+ if(minor != 0)
+ return RTEMS_INVALID_NUMBER;
+
+ rtc_write_enable();
+
+ /* Wait till the busy bit is reset to write again*/
+ a = t->second;
+ rv=rtc_write_wait();
+ if(rv != RTEMS_SUCCESSFUL)
+ return rv;
+ a = mmio_write(AM335X_RTC_BASE+AM335X_RTC_SECS,dec(a) & 0x7f);
+
+ a = t->minute;
+ rv=rtc_write_wait();
+ if(rv != RTEMS_SUCCESSFUL)
+ return rv;
+ a = mmio_write(AM335X_RTC_BASE+AM335X_RTC_MINS,dec(a) & 0x7f);
+
+ a = t->hour;
+ rv=rtc_write_wait();
+ if(rv != RTEMS_SUCCESSFUL)
+ return rv;
+ a = mmio_write(AM335X_RTC_BASE+AM335X_RTC_HOURS,dec(a) & 0x3f);
+
+ a = t->day;
+ rv=rtc_write_wait();
+ if(rv != RTEMS_SUCCESSFUL)
+ return rv;
+ a = mmio_write(AM335X_RTC_BASE+AM335X_RTC_DAYS,dec(a) & 0x3f);
+
+ a = t->month;
+ rv=rtc_write_wait();
+ if(rv != RTEMS_SUCCESSFUL)
+ return rv;
+ a = mmio_write(AM335X_RTC_BASE+AM335X_RTC_MONTHS,dec(a) & 0x1f);
+
+ a = t->year;
+ rv=rtc_write_wait();
+ if(rv != RTEMS_SUCCESSFUL)
+ return rv;
+ a = mmio_write(AM335X_RTC_BASE+AM335X_RTC_YEARS,(dec(a)%100) & 0xff);
+
+ rtc_write_disable();
+ return rv;
+}
+
+#if BBB_DEBUG
+void print_time(void)
+{
+ uint32_t a = 0x0;
+ a = mmio_read(AM335X_RTC_BASE+AM335X_RTC_SECS);
+ printk("\n\rSecs %x",a);
+ a = mmio_read(AM335X_RTC_BASE+AM335X_RTC_MINS);
+ printk("\n\rMins %x",a);
+ a = mmio_read(AM335X_RTC_BASE+AM335X_RTC_HOURS);
+ printk("\n\rHours %x",a);
+ a = mmio_read(AM335X_RTC_BASE+AM335X_RTC_DAYS);
+ printk("\n\rDays %x",a);
+ a = mmio_read(AM335X_RTC_BASE+AM335X_RTC_MONTHS);
+ printk("\n\r Months %x",a);
+ a = mmio_read(AM335X_RTC_BASE+AM335X_RTC_YEARS);
+ printk("\n\rYears %x",a);
+ a = mmio_read(AM335X_RTC_BASE+AM335X_RTC_WEEKS);
+ printk("\n\rWeeks %x",a);
+}
+
+void am335x_rtc_debug(void)
+{
+ int i;
+ rtems_time_of_day t,r;
+
+ t.second = 1;
+ t.minute = 1;
+ t.hour = 1;
+ t.day = 7;
+ t.month = 3;
+ t. year = 2015;
+
+ am335x_rtc_settime(0,&t);
+ am335x_rtc_gettime(0,&r);
+
+ printk("Secs %x",r.second);
+ printk("Mins %x",r.minute);
+ printk("Hours %x",r.hour);
+ printk("Days %x",r.day);
+ printk("Months %x",r.month);
+ printk("Years %x",r.year);
+}
+#endif
+
+/*
+ * driver function table.
+ */
+rtc_fns am335x_rtc_fns = {
+ rtc_init,
+ am335x_rtc_gettime,
+ am335x_rtc_settime
+};
+
+/*
+ * the following table configures the RTC drivers used in this BSP
+ */
+
+rtc_tbl RTC_Table[] = {
+ {
+ "/dev/rtc", /* sDeviceName */
+ RTC_CUSTOM, /* deviceType */
+ &am335x_rtc_fns, /* pDeviceFns */
+ am335x_rtc_probe, /* deviceProbe */
+ NULL, /* pDeviceParams */
+ 0, /* ulCtrlPort1 */
+ 0, /* ulDataPort */
+ NULL, /* getRegister */
+ NULL /* setRegister */
+ }
+};
+
+#endif