source: mainline/kernel/genarch/src/drivers/pl011/pl011.c@ b83c5e4

ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since b83c5e4 was 28a5ebd, checked in by Martin Decky <martin@…>, 6 years ago

Use char32_t instead of wchat_t to represent UTF-32 strings

The intention of the native HelenOS string API has been always to
support Unicode in the UTF-8 and UTF-32 encodings as the sole character
representations and ignore the obsolete mess of older single-byte and
multibyte character encodings. Before C11, the wchar_t type has been
slightly misused for the purpose of the UTF-32 strings. The newer
char32_t type is obviously a much more suitable option. The standard
defines char32_t as uint_least32_t, thus we can take the liberty to fix
it to uint32_t.

To maintain compatilibity with the C Standard, the putwchar(wchar_t)
functions has been replaced by our custom putuchar(char32_t) functions
where appropriate.

  • Property mode set to 100644
File size: 4.7 KB
Line 
1/*
2 * Copyright (c) 2012 Jan Vesely
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup kernel_genarch
30 * @{
31 */
32/**
33 * @file
34 * @brief ARM PrimeCell PL011 UART driver.
35 */
36
37#include <assert.h>
38#include <genarch/drivers/pl011/pl011.h>
39#include <console/chardev.h>
40#include <console/console.h>
41#include <arch/asm.h>
42#include <mm/slab.h>
43#include <mm/page.h>
44#include <mm/km.h>
45#include <sysinfo/sysinfo.h>
46#include <str.h>
47
48static void pl011_uart_sendb(pl011_uart_t *uart, uint8_t byte)
49{
50 /* Wait for space becoming available in Tx FIFO. */
51 // TODO make pio_read accept consts pointers and remove the cast
52 while ((pio_read_32((ioport32_t *)&uart->regs->flag) & PL011_UART_FLAG_TXFF_FLAG) != 0)
53 ;
54
55 pio_write_32(&uart->regs->data, byte);
56}
57
58static void pl011_uart_putuchar(outdev_t *dev, char32_t ch)
59{
60 pl011_uart_t *uart = dev->data;
61
62 /* If the userspace owns the console, do not output anything. */
63 if (uart->parea.mapped && !console_override)
64 return;
65
66 if (!ascii_check(ch))
67 pl011_uart_sendb(uart, U_SPECIAL);
68 else {
69 if (ch == '\n')
70 pl011_uart_sendb(uart, (uint8_t) '\r');
71 pl011_uart_sendb(uart, (uint8_t) ch);
72 }
73}
74
75static outdev_operations_t pl011_uart_ops = {
76 .write = pl011_uart_putuchar,
77 .redraw = NULL,
78 .scroll_up = NULL,
79 .scroll_down = NULL
80};
81
82static irq_ownership_t pl011_uart_claim(irq_t *irq)
83{
84 return IRQ_ACCEPT;
85}
86
87static void pl011_uart_irq_handler(irq_t *irq)
88{
89 pl011_uart_t *uart = irq->instance;
90
91 // TODO make pio_read accept const pointers and remove the cast
92 while ((pio_read_32((ioport32_t *)&uart->regs->flag) & PL011_UART_FLAG_RXFE_FLAG) == 0) {
93 /* We ignore all error flags here */
94 const uint8_t data = pio_read_32(&uart->regs->data);
95 if (uart->indev)
96 indev_push_character(uart->indev, data);
97 }
98 /* Ack interrupts */
99 pio_write_32(&uart->regs->interrupt_clear, PL011_UART_INTERRUPT_ALL);
100}
101
102bool pl011_uart_init(pl011_uart_t *uart, inr_t interrupt, uintptr_t addr)
103{
104 assert(uart);
105 uart->regs = (void *)km_map(addr, sizeof(pl011_uart_regs_t),
106 KM_NATURAL_ALIGNMENT, PAGE_WRITE | PAGE_NOT_CACHEABLE);
107 assert(uart->regs);
108
109 /* Disable UART */
110 uart->regs->control &= ~PL011_UART_CONTROL_UARTEN_FLAG;
111
112 /* Enable hw flow control */
113 uart->regs->control |=
114 PL011_UART_CONTROL_RTSE_FLAG |
115 PL011_UART_CONTROL_CTSE_FLAG;
116
117 /* Mask all interrupts */
118 uart->regs->interrupt_mask = 0;
119 /* Clear interrupts */
120 uart->regs->interrupt_clear = PL011_UART_INTERRUPT_ALL;
121 /* Enable UART, TX and RX */
122 uart->regs->control |=
123 PL011_UART_CONTROL_UARTEN_FLAG |
124 PL011_UART_CONTROL_TXE_FLAG |
125 PL011_UART_CONTROL_RXE_FLAG;
126
127 outdev_initialize("pl011_uart_dev", &uart->outdev, &pl011_uart_ops);
128 uart->outdev.data = uart;
129
130 /* Initialize IRQ */
131 irq_initialize(&uart->irq);
132 uart->irq.inr = interrupt;
133 uart->irq.claim = pl011_uart_claim;
134 uart->irq.handler = pl011_uart_irq_handler;
135 uart->irq.instance = uart;
136
137 ddi_parea_init(&uart->parea);
138 uart->parea.pbase = addr;
139 uart->parea.frames = 1;
140 uart->parea.unpriv = false;
141 uart->parea.mapped = false;
142 ddi_parea_register(&uart->parea);
143
144 return true;
145}
146
147void pl011_uart_input_wire(pl011_uart_t *uart, indev_t *indev)
148{
149 assert(uart);
150 assert(indev);
151
152 uart->indev = indev;
153 irq_register(&uart->irq);
154 /* Enable receive interrupts */
155 uart->regs->interrupt_mask |=
156 PL011_UART_INTERRUPT_RX_FLAG |
157 PL011_UART_INTERRUPT_RT_FLAG;
158}
159
160/** @}
161 */
Note: See TracBrowser for help on using the repository browser.