source: rtems/bsps/m68k/uC5282/clock/clock.c @ d7d66d7

5
Last change on this file since d7d66d7 was 7632906, checked in by Sebastian Huber <sebastian.huber@…>, on 04/19/18 at 04:35:52

bsps: Move clock drivers to bsps

This patch is a part of the BSP source reorganization.

Update #3285.

  • Property mode set to 100644
File size: 5.5 KB
Line 
1/*
2 * Use the last periodic interval timer (PIT3) as the system clock.
3 *
4 *  Author: W. Eric Norum <norume@aps.anl.gov>
5 *
6 *  COPYRIGHT (c) 2005.
7 *  On-Line Applications Research Corporation (OAR).
8 *
9 *  The license and distribution terms for this file may be
10 *  found in the file LICENSE in this distribution or at
11 *  http://www.rtems.org/license/LICENSE.
12 */
13
14#include <rtems.h>
15#include <rtems/timecounter.h>
16#include <bsp.h>
17#include <mcf5282/mcf5282.h>
18
19/*
20 * CPU load counters
21 * Place in static RAM so updates don't hit the SDRAM
22 */
23#define IDLE_COUNTER    __SRAMBASE.idle_counter
24#define FILTERED_IDLE   __SRAMBASE.filtered_idle
25#define MAX_IDLE_COUNT  __SRAMBASE.max_idle_count
26#define PITC_PER_TICK   __SRAMBASE.pitc_per_tick
27#define NSEC_PER_PITC   __SRAMBASE.nsec_per_pitc
28#define FILTER_SHIFT    6
29
30/*
31 * Use INTC0 base
32 */
33#define CLOCK_VECTOR (64+58)
34
35static rtems_timecounter_simple uC5282_tc;
36
37static uint32_t uC5282_tc_get(rtems_timecounter_simple *tc)
38{
39  return MCF5282_PIT3_PCNTR;
40}
41
42static bool uC5282_tc_is_pending(rtems_timecounter_simple *tc)
43{
44  return (MCF5282_PIT3_PCSR & MCF5282_PIT_PCSR_PIF) != 0;
45}
46
47static uint32_t uC5282_tc_get_timecount(struct timecounter *tc)
48{
49  return rtems_timecounter_simple_downcounter_get(
50    tc,
51    uC5282_tc_get,
52    uC5282_tc_is_pending
53  );
54}
55
56static void uC5282_tc_at_tick(rtems_timecounter_simple *tc)
57{
58  unsigned idle = IDLE_COUNTER;
59  IDLE_COUNTER = 0;
60  if (idle > MAX_IDLE_COUNT)
61    MAX_IDLE_COUNT = idle;
62  FILTERED_IDLE = idle + FILTERED_IDLE - (FILTERED_IDLE>>FILTER_SHIFT);
63  MCF5282_PIT3_PCSR |= MCF5282_PIT_PCSR_PIF;
64}
65
66static void uC5282_tc_tick(void)
67{
68  rtems_timecounter_simple_downcounter_tick(
69    &uC5282_tc,
70    uC5282_tc_get,
71    uC5282_tc_at_tick
72  );
73}
74
75/*
76 * Attach clock interrupt handler
77 */
78#define Clock_driver_support_install_isr( _new ) \
79    set_vector(_new, CLOCK_VECTOR, 1)
80
81/*
82 * Turn off the clock
83 */
84#define Clock_driver_support_shutdown_hardware()   \
85    do {                                           \
86        MCF5282_PIT3_PCSR &= ~MCF5282_PIT_PCSR_EN; \
87    } while(0)
88
89/*
90 * Set up the clock hardware
91 *
92 * f_pit = f_clk / 2^(preScaleCode+1) / N  = 1/(us_per_tick/us_per_s)
93 *
94 * N = f_clk / 2^(preScaleCode+1) * us_per_tick / us_per_s
95 *
96 * ns_per_pit_clk = ns_per_s / (f_clk / 2^(preScaleCode+1))
97 *                = ns_per_s * 2^(preScaleCode+1) / f_clk;
98 */
99#define Clock_driver_support_initialize_hardware()                       \
100    do {                                                                 \
101        unsigned long long N;                                            \
102        int level;                                                       \
103        int preScaleCode = 0;                                            \
104                N  = bsp_get_CPU_clock_speed();                                  \
105                N *= rtems_configuration_get_microseconds_per_tick();            \
106                N /= 2*1000000; /* min_prescale * us_per_s */                    \
107                while ( N > 0x10000 ) {                                          \
108                        preScaleCode++;                                              \
109                        N >>= 1;                                                     \
110                }                                                                \
111                PITC_PER_TICK  = N;                                              \
112                N  = 2000000000ULL << preScaleCode;                              \
113                N /= bsp_get_CPU_clock_speed();                                  \
114                NSEC_PER_PITC  = N;                                              \
115        IDLE_COUNTER   = 0;                                              \
116        FILTERED_IDLE  = 0;                                              \
117        MAX_IDLE_COUNT = 0;                                              \
118        bsp_allocate_interrupt(PIT3_IRQ_LEVEL, PIT3_IRQ_PRIORITY);       \
119        MCF5282_INTC0_ICR58 = MCF5282_INTC_ICR_IL(PIT3_IRQ_LEVEL) |      \
120                              MCF5282_INTC_ICR_IP(PIT3_IRQ_PRIORITY);    \
121        rtems_interrupt_disable( level );                                \
122        MCF5282_INTC0_IMRH &= ~MCF5282_INTC_IMRH_INT58;                  \
123        MCF5282_PIT3_PCSR &= ~MCF5282_PIT_PCSR_EN;                       \
124        rtems_interrupt_enable( level );                                 \
125        MCF5282_PIT3_PCSR = MCF5282_PIT_PCSR_PRE(preScaleCode) |         \
126                            MCF5282_PIT_PCSR_OVW |                       \
127                            MCF5282_PIT_PCSR_PIE |                       \
128                            MCF5282_PIT_PCSR_RLD;                        \
129        MCF5282_PIT3_PMR = PITC_PER_TICK - 1;                            \
130        MCF5282_PIT3_PCSR = MCF5282_PIT_PCSR_PRE(preScaleCode) |         \
131                            MCF5282_PIT_PCSR_PIE |                       \
132                            MCF5282_PIT_PCSR_RLD |                       \
133                            MCF5282_PIT_PCSR_EN;                         \
134         rtems_timecounter_simple_install( \
135           &uC5282_tc, \
136           bsp_get_CPU_clock_speed() >> (preScaleCode + 1), \
137           PITC_PER_TICK, \
138           uC5282_tc_get_timecount \
139         ); \
140    } while (0)
141
142/*
143 * Provide our own version of the idle task
144 */
145void * bsp_idle_thread(uint32_t ignored)
146{
147  /* Atomic increment */
148  for(;;)
149    __asm__ volatile ("addq.l #1,%0"::"m"(IDLE_COUNTER));
150}
151
152int bsp_cpu_load_percentage(void)
153{
154    return MAX_IDLE_COUNT ?
155           (100 - ((100 * (FILTERED_IDLE >> FILTER_SHIFT)) / MAX_IDLE_COUNT)) :
156           0;
157}
158
159#define Clock_driver_timecounter_tick() uC5282_tc_tick()
160
161#include "../../../shared/dev/clock/clockimpl.h"
Note: See TracBrowser for help on using the repository browser.