Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:22:48

0001 /**
0002  * @file
0003  *
0004  * @ingroup arm_beagle
0005  *
0006  * @brief Clock driver configuration.
0007  */
0008 
0009 /*
0010  * Copyright (c) 2014 Ben Gras <beng@shrike-systems.com>.
0011  *
0012  * The license and distribution terms for this file may be
0013  * found in the file LICENSE in this distribution or at
0014  * http://www.rtems.org/license/LICENSE.
0015  */
0016 
0017 #include <rtems.h>
0018 #include <rtems/timecounter.h>
0019 #include <bsp.h>
0020 
0021 #include <libcpu/omap_timer.h>
0022 
0023 static struct timecounter beagle_clock_tc;
0024 
0025 static omap_timer_registers_t regs_v1 = {
0026   .TIDR = OMAP3_TIMER_TIDR,
0027   .TIOCP_CFG = OMAP3_TIMER_TIOCP_CFG,
0028   .TISTAT = OMAP3_TIMER_TISTAT,
0029   .TISR = OMAP3_TIMER_TISR,
0030   .TIER = OMAP3_TIMER_TIER,
0031   .TWER = OMAP3_TIMER_TWER,
0032   .TCLR = OMAP3_TIMER_TCLR,
0033   .TCRR = OMAP3_TIMER_TCRR,
0034   .TLDR = OMAP3_TIMER_TLDR,
0035   .TTGR = OMAP3_TIMER_TTGR,
0036   .TWPS = OMAP3_TIMER_TWPS,
0037   .TMAR = OMAP3_TIMER_TMAR,
0038   .TCAR1 = OMAP3_TIMER_TCAR1,
0039   .TSICR = OMAP3_TIMER_TSICR,
0040   .TCAR2 = OMAP3_TIMER_TCAR2,
0041   .TPIR = OMAP3_TIMER_TPIR,
0042   .TNIR = OMAP3_TIMER_TNIR,
0043   .TCVR = OMAP3_TIMER_TCVR,
0044   .TOCR = OMAP3_TIMER_TOCR,
0045   .TOWR = OMAP3_TIMER_TOWR,
0046 };
0047 
0048 #if IS_AM335X
0049 /* AM335X has a different ip block for the non 1ms timers */
0050 static omap_timer_registers_t regs_v2 = {
0051   .TIDR = AM335X_TIMER_TIDR,
0052   .TIOCP_CFG = AM335X_TIMER_TIOCP_CFG,
0053   .TISTAT = AM335X_TIMER_IRQSTATUS_RAW,
0054   .TISR = AM335X_TIMER_IRQSTATUS,
0055   .TIER = AM335X_TIMER_IRQENABLE_SET,
0056   .TWER = AM335X_TIMER_IRQWAKEEN,
0057   .TCLR = AM335X_TIMER_TCLR,
0058   .TCRR = AM335X_TIMER_TCRR,
0059   .TLDR = AM335X_TIMER_TLDR,
0060   .TTGR = AM335X_TIMER_TTGR,
0061   .TWPS = AM335X_TIMER_TWPS,
0062   .TMAR = AM335X_TIMER_TMAR,
0063   .TCAR1 = AM335X_TIMER_TCAR1,
0064   .TSICR = AM335X_TIMER_TSICR,
0065   .TCAR2 = AM335X_TIMER_TCAR2,
0066   .TPIR = -1,       /* UNDEF */
0067   .TNIR = -1,       /* UNDEF */
0068   .TCVR = -1,       /* UNDEF */
0069   .TOCR = -1,       /* UNDEF */
0070   .TOWR = -1        /* UNDEF */
0071 };
0072 #endif
0073 
0074 /* which timers are in use? target-dependent.
0075  * initialize at compile time.
0076  */
0077 
0078 #if IS_DM3730
0079 
0080 static omap_timer_t dm37xx_timer = {
0081   .base = OMAP3_GPTIMER1_BASE,
0082   .irq_nr = OMAP3_GPT1_IRQ,
0083   .regs = &regs_v1
0084 };
0085 
0086 /* free running timer */
0087 static omap_timer_t dm37xx_fr_timer = {
0088   .base = OMAP3_GPTIMER10_BASE,
0089   .irq_nr = OMAP3_GPT10_IRQ,
0090   .regs = &regs_v1
0091 };
0092 
0093 static struct omap_timer *fr_timer = &dm37xx_fr_timer;
0094 static struct omap_timer *timer = &dm37xx_timer;
0095 
0096 #endif
0097 
0098 #if IS_AM335X
0099 
0100 /* normal timer */
0101 static omap_timer_t am335x_timer = {
0102   .base = AM335X_DMTIMER1_1MS_BASE,
0103   .irq_nr = AM335X_INT_TINT1_1MS,
0104   .regs = &regs_v1
0105 };
0106 
0107 /* free running timer */
0108 static omap_timer_t am335x_fr_timer = {
0109   .base = AM335X_DMTIMER7_BASE,
0110   .irq_nr = AM335X_INT_TINT7,
0111   .regs = &regs_v2
0112 };
0113 
0114 static struct omap_timer *fr_timer = &am335x_fr_timer;
0115 static struct omap_timer *timer = &am335x_timer;
0116 
0117 #endif
0118 
0119 #if IS_AM335X
0120 #define FRCLOCK_HZ (16*1500000)
0121 #endif
0122 
0123 #if IS_DM3730
0124 #define FRCLOCK_HZ (8*1625000)
0125 #endif
0126 
0127 #ifndef FRCLOCK_HZ
0128 #error expected IS_AM335X or IS_DM3730 to be defined.
0129 #endif
0130 
0131 static void
0132 omap3_frclock_init(void)
0133 {
0134   uint32_t tisr;
0135 
0136 #if IS_DM3730
0137   /* Stop timer */
0138   mmio_clear(fr_timer->base + fr_timer->regs->TCLR,
0139       OMAP3_TCLR_ST);
0140 
0141   /* Use functional clock source for GPTIMER10 */
0142   mmio_set(OMAP3_CM_CLKSEL_CORE, OMAP3_CLKSEL_GPT10);
0143 #endif
0144 
0145 #if IS_AM335X
0146   /* Disable the module and wait for the module to be disabled */
0147   set32(CM_PER_TIMER7_CLKCTRL, CM_MODULEMODE_MASK,
0148       CM_MODULEMODE_DISABLED);
0149   while ((mmio_read(CM_PER_TIMER7_CLKCTRL) & CM_CLKCTRL_IDLEST)
0150       != CM_CLKCTRL_IDLEST_DISABLE);
0151 
0152   set32(CLKSEL_TIMER7_CLK, CLKSEL_TIMER7_CLK_SEL_MASK,
0153       CLKSEL_TIMER7_CLK_SEL_SEL2);
0154   while ((read32(CLKSEL_TIMER7_CLK) & CLKSEL_TIMER7_CLK_SEL_MASK)
0155       != CLKSEL_TIMER7_CLK_SEL_SEL2);
0156 
0157   /* enable the module and wait for the module to be ready */
0158   set32(CM_PER_TIMER7_CLKCTRL, CM_MODULEMODE_MASK,
0159       CM_MODULEMODE_ENABLE);
0160   while ((mmio_read(CM_PER_TIMER7_CLKCTRL) & CM_CLKCTRL_IDLEST)
0161       != CM_CLKCTRL_IDLEST_FUNC);
0162 
0163   /* Stop timer */
0164   mmio_clear(fr_timer->base + fr_timer->regs->TCLR,
0165       OMAP3_TCLR_ST);
0166 #endif
0167 
0168   /* Start and auto-reload at 0 */
0169   mmio_write(fr_timer->base + fr_timer->regs->TLDR, 0x0);
0170   mmio_write(fr_timer->base + fr_timer->regs->TCRR, 0x0);
0171 
0172   /* Set up overflow interrupt */
0173   tisr = OMAP3_TISR_MAT_IT_FLAG | OMAP3_TISR_OVF_IT_FLAG |
0174       OMAP3_TISR_TCAR_IT_FLAG;
0175   /* Clear interrupt status */
0176   mmio_write(fr_timer->base + fr_timer->regs->TISR, tisr);
0177   mmio_write(fr_timer->base + fr_timer->regs->TIER,
0178       OMAP3_TIER_OVF_IT_ENA);
0179 
0180   /* Start timer, without prescaler */
0181   mmio_set(fr_timer->base + fr_timer->regs->TCLR,
0182       OMAP3_TCLR_OVF_TRG | OMAP3_TCLR_AR | OMAP3_TCLR_ST);
0183 }
0184 
0185 static uint32_t
0186 beagle_clock_get_timecount(struct timecounter *tc)
0187 {
0188   return mmio_read(fr_timer->base + fr_timer->regs->TCRR);
0189 }
0190 
0191 static void
0192 beagle_clock_initialize(void)
0193 {
0194   uint32_t freq = 1000000UL/rtems_configuration_get_microseconds_per_tick();
0195 
0196   /* we only support 1ms resolution */
0197   uint32_t tisr;
0198 #if IS_DM3730
0199   /* Stop timer */
0200   mmio_clear(timer->base + timer->regs->TCLR, OMAP3_TCLR_ST);
0201 
0202   /* Use 32 KHz clock source for GPTIMER1 */
0203   mmio_clear(OMAP3_CM_CLKSEL_WKUP, OMAP3_CLKSEL_GPT1);
0204 #endif
0205 
0206 #if IS_AM335X
0207   /* disable the module and wait for the module to be disabled */
0208   set32(CM_WKUP_TIMER1_CLKCTRL, CM_MODULEMODE_MASK,
0209       CM_MODULEMODE_DISABLED);
0210   while ((mmio_read(CM_WKUP_TIMER1_CLKCTRL) & CM_CLKCTRL_IDLEST)
0211       != CM_CLKCTRL_IDLEST_DISABLE);
0212 
0213   set32(CLKSEL_TIMER1MS_CLK, CLKSEL_TIMER1MS_CLK_SEL_MASK,
0214       CLKSEL_TIMER1MS_CLK_SEL_SEL2);
0215   while ((read32(CLKSEL_TIMER1MS_CLK) &
0216     CLKSEL_TIMER1MS_CLK_SEL_MASK) !=
0217       CLKSEL_TIMER1MS_CLK_SEL_SEL2);
0218 
0219   /* enable the module and wait for the module to be ready */
0220   set32(CM_WKUP_TIMER1_CLKCTRL, CM_MODULEMODE_MASK,
0221       CM_MODULEMODE_ENABLE);
0222   while ((mmio_read(CM_WKUP_TIMER1_CLKCTRL) & CM_CLKCTRL_IDLEST)
0223       != CM_CLKCTRL_IDLEST_FUNC);
0224 
0225   /* Stop timer */
0226   mmio_clear(timer->base + timer->regs->TCLR, OMAP3_TCLR_ST);
0227 #endif
0228 
0229   /* Use 1-ms tick mode for GPTIMER1 TRM 16.2.4.2.1 */
0230   mmio_write(timer->base + timer->regs->TPIR, 232000);
0231   mmio_write(timer->base + timer->regs->TNIR, -768000);
0232   mmio_write(timer->base + timer->regs->TLDR,
0233       0xffffffff - (32768 / freq) + 1);
0234   mmio_write(timer->base + timer->regs->TCRR,
0235       0xffffffff - (32768 / freq) + 1);
0236 
0237   /* Set up overflow interrupt */
0238   tisr = OMAP3_TISR_MAT_IT_FLAG | OMAP3_TISR_OVF_IT_FLAG |
0239       OMAP3_TISR_TCAR_IT_FLAG;
0240   /* Clear interrupt status */
0241   mmio_write(timer->base + timer->regs->TISR, tisr);
0242   mmio_write(timer->base + timer->regs->TIER, OMAP3_TIER_OVF_IT_ENA);
0243 
0244   /* Start timer */
0245   mmio_set(timer->base + timer->regs->TCLR,
0246       OMAP3_TCLR_OVF_TRG | OMAP3_TCLR_AR | OMAP3_TCLR_ST);
0247   /* also initilize the free runnning timer */
0248   omap3_frclock_init();
0249 
0250 #if IS_AM335X
0251   /* Disable AM335X watchdog */
0252   mmio_write(AM335X_WDT_BASE+AM335X_WDT_WSPR, 0xAAAA);
0253   while(mmio_read(AM335X_WDT_BASE+AM335X_WDT_WWPS) != 0) ;
0254   mmio_write(AM335X_WDT_BASE+AM335X_WDT_WSPR, 0x5555);
0255   while(mmio_read(AM335X_WDT_BASE+AM335X_WDT_WWPS) != 0) ;
0256 #endif
0257 
0258   /* Install timecounter */ \
0259   beagle_clock_tc.tc_get_timecount = beagle_clock_get_timecount;
0260   beagle_clock_tc.tc_counter_mask = 0xffffffff;
0261   beagle_clock_tc.tc_frequency = FRCLOCK_HZ;
0262   beagle_clock_tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
0263   rtems_timecounter_install(&beagle_clock_tc);
0264 }
0265 
0266 static void beagle_clock_at_tick(void)
0267 {
0268   mmio_write(timer->base + timer->regs->TISR,
0269     OMAP3_TISR_MAT_IT_FLAG | OMAP3_TISR_OVF_IT_FLAG |
0270       OMAP3_TISR_TCAR_IT_FLAG);
0271 }
0272 
0273 static rtems_interrupt_handler clock_isr = NULL;
0274 
0275 static void beagle_clock_handler_install(rtems_interrupt_handler isr)
0276 {
0277   rtems_status_code sc = RTEMS_SUCCESSFUL;
0278 
0279   sc = rtems_interrupt_handler_install(
0280     timer->irq_nr,
0281     "Clock",
0282     RTEMS_INTERRUPT_UNIQUE,
0283     isr,
0284     NULL
0285   );
0286 
0287   if (sc != RTEMS_SUCCESSFUL) {
0288     rtems_fatal_error_occurred(0xdeadbeef);
0289   }
0290   clock_isr = isr;
0291 }
0292 
0293 #define Clock_driver_support_at_tick(arg) beagle_clock_at_tick()
0294 #define Clock_driver_support_initialize_hardware() beagle_clock_initialize()
0295 #define Clock_driver_support_install_isr(isr) \
0296   beagle_clock_handler_install(isr)
0297 
0298 /* Include shared source clock driver code */
0299 #include "../../shared/dev/clock/clockimpl.h"