]>
Commit | Line | Data |
---|---|---|
1e9a164e DH |
1 | /* Initializes CPU and basic hardware such as memory |
2 | * controllers, IRQ controller and system timer 0. | |
3 | * | |
898cc81d DH |
4 | * (C) Copyright 2007, 2015 |
5 | * Daniel Hellstrom, Cobham Gaisler, daniel@gaisler.com | |
1e9a164e | 6 | * |
1a459660 | 7 | * SPDX-License-Identifier: GPL-2.0+ |
1e9a164e DH |
8 | */ |
9 | ||
10 | #include <common.h> | |
11 | #include <asm/asi.h> | |
12 | #include <asm/leon.h> | |
13 | #include <ambapp.h> | |
f2879f59 DH |
14 | #include <grlib/irqmp.h> |
15 | #include <grlib/gptimer.h> | |
e43ce3fc | 16 | #include <debug_uart.h> |
1e9a164e DH |
17 | |
18 | #include <config.h> | |
19 | ||
898cc81d DH |
20 | /* Default Plug&Play I/O area */ |
21 | #ifndef CONFIG_AMBAPP_IOAREA | |
22 | #define CONFIG_AMBAPP_IOAREA AMBA_DEFAULT_IOAREA | |
23 | #endif | |
24 | ||
1c1c7506 DH |
25 | #define TIMER_BASE_CLK 1000000 |
26 | #define US_PER_TICK (1000000 / CONFIG_SYS_HZ) | |
27 | ||
1e9a164e DH |
28 | DECLARE_GLOBAL_DATA_PTR; |
29 | ||
1e9a164e | 30 | ambapp_dev_irqmp *irqmp = NULL; |
1e9a164e DH |
31 | ambapp_dev_gptimer *gptimer = NULL; |
32 | unsigned int gptimer_irq = 0; | |
33 | int leon3_snooping_avail = 0; | |
34 | ||
1e9a164e DH |
35 | /* |
36 | * Breath some life into the CPU... | |
37 | * | |
1e9a164e | 38 | * Run from FLASH/PROM: |
6052cbab | 39 | * - until memory controller is set up, only registers available |
898cc81d | 40 | * - memory controller has already been setup up, stack can be used |
1e9a164e | 41 | * - no global variables available for writing |
6052cbab | 42 | * - constants available |
1e9a164e | 43 | */ |
1e9a164e DH |
44 | void cpu_init_f(void) |
45 | { | |
e43ce3fc FR |
46 | #ifdef CONFIG_DEBUG_UART |
47 | debug_uart_init(); | |
48 | #endif | |
1e9a164e DH |
49 | } |
50 | ||
898cc81d DH |
51 | /* Routine called from start.S, |
52 | * | |
53 | * Run from FLASH/PROM: | |
54 | * - memory controller has already been setup up, stack can be used | |
55 | * - global variables available for read/writing | |
56 | * - constants avaiable | |
57 | */ | |
1e9a164e DH |
58 | void cpu_init_f2(void) |
59 | { | |
898cc81d DH |
60 | /* Initialize the AMBA Plug & Play bus structure, the bus |
61 | * structure represents the AMBA bus that the CPU is located at. | |
62 | */ | |
63 | ambapp_bus_init(CONFIG_AMBAPP_IOAREA, CONFIG_SYS_CLK_FREQ, &ambapp_plb); | |
1e9a164e DH |
64 | } |
65 | ||
e17c5200 FR |
66 | int arch_cpu_init(void) |
67 | { | |
68 | gd->cpu_clk = CONFIG_SYS_CLK_FREQ; | |
69 | gd->bus_clk = CONFIG_SYS_CLK_FREQ; | |
70 | gd->ram_size = CONFIG_SYS_SDRAM_SIZE; | |
71 | ||
72 | return 0; | |
73 | } | |
74 | ||
1e9a164e DH |
75 | /* |
76 | * initialize higher level parts of CPU like time base and timers | |
77 | */ | |
78 | int cpu_init_r(void) | |
79 | { | |
80 | ambapp_apbdev apbdev; | |
898cc81d DH |
81 | int index, cpu; |
82 | ambapp_dev_gptimer *timer = NULL; | |
83 | unsigned int bus_freq; | |
1e9a164e DH |
84 | |
85 | /* | |
86 | * Find AMBA APB IRQMP Controller, | |
1e9a164e | 87 | */ |
898cc81d DH |
88 | if (ambapp_apb_find(&ambapp_plb, VENDOR_GAISLER, |
89 | GAISLER_IRQMP, 0, &apbdev) != 1) { | |
90 | panic("%s: IRQ controller not found\n", __func__); | |
91 | return -1; | |
1e9a164e | 92 | } |
898cc81d | 93 | irqmp = (ambapp_dev_irqmp *)apbdev.address; |
1e9a164e | 94 | |
898cc81d DH |
95 | /* initialize the IRQMP */ |
96 | irqmp->ilevel = 0xf; /* all IRQ off */ | |
97 | irqmp->iforce = 0; | |
98 | irqmp->ipend = 0; | |
99 | irqmp->iclear = 0xfffe; /* clear all old pending interrupts */ | |
100 | for (cpu = 0; cpu < 16; cpu++) { | |
101 | /* mask and clear force for all IRQs on CPU[N] */ | |
102 | irqmp->cpu_mask[cpu] = 0; | |
103 | irqmp->cpu_force[cpu] = 0; | |
1e9a164e DH |
104 | } |
105 | ||
898cc81d DH |
106 | /* timer */ |
107 | index = 0; | |
108 | while (ambapp_apb_find(&ambapp_plb, VENDOR_GAISLER, GAISLER_GPTIMER, | |
109 | index, &apbdev) == 1) { | |
110 | timer = (ambapp_dev_gptimer *)apbdev.address; | |
111 | if (gptimer == NULL) { | |
112 | gptimer = timer; | |
113 | gptimer_irq = apbdev.irq; | |
114 | } | |
115 | ||
116 | /* Different buses may have different frequency, the | |
117 | * frequency of the bus tell in which frequency the timer | |
118 | * prescaler operates. | |
119 | */ | |
120 | bus_freq = ambapp_bus_freq(&ambapp_plb, apbdev.ahb_bus_index); | |
1e9a164e | 121 | |
898cc81d DH |
122 | /* initialize prescaler common to all timers to 1MHz */ |
123 | timer->scalar = timer->scalar_reload = | |
124 | (((bus_freq / 1000) + 500) / 1000) - 1; | |
1e9a164e | 125 | |
898cc81d | 126 | index++; |
1e9a164e | 127 | } |
898cc81d DH |
128 | if (!gptimer) { |
129 | printf("%s: gptimer not found!\n", __func__); | |
130 | return 1; | |
1e9a164e | 131 | } |
898cc81d | 132 | return 0; |
1e9a164e DH |
133 | } |
134 | ||
135 | /* Uses Timer 0 to get accurate | |
136 | * pauses. Max 2 raised to 32 ticks | |
137 | * | |
138 | */ | |
139 | void cpu_wait_ticks(unsigned long ticks) | |
140 | { | |
141 | unsigned long start = get_timer(0); | |
142 | while (get_timer(start) < ticks) ; | |
143 | } | |
144 | ||
1c1c7506 | 145 | /* initiate and setup timer0 interrupt to configured HZ. Base clock is 1MHz. |
1e9a164e DH |
146 | * Return irq number for timer int or a negative number for |
147 | * dealing with self | |
148 | */ | |
149 | int timer_interrupt_init_cpu(void) | |
150 | { | |
1c1c7506 | 151 | /* SYS_HZ ticks per second */ |
1e9a164e | 152 | gptimer->e[0].val = 0; |
1c1c7506 | 153 | gptimer->e[0].rld = (TIMER_BASE_CLK / CONFIG_SYS_HZ) - 1; |
1e9a164e | 154 | gptimer->e[0].ctrl = |
f2879f59 DH |
155 | (GPTIMER_CTRL_EN | GPTIMER_CTRL_RS | |
156 | GPTIMER_CTRL_LD | GPTIMER_CTRL_IE); | |
1e9a164e DH |
157 | |
158 | return gptimer_irq; | |
159 | } | |
160 | ||
4148b3d0 DH |
161 | ulong get_tbclk(void) |
162 | { | |
163 | return TIMER_BASE_CLK; | |
164 | } | |
165 | ||
1e9a164e DH |
166 | /* |
167 | * This function is intended for SHORT delays only. | |
168 | */ | |
169 | unsigned long cpu_usec2ticks(unsigned long usec) | |
170 | { | |
1c1c7506 | 171 | if (usec < US_PER_TICK) |
1e9a164e | 172 | return 1; |
1c1c7506 | 173 | return usec / US_PER_TICK; |
1e9a164e DH |
174 | } |
175 | ||
176 | unsigned long cpu_ticks2usec(unsigned long ticks) | |
177 | { | |
1c1c7506 | 178 | return ticks * US_PER_TICK; |
1e9a164e | 179 | } |