summaryrefslogtreecommitdiff
path: root/bootwrapper/uart.c
blob: 5c858f6f76f00f1ebefb5b5cbee1bc5fac04e731 (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
/*
 * 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 <stdio.h>
#include "bootwrapper.h"
#include "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;

void config_uart(void)
{
        uart_base = UART0_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;
}