summaryrefslogtreecommitdiff
path: root/big-little/lib/uart.c
blob: 26d00e5bc00eb05cfa87887a58b8e2125323a535 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
/*
 * Copyright (c) 2012, ARM Limited. All rights reserved.
 *       
 * Redistribution and use in source and binary forms, with
 * or without modification, are permitted provided that the
 * following conditions are met:
 *     
 * Redistributions of source code must retain the above
 * copyright notice, this list of conditions and the 
 * following disclaimer.
 *
 * Redistributions in binary form must reproduce the
 * above copyright notice, this list of conditions and 
 * the following disclaimer in the documentation 
 * and/or other materials provided with the distribution.
 *      
 * Neither the name of ARM nor the names of its
 * contributors may be used to endorse or promote products
 * derived from this software without specific prior written
 * permission.                        
 */

/*
 * uart.c - boot code to output characters on a PL011 uart
 * Not SMP-safe, so make sure you only call these functions
 * from one CPU at a time.
 * Call config_uart first.
 * Implements fputc() so you can use printf() in your code.
 */

#include "misc.h"
#include "hyp_vmmap.h"
#include "virt_helpers.h"

//* PL011 Registers Offsets from UART Base adress */
#define PL011_DR                   0x0
#define PL011_RSR                  0x4
#define PL011_ECR                  0x4
#define PL011_FR                   0x18
#define PL011_ILPR                 0x20
#define PL011_IBRD                 0x24
#define PL011_FBRD                 0x28
#define PL011_LCRH                 0x2C
#define PL011_CR                   0x30
#define PL011_IFLS                 0x34
#define PL011_IMSC                 0x38
#define PL011_RIS                  0x3C
#define PL011_MIS                  0x40
#define PL011_ICR                  0x44
#define PL011_DMACR                0x48

#define PL011_TXFE                 0x80
#define PL011_TXFF                 0x20

static unsigned uart_base = NULL;

#define write32(addr, val) (*(volatile unsigned int *)(addr) = (val))
#define read32(addr) (*(volatile unsigned int *)(addr))

void config_uart(void)
{
	uart_base = UART1_PHY_BASE;
	write32(uart_base + PL011_CR, 0);
	write32(uart_base + PL011_FBRD, 0x01);
	write32(uart_base + PL011_IBRD, 0x27);
	write32(uart_base + PL011_LCRH, 0x70);
	write32(uart_base + PL011_CR, 0xf01);	/* TXE|RXE|En|DTR|CTS */
}

void drain_uart_fifo(void)
{
	while (!(read32(uart_base + PL011_FR) & PL011_TXFE)) {
		/* Do nothing */
	}
}

static __inline void wait_for_space(void)
{
	while ((read32(uart_base + PL011_FR) & PL011_TXFF)) {
		/* Do nothing */
	}
}

void output_char(int c)
{
	if (c == '\n') {
		wait_for_space();
		write32(uart_base + PL011_DR, '\r');
	}
	wait_for_space();
	write32(uart_base + PL011_DR, c);
}

void output_string(const char *string)
{
	int i;

	for (i = 0; string[i]; ++i) {
		output_char(string[i]);
	}
}

void hexword(unsigned value)
{
	printf(" 0x%8.8x", value);
	drain_uart_fifo();
}

typedef struct __FILE {
	int dummy;
} FILE;

FILE __stdout;

int fputc(int c, FILE * f)
{
	output_char(c);
	return c;
}