| 
						
						
							
								
							
						
						
					 | 
				
			
			 | 
			 | 
			
				@ -5,22 +5,29 @@
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				#include "microwatt_soc.h"
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				#include "io.h"
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				#define UART_FREQ 115200
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				#define UART_BAUDS 115200
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				/*
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 * Core UART functions to implement for a port
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static uint64_t potato_uart_base;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				bool uart_is_std;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static uint64_t uart_base;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static unsigned long uart_divisor(unsigned long uart_freq, unsigned long bauds)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					return uart_freq / (bauds * 16);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static uint64_t potato_uart_reg_read(int offset)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					return readq(potato_uart_base + offset);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					return readq(uart_base + offset);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static void potato_uart_reg_write(int offset, uint64_t val)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					writeq(val, potato_uart_base + offset);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					writeq(val, uart_base + offset);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static int potato_uart_rx_empty(void)
 | 
			
		
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
			
			 | 
			 | 
			
				@ -65,22 +72,13 @@ static void potato_uart_write(char c)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					potato_uart_reg_write(POTATO_CONSOLE_TX, val);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static unsigned long potato_uart_divisor(unsigned long proc_freq, unsigned long uart_freq)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static void potato_uart_init(uint64_t uart_freq)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					return proc_freq / (uart_freq * 16) - 1;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				void potato_uart_init(void)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					uint64_t proc_freq;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					potato_uart_base = UART_BASE;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					proc_freq = readq(SYSCON_BASE + SYS_REG_CLKINFO) & SYS_REG_CLKINFO_FREQ_MASK;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					potato_uart_reg_write(POTATO_CONSOLE_CLOCK_DIV, potato_uart_divisor(proc_freq, UART_FREQ));
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					unsigned long div = uart_divisor(uart_freq, UART_BAUDS) - 1;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					potato_uart_reg_write(POTATO_CONSOLE_CLOCK_DIV, div);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				void potato_uart_set_irq_en(bool rx_irq, bool tx_irq)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static void potato_uart_set_irq_en(bool rx_irq, bool tx_irq)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					uint64_t en = 0;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
			
			 | 
			 | 
			
				@ -91,25 +89,76 @@ void potato_uart_set_irq_en(bool rx_irq, bool tx_irq)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					potato_uart_reg_write(POTATO_CONSOLE_IRQ_EN, en);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				void potato_uart_irq_dis(void)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static bool std_uart_rx_empty(void)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					potato_uart_reg_write(POTATO_CONSOLE_IRQ_EN, 0x00);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					return !(readb(uart_base + UART_REG_LSR) & UART_REG_LSR_DR);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static uint8_t std_uart_read(void)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					return readb(uart_base + UART_REG_RX);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static bool std_uart_tx_full(void)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					return !(readb(uart_base + UART_REG_LSR) & UART_REG_LSR_THRE);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static void std_uart_write(uint8_t c)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					writeb(c, uart_base + UART_REG_TX);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static void std_uart_set_irq_en(bool rx_irq, bool tx_irq)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					uint8_t ier = 0;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (tx_irq)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						ier |= UART_REG_IER_THRI;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (rx_irq)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						ier |= UART_REG_IER_RDI;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					writeb(ier, uart_base + UART_REG_IER);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static void std_uart_init(uint64_t uart_freq)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					unsigned long div = uart_divisor(uart_freq, UART_BAUDS);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					writeb(UART_REG_LCR_DLAB,     uart_base + UART_REG_LCR);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					writeb(div & 0xff,            uart_base + UART_REG_DLL);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					writeb(div >> 8,              uart_base + UART_REG_DLM);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					writeb(UART_REG_LCR_8BIT,     uart_base + UART_REG_LCR);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					writeb(UART_REG_MCR_DTR |
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					       UART_REG_MCR_RTS,      uart_base + UART_REG_MCR);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					writeb(UART_REG_FCR_EN_FIFO |
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					       UART_REG_FCR_CLR_RCVR |
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					       UART_REG_FCR_CLR_XMIT, uart_base + UART_REG_FCR);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				int getchar(void)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (uart_is_std) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						while (std_uart_rx_empty())
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							/* Do nothing */ ;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						return std_uart_read();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					} else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						while (potato_uart_rx_empty())
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							/* Do nothing */ ;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						return potato_uart_read();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				int putchar(int c)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (uart_is_std) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						while(std_uart_tx_full())
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							/* Do Nothing */;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						std_uart_write(c);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					} else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						while (potato_uart_tx_full())
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							/* Do Nothing */;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						potato_uart_write(c);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					return c;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
			
			 | 
			 | 
			
				@ -140,10 +189,35 @@ size_t strlen(const char *s)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				void console_init(void)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					potato_uart_init();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					uint64_t sys_info;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					uint64_t proc_freq;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					uint64_t uart_info = 0;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					uint64_t uart_freq = 0;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					proc_freq = readq(SYSCON_BASE + SYS_REG_CLKINFO) & SYS_REG_CLKINFO_FREQ_MASK;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					sys_info  = readq(SYSCON_BASE + SYS_REG_INFO);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (sys_info & SYS_REG_INFO_HAS_LARGE_SYSCON) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						uart_info = readq(SYSCON_BASE + SYS_REG_UART0_INFO);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						uart_freq = uart_info & 0xffffffff;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (uart_freq == 0)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						uart_freq = proc_freq;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					uart_base = UART_BASE;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (uart_info & SYS_REG_UART_IS_16550) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						uart_is_std = true;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						std_uart_init(proc_freq);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					} else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						uart_is_std = false;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						potato_uart_init(proc_freq);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				void console_set_irq_en(bool rx_irq, bool tx_irq)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (uart_is_std)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						std_uart_set_irq_en(rx_irq, tx_irq);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					else
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						potato_uart_set_irq_en(rx_irq, tx_irq);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
	
		
			
				
					| 
						
						
						
					 | 
				
			
			 | 
			 | 
			
				
 
 |