Add lm32 cpu and milkymist port
[mw/micromonitor-lm32.git] / umon_ports / milkymist / cpuio.c
1 /*
2  * Author: Michael Walle <michael@walle.cc>
3  * License: Lucent Public License 1.02
4  */
5
6 #include "config.h"
7 #include "stddefs.h"
8 #include "cpuio.h"
9 #include "genlib.h"
10 #include "cache.h"
11 #include "warmstart.h"
12 #include "timer.h"
13 #include "lm32.h"
14 #include "ps2_kbd.h"
15
16 /* devInit():
17  * As a bare minimum, initialize the console UART here using the
18  * incoming 'baud' value as the baud rate.
19  */
20 void
21 devInit(int baud)
22 {
23         ConsoleBaudSet(baud);
24
25 #if INCLUDE_PS2KBD
26         ps2_kbd_init();
27 #endif
28 }
29
30 /* ConsoleBaudSet():
31  * Provide a means to change the baud rate of the running
32  * console interface.  If the incoming value is not a valid
33  * baud rate, then default to 9600.
34  * In the early stages of a new port this can be left empty.
35  * Return 0 if successful; else -1.
36  */
37 int
38 ConsoleBaudSet(int baud)
39 {
40         UART_DIVISOR = CPU_FREQUENCY/baud/16;
41
42         return(0);
43 }
44
45 ulong
46 target_timer(void)
47 {
48         return TIMER0_COUNTER;
49 }
50
51 /* target_console_empty():
52  * Target-specific portion of flush_console() in chario.c.
53  * This function returns 1 if there are no characters waiting to
54  * be put out on the UART; else return 0 indicating that the UART
55  * is still busy outputting characters from its FIFO.
56  * In the early stages of a new port this can simply return 1.
57  */
58 int
59 target_console_empty(void)
60 {
61         return(1);
62 }
63
64 /* target_putchar():
65  * When buffer has space available, load the incoming character
66  * into the UART.
67  */
68 int
69 target_putchar(char c)
70 {
71         UART_RXTX = c;
72
73     /* Wait for transmit ready bit */
74     while(1) {
75                 if (lm32_get_ip() & (1 << UART_IRQ_TX))
76             break;
77     }
78         lm32_set_ip(1 << UART_IRQ_TX);
79
80     return((int)c);
81 }
82
83 int
84 uart_gotachar(void)
85 {
86         if (lm32_get_ip() & (1 << UART_IRQ_RX))
87         return(1);
88         return(0);
89 }
90
91 /* target_gotachar():
92  * Return 0 if no char is avaialable at UART rcv fifo; else 1.
93  * Do NOT pull character out of fifo, just return status. 
94  *
95  * Define INCLUDE_BLINKLED in config.h and add STATLED_ON()
96  * and STATLED_OFF() macros (or functions)  so that uMon will
97  * run and blink a target LED at a configured (or default 500msec)
98  * interval...
99  */
100 int
101 target_gotachar(void)
102 {
103 #if INCLUDE_BLINKLED
104         static uint8_t ledstate;
105         static struct elapsed_tmr tmr;
106
107 #ifndef BLINKON_MSEC
108 #define BLINKON_MSEC 500
109 #define BLINKOFF_MSEC 500
110 #endif
111
112         switch(ledstate) {
113                 case 0:
114                         startElapsedTimer(&tmr,BLINKON_MSEC);
115                         ledstate = 1;
116                         STATLED_ON();
117                         break;
118                 case 1:
119                         if(msecElapsed(&tmr)) {
120                                 STATLED_OFF();
121                                 ledstate = 2;
122                                 startElapsedTimer(&tmr,BLINKOFF_MSEC);
123                         }
124                         break;
125                 case 2:
126                         if(msecElapsed(&tmr)) {
127                                 STATLED_ON();
128                                 ledstate = 1;
129                                 startElapsedTimer(&tmr,BLINKON_MSEC);
130                         }
131                         break;
132         }
133 #endif
134         if (uart_gotachar())
135         return(1);
136 #if INCLUDE_PS2KBD
137         if (ps2_gotachar())
138                 return(1);
139 #endif
140     return(0);
141 }
142
143 /* target_getchar():
144  * Assume there is a character in the UART's input buffer and just
145  * pull it out and return it.
146  */
147 int 
148 target_getchar(void)
149 {
150     char    c;
151
152 #if INCLUDE_PS2KBD
153         if (ps2_gotachar()) {
154                 c = ps2_getchar();
155         } else
156 #endif
157         {
158                 lm32_set_ip(1 << UART_IRQ_RX);
159                 c = UART_RXTX;
160         }
161
162     return((int)c);
163 }
164
165 /* intsoff():
166  * Disable all system interrupts here and return a value that can
167  * be used by intsrestore() (later) to restore the interrupt state.
168  */
169 ulong
170 intsoff(void)
171 {
172         ulong status;
173
174         status = 0;
175         /* ADD_CODE_HERE */
176         return(status);
177 }
178
179 /* intsrestore():
180  * Re-establish system interrupts here by using the status value
181  * that was returned by an earlier call to intsoff().
182  */
183 void
184 intsrestore(ulong status)
185 {
186         /* ADD_CODE_HERE */
187 }
188
189 /* cacheInitForTarget():
190  * Establish target specific function pointers and
191  * enable i-cache...
192  * Refer to $core/cache.c for a description of the function pointers.
193  * NOTE:
194  * If cache (either I or D or both) is enabled, then it is important
195  * that the appropriate cacheflush/invalidate function be established.
196  * This is very important because programs (i.e. cpu instructions) are
197  * transferred to memory using data memory accesses and could
198  * potentially result in cache coherency problems.
199  */
200 void
201 cacheInitForTarget(void)
202 {
203         /* ADD_CODE_HERE */
204 }
205
206 /* target_reset():
207  * The default (absolute minimum) action to be taken by this function
208  * is to call monrestart(INITIALIZE).  It would be better if there was
209  * some target-specific function that would really cause the target
210  * to reset...
211  */
212 void
213 target_reset(void)
214 {
215         flushDcache(0,0);
216         disableDcache();
217         invalidateIcache(0,0);
218         disableIcache();
219         monrestart(INITIALIZE);
220 }
221
222 void
223 timer_init(void)
224 {
225         TIMER0_COUNTER = 0;
226         TIMER0_CONTROL = TIMER_ENABLE;
227 }
228
229 /* If any CPU IO wasn't initialized in reset.S, do it here...
230  * This just provides a "C-level" IO init opportunity. 
231  */
232 void
233 initCPUio(void)
234 {
235         /* ADD_CODE_HERE */
236 }