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:
323
bsps/arm/beagle/clock/clock.c
Normal file
323
bsps/arm/beagle/clock/clock.c
Normal file
@@ -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 = ®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"
|
||||
Reference in New Issue
Block a user