sparc: Update cpu_init.c to use generic timer infrastructure
[oweals/u-boot.git] / arch / sparc / cpu / leon2 / cpu_init.c
1 /* Initializes CPU and basic hardware such as memory
2  * controllers, IRQ controller and system timer 0.
3  *
4  * (C) Copyright 2007, 2015
5  * Daniel Hellstrom, Cobham Gaisler, daniel@gaisler.com
6  *
7  * SPDX-License-Identifier:     GPL-2.0+
8  */
9
10 #include <common.h>
11 #include <asm/asi.h>
12 #include <asm/leon.h>
13 #include <asm/io.h>
14
15 #include <config.h>
16
17 #define TIMER_BASE_CLK 1000000
18 #define US_PER_TICK (1000000 / CONFIG_SYS_HZ)
19
20 DECLARE_GLOBAL_DATA_PTR;
21
22 /*
23  * Breath some life into the CPU...
24  *
25  * Set up the memory map,
26  * initialize a bunch of registers.
27  *
28  * Run from FLASH/PROM:
29  *  - until memory controller is set up, only registers available
30  *  - no global variables available for writing
31  *  - constants available
32  */
33
34 void cpu_init_f(void)
35 {
36         LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS;
37
38         /* initialize the IRQMP */
39         leon2->Interrupt_Force = 0;
40         leon2->Interrupt_Pending = 0;
41         leon2->Interrupt_Clear = 0xfffe;        /* clear all old pending interrupts */
42         leon2->Interrupt_Mask = 0xfffe0000;     /* mask all IRQs */
43
44         /* cache */
45
46         /* I/O port setup */
47 #ifdef LEON2_IO_PORT_DIR
48         leon2->PIO_Direction = LEON2_IO_PORT_DIR;
49 #endif
50 #ifdef LEON2_IO_PORT_DATA
51         leon2->PIO_Data = LEON2_IO_PORT_DATA;
52 #endif
53 #ifdef LEON2_IO_PORT_INT
54         leon2->PIO_Interrupt = LEON2_IO_PORT_INT;
55 #else
56         leon2->PIO_Interrupt = 0;
57 #endif
58
59         /* disable timers */
60         leon2->Timer_Control_1 = leon2->Timer_Control_2 = 0;
61 }
62
63 int arch_cpu_init(void)
64 {
65         gd->cpu_clk = CONFIG_SYS_CLK_FREQ;
66         gd->bus_clk = CONFIG_SYS_CLK_FREQ;
67         gd->ram_size = CONFIG_SYS_SDRAM_SIZE;
68
69         return 0;
70 }
71
72 /*
73  * initialize higher level parts of CPU
74  */
75 int cpu_init_r(void)
76 {
77         return 0;
78 }
79
80 /* Uses Timer 0 to get accurate
81  * pauses. Max 2 raised to 32 ticks
82  *
83  */
84 void cpu_wait_ticks(unsigned long ticks)
85 {
86         unsigned long start = get_timer(0);
87         while (get_timer(start) < ticks) ;
88 }
89
90 /* initiate and setup timer0 interrupt to configured HZ. Base clock is 1MHz.
91  * Return irq number for timer int or a negative number for
92  * dealing with self
93  */
94 int timer_interrupt_init_cpu(void)
95 {
96         LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS;
97
98         /* SYS_HZ ticks per second */
99         leon2->Timer_Counter_1 = 0;
100         leon2->Timer_Reload_1 = (TIMER_BASE_CLK / CONFIG_SYS_HZ) - 1;
101         leon2->Timer_Control_1 =
102             (LEON2_TIMER_CTRL_EN | LEON2_TIMER_CTRL_RS | LEON2_TIMER_CTRL_LD);
103
104         return LEON2_TIMER1_IRQNO;
105 }
106
107 /*
108  * This function is intended for SHORT delays only.
109  */
110 unsigned long cpu_usec2ticks(unsigned long usec)
111 {
112         if (usec < US_PER_TICK)
113                 return 1;
114         return usec / US_PER_TICK;
115 }
116
117 unsigned long cpu_ticks2usec(unsigned long ticks)
118 {
119         return ticks * US_PER_TICK;
120 }
121
122 int timer_init(void)
123 {
124         LEON2_regs *leon2 = (LEON2_regs *)LEON2_PREGS;
125
126         /* initialize prescaler common to all timers to 1MHz */
127         leon2->Scaler_Counter = leon2->Scaler_Reload =
128                 (((CONFIG_SYS_CLK_FREQ / 1000) + 500) / 1000) - 1;
129
130         /* SYS_HZ ticks per second */
131         leon2->Timer_Counter_1 = 0;
132         leon2->Timer_Reload_1 = (CONFIG_SYS_TIMER_RATE / CONFIG_SYS_HZ) - 1;
133         leon2->Timer_Control_1 = LEON2_TIMER_CTRL_EN | LEON2_TIMER_CTRL_RS |
134                 LEON2_TIMER_CTRL_LD;
135
136         CONFIG_SYS_TIMER_COUNTER = (void *)&leon2->Timer_Counter_1;
137         return 0;
138 }