source: rtems/c/src/lib/libbsp/powerpc/mpc55xxevb/clock/clock-config.c @ c082b575

4.115
Last change on this file since c082b575 was c082b575, checked in by Sebastian Huber <sebastian.huber@…>, on 02/05/13 at 16:23:55

bsp/mpc55xx: Add and use BSP specific fatal codes

  • Property mode set to 100644
File size: 5.6 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup mpc55xx
5 *
6 * @brief Clock driver configuration.
7 */
8
9/*
10 * Copyright (c) 2009-2011 embedded brains GmbH.  All rights reserved.
11 *
12 *  embedded brains GmbH
13 *  Obere Lagerstr. 30
14 *  82178 Puchheim
15 *  Germany
16 *  <rtems@embedded-brains.de>
17 *
18 * The license and distribution terms for this file may be
19 * found in the file LICENSE in this distribution or at
20 * http://www.rtems.com/license/LICENSE.
21 */
22
23#include <bsp.h>
24#include <bsp/irq.h>
25
26#include <mpc55xx/regs.h>
27
28static uint64_t mpc55xx_clock_factor;
29
30#if defined(MPC55XX_CLOCK_EMIOS_CHANNEL)
31
32#include <mpc55xx/emios.h>
33
34static void mpc55xx_clock_at_tick(void)
35{
36  union EMIOS_CSR_tag csr = MPC55XX_ZERO_FLAGS;
37  csr.B.FLAG = 1;
38  EMIOS.CH [MPC55XX_CLOCK_EMIOS_CHANNEL].CSR.R = csr.R;
39}
40
41static void mpc55xx_clock_handler_install(rtems_isr_entry isr)
42{
43  rtems_status_code sc = RTEMS_SUCCESSFUL;
44
45  sc = mpc55xx_interrupt_handler_install(
46    MPC55XX_IRQ_EMIOS(MPC55XX_CLOCK_EMIOS_CHANNEL),
47    "clock",
48    RTEMS_INTERRUPT_UNIQUE,
49    MPC55XX_INTC_MIN_PRIORITY,
50    (rtems_interrupt_handler) isr,
51    NULL
52  );
53  if (sc != RTEMS_SUCCESSFUL) {
54    mpc55xx_fatal(MPC55XX_FATAL_CLOCK_EMIOS_IRQ_INSTALL);
55  }
56}
57
58static void mpc55xx_clock_initialize(void)
59{
60  volatile struct EMIOS_CH_tag *regs = &EMIOS.CH [MPC55XX_CLOCK_EMIOS_CHANNEL];
61  union EMIOS_CCR_tag ccr = MPC55XX_ZERO_FLAGS;
62  union EMIOS_CSR_tag csr = MPC55XX_ZERO_FLAGS;
63  unsigned prescaler = mpc55xx_emios_global_prescaler();
64  uint64_t reference_clock = bsp_clock_speed;
65  uint64_t us_per_tick = rtems_configuration_get_microseconds_per_tick();
66  uint64_t interval = (reference_clock * us_per_tick) / 1000000;
67
68  mpc55xx_clock_factor = (1000000000ULL << 32) / reference_clock;
69
70  /* Apply prescaler */
71  if (prescaler > 0) {
72    interval /= (uint64_t) prescaler;
73  } else {
74    mpc55xx_fatal(MPC55XX_FATAL_CLOCK_EMIOS_PRESCALER);
75  }
76
77  /* Check interval */
78  if (interval == 0 || interval > MPC55XX_EMIOS_VALUE_MAX) {
79    mpc55xx_fatal(MPC55XX_FATAL_CLOCK_EMIOS_INTERVAL);
80  }
81
82  /* Configure eMIOS channel */
83
84  /* Set channel in GPIO mode */
85  ccr.B.MODE = MPC55XX_EMIOS_MODE_GPIO_INPUT;
86  regs->CCR.R = ccr.R;
87
88  /* Clear status flags */
89  csr.B.OVR = 1;
90  csr.B.OVFL = 1;
91  csr.B.FLAG = 1;
92  regs->CSR.R = csr.R;
93
94  /* Set internal counter start value */
95  regs->CCNTR.R = 1;
96
97  /* Set timer period */
98  regs->CADR.R = (uint32_t) interval - 1;
99
100  /* Set control register */
101  #if MPC55XX_CHIP_FAMILY == 551
102    ccr.B.MODE = MPC55XX_EMIOS_MODE_MCB_UP_INT_CLK;
103  #else
104    ccr.B.MODE = MPC55XX_EMIOS_MODE_MC_UP_INT_CLK;
105  #endif
106  ccr.B.UCPREN = 1;
107  ccr.B.FEN = 1;
108  ccr.B.FREN = 1;
109  regs->CCR.R = ccr.R;
110}
111
112static void mpc55xx_clock_cleanup(void)
113{
114  volatile struct EMIOS_CH_tag *regs = &EMIOS.CH [MPC55XX_CLOCK_EMIOS_CHANNEL];
115  union EMIOS_CCR_tag ccr = MPC55XX_ZERO_FLAGS;
116
117  /* Set channel in GPIO mode */
118  ccr.B.MODE = MPC55XX_EMIOS_MODE_GPIO_INPUT;
119  regs->CCR.R = ccr.R;
120}
121
122static uint32_t mpc55xx_clock_nanoseconds_since_last_tick(void)
123{
124  volatile struct EMIOS_CH_tag *regs = &EMIOS.CH [MPC55XX_CLOCK_EMIOS_CHANNEL];
125  uint64_t c = regs->CCNTR.R;
126  union EMIOS_CSR_tag csr = { .R = regs->CSR.R };
127  uint64_t k = mpc55xx_clock_factor;
128
129  if (csr.B.FLAG != 0) {
130    c = regs->CCNTR.R + regs->CADR.R + 1;
131  }
132
133  return (uint32_t) ((c * k) >> 32);
134}
135
136#elif defined(MPC55XX_CLOCK_PIT_CHANNEL)
137
138static void mpc55xx_clock_at_tick(void)
139{
140  volatile PIT_RTI_CHANNEL_tag *channel =
141    &PIT_RTI.CHANNEL [MPC55XX_CLOCK_PIT_CHANNEL];
142  PIT_RTI_TFLG_32B_tag tflg = { .B = { .TIF = 1 } };
143
144  channel->TFLG.R = tflg.R;
145}
146
147static void mpc55xx_clock_handler_install(rtems_isr_entry isr)
148{
149  rtems_status_code sc = RTEMS_SUCCESSFUL;
150
151  sc = mpc55xx_interrupt_handler_install(
152    MPC55XX_IRQ_PIT_CHANNEL(MPC55XX_CLOCK_PIT_CHANNEL),
153    "clock",
154    RTEMS_INTERRUPT_UNIQUE,
155    MPC55XX_INTC_MIN_PRIORITY,
156    (rtems_interrupt_handler) isr,
157    NULL
158  );
159  if (sc != RTEMS_SUCCESSFUL) {
160    mpc55xx_fatal(MPC55XX_FATAL_CLOCK_PIT_IRQ_INSTALL);
161  }
162}
163
164static void mpc55xx_clock_initialize(void)
165{
166  volatile PIT_RTI_CHANNEL_tag *channel =
167    &PIT_RTI.CHANNEL [MPC55XX_CLOCK_PIT_CHANNEL];
168  uint64_t reference_clock = bsp_clock_speed;
169  uint64_t us_per_tick = rtems_configuration_get_microseconds_per_tick();
170  uint64_t interval = (reference_clock * us_per_tick) / 1000000;
171  PIT_RTI_PITMCR_32B_tag pitmcr = { .B = { .FRZ = 1 } };
172  PIT_RTI_TCTRL_32B_tag tctrl = { .B = { .TIE = 1, .TEN = 1 } };
173
174  mpc55xx_clock_factor = (1000000000ULL << 32) / reference_clock;
175
176  PIT_RTI.PITMCR.R = pitmcr.R;
177  channel->LDVAL.R = interval;
178  channel->TCTRL.R = tctrl.R;
179}
180
181static void mpc55xx_clock_cleanup(void)
182{
183  volatile PIT_RTI_CHANNEL_tag *channel =
184    &PIT_RTI.CHANNEL [MPC55XX_CLOCK_PIT_CHANNEL];
185
186  channel->TCTRL.R = 0;
187}
188
189static uint32_t mpc55xx_clock_nanoseconds_since_last_tick(void)
190{
191  volatile PIT_RTI_CHANNEL_tag *channel =
192    &PIT_RTI.CHANNEL [MPC55XX_CLOCK_PIT_CHANNEL];
193  uint32_t c = channel->CVAL.R;
194  uint32_t i = channel->LDVAL.R;
195  uint64_t k = mpc55xx_clock_factor;
196
197  if (channel->TFLG.B.TIF != 0) {
198    c = channel->CVAL.R - i;
199  }
200
201  return (uint32_t) (((i - c) * k) >> 32);
202}
203
204#endif
205
206#define Clock_driver_support_at_tick() \
207  mpc55xx_clock_at_tick()
208#define Clock_driver_support_initialize_hardware() \
209  mpc55xx_clock_initialize()
210#define Clock_driver_support_install_isr(isr, old_isr) \
211  do { \
212    mpc55xx_clock_handler_install(isr); \
213    old_isr = NULL; \
214  } while (0)
215#define Clock_driver_support_shutdown_hardware() \
216  mpc55xx_clock_cleanup()
217#define Clock_driver_nanoseconds_since_last_tick \
218  mpc55xx_clock_nanoseconds_since_last_tick
219
220/* Include shared source clock driver code */
221#include "../../../../libbsp/shared/clockdrv_shell.h"
Note: See TracBrowser for help on using the repository browser.