source: rtems/c/src/lib/libbsp/arm/beagle/clock.c @ 13d9029

4.115
Last change on this file since 13d9029 was 13d9029, checked in by Ben Gras <beng@…>, on 12/04/14 at 17:21:11

beagle bsp: disable watchdog on am335x

On recent u-boots, the watchdog is turned on / left enabled. The
Beaglebone Black rev. C ships with such a u-boot internally so any
application booting from it must disable the watchdog.

Therefore this change is needed to boot an RTEMS app out-of-the-box
on a BBB Rev C - otherwise the user button must be held during boot
(to bypass the stock uboot) or the internal uboot must be updated. To
allow for a better out-of-the-box experience, we just turn off the
watchdog.

  • Property mode set to 100644
File size: 8.8 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup arm_beagle
5 *
6 * @brief Clock driver configuration.
7 */
8
9/*
10 * Copyright (c) 2014 Ben Gras <beng@shrike-systems.com>.
11 *
12 * The license and distribution terms for this file may be
13 * found in the file LICENSE in this distribution or at
14 * http://www.rtems.com/license/LICENSE.
15 */
16
17#include <rtems.h>
18#include <bsp.h>
19
20#include <libcpu/omap_timer.h>
21
22#ifdef ARM_MULTILIB_ARCH_V4
23
24static omap_timer_registers_t regs_v1 = {
25  .TIDR = OMAP3_TIMER_TIDR,
26  .TIOCP_CFG = OMAP3_TIMER_TIOCP_CFG,
27  .TISTAT = OMAP3_TIMER_TISTAT,
28  .TISR = OMAP3_TIMER_TISR,
29  .TIER = OMAP3_TIMER_TIER,
30  .TWER = OMAP3_TIMER_TWER,
31  .TCLR = OMAP3_TIMER_TCLR,
32  .TCRR = OMAP3_TIMER_TCRR,
33  .TLDR = OMAP3_TIMER_TLDR,
34  .TTGR = OMAP3_TIMER_TTGR,
35  .TWPS = OMAP3_TIMER_TWPS,
36  .TMAR = OMAP3_TIMER_TMAR,
37  .TCAR1 = OMAP3_TIMER_TCAR1,
38  .TSICR = OMAP3_TIMER_TSICR,
39  .TCAR2 = OMAP3_TIMER_TCAR2,
40  .TPIR = OMAP3_TIMER_TPIR,
41  .TNIR = OMAP3_TIMER_TNIR,
42  .TCVR = OMAP3_TIMER_TCVR,
43  .TOCR = OMAP3_TIMER_TOCR,
44  .TOWR = OMAP3_TIMER_TOWR,
45};
46
47/* AM335X has a different ip block for the non 1ms timers */
48static omap_timer_registers_t regs_v2 = {
49  .TIDR = AM335X_TIMER_TIDR,
50  .TIOCP_CFG = AM335X_TIMER_TIOCP_CFG,
51  .TISTAT = AM335X_TIMER_IRQSTATUS_RAW,
52  .TISR = AM335X_TIMER_IRQSTATUS,
53  .TIER = AM335X_TIMER_IRQENABLE_SET,
54  .TWER = AM335X_TIMER_IRQWAKEEN,
55  .TCLR = AM335X_TIMER_TCLR,
56  .TCRR = AM335X_TIMER_TCRR,
57  .TLDR = AM335X_TIMER_TLDR,
58  .TTGR = AM335X_TIMER_TTGR,
59  .TWPS = AM335X_TIMER_TWPS,
60  .TMAR = AM335X_TIMER_TMAR,
61  .TCAR1 = AM335X_TIMER_TCAR1,
62  .TSICR = AM335X_TIMER_TSICR,
63  .TCAR2 = AM335X_TIMER_TCAR2,
64  .TPIR = -1,           /* UNDEF */
65  .TNIR = -1,           /* UNDEF */
66  .TCVR = -1,           /* UNDEF */
67  .TOCR = -1,           /* UNDEF */
68  .TOWR = -1            /* UNDEF */
69};
70
71/* which timers are in use? target-dependent.
72 * initialize at compile time.
73 */
74
75#if IS_DM3730
76
77static omap_timer_t dm37xx_timer = {
78  .base = OMAP3_GPTIMER1_BASE,
79  .irq_nr = OMAP3_GPT1_IRQ,
80  .regs = &regs_v1
81};
82
83/* free running timer */
84static omap_timer_t dm37xx_fr_timer = {
85  .base = OMAP3_GPTIMER10_BASE,
86  .irq_nr = OMAP3_GPT10_IRQ,
87  .regs = &regs_v1
88};
89
90static struct omap_timer *fr_timer = &dm37xx_fr_timer;
91static struct omap_timer *timer = &dm37xx_timer;
92
93#endif
94
95#if IS_AM335X
96
97/* normal timer */
98static omap_timer_t am335x_timer = {
99  .base = AM335X_DMTIMER1_1MS_BASE,
100  .irq_nr = AM335X_INT_TINT1_1MS,
101  .regs = &regs_v1
102};
103
104/* free running timer */
105static omap_timer_t am335x_fr_timer = {
106  .base = AM335X_DMTIMER7_BASE,
107  .irq_nr = AM335X_INT_TINT7,
108  .regs = &regs_v2
109};
110
111static struct omap_timer *fr_timer = &am335x_fr_timer;
112static struct omap_timer *timer = &am335x_timer;
113
114#endif
115
116static int done = 0;
117
118#if IS_AM335X
119#define FRCLOCK_HZ (16*1500000)
120#endif
121
122#if IS_DM3730
123#define FRCLOCK_HZ (8*1625000)
124#endif
125
126#ifndef FRCLOCK_HZ
127#error expected IS_AM335X or IS_DM3730 to be defined.
128#endif
129
130static void
131omap3_frclock_init(void)
132{
133  uint32_t tisr;
134
135#if IS_DM3730
136  /* Stop timer */
137  mmio_clear(fr_timer->base + fr_timer->regs->TCLR,
138      OMAP3_TCLR_ST);
139
140  /* Use functional clock source for GPTIMER10 */
141  mmio_set(OMAP3_CM_CLKSEL_CORE, OMAP3_CLKSEL_GPT10);
142#endif
143
144#if IS_AM335X
145  /* Disable the module and wait for the module to be disabled */
146  set32(CM_PER_TIMER7_CLKCTRL, CM_MODULEMODE_MASK,
147      CM_MODULEMODE_DISABLED);
148  while ((mmio_read(CM_PER_TIMER7_CLKCTRL) & CM_CLKCTRL_IDLEST)
149      != CM_CLKCTRL_IDLEST_DISABLE);
150
151  set32(CLKSEL_TIMER7_CLK, CLKSEL_TIMER7_CLK_SEL_MASK,
152      CLKSEL_TIMER7_CLK_SEL_SEL2);
153  while ((read32(CLKSEL_TIMER7_CLK) & CLKSEL_TIMER7_CLK_SEL_MASK)
154      != CLKSEL_TIMER7_CLK_SEL_SEL2);
155
156  /* enable the module and wait for the module to be ready */
157  set32(CM_PER_TIMER7_CLKCTRL, CM_MODULEMODE_MASK,
158      CM_MODULEMODE_ENABLE);
159  while ((mmio_read(CM_PER_TIMER7_CLKCTRL) & CM_CLKCTRL_IDLEST)
160      != CM_CLKCTRL_IDLEST_FUNC);
161
162  /* Stop timer */
163  mmio_clear(fr_timer->base + fr_timer->regs->TCLR,
164      OMAP3_TCLR_ST);
165#endif
166
167  /* Start and auto-reload at 0 */
168  mmio_write(fr_timer->base + fr_timer->regs->TLDR, 0x0);
169  mmio_write(fr_timer->base + fr_timer->regs->TCRR, 0x0);
170
171  /* Set up overflow interrupt */
172  tisr = OMAP3_TISR_MAT_IT_FLAG | OMAP3_TISR_OVF_IT_FLAG |
173      OMAP3_TISR_TCAR_IT_FLAG;
174  /* Clear interrupt status */
175  mmio_write(fr_timer->base + fr_timer->regs->TISR, tisr);
176  mmio_write(fr_timer->base + fr_timer->regs->TIER,
177      OMAP3_TIER_OVF_IT_ENA);
178
179  /* Start timer, without prescaler */
180  mmio_set(fr_timer->base + fr_timer->regs->TCLR,
181      OMAP3_TCLR_OVF_TRG | OMAP3_TCLR_AR | OMAP3_TCLR_ST);
182  done = 1;
183}
184
185static inline uint32_t
186read_frc(void)
187{
188  if (done == 0) {
189    return 0;
190  }
191  return mmio_read(fr_timer->base + fr_timer->regs->TCRR);
192}
193
194static uint32_t last_tick_nanoseconds;
195
196static void
197beagle_clock_initialize(void)
198{
199  uint32_t freq = 1000000UL/rtems_configuration_get_microseconds_per_tick();
200
201  /* we only support 1ms resolution */
202  uint32_t tisr;
203#if IS_DM3730
204  /* Stop timer */
205  mmio_clear(timer->base + timer->regs->TCLR, OMAP3_TCLR_ST);
206
207  /* Use 32 KHz clock source for GPTIMER1 */
208  mmio_clear(OMAP3_CM_CLKSEL_WKUP, OMAP3_CLKSEL_GPT1);
209#endif
210
211#if IS_AM335X
212  /* disable the module and wait for the module to be disabled */
213  set32(CM_WKUP_TIMER1_CLKCTRL, CM_MODULEMODE_MASK,
214      CM_MODULEMODE_DISABLED);
215  while ((mmio_read(CM_WKUP_TIMER1_CLKCTRL) & CM_CLKCTRL_IDLEST)
216      != CM_CLKCTRL_IDLEST_DISABLE);
217
218  set32(CLKSEL_TIMER1MS_CLK, CLKSEL_TIMER1MS_CLK_SEL_MASK,
219      CLKSEL_TIMER1MS_CLK_SEL_SEL2);
220  while ((read32(CLKSEL_TIMER1MS_CLK) &
221    CLKSEL_TIMER1MS_CLK_SEL_MASK) !=
222      CLKSEL_TIMER1MS_CLK_SEL_SEL2);
223
224  /* enable the module and wait for the module to be ready */
225  set32(CM_WKUP_TIMER1_CLKCTRL, CM_MODULEMODE_MASK,
226      CM_MODULEMODE_ENABLE);
227  while ((mmio_read(CM_WKUP_TIMER1_CLKCTRL) & CM_CLKCTRL_IDLEST)
228      != CM_CLKCTRL_IDLEST_FUNC);
229
230  /* Stop timer */
231  mmio_clear(timer->base + timer->regs->TCLR, OMAP3_TCLR_ST);
232#endif
233
234  /* Use 1-ms tick mode for GPTIMER1 TRM 16.2.4.2.1 */
235  mmio_write(timer->base + timer->regs->TPIR, 232000);
236  mmio_write(timer->base + timer->regs->TNIR, -768000);
237  mmio_write(timer->base + timer->regs->TLDR,
238      0xffffffff - (32768 / freq) + 1);
239  mmio_write(timer->base + timer->regs->TCRR,
240      0xffffffff - (32768 / freq) + 1);
241
242  /* Set up overflow interrupt */
243  tisr = OMAP3_TISR_MAT_IT_FLAG | OMAP3_TISR_OVF_IT_FLAG |
244      OMAP3_TISR_TCAR_IT_FLAG;
245  /* Clear interrupt status */
246  mmio_write(timer->base + timer->regs->TISR, tisr);
247  mmio_write(timer->base + timer->regs->TIER, OMAP3_TIER_OVF_IT_ENA);
248
249  /* Start timer */
250  mmio_set(timer->base + timer->regs->TCLR,
251      OMAP3_TCLR_OVF_TRG | OMAP3_TCLR_AR | OMAP3_TCLR_ST);
252  /* also initilize the free runnning timer */
253  omap3_frclock_init();
254
255#if IS_AM335X
256  /* Disable AM335X watchdog */
257  mmio_write(AM335X_WDT_BASE+AM335X_WDT_WSPR, 0xAAAA);
258  while(mmio_read(AM335X_WDT_BASE+AM335X_WDT_WWPS) != 0) ;
259  mmio_write(AM335X_WDT_BASE+AM335X_WDT_WSPR, 0x5555);
260  while(mmio_read(AM335X_WDT_BASE+AM335X_WDT_WWPS) != 0) ;
261#endif
262
263}
264
265static void beagle_clock_at_tick(void)
266{
267  uint32_t tisr;
268
269  last_tick_nanoseconds = read_frc();
270
271  mmio_write(timer->base + timer->regs->TISR,
272    OMAP3_TISR_MAT_IT_FLAG | OMAP3_TISR_OVF_IT_FLAG |
273      OMAP3_TISR_TCAR_IT_FLAG);
274}
275
276static rtems_interrupt_handler clock_isr = NULL;
277
278static void beagle_clock_handler_install(rtems_interrupt_handler isr)
279{
280  rtems_status_code sc = RTEMS_SUCCESSFUL;
281
282  sc = rtems_interrupt_handler_install(
283    timer->irq_nr,
284    "Clock",
285    RTEMS_INTERRUPT_UNIQUE,
286    isr,
287    NULL
288  );
289
290  if (sc != RTEMS_SUCCESSFUL) {
291    rtems_fatal_error_occurred(0xdeadbeef);
292  }
293  clock_isr = isr;
294}
295
296static void beagle_clock_cleanup(void)
297{
298  rtems_status_code sc = RTEMS_SUCCESSFUL;
299
300  /* Disable timer */
301  mmio_clear(timer->base + timer->regs->TCLR, OMAP3_TCLR_ST);
302
303  /* Remove interrupt handler */
304  sc = rtems_interrupt_handler_remove(
305    timer->irq_nr,
306    clock_isr,
307    NULL
308  );
309  if (sc != RTEMS_SUCCESSFUL) {
310    rtems_fatal_error_occurred(0xdeadbeef);
311  }
312  clock_isr = NULL;
313
314  /* stop frclock */
315  mmio_clear(fr_timer->base + fr_timer->regs->TCLR, OMAP3_TCLR_ST);
316}
317
318static inline uint32_t beagle_clock_nanoseconds_since_last_tick(void)
319{
320  /* this arithmetic also works if read_frc() wraps around, as long
321   * as the subtraction wraps around too
322   */
323  return (read_frc() - (uint64_t) last_tick_nanoseconds) * 1000000000 / FRCLOCK_HZ;
324}
325
326#define Clock_driver_support_at_tick() beagle_clock_at_tick()
327#define Clock_driver_support_initialize_hardware() beagle_clock_initialize()
328#define Clock_driver_support_install_isr(isr, old_isr) \
329  do {                   \
330    beagle_clock_handler_install(isr);          \
331    old_isr = NULL;              \
332  } while (0)
333
334#define Clock_driver_support_shutdown_hardware() beagle_clock_cleanup()
335#define Clock_driver_nanoseconds_since_last_tick \
336  beagle_clock_nanoseconds_since_last_tick
337
338/* Include shared source clock driver code */
339#include "../../shared/clockdrv_shell.h"
340
341#endif /* ARM_MULTILIB_ARCH_V4 */
Note: See TracBrowser for help on using the repository browser.