2 * Copyright (c) 2012 Jan Vesely
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
28 /** @addtogroup genarch
33 * @brief Texas Instruments AMDM37x on-chip uart serial line driver.
36 #include <genarch/drivers/amdm37x/uart.h>
37 #include <ddi/device.h>
41 static void amdm37x_uart_txb(amdm37x_uart_t
*uart
, uint8_t b
)
44 while (uart
->regs
->ssr
& AMDM37x_UART_SSR_TX_FIFO_FULL_FLAG
);
45 /* Write to the outgoing fifo */
49 static void amdm37x_uart_putchar(outdev_t
*dev
, wchar_t ch
)
51 amdm37x_uart_t
*uart
= dev
->data
;
52 if (!ascii_check(ch
)) {
53 amdm37x_uart_txb(uart
, U_SPECIAL
);
56 amdm37x_uart_txb(uart
, '\r');
57 amdm37x_uart_txb(uart
, ch
);
61 static outdev_operations_t amdm37x_uart_ops
= {
63 .write
= amdm37x_uart_putchar
,
66 static irq_ownership_t
amdm37x_uart_claim(irq_t
*irq
)
71 static void amdm37x_uart_handler(irq_t
*irq
)
73 amdm37x_uart_t
*uart
= irq
->instance
;
74 while ((uart
->regs
->rx_fifo_lvl
)) {
75 const uint8_t val
= uart
->regs
->rhr
;
76 if (uart
->indev
&& val
) {
77 indev_push_character(uart
->indev
, val
);
82 bool amdm37x_uart_init(
83 amdm37x_uart_t
*uart
, inr_t interrupt
, uintptr_t addr
, size_t size
)
86 uart
->regs
= (void *)km_map(addr
, size
, PAGE_NOT_CACHEABLE
);
90 /* See TI OMAP35X TRM ch 17.5.1.1 p. 2732 for startup routine */
92 /* Soft reset the port */
93 uart
->regs
->sysc
= AMDM37x_UART_SYSC_SOFTRESET_FLAG
;
94 while (!(uart
->regs
->syss
& AMDM37x_UART_SYSS_RESETDONE_FLAG
)) ;
97 /* Enable access to EFR register */
98 const uint8_t lcr
= uart
->regs
->lcr
; /* Save old value */
99 uart
->regs
->lcr
= 0xbf; /* Sets config mode B */
101 /* Enable access to TCL_TLR register */
102 const bool enhanced
= uart
->regs
->efr
& AMDM37x_UART_EFR_ENH_FLAG
;
103 uart
->regs
->efr
|= AMDM37x_UART_EFR_ENH_FLAG
; /* Turn on enh. */
104 uart
->regs
->lcr
= 0x80; /* Config mode A */
106 /* Set default (val 0) triggers, disable DMA enable FIFOs */
107 const bool tcl_tlr
= uart
->regs
->mcr
& AMDM37x_UART_MCR_TCR_TLR_FLAG
;
108 /* Enable access to tcr and tlr registers */
109 uart
->regs
->mcr
|= AMDM37x_UART_MCR_TCR_TLR_FLAG
;
112 uart
->regs
->fcr
= AMDM37x_UART_FCR_FIFO_EN_FLAG
;
114 /* Eneble fine granularity for RX FIFO and set trigger level to 1,
115 * TX FIFO, trigger level is irelevant*/
116 uart
->regs
->lcr
= 0xbf; /* Sets config mode B */
117 uart
->regs
->scr
= AMDM37x_UART_SCR_RX_TRIG_GRANU1_FLAG
;
118 uart
->regs
->tlr
= 1 << AMDM37x_UART_TLR_RX_FIFO_TRIG_SHIFT
;
120 /* Restore enhanced */
122 uart
->regs
->efr
&= ~AMDM37x_UART_EFR_ENH_FLAG
;
124 uart
->regs
->lcr
= 0x80; /* Config mode A */
125 /* Restore tcl_lcr access flag*/
127 uart
->regs
->mcr
&= ~AMDM37x_UART_MCR_TCR_TLR_FLAG
;
130 uart
->regs
->lcr
= lcr
;
132 /* Disable interrupts */
136 outdev_initialize("amdm37x_uart_dev", &uart
->outdev
, &amdm37x_uart_ops
);
137 uart
->outdev
.data
= uart
;
140 irq_initialize(&uart
->irq
);
141 uart
->irq
.devno
= device_assign_devno();
142 uart
->irq
.inr
= interrupt
;
143 uart
->irq
.claim
= amdm37x_uart_claim
;
144 uart
->irq
.handler
= amdm37x_uart_handler
;
145 uart
->irq
.instance
= uart
;
150 void amdm37x_uart_input_wire(amdm37x_uart_t
*uart
, indev_t
*indev
)
155 /* Register interrupt. */
156 irq_register(&uart
->irq
);
157 /* Enable interrupt on receive */
158 uart
->regs
->ier
|= AMDM37x_UART_IER_RHR_IRQ_FLAG
;