1 /* Initializes CPU and basic hardware such as memory
2 * controllers, IRQ controller and system timer 0.
4 * (C) Copyright 2007, 2015
5 * Daniel Hellstrom, Cobham Gaisler, daniel@gaisler.com
7 * SPDX-License-Identifier: GPL-2.0+
16 #include <grlib/irqmp.h>
17 #include <grlib/gptimer.h>
18 #include <debug_uart.h>
22 /* Default Plug&Play I/O area */
23 #ifndef CONFIG_AMBAPP_IOAREA
24 #define CONFIG_AMBAPP_IOAREA AMBA_DEFAULT_IOAREA
27 /* Select which TIMER that will become the time base */
28 #ifndef CONFIG_SYS_GRLIB_GPTIMER_INDEX
29 #define CONFIG_SYS_GRLIB_GPTIMER_INDEX 0
32 #define TIMER_BASE_CLK 1000000
33 #define US_PER_TICK (1000000 / CONFIG_SYS_HZ)
35 DECLARE_GLOBAL_DATA_PTR
;
37 ambapp_dev_irqmp
*irqmp
= NULL
;
40 * Breath some life into the CPU...
42 * Run from FLASH/PROM:
43 * - until memory controller is set up, only registers available
44 * - memory controller has already been setup up, stack can be used
45 * - no global variables available for writing
46 * - constants available
50 #ifdef CONFIG_DEBUG_UART
55 /* If cache snooping is available in hardware the result will be set
56 * to 0x800000, otherwise 0.
58 static unsigned int snoop_detect(void)
61 asm("lda [%%g0] 2, %0" : "=r"(result
));
62 return result
& 0x00800000;
65 int arch_cpu_init(void)
70 gd
->cpu_clk
= CONFIG_SYS_CLK_FREQ
;
71 gd
->bus_clk
= CONFIG_SYS_CLK_FREQ
;
72 gd
->ram_size
= CONFIG_SYS_SDRAM_SIZE
;
74 gd
->arch
.snooping_available
= snoop_detect();
76 /* Initialize the AMBA Plug & Play bus structure, the bus
77 * structure represents the AMBA bus that the CPU is located at.
79 ambapp_bus_init(CONFIG_AMBAPP_IOAREA
, CONFIG_SYS_CLK_FREQ
, &ambapp_plb
);
81 /* Initialize/clear all the timers in the system.
83 for (index
= 0; ambapp_apb_find(&ambapp_plb
, VENDOR_GAISLER
,
84 GAISLER_GPTIMER
, index
, &apbdev
) == 1; index
++) {
85 ambapp_dev_gptimer
*timer
;
86 unsigned int bus_freq
;
89 timer
= (ambapp_dev_gptimer
*)apbdev
.address
;
91 /* Different buses may have different frequency, the
92 * frequency of the bus tell in which frequency the timer
95 bus_freq
= ambapp_bus_freq(&ambapp_plb
, apbdev
.ahb_bus_index
);
97 /* Initialize prescaler common to all timers to 1MHz */
98 timer
->scalar
= timer
->scalar_reload
=
99 (((bus_freq
/ 1000) + 500) / 1000) - 1;
101 /* Clear all timers */
102 ntimers
= timer
->config
& 0x7;
103 for (i
= 0; i
< ntimers
; i
++) {
104 timer
->e
[i
].ctrl
= GPTIMER_CTRL_IP
;
106 timer
->e
[i
].ctrl
= GPTIMER_CTRL_LD
;
114 * initialize higher level parts of CPU like time base and timers
118 ambapp_apbdev apbdev
;
122 * Find AMBA APB IRQMP Controller,
124 if (ambapp_apb_find(&ambapp_plb
, VENDOR_GAISLER
,
125 GAISLER_IRQMP
, 0, &apbdev
) != 1) {
126 panic("%s: IRQ controller not found\n", __func__
);
129 irqmp
= (ambapp_dev_irqmp
*)apbdev
.address
;
131 /* initialize the IRQMP */
132 irqmp
->ilevel
= 0xf; /* all IRQ off */
135 irqmp
->iclear
= 0xfffe; /* clear all old pending interrupts */
136 for (cpu
= 0; cpu
< 16; cpu
++) {
137 /* mask and clear force for all IRQs on CPU[N] */
138 irqmp
->cpu_mask
[cpu
] = 0;
139 irqmp
->cpu_force
[cpu
] = 0;
145 /* Busy wait a number of ms */
146 void cpu_wait_ms_busy(unsigned long ms
)
148 unsigned int ms_delay
;
149 volatile unsigned int tmp
;
151 /* ~10-20 cycles per decrement */
152 ms_delay
= leon_cpu_freq
/ (1000 * 10);
161 /* Uses Timer 0 to get accurate
162 * pauses. Max 2 raised to 32 ticks
165 void cpu_wait_ticks(unsigned long ticks
)
169 if (interrupt_is_enabled()) {
170 start
= get_timer(0);
171 while (get_timer(start
) < ticks
)
174 /* Interrupts disabled, this means that we cannot
175 * use get_timer(), it relies on IRQ. Instead the
176 * CPU frequency is used.
178 cpu_wait_ms_busy(ticks2usec(ticks
) / 1000);
182 int timer_interrupt_init_cpu(void)
188 * This function is intended for SHORT delays only.
190 unsigned long cpu_usec2ticks(unsigned long usec
)
192 if (usec
< US_PER_TICK
)
194 return usec
/ US_PER_TICK
;
197 unsigned long cpu_ticks2usec(unsigned long ticks
)
199 return ticks
* US_PER_TICK
;
204 ambapp_dev_gptimer_element
*tmr
;
205 ambapp_dev_gptimer
*gptimer
;
206 ambapp_apbdev apbdev
;
209 if (ambapp_apb_find(&ambapp_plb
, VENDOR_GAISLER
, GAISLER_GPTIMER
,
210 CONFIG_SYS_GRLIB_GPTIMER_INDEX
, &apbdev
) != 1) {
211 panic("%s: gptimer not found!\n", __func__
);
215 gptimer
= (ambapp_dev_gptimer
*) apbdev
.address
;
217 /* Different buses may have different frequency, the
218 * frequency of the bus tell in which frequency the timer
219 * prescaler operates.
221 bus_freq
= ambapp_bus_freq(&ambapp_plb
, apbdev
.ahb_bus_index
);
223 /* initialize prescaler common to all timers to 1MHz */
224 gptimer
->scalar
= gptimer
->scalar_reload
=
225 (((bus_freq
/ 1000) + 500) / 1000) - 1;
227 tmr
= (ambapp_dev_gptimer_element
*)&gptimer
->e
[0];
231 tmr
->ctrl
= GPTIMER_CTRL_EN
| GPTIMER_CTRL_RS
| GPTIMER_CTRL_LD
;
233 CONFIG_SYS_TIMER_COUNTER
= (void *)&tmr
->val
;