Change the default cross compiler prefix to powerpc64le-linux-gnu-
[microwatt.git] / hello_world / console.c
1 #include <stdint.h>
2 #include <stdbool.h>
3
4 #include "console.h"
5
6 /*
7 * Core UART functions to implement for a port
8 */
9
10 static uint64_t potato_uart_base;
11
12 #define PROC_FREQ 50000000
13 #define UART_FREQ 115200
14 #define UART_BASE 0xc0002000
15
16 #define POTATO_CONSOLE_TX 0x00
17 #define POTATO_CONSOLE_RX 0x08
18 #define POTATO_CONSOLE_STATUS 0x10
19 #define POTATO_CONSOLE_STATUS_RX_EMPTY 0x01
20 #define POTATO_CONSOLE_STATUS_TX_EMPTY 0x02
21 #define POTATO_CONSOLE_STATUS_RX_FULL 0x04
22 #define POTATO_CONSOLE_STATUS_TX_FULL 0x08
23 #define POTATO_CONSOLE_CLOCK_DIV 0x18
24 #define POTATO_CONSOLE_IRQ_EN 0x20
25
26 static uint64_t potato_uart_reg_read(int offset)
27 {
28 uint64_t val;
29
30 __asm__ volatile("ldcix %0,%1,%2" : "=r" (val) : "b" (potato_uart_base), "r" (offset));
31
32 return val;
33 }
34
35 static void potato_uart_reg_write(int offset, uint64_t val)
36 {
37 __asm__ volatile("stdcix %0,%1,%2" : : "r" (val), "b" (potato_uart_base), "r" (offset));
38 }
39
40 static int potato_uart_rx_empty(void)
41 {
42 uint64_t val;
43
44 val = potato_uart_reg_read(POTATO_CONSOLE_STATUS);
45
46 if (val & POTATO_CONSOLE_STATUS_RX_EMPTY)
47 return 1;
48
49 return 0;
50 }
51
52 static int potato_uart_tx_full(void)
53 {
54 uint64_t val;
55
56 val = potato_uart_reg_read(POTATO_CONSOLE_STATUS);
57
58 if (val & POTATO_CONSOLE_STATUS_TX_FULL)
59 return 1;
60
61 return 0;
62 }
63
64 static char potato_uart_read(void)
65 {
66 uint64_t val;
67
68 val = potato_uart_reg_read(POTATO_CONSOLE_RX);
69
70 return (char)(val & 0x000000ff);
71 }
72
73 static void potato_uart_write(char c)
74 {
75 uint64_t val;
76
77 val = c;
78
79 potato_uart_reg_write(POTATO_CONSOLE_TX, val);
80 }
81
82 static unsigned long potato_uart_divisor(unsigned long proc_freq, unsigned long uart_freq)
83 {
84 return proc_freq / (uart_freq * 16) - 1;
85 }
86
87 void potato_uart_init(void)
88 {
89 potato_uart_base = UART_BASE;
90
91 potato_uart_reg_write(POTATO_CONSOLE_CLOCK_DIV, potato_uart_divisor(PROC_FREQ, UART_FREQ));
92 }
93
94 int getchar(void)
95 {
96 while (potato_uart_rx_empty())
97 /* Do nothing */ ;
98
99 return potato_uart_read();
100 }
101
102 void putchar(unsigned char c)
103 {
104 while (potato_uart_tx_full())
105 /* Do Nothing */;
106
107 potato_uart_write(c);
108 }
109
110 void putstr(const char *str, unsigned long len)
111 {
112 for (unsigned long i = 0; i < len; i++) {
113 putchar(str[i]);
114 }
115 }
116
117 size_t strlen(const char *s)
118 {
119 size_t len = 0;
120
121 while (*s++)
122 len++;
123
124 return len;
125 }