source: rtems/c/src/lib/libcpu/m68k/mcf5272/clock/ckinit.c @ 5c9be63

4.104.114.95
Last change on this file since 5c9be63 was 0f9ecc4e, checked in by Joel Sherrill <joel.sherrill@…>, on 12/11/07 at 15:45:54

2007-12-11 Joel Sherrill <joel.sherrill@…>

  • mcf5206/clock/ckinit.c, mcf5272/clock/ckinit.c: Eliminate copies of the Configuration Table. Use the RTEMS provided accessor macros to obtain configuration fields.
  • Property mode set to 100644
File size: 6.2 KB
Line 
1/*
2 *  Clock Driver for MCF5272 CPU
3 *
4 *  This driver initailizes timer1 on the MCF5272 as the
5 *  main system clock
6 *
7 *  Copyright 2004 Cogent Computer Systems
8 *  Author: Jay Monkman <jtm@lopingdog.com>
9 *
10 *  Based on MCF5206 clock driver by
11 *    Victor V. Vengerov <vvv@oktet.ru>
12 *
13 *  Based on work:
14 *    David Fiddes, D.J@fiddes.surfaid.org
15 *    http://www.calm.hw.ac.uk/davidf/coldfire/
16 *
17 *  COPYRIGHT (c) 1989-1998.
18 *  On-Line Applications Research Corporation (OAR).
19 *
20 *  The license and distribution terms for this file may be
21 *  found in the file LICENSE in this distribution or at
22 *
23 *  http://www.rtems.com/license/LICENSE.
24 *
25 *  ckinit.c,v 1.1 2001/10/26 19:32:40 joel Exp
26 */
27
28#include <stdlib.h>
29#include <bsp.h>
30#include <rtems/libio.h>
31#include <mcf5272/mcf5272.h>
32
33/*
34 * Clock_driver_ticks is a monotonically increasing counter of the
35 * number of clock ticks since the driver was initialized.
36 */
37volatile uint32_t Clock_driver_ticks;
38
39
40/*
41 * These are set by clock driver during its init
42 */
43 
44rtems_device_major_number rtems_clock_major = ~0;
45rtems_device_minor_number rtems_clock_minor;
46
47rtems_isr (*rtems_clock_hook)(rtems_vector_number) = NULL;
48
49/* Clock_isr --
50 *     This handles the timer interrupt by clearing the timer's interrupt
51 *     flag and announcing the clock tick to the system.
52 *
53 * PARAMETERS:
54 *     vector - timer interrupt vector number
55 
56 * RETURNS:
57 *     none
58 */
59rtems_isr
60Clock_isr (rtems_vector_number vector)
61{
62    /* Clear pending interrupt... */
63    g_timer_regs->ter1 = MCF5272_TER_REF | MCF5272_TER_CAP;
64
65    /* Announce the clock tick */
66    Clock_driver_ticks++;
67    rtems_clock_tick();
68    if (rtems_clock_hook != NULL) {
69        rtems_clock_hook(vector);
70    }
71}
72
73
74/* Clock_exit --
75 *     This shuts down the timer if it was enabled and removes it
76 *     from the MCF5206E interrupt mask.
77 *
78 * PARAMETERS:
79 *     none
80 *
81 * RETURNS:
82 *     none
83 */
84void
85Clock_exit(void)
86{
87    if (rtems_configuration_get_ticks_per_timeslice()) {
88        uint32_t icr;
89        /* disable all timer1 interrupts */
90        icr = g_intctrl_regs->icr1;
91        icr = icr & ~(MCF5272_ICR1_TMR1_MASK | MCF5272_ICR1_TMR1_PI);
92        icr |= (MCF5272_ICR1_TMR1_IPL(0) | MCF5272_ICR1_TMR1_PI);
93        g_intctrl_regs->icr1 = icr;
94       
95        /* reset timer1 */
96        g_timer_regs->tmr1 = MCF5272_TMR_CLK_STOP;
97       
98        /* clear pending */
99        g_timer_regs->ter1 = MCF5272_TER_REF | MCF5272_TER_CAP;
100    }
101}
102
103
104/* Install_clock --
105 *     This initialises timer1 with the BSP timeslice config value
106 *     as a reference and sets up the interrupt handler for clock ticks.
107 *
108 * PARAMETERS:
109 *     clock_isr - clock interrupt handler routine
110 *
111 * RETURNS:
112 *     none.
113 */
114static void
115Install_clock(rtems_isr_entry clock_isr)
116{
117  uint32_t icr;
118  Clock_driver_ticks = 0;
119  if (rtems_configuration_get_ticks_per_timeslice()) {
120     
121      /* Register the interrupt handler */
122      set_vector(clock_isr, BSP_INTVEC_TMR1, 1);
123     
124      /* Reset timer 1 */
125      g_timer_regs->tmr1 = MCF5272_TMR_RST;
126      g_timer_regs->tmr1 = MCF5272_TMR_CLK_STOP;
127      g_timer_regs->tmr1 = MCF5272_TMR_RST;
128      g_timer_regs->tcn1 = 0;  /* reset counter */
129      g_timer_regs->ter1 = MCF5272_TER_REF | MCF5272_TER_CAP;
130     
131      /* Set Timer 1 prescaler so that it counts in microseconds */
132      g_timer_regs->tmr1 = (
133          ((((BSP_SYSTEM_FREQUENCY / 1000000) - 1) << MCF5272_TMR_PS_SHIFT) |
134           MCF5272_TMR_CE_DISABLE                                      |
135           MCF5272_TMR_ORI                                             |
136           MCF5272_TMR_FRR                                             |
137           MCF5272_TMR_CLK_MSTR                                        |
138           MCF5272_TMR_RST));
139
140      /* Set the timer timeout value from the BSP config */     
141      g_timer_regs->trr1 = rtems_configuration_get_microseconds_per_tick() - 1;
142
143      /* Feed system frequency to the timer */
144      g_timer_regs->tmr1 |= MCF5272_TMR_CLK_MSTR;
145         
146      /* Configure timer1 interrupts */
147      icr = g_intctrl_regs->icr1;
148      icr = icr & ~(MCF5272_ICR1_TMR1_MASK | MCF5272_ICR1_TMR1_PI);
149      icr |= (MCF5272_ICR1_TMR1_IPL(BSP_INTLVL_TMR1) | MCF5272_ICR1_TMR1_PI);
150      g_intctrl_regs->icr1 = icr;
151
152      /* Register the driver exit procedure so we can shutdown */
153      atexit(Clock_exit);
154  }
155}
156
157
158/* Clock_initialize --
159 *     This is called to setup the clock driver. It calls the hardware
160 *     setup function and make the driver major/minor values available
161 *     for other.
162 *
163 * PARAMETERS:
164 *     major - clock device major number
165 *     minor - clock device minor number
166 *     pargp - device driver initialization argument (not used)
167 *
168 * RETURNS:
169 *     RTEMS status code
170 */
171rtems_device_driver
172Clock_initialize(rtems_device_major_number major,
173                 rtems_device_minor_number minor,
174                 void *pargp)
175{
176    Install_clock (Clock_isr);
177 
178    /* Make major/minor avail to others such as shared memory driver */
179    rtems_clock_major = major;
180    rtems_clock_minor = minor;
181 
182    return RTEMS_SUCCESSFUL;
183}
184 
185
186/* Clock_control --
187 *     I/O control (IOCTL) function for Clock driver. At this moment this
188 *     just runs the interrupt handler or re-registers the interrupt handler
189 *     on request.
190 *
191 * PARAMETERS:
192 *     major - clock major device number
193 *     minor - clock minor device number
194 *     pargp - pointer to IOCTL arguments
195 *
196 * RETURNS:
197 *     RTEMS status code
198 */
199rtems_device_driver
200Clock_control(rtems_device_major_number major,
201              rtems_device_minor_number minor,
202              void *pargp)
203{
204    uint32_t isrlevel;
205    rtems_libio_ioctl_args_t *args = pargp;
206
207    if (args)
208    {
209        /*
210         * This is hokey, but until we get a defined interface
211         * to do this, it will just be this simple...
212         */
213        if (args->command == rtems_build_name('I', 'S', 'R', ' '))
214        {
215            Clock_isr(BSP_INTVEC_TMR1);
216        }
217        else if (args->command == rtems_build_name('N', 'E', 'W', ' '))
218        {
219            rtems_interrupt_disable( isrlevel );
220            (void) set_vector( args->buffer, BSP_INTVEC_TMR1, 1 );
221            rtems_interrupt_enable( isrlevel );
222        }
223    }
224    return RTEMS_SUCCESSFUL;
225}
Note: See TracBrowser for help on using the repository browser.