source: mainline/kernel/genarch/src/drivers/arm926_uart/arm926_uart.c@ f09f059

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since f09f059 was 3ffd4c3, checked in by Jan Vesely <jano.vesely@…>, 13 years ago

arm32, icp: Fix serial line interrupt masks.

  • Property mode set to 100644
File size: 4.1 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 genarch
30 * @{
31 */
32/**
33 * @file
34 * @brief ARM926 on-chip UART (PrimeCell UART, PL011) driver.
35 */
36
37#include <genarch/drivers/arm926_uart/arm926_uart.h>
38#include <console/chardev.h>
39#include <console/console.h>
40#include <ddi/device.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 arm926_uart_sendb(arm926_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) & ARM926_UART_FLAG_TXFF_FLAG) != 0)
53 ;
54
55 pio_write_32(&uart->regs->data, byte);
56}
57
58static void arm926_uart_putchar(outdev_t *dev, wchar_t ch)
59{
60 arm926_uart_t *uart = dev->data;
61
62 if (!ascii_check(ch)) {
63 arm926_uart_sendb(uart, U_SPECIAL);
64 } else {
65 if (ch == '\n')
66 arm926_uart_sendb(uart, (uint8_t) '\r');
67 arm926_uart_sendb(uart, (uint8_t) ch);
68 }
69}
70
71static outdev_operations_t arm926_uart_ops = {
72 .write = arm926_uart_putchar,
73 .redraw = NULL,
74};
75
76static irq_ownership_t arm926_uart_claim(irq_t *irq)
77{
78 return IRQ_ACCEPT;
79}
80
81static void arm926_uart_irq_handler(irq_t *irq)
82{
83 arm926_uart_t *uart = irq->instance;
84
85 // TODO make pio_read accept const pointers and remove the cast
86 while ((pio_read_32((ioport32_t*)&uart->regs->flag) & ARM926_UART_FLAG_RXFE_FLAG) == 0) {
87 /* We ignore all error flags here */
88 const uint8_t data = pio_read_32(&uart->regs->data);
89 if (uart->indev)
90 indev_push_character(uart->indev, data);
91 }
92 /* Ack interrupts */
93 pio_write_32(&uart->regs->interrupt_clear, ARM926_UART_INTERRUPT_ALL);
94}
95
96bool arm926_uart_init(
97 arm926_uart_t *uart, inr_t interrupt, uintptr_t addr, size_t size)
98{
99 ASSERT(uart);
100 uart->regs = (void*)km_map(addr, size, PAGE_NOT_CACHEABLE);
101
102 ASSERT(uart->regs);
103
104 /* Enable hw flow control */
105 uart->regs->control = 0 |
106 ARM926_UART_CONTROL_UARTEN_FLAG |
107 ARM926_UART_CONTROL_RTSE_FLAG |
108 ARM926_UART_CONTROL_CTSE_FLAG;
109
110 /* Mask all interrupts */
111 uart->regs->interrupt_mask = 0;
112
113 outdev_initialize("arm926_uart_dev", &uart->outdev, &arm926_uart_ops);
114 uart->outdev.data = uart;
115
116 /* Initialize IRQ */
117 irq_initialize(&uart->irq);
118 uart->irq.devno = device_assign_devno();
119 uart->irq.inr = interrupt;
120 uart->irq.claim = arm926_uart_claim;
121 uart->irq.handler = arm926_uart_irq_handler;
122 uart->irq.instance = uart;
123
124 return true;
125}
126
127void arm926_uart_input_wire(arm926_uart_t *uart, indev_t *indev)
128{
129 ASSERT(uart);
130 ASSERT(indev);
131
132 uart->indev = indev;
133 irq_register(&uart->irq);
134 /* Enable receive interrupt */
135 uart->regs->interrupt_mask |= ARM926_UART_INTERRUPT_RX_FLAG;
136}
137
138/** @}
139 */
140
Note: See TracBrowser for help on using the repository browser.