summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/arm/csb336/startup/bspstart.c
blob: 4e723a856e7bf5a28459b6a83032aadb8e0684f2 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/*
 * Cogent CSB336 - MC9328MXL SBC startup code
 *
 * Copyright (c) 2004 by Cogent Computer Systems
 * Written by Jay Monkman <jtm@lopingdog.com>
 *
 * The license and distribution terms for this file may be
 * found in the file LICENSE in this distribution or at
 * http://www.rtems.org/license/LICENSE.
 */

#include <bsp.h>
#include <bsp/irq-generic.h>
#include <rtems/bspIo.h>
#include <mc9328mxl.h>

extern void rtems_exception_init_mngt(void);

extern void mmu_set_cpu_async_mode(void);

/*
 * bsp_start_default - BSP initialization function
 *
 *   This function is called before RTEMS is initialized and used
 *   adjust the kernel's configuration.
 *
 *   This function also configures the CPU's memory protection unit.
 *
 * RESTRICTIONS/LIMITATIONS:
 *   Since RTEMS is not configured, no RTEMS functions can be called.
 *
 */
void bsp_start_default( void )
{
  int i;

  /* Set the MCU prescaler to divide by 1 */
  MC9328MXL_PLL_CSCR &= ~MC9328MXL_PLL_CSCR_PRESC;

  /* Enable the MCU PLL */
  MC9328MXL_PLL_CSCR |= MC9328MXL_PLL_CSCR_MPEN;

  /* Delay to allow time for PLL to get going */
  for (i = 0; i < 100; i++) {
    __asm__ volatile ("nop\n");
  }

  /* Set the CPU to asynchrous clock mode, so it uses its fastest clock */
  mmu_set_cpu_async_mode();

  /* disable interrupts */
  MC9328MXL_AITC_INTENABLEL = 0;
  MC9328MXL_AITC_INTENABLEH = 0;

  /* Set interrupt priority to -1 (allow all priorities) */
  MC9328MXL_AITC_NIMASK = 0x1f;

  /*
   * Init rtems exceptions management
   */
  rtems_exception_init_mngt();

  /*
   * Init rtems interrupt management
   */
  bsp_interrupt_initialize();
} /* bsp_start */

/* Calcuate the frequency for perclk1 */
int get_perclk1_freq(void)
{
  unsigned int fin;
  unsigned int fpll;
  unsigned int pd;
  unsigned int mfd;
  unsigned int mfi;
  unsigned int mfn;
  uint32_t reg;
  int perclk1;

  if (MC9328MXL_PLL_CSCR & MC9328MXL_PLL_CSCR_SYSSEL) {
    /* Use external oscillator */
    fin = BSP_OSC_FREQ;
  } else {
    /* Use scaled xtal freq */
    fin = BSP_XTAL_FREQ * 512;
  }

  /* calculate the output of the system PLL */
  reg = MC9328MXL_PLL_SPCTL0;
  pd = ((reg & MC9328MXL_PLL_SPCTL_PD_MASK) >>
        MC9328MXL_PLL_SPCTL_PD_SHIFT);
  mfd = ((reg & MC9328MXL_PLL_SPCTL_MFD_MASK) >>
         MC9328MXL_PLL_SPCTL_MFD_SHIFT);
  mfi = ((reg & MC9328MXL_PLL_SPCTL_MFI_MASK) >>
         MC9328MXL_PLL_SPCTL_MFI_SHIFT);
  mfn = ((reg & MC9328MXL_PLL_SPCTL_MFN_MASK) >>
         MC9328MXL_PLL_SPCTL_MFN_SHIFT);

#if 0
  printk("fin = %d\n", fin);
  printk("pd = %d\n", pd);
  printk("mfd = %d\n", mfd);
  printk("mfi = %d\n", mfi);
  printk("mfn = %d\n", mfn);
  printk("rounded (fin * mfi) / (pd + 1) = %d\n", (fin * mfi) / (pd + 1));
  printk("rounded (fin * mfn) / ((pd + 1) * (mfd + 1)) = %d\n",
         ((long long)fin * mfn) / ((pd + 1) * (mfd + 1)));
#endif

  fpll = 2 * ( ((fin * mfi  + (pd + 1) / 2) / (pd + 1)) +
               (((long long)fin * mfn + ((pd + 1) * (mfd + 1)) / 2) /
               ((pd + 1) * (mfd + 1))) );

  /* calculate the output of the PERCLK1 divider */
  reg = MC9328MXL_PLL_PCDR;
  perclk1 = fpll / (1 + ((reg & MC9328MXL_PLL_PCDR_PCLK1_MASK) >>
                         MC9328MXL_PLL_PCDR_PCLK1_SHIFT));

  return perclk1;
}

/*
 *  By making this a weak alias for bsp_start_default, a brave soul
 *  can override the actual bsp_start routine used.
 */
void bsp_start (void) __attribute__ ((weak, alias("bsp_start_default")));