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;
}
|