forked from Imagelibrary/rtems
bsp/beagle: Move source files to bsps
This patch is a part of the BSP source reorganization. Update #3285.
This commit is contained in:
@@ -71,16 +71,16 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/beagle/console/console-confi
|
||||
librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/beagle/i2c/bbb-i2c.c
|
||||
|
||||
# GPIO
|
||||
librtemsbsp_a_SOURCES += gpio/bbb-gpio.c
|
||||
librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/beagle/gpio/bbb-gpio.c
|
||||
|
||||
#pwm
|
||||
librtemsbsp_a_SOURCES += pwm/pwm.c
|
||||
librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/beagle/pwm/pwm.c
|
||||
|
||||
#RTC
|
||||
librtemsbsp_a_SOURCES += rtc.c
|
||||
librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/beagle/rtc/rtc.c
|
||||
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/rtc/rtc-support.c
|
||||
# Clock
|
||||
librtemsbsp_a_SOURCES += clock.c
|
||||
librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/beagle/clock/clock.c
|
||||
|
||||
# Cache
|
||||
librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/shared/cache/cache-cp15.c
|
||||
|
||||
@@ -1,323 +0,0 @@
|
||||
/**
|
||||
* @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 = ®s_v1
|
||||
};
|
||||
|
||||
/* free running timer */
|
||||
static omap_timer_t dm37xx_fr_timer = {
|
||||
.base = OMAP3_GPTIMER10_BASE,
|
||||
.irq_nr = OMAP3_GPT10_IRQ,
|
||||
.regs = ®s_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 = ®s_v1
|
||||
};
|
||||
|
||||
/* free running timer */
|
||||
static omap_timer_t am335x_fr_timer = {
|
||||
.base = AM335X_DMTIMER7_BASE,
|
||||
.irq_nr = AM335X_INT_TINT7,
|
||||
.regs = ®s_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"
|
||||
@@ -1,564 +0,0 @@
|
||||
/**
|
||||
* @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 */
|
||||
@@ -1,454 +0,0 @@
|
||||
/**
|
||||
* @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
|
||||
@@ -1,276 +0,0 @@
|
||||
/**
|
||||
* @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
|
||||
Reference in New Issue
Block a user