source: rtems/c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/src/hwmgr/alt_16550_uart.c @ 76386c1

4.115
Last change on this file since 76386c1 was 76386c1, checked in by Sebastian Huber <sebastian.huber@…>, on Aug 26, 2014 at 2:00:44 PM

bsp/altera-cyclone-v: Add DMA support hwlib files

  • Property mode set to 100644
File size: 37.0 KB
Line 
1/******************************************************************************
2 *
3 * Copyright 2013 Altera Corporation. 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 are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO
21 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 ******************************************************************************/
30
31#include "alt_16550_uart.h"
32#include "alt_clock_manager.h"
33#include "socal/alt_rstmgr.h"
34#include "socal/alt_uart.h"
35#include "socal/hps.h"
36#include "socal/socal.h"
37
38/////
39
40#define ALT_16550_HANDLE_DATA_UART_ENABLED_MSK   (1UL << 31)
41#define ALT_16550_HANDLE_DATA_DIVISOR_VALUE_GET(value) (value & 0xffff)
42
43#define ALT_ALTERA_16550_CPR_OFST        (0xF4)
44#define ALT_ALTERA_16550_CPR_ADDR(base)  ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_ALTERA_16550_CPR_OFST))
45#define ALT_ALTERA_16550_CPR_FIFO_MODE_GET(value) (((value) >> 16) & 0xff)
46#define ALT_ALTERA_16550_CPR_AFCE_MODE_SET_MSK (1 << 4)
47
48/////
49
50// Remove these macros as part of case:123835.
51#define ALT_UART_IER_DLH_VALUE_SET(value) ((value) & 0xff)
52#define ALT_UART_IER_DLH_ETBEI_DLH1_SET_MSK ALT_UART_IER_DLH_ETBEI_DLHL_SET_MSK
53
54/////
55
56//
57// Helper function which resets the UART and if requested, initializes the UART
58// to the default settings. Currently the default settings are:
59//  - 8 databits
60//  - no parity
61//  - 1 stopbit
62//  - 57600 baudrate
63// The reset routines depends on the hardware implementation of the UART.
64//
65
66// This helper is needed because the regular alt_read_word(src) essentially
67// resolves to "*(volatile uint32_t *)src". As there is no assignment, this
68// could potentially be optimized away. With the helper, the actual register
69// read should occur and be returned (and subsequently discarded).
70static inline uint32_t alt_read_word_helper(const void * addr)
71{
72    return alt_read_word(addr);
73}
74
75//
76// Helper function write the divisor in hardware.
77//
78static ALT_STATUS_CODE alt_16550_write_divisor_helper(ALT_16550_HANDLE_t * handle,
79                                                      uint32_t divisor)
80{
81    // Validate the divisor parameter.
82    if (divisor > 0xffff)
83    {
84        // This should never happen as it is verified in divisor_set.
85        return ALT_E_ERROR;
86    }
87
88    switch (handle->device)
89    {
90    case ALT_16550_DEVICE_SOCFPGA_UART0:
91    case ALT_16550_DEVICE_SOCFPGA_UART1:
92    case ALT_16550_DEVICE_ALTERA_16550_UART:
93        // Set LCR::DLAB (Line Control Register :: Divisor Latch Access Bit)
94        alt_setbits_word(ALT_UART_LCR_ADDR(handle->location), ALT_UART_LCR_DLAB_SET_MSK);
95
96        // Write DLL (Divisor Latch Low).
97        alt_write_word(ALT_UART_RBR_THR_DLL_ADDR(handle->location), ALT_UART_RBR_THR_DLL_VALUE_SET(divisor));
98
99        // Write DLH (Divisor Latch High).
100        alt_write_word(ALT_UART_IER_DLH_ADDR(handle->location), ALT_UART_IER_DLH_VALUE_SET(divisor >> 8));
101
102        // Clear LCR::DLAB (Line Control Register :: Divisor Latch Access Bit)
103        alt_clrbits_word(ALT_UART_LCR_ADDR(handle->location), ALT_UART_LCR_DLAB_SET_MSK);
104
105        break;
106
107    default:
108        return ALT_E_ERROR;
109    }
110
111    // Update the enabled state in the handle data.
112    if (divisor != 0)
113    {
114        handle->data |= ALT_16550_HANDLE_DATA_UART_ENABLED_MSK;
115    }
116    else
117    {
118        handle->data &= ~ALT_16550_HANDLE_DATA_UART_ENABLED_MSK;
119    }
120
121    return ALT_E_SUCCESS;
122}
123
124//
125// Helper function to reset the UART.
126//
127static ALT_STATUS_CODE alt_16550_reset_helper(ALT_16550_HANDLE_t * handle, bool enable_init)
128{
129    switch (handle->device)
130    {
131    case ALT_16550_DEVICE_SOCFPGA_UART0:
132    case ALT_16550_DEVICE_SOCFPGA_UART1:
133        // Write SRR::UR (Shadow Reset Register :: UART Reset)
134        alt_write_word(ALT_UART_SRR_ADDR(handle->location), ALT_UART_SRR_UR_SET_MSK);
135
136        // Read the MSR to work around case:119085.
137        alt_read_word_helper(ALT_UART_MSR_ADDR(handle->location));
138        break;
139
140    case ALT_16550_DEVICE_ALTERA_16550_UART:
141        alt_16550_write_divisor_helper(handle, 0); // Disable UART
142        alt_16550_int_disable_all(handle);         // Disable interrupts
143        alt_16550_fifo_disable(handle);            // Disable FIFOs
144        alt_write_word(ALT_UART_MCR_ADDR(handle->location), 0); // 0 -> MCR (AFCE, LP, OUT2, OUT1, RTS, DTR)
145        break;
146
147    default:
148        return ALT_E_ERROR;
149    }
150
151    // If we are initializing (as opposed to just uninitializing)
152    if (enable_init)
153    {
154        ALT_STATUS_CODE status;
155
156        // Set bit IER::PTIME (Interrupt Enable Register :: Programmable THRE Mode Enable)
157        alt_setbits_word(ALT_UART_IER_DLH_ADDR(handle->location), ALT_UART_IER_DLH_PTIME_DLH7_SET_MSK);
158
159        // Set the line configuration to use 8-N-1.
160        status = alt_16550_line_config_set(handle, ALT_16550_DATABITS_8,
161                                                   ALT_16550_PARITY_DISABLE,
162                                                   ALT_16550_STOPBITS_1);
163        if (status != ALT_E_SUCCESS)
164        {
165            return status;
166        }
167
168        uint32_t divisor = ALT_16550_HANDLE_DATA_DIVISOR_VALUE_GET(handle->data);
169        if (divisor == 0)
170        {
171            // Set the default baudrate to 57600.
172            status = alt_16550_baudrate_set(handle, ALT_16550_BAUDRATE_57600);
173            if (status != ALT_E_SUCCESS)
174            {
175                return status;
176            }
177        }
178    }
179
180    return ALT_E_SUCCESS;
181}
182
183ALT_STATUS_CODE alt_16550_init(ALT_16550_DEVICE_t device,
184                               void * location,
185                               alt_freq_t clock_freq,
186                               ALT_16550_HANDLE_t * handle)
187{
188    handle->device = device;
189    handle->data   = 0;
190    handle->fcr    = 0;
191
192    switch (device)
193    {
194    case ALT_16550_DEVICE_SOCFPGA_UART0:
195    case ALT_16550_DEVICE_SOCFPGA_UART1:
196        // The ALT_CLK_L4_SP is required for all SoCFPGA UARTs. Check that it's enabled.
197        if (alt_clk_is_enabled(ALT_CLK_L4_SP) != ALT_E_TRUE)
198        {
199            return ALT_E_BAD_CLK;
200        }
201        else
202        {
203            ALT_STATUS_CODE status;
204            status = alt_clk_freq_get(ALT_CLK_L4_SP, &handle->clock_freq);
205            if (status != ALT_E_SUCCESS)
206            {
207                return status;
208            }
209
210            if (device == ALT_16550_DEVICE_SOCFPGA_UART0)
211            {
212                handle->location = ALT_UART0_ADDR;
213
214                // Bring UART0 out of reset.
215                alt_clrbits_word(ALT_RSTMGR_PERMODRST_ADDR, ALT_RSTMGR_PERMODRST_UART0_SET_MSK);
216            }
217            else // device == ALT_16550_DEVICE_SOCFPGA_UART1
218            {
219                handle->location = ALT_UART1_ADDR;
220
221                // Bring UART1 out of reset.
222                alt_clrbits_word(ALT_RSTMGR_PERMODRST_ADDR, ALT_RSTMGR_PERMODRST_UART1_SET_MSK);
223            } 
224
225            // Verify the UCR (UART Component Version)
226            uint32_t ucr = alt_read_word(ALT_UART_UCV_ADDR(handle->location));
227            if (ucr != ALT_UART_UCV_UART_COMPONENT_VER_RESET)
228            {
229                return ALT_E_ERROR;
230            }
231        }
232        break;
233    case ALT_16550_DEVICE_ALTERA_16550_UART:
234        handle->location   = location;
235        handle->clock_freq = clock_freq;
236        break;
237    default:
238        return ALT_E_BAD_ARG;
239    }
240
241    return alt_16550_reset_helper(handle, true);
242}
243
244ALT_STATUS_CODE alt_16550_uninit(ALT_16550_HANDLE_t * handle)
245{
246    switch (handle->device)
247    {
248    case ALT_16550_DEVICE_SOCFPGA_UART0:
249        alt_setbits_word(ALT_RSTMGR_PERMODRST_ADDR, ALT_RSTMGR_PERMODRST_UART0_SET_MSK);
250        return ALT_E_SUCCESS;
251    case ALT_16550_DEVICE_SOCFPGA_UART1:
252        alt_setbits_word(ALT_RSTMGR_PERMODRST_ADDR, ALT_RSTMGR_PERMODRST_UART1_SET_MSK);
253        return ALT_E_SUCCESS;
254    case ALT_16550_DEVICE_ALTERA_16550_UART:
255    default:
256        return alt_16550_reset_helper(handle, false);
257    }
258}
259
260ALT_STATUS_CODE alt_16550_reset(ALT_16550_HANDLE_t * handle)
261{
262    return alt_16550_reset_helper(handle, true);
263}
264
265ALT_STATUS_CODE alt_16550_enable(ALT_16550_HANDLE_t * handle)
266{
267    // Write the divisor cached in the handle data to the divisor registers.
268    // This will effectively enable the UART.
269    return alt_16550_write_divisor_helper(handle,
270                                          ALT_16550_HANDLE_DATA_DIVISOR_VALUE_GET(handle->data));
271}
272
273ALT_STATUS_CODE alt_16550_disable(ALT_16550_HANDLE_t * handle)
274{
275    // Write 0 to the divisor the divisor registers. This will effectively
276    // disable the UART.
277    return alt_16550_write_divisor_helper(handle, 0);
278}
279
280ALT_STATUS_CODE alt_16550_read(ALT_16550_HANDLE_t * handle,
281                               char * item)
282{
283    // Verify that the UART is enabled
284    if (!(handle->data & ALT_16550_HANDLE_DATA_UART_ENABLED_MSK))
285    {
286        return ALT_E_ERROR;
287    }
288
289    // Verify that the FIFO is disabled
290    if (handle->fcr & ALT_UART_FCR_FIFOE_SET_MSK)
291    {
292        return ALT_E_ERROR;
293    }
294
295    switch (handle->device)
296    {
297    case ALT_16550_DEVICE_SOCFPGA_UART0:
298    case ALT_16550_DEVICE_SOCFPGA_UART1:
299    case ALT_16550_DEVICE_ALTERA_16550_UART:
300        // Read the RBR (Receive Buffer Register) into *item.
301        *item = ALT_UART_RBR_THR_DLL_VALUE_GET(alt_read_word(ALT_UART_RBR_THR_DLL_ADDR(handle->location)));
302        break;
303    default:
304        return ALT_E_ERROR;
305    }
306    return ALT_E_SUCCESS;
307}
308
309ALT_STATUS_CODE alt_16550_write(ALT_16550_HANDLE_t * handle,
310                                char item)
311{
312    // Verify that the UART is enabled
313    if (!(handle->data & ALT_16550_HANDLE_DATA_UART_ENABLED_MSK))
314    {
315        return ALT_E_ERROR;
316    }
317
318    // Verify that the FIFO is disabled
319    if (handle->fcr & ALT_UART_FCR_FIFOE_SET_MSK)
320    {
321        return ALT_E_ERROR;
322    }
323
324    switch (handle->device)
325    {
326    case ALT_16550_DEVICE_SOCFPGA_UART0:
327    case ALT_16550_DEVICE_SOCFPGA_UART1:
328    case ALT_16550_DEVICE_ALTERA_16550_UART:
329        // Write the buffer into the THR (Transmit Holding Register)
330        alt_write_word(ALT_UART_RBR_THR_DLL_ADDR(handle->location), item);
331        break;
332    default:
333        return ALT_E_ERROR;
334    }
335
336    return ALT_E_SUCCESS;
337}
338
339/////
340
341ALT_STATUS_CODE alt_16550_fifo_enable(ALT_16550_HANDLE_t * handle)
342{
343    switch (handle->device)
344    {
345    case ALT_16550_DEVICE_SOCFPGA_UART0:
346    case ALT_16550_DEVICE_SOCFPGA_UART1:
347    case ALT_16550_DEVICE_ALTERA_16550_UART:
348        // Set FCR::FIFOE (FIFO Control Register :: FIFO Enable) bit.
349        handle->fcr |= ALT_UART_FCR_FIFOE_SET_MSK;
350        alt_write_word(ALT_UART_FCR_ADDR(handle->location), handle->fcr);
351        break;
352    default:
353        return ALT_E_ERROR;
354    }
355
356    // No need to reset / clear the FIFOs. This is done automatically when
357    // FCR::FIFOE is changed.
358    return ALT_E_SUCCESS;
359}
360
361ALT_STATUS_CODE alt_16550_fifo_disable(ALT_16550_HANDLE_t * handle)
362{
363    switch (handle->device)
364    {
365    case ALT_16550_DEVICE_SOCFPGA_UART0:
366    case ALT_16550_DEVICE_SOCFPGA_UART1:
367    case ALT_16550_DEVICE_ALTERA_16550_UART:
368        // Clear FCR::FIFOE (FIFO Control Register :: FIFO Enable) bit.
369        handle->fcr &= ~ALT_UART_FCR_FIFOE_SET_MSK;
370        alt_write_word(ALT_UART_FCR_ADDR(handle->location), handle->fcr);
371        break;
372    default:
373        return ALT_E_ERROR;
374    }
375
376    return ALT_E_SUCCESS;
377}
378
379ALT_STATUS_CODE alt_16550_fifo_read(ALT_16550_HANDLE_t * handle,
380                                    char * buffer,
381                                    size_t count)
382{
383    // Verify that the UART is enabled
384    if (!(handle->data & ALT_16550_HANDLE_DATA_UART_ENABLED_MSK))
385    {
386        return ALT_E_ERROR;
387    }
388
389    // Verify that the FIFO is enabled
390    if (!(handle->fcr & ALT_UART_FCR_FIFOE_SET_MSK))
391    {
392        return ALT_E_ERROR;
393    }
394
395    switch (handle->device)
396    {
397    case ALT_16550_DEVICE_SOCFPGA_UART0:
398    case ALT_16550_DEVICE_SOCFPGA_UART1:
399    case ALT_16550_DEVICE_ALTERA_16550_UART:
400        // Read the RBR (Receive Buffer Register) into the buffer
401        for (size_t i = 0; i < count; ++i)
402        {
403            buffer[i] = ALT_UART_RBR_THR_DLL_VALUE_GET(alt_read_word(ALT_UART_RBR_THR_DLL_ADDR(handle->location)));
404        }
405        break;
406    default:
407        return ALT_E_ERROR;
408    }
409
410    return ALT_E_SUCCESS;
411}
412
413ALT_STATUS_CODE alt_16550_fifo_write(ALT_16550_HANDLE_t * handle,
414                                     const char * buffer,
415                                     size_t count)
416{
417    // Verify that the UART is enabled
418    if (!(handle->data & ALT_16550_HANDLE_DATA_UART_ENABLED_MSK))
419    {
420        return ALT_E_ERROR;
421    }
422
423    // Verify that the FIFO is enabled
424    if (!(handle->fcr & ALT_UART_FCR_FIFOE_SET_MSK))
425    {
426        return ALT_E_ERROR;
427    }
428
429    switch (handle->device)
430    {
431    case ALT_16550_DEVICE_SOCFPGA_UART0:
432    case ALT_16550_DEVICE_SOCFPGA_UART1:
433    case ALT_16550_DEVICE_ALTERA_16550_UART:
434        // Write the buffer into the THR (Transmit Holding Register)
435        for (size_t i = 0; i < count; ++i)
436        {
437            alt_write_word(ALT_UART_RBR_THR_DLL_ADDR(handle->location), buffer[i]);
438        }
439        break;
440    default:
441        return ALT_E_ERROR;
442    }
443
444    return ALT_E_SUCCESS;
445}
446
447ALT_STATUS_CODE alt_16550_fifo_clear_rx(ALT_16550_HANDLE_t * handle)
448{
449    // Verify that the FIFO is enabled
450    if (!(handle->fcr & ALT_UART_FCR_FIFOE_SET_MSK))
451    {
452        return ALT_E_ERROR;
453    }
454
455    switch (handle->device)
456    {
457    case ALT_16550_DEVICE_SOCFPGA_UART0:
458    case ALT_16550_DEVICE_SOCFPGA_UART1:
459        // Write SRR::RFR (Shadow Reset Register :: Receiver FIFO Reset) bit.
460        alt_write_word(ALT_UART_SRR_ADDR(handle->location), ALT_UART_SRR_RFR_SET_MSK);
461        break;
462    case ALT_16550_DEVICE_ALTERA_16550_UART:
463        // Write FCR::RFIFOR (FIFO Control Register :: Receiver FIFO Reset) bit.
464        alt_write_word(ALT_UART_FCR_ADDR(handle->location), handle->fcr | ALT_UART_FCR_RFIFOR_SET_MSK);
465        break;
466    default:
467        return ALT_E_ERROR;
468    }
469
470    return ALT_E_SUCCESS;
471}
472
473ALT_STATUS_CODE alt_16550_fifo_clear_tx(ALT_16550_HANDLE_t * handle)
474{
475    // Verify that the FIFO is enabled
476    if (!(handle->fcr & ALT_UART_FCR_FIFOE_SET_MSK))
477    {
478        return ALT_E_ERROR;
479    }
480
481    switch (handle->device)
482    {
483    case ALT_16550_DEVICE_SOCFPGA_UART0:
484    case ALT_16550_DEVICE_SOCFPGA_UART1:
485        // Write SRR::XFR (Shadow Reset Register :: Xmitter FIFO Reset) bit.
486        alt_write_word(ALT_UART_SRR_ADDR(handle->location), ALT_UART_SRR_XFR_SET_MSK);
487        break;
488    case ALT_16550_DEVICE_ALTERA_16550_UART:
489        // Write FCR::XFIFOR (FIFO Control Register :: Xmitter FIFO Reset) bit.
490        alt_write_word(ALT_UART_FCR_ADDR(handle->location), handle->fcr | ALT_UART_FCR_XFIFOR_SET_MSK);
491        break;
492    default:
493        return ALT_E_ERROR;
494    }
495
496    return ALT_E_SUCCESS;
497}
498
499ALT_STATUS_CODE alt_16550_fifo_clear_all(ALT_16550_HANDLE_t * handle)
500{
501    // Verify that the FIFO is enabled
502    if (!(handle->fcr & ALT_UART_FCR_FIFOE_SET_MSK))
503    {
504        return ALT_E_ERROR;
505    }
506
507    switch (handle->device)
508    {
509    case ALT_16550_DEVICE_SOCFPGA_UART0:
510    case ALT_16550_DEVICE_SOCFPGA_UART1:
511        // Write SRR::(RFR | XFR)
512        //   (Shadow Reset Register :: (Receiver FIFO Reset | Xmitter FIFO Reset)) bits.
513        alt_write_word(ALT_UART_SRR_ADDR(handle->location),
514                       ALT_UART_SRR_RFR_SET_MSK | ALT_UART_SRR_XFR_SET_MSK);
515        break;
516    case ALT_16550_DEVICE_ALTERA_16550_UART:
517        // Write FCR::(RFIFOR |XFIFOR)
518        //   (FIFO Control Register :: (Receiver FIFO Reset | Xmitter FIFO Reset)) bits.
519        alt_write_word(ALT_UART_FCR_ADDR(handle->location),
520                       handle->fcr | ALT_UART_FCR_RFIFOR_SET_MSK | ALT_UART_FCR_XFIFOR_SET_MSK);
521        break;
522    default:
523        return ALT_E_ERROR;
524    }
525
526    return ALT_E_SUCCESS;
527}
528
529ALT_STATUS_CODE alt_16550_fifo_size_get_rx(ALT_16550_HANDLE_t * handle,
530                                           uint32_t * size)
531{
532    switch (handle->device)
533    {
534    case ALT_16550_DEVICE_SOCFPGA_UART0:
535    case ALT_16550_DEVICE_SOCFPGA_UART1:
536        // Read the CPR::FIFO_Mod (Component Parameter Register :: FIFO Mode).
537        // The FIFO size is 16x this value.
538        *size = ALT_UART_CPR_FIFO_MOD_GET(alt_read_word(ALT_UART_CPR_ADDR(handle->location))) << 4;
539        break;
540    case ALT_16550_DEVICE_ALTERA_16550_UART:
541        // Altera 16550 Compatible Soft UARTs have a configurable size and is
542        // stored in the CPR::FIFO_Mode (Component Parameter Register :: FIFO Depth).
543        *size = ALT_ALTERA_16550_CPR_FIFO_MODE_GET(alt_read_word(ALT_ALTERA_16550_CPR_ADDR(handle->location))) << 4;
544        break;
545    default:
546        return ALT_E_ERROR;
547    }
548
549    return ALT_E_SUCCESS;
550}
551
552ALT_STATUS_CODE alt_16550_fifo_size_get_tx(ALT_16550_HANDLE_t * handle,
553                                           uint32_t * size)
554{
555    switch (handle->device)
556    {
557    case ALT_16550_DEVICE_SOCFPGA_UART0:
558    case ALT_16550_DEVICE_SOCFPGA_UART1:
559        // Read the CPR::FIFO_Mod (Component Parameter Register :: FIFO Mode).
560        // The FIFO size is 16x this value.
561        *size = ALT_UART_CPR_FIFO_MOD_GET(alt_read_word(ALT_UART_CPR_ADDR(handle->location))) << 4;
562        break;
563    case ALT_16550_DEVICE_ALTERA_16550_UART:
564        // Altera 16550 Compatible Soft UARTs have a configurable size and is
565        // stored in the CPR::FIFO_Mode (Component Parameter Register :: FIFO Depth).
566        // The FIFO size is 16x this value.
567        *size = ALT_ALTERA_16550_CPR_FIFO_MODE_GET(alt_read_word(ALT_ALTERA_16550_CPR_ADDR(handle->location))) << 4;
568        break;
569    default:
570        return ALT_E_ERROR;
571    }
572
573    return ALT_E_SUCCESS;
574}
575
576ALT_STATUS_CODE alt_16550_fifo_level_get_rx(ALT_16550_HANDLE_t * handle,
577                                            uint32_t * level)
578{
579    // Verify that the FIFO is enabled
580    if (!(handle->fcr & ALT_UART_FCR_FIFOE_SET_MSK))
581    {
582        return ALT_E_ERROR;
583    }
584
585    switch (handle->device)
586    {
587    case ALT_16550_DEVICE_SOCFPGA_UART0:
588    case ALT_16550_DEVICE_SOCFPGA_UART1:
589        // Read RFL (Receive FIFO Level).
590        *level = alt_read_word(ALT_UART_RFL_ADDR(handle->location));
591        break;
592    case ALT_16550_DEVICE_ALTERA_16550_UART:
593        // RFL not implemented. Return 0.
594        *level = 0;
595        break;
596    default:
597        return ALT_E_ERROR;
598    }
599
600    return ALT_E_SUCCESS;
601}
602
603ALT_STATUS_CODE alt_16550_fifo_level_get_tx(ALT_16550_HANDLE_t * handle,
604                                            uint32_t * level)
605{
606    // Verify that the FIFO is enabled
607    if (!(handle->fcr & ALT_UART_FCR_FIFOE_SET_MSK))
608    {
609        return ALT_E_ERROR;
610    }
611
612    switch (handle->device)
613    {
614    case ALT_16550_DEVICE_SOCFPGA_UART0:
615    case ALT_16550_DEVICE_SOCFPGA_UART1:
616        // Read TFL (Transmit FIFO Level).
617        *level = alt_read_word(ALT_UART_TFL_ADDR(handle->location));
618        break;
619    case ALT_16550_DEVICE_ALTERA_16550_UART:
620        // TFL not implemented. Return 0.
621        *level = 0;
622        break;
623    default:
624        return ALT_E_ERROR;
625    }
626
627    return ALT_E_SUCCESS;
628}
629
630ALT_STATUS_CODE alt_16550_fifo_trigger_set_rx(ALT_16550_HANDLE_t * handle,
631                                              ALT_16550_FIFO_TRIGGER_RX_t trigger)
632{
633    // Verify that the FIFO is enabled
634    if (!(handle->fcr & ALT_UART_FCR_FIFOE_SET_MSK))
635    {
636        return ALT_E_ERROR;
637    }
638
639    // Verify triggering parameter
640    switch (trigger)
641    {
642    case ALT_16550_FIFO_TRIGGER_RX_ANY:
643    case ALT_16550_FIFO_TRIGGER_RX_QUARTER_FULL:
644    case ALT_16550_FIFO_TRIGGER_RX_HALF_FULL:
645    case ALT_16550_FIFO_TRIGGER_RX_ALMOST_FULL:
646        break;
647    default:
648        return ALT_E_BAD_ARG;
649    }
650
651    switch (handle->device)
652    {
653    case ALT_16550_DEVICE_SOCFPGA_UART0:
654    case ALT_16550_DEVICE_SOCFPGA_UART1:
655    case ALT_16550_DEVICE_ALTERA_16550_UART:
656        // Update FCR::RT (FIFO Control Register :: Receiver Trigger)
657        handle->fcr &= ~ALT_UART_FCR_RT_SET_MSK;
658        handle->fcr |= ALT_UART_FCR_RT_SET(trigger);
659        alt_write_word(ALT_UART_FCR_ADDR(handle->location), handle->fcr);
660        break;
661    default:
662        return ALT_E_ERROR;
663    }
664
665    return ALT_E_SUCCESS;
666}
667
668ALT_STATUS_CODE alt_16550_fifo_trigger_set_tx(ALT_16550_HANDLE_t * handle,
669                                              ALT_16550_FIFO_TRIGGER_TX_t trigger)
670{
671    // Verify that the FIFO is enabled
672    if (!(handle->fcr & ALT_UART_FCR_FIFOE_SET_MSK))
673    {
674        return ALT_E_ERROR;
675    }
676
677    // Verify triggering parameter
678    switch (trigger)
679    {
680    case ALT_16550_FIFO_TRIGGER_TX_EMPTY:
681    case ALT_16550_FIFO_TRIGGER_TX_ALMOST_EMPTY:
682    case ALT_16550_FIFO_TRIGGER_TX_QUARTER_FULL:
683    case ALT_16550_FIFO_TRIGGER_TX_HALF_FULL:
684        break;
685    default:
686        return ALT_E_BAD_ARG;
687    }
688
689    switch (handle->device)
690    {
691    case ALT_16550_DEVICE_SOCFPGA_UART0:
692    case ALT_16550_DEVICE_SOCFPGA_UART1:
693    case ALT_16550_DEVICE_ALTERA_16550_UART:
694        // Update FCR::TET (FIFO Control Register :: Transmit Empty Trigger)
695        handle->fcr &= ~ALT_UART_FCR_TET_SET_MSK;
696        handle->fcr |= ALT_UART_FCR_TET_SET(trigger);
697        alt_write_word(ALT_UART_FCR_ADDR(handle->location), handle->fcr);
698        break;
699    default:
700        return ALT_E_ERROR;
701    }
702
703    return ALT_E_SUCCESS;
704}
705
706/////
707
708ALT_STATUS_CODE alt_16550_baudrate_get(ALT_16550_HANDLE_t * handle,
709                                       uint32_t * baudrate)
710{
711    // Query the divisor cached in the handle data
712    uint32_t divisor = ALT_16550_HANDLE_DATA_DIVISOR_VALUE_GET(handle->data);
713
714    // The divisor should never be zero. It is set to allow for a baud of 57600
715    // on initialization and a valid value is checked at
716    // alt_16550_divisor_set(). We do not check for users altering the data in
717    // the handle structure.
718
719    // Formula for calculating the baudrate:
720    //    baudrate = clock / (16 * divisor)
721
722    *baudrate = (handle->clock_freq >> 4) / divisor;
723
724    return ALT_E_SUCCESS;
725}
726
727ALT_STATUS_CODE alt_16550_baudrate_set(ALT_16550_HANDLE_t * handle,
728                                       uint32_t baudrate)
729{
730    if (baudrate == 0)
731    {
732        return ALT_E_ARG_RANGE;
733    }
734
735    // Formula for calculating the divisor:
736    //    baudrate = clock / (16 * divisor)
737    // => baudrate * 16 * divisor = clock
738    // => divisor = clock / (baudrate * 16)
739    // => divisor = (clock / 16) / baudrate
740
741    // Add half of the denominator to address rounding errors.
742    uint32_t divisor = ((handle->clock_freq + (8 * baudrate)) / (16 * baudrate));
743
744    // Check for divisor range is in alt_16550_divisor_set().
745    return alt_16550_divisor_set(handle, divisor);
746}
747
748ALT_STATUS_CODE alt_16550_divisor_get(ALT_16550_HANDLE_t * handle,
749                                      uint32_t * divisor)
750{
751    // Just read the divisor portion of the handle data.
752    *divisor = ALT_16550_HANDLE_DATA_DIVISOR_VALUE_GET(handle->data);
753
754    return ALT_E_SUCCESS;
755}
756
757ALT_STATUS_CODE alt_16550_divisor_set(ALT_16550_HANDLE_t * handle,
758                                      uint32_t divisor)
759{
760    // Verify divisor value is in range.
761    if ((divisor > 0xffff) || (divisor == 0))
762    {
763        return ALT_E_ARG_RANGE;
764    }
765
766    // Set the divisor portion of the handle data.
767    handle->data &= ~(0xffff);
768    handle->data |= divisor;
769
770    // Even if the UART is enabled, don't do anything. It is documented that
771    // the change will take effect when the UART move to the enabled state.
772
773    return ALT_E_SUCCESS;
774}
775
776/////
777
778static ALT_STATUS_CODE alt_16550_ier_mask_set_helper(ALT_16550_HANDLE_t * handle, uint32_t setmask)
779{
780    switch (handle->device)
781    {
782    case ALT_16550_DEVICE_SOCFPGA_UART0:
783    case ALT_16550_DEVICE_SOCFPGA_UART1:
784    case ALT_16550_DEVICE_ALTERA_16550_UART:
785        // Set bit in IER (Interrupt Enable Register)
786        alt_setbits_word(ALT_UART_IER_DLH_ADDR(handle->location), setmask);
787        break;
788    default:
789        return ALT_E_ERROR;
790    }
791
792    return ALT_E_SUCCESS;
793}
794
795static ALT_STATUS_CODE alt_16550_ier_mask_clr_helper(ALT_16550_HANDLE_t * handle, uint32_t setmask)
796{
797    switch (handle->device)
798    {
799    case ALT_16550_DEVICE_SOCFPGA_UART0:
800    case ALT_16550_DEVICE_SOCFPGA_UART1:
801    case ALT_16550_DEVICE_ALTERA_16550_UART:
802        // Clear bit in IER (Interrupt Enable Register)
803        alt_clrbits_word(ALT_UART_IER_DLH_ADDR(handle->location), setmask);
804        break;
805    default:
806        return ALT_E_ERROR;
807    }
808
809    return ALT_E_SUCCESS;
810}
811
812ALT_STATUS_CODE alt_16550_int_enable_rx(ALT_16550_HANDLE_t * handle)
813{
814    // Set the IER::ERBFI (Interrupt Enable Register :: Enable Receive Buffer Full Interrupt) bit.
815    return alt_16550_ier_mask_set_helper(handle, ALT_UART_IER_DLH_ERBFI_DLH0_SET_MSK);
816}
817
818ALT_STATUS_CODE alt_16550_int_disable_rx(ALT_16550_HANDLE_t * handle)
819{
820    // Clear the IER::ERBFI (Interrupt Enable Register :: Enable Receive Buffer Full Interrupt) bit.
821    return alt_16550_ier_mask_clr_helper(handle, ALT_UART_IER_DLH_ERBFI_DLH0_SET_MSK);
822}
823
824ALT_STATUS_CODE alt_16550_int_enable_tx(ALT_16550_HANDLE_t * handle)
825{
826    // Set the IER::ETBEI (Interrupt Enable Register :: Enable Transmit Buffer Empty Interrupt) bit.
827    return alt_16550_ier_mask_set_helper(handle, ALT_UART_IER_DLH_ETBEI_DLH1_SET_MSK);
828}
829
830ALT_STATUS_CODE alt_16550_int_disable_tx(ALT_16550_HANDLE_t * handle)
831{
832    // Clear the IER::ETBEI (Interrupt Enable Register :: Enable Transmit Buffer Empty Interrupt) bit.
833    return alt_16550_ier_mask_clr_helper(handle, ALT_UART_IER_DLH_ETBEI_DLH1_SET_MSK);
834}
835
836ALT_STATUS_CODE alt_16550_int_enable_line(ALT_16550_HANDLE_t * handle)
837{
838    // Set the IER::ELSI (Interrupt Enable Register :: Enable Line Status Interrupt) bit.
839    return alt_16550_ier_mask_set_helper(handle, ALT_UART_IER_DLH_ELSI_DHL2_SET_MSK);
840}
841
842ALT_STATUS_CODE alt_16550_int_disable_line(ALT_16550_HANDLE_t * handle)
843{
844    // Clear the IER::ELSI (Interrupt Enable Register :: Enable Line Status Interrupt) bit.
845    return alt_16550_ier_mask_clr_helper(handle, ALT_UART_IER_DLH_ELSI_DHL2_SET_MSK);
846}
847
848ALT_STATUS_CODE alt_16550_int_enable_modem(ALT_16550_HANDLE_t * handle)
849{
850    // Set the IER::EDSSI (Interrupt Enable Register :: Enable Modem Status Interrupt) bit.
851    return alt_16550_ier_mask_set_helper(handle, ALT_UART_IER_DLH_EDSSI_DHL3_SET_MSK);
852}
853
854ALT_STATUS_CODE alt_16550_int_disable_modem(ALT_16550_HANDLE_t * handle)
855{
856    // Clear the IER::EDSSI (Interrupt Enable Register :: Enable Modem Status Interrupt) bit.
857    return alt_16550_ier_mask_clr_helper(handle, ALT_UART_IER_DLH_EDSSI_DHL3_SET_MSK);
858}
859
860ALT_STATUS_CODE alt_16550_int_disable_all(ALT_16550_HANDLE_t * handle)
861{
862    // Clear the IER::(ERBFI | ETBEI | ELSI | EDSSI)
863    //   (Interrupt Enable Register :: (Enable Receive Buffer Full Interrupt   |
864    //                                  Enable Transmit Buffer Empty Interrupt |
865    //                                  Enable Line Status Interrupt           |
866    //                                  Enable Modem Status Interrupt)) bits
867    return alt_16550_ier_mask_clr_helper(handle, ALT_UART_IER_DLH_ERBFI_DLH0_SET_MSK |
868                                                 ALT_UART_IER_DLH_ETBEI_DLH1_SET_MSK |
869                                                 ALT_UART_IER_DLH_ELSI_DHL2_SET_MSK  |
870                                                 ALT_UART_IER_DLH_EDSSI_DHL3_SET_MSK);
871}
872
873ALT_STATUS_CODE alt_16550_int_status_get(ALT_16550_HANDLE_t * handle,
874                                         ALT_16550_INT_STATUS_t * status)
875{
876    switch (handle->device)
877    {
878    case ALT_16550_DEVICE_SOCFPGA_UART0:
879    case ALT_16550_DEVICE_SOCFPGA_UART1:
880    case ALT_16550_DEVICE_ALTERA_16550_UART:
881        // Read IIR::IID (Interrupt Identity Register :: Interrupt ID)
882        *status = (ALT_16550_INT_STATUS_t) ALT_UART_IIR_ID_GET(alt_read_word(ALT_UART_IIR_ADDR(handle->location)));
883        break;
884    default:
885        return ALT_E_ERROR;
886    }
887
888    return ALT_E_SUCCESS;
889}
890
891/////
892
893ALT_STATUS_CODE alt_16550_line_config_set(ALT_16550_HANDLE_t * handle,
894                                          ALT_16550_DATABITS_t databits,
895                                          ALT_16550_PARITY_t parity,
896                                          ALT_16550_STOPBITS_t stopbits)
897{
898    // Validate the databits parameter.
899    switch (databits)
900    {
901    case ALT_16550_DATABITS_5:
902    case ALT_16550_DATABITS_6:
903    case ALT_16550_DATABITS_7:
904    case ALT_16550_DATABITS_8:
905        break;
906    default:
907        return ALT_E_ERROR;
908    }
909
910    // Validate the parity parameter.
911    switch (parity)
912    {
913    case ALT_16550_PARITY_DISABLE:
914    case ALT_16550_PARITY_ODD:
915    case ALT_16550_PARITY_EVEN:
916        break;
917    default:
918        return ALT_E_ERROR;
919    }
920
921    // Validate the stopbits parameter.
922    switch (stopbits)
923    {
924    case ALT_16550_STOPBITS_1:
925    case ALT_16550_STOPBITS_2:
926        break;
927    default:
928        return ALT_E_ERROR;
929    }
930
931    // LCR (Line Control Register) cache.
932    uint32_t lcr = 0;
933
934    switch (handle->device)
935    {
936    case ALT_16550_DEVICE_SOCFPGA_UART0:
937    case ALT_16550_DEVICE_SOCFPGA_UART1:
938    case ALT_16550_DEVICE_ALTERA_16550_UART:
939
940        // Configure the number of databits
941        lcr |= ALT_UART_LCR_DLS_SET(databits);
942
943        // Configure the number of stopbits
944        lcr |= ALT_UART_LCR_STOP_SET(stopbits);
945
946        // Configure the parity
947        if (parity != ALT_16550_PARITY_DISABLE)
948        {
949            // Enable parity in LCR
950            lcr |= ALT_UART_LCR_PEN_SET_MSK;
951
952            if (parity == ALT_16550_PARITY_EVEN)
953            {
954                // Enable even parity in LCR; otherwise it's odd parity.
955                lcr |= ALT_UART_LCR_EPS_SET_MSK;
956            }
957        }
958
959        // Update LCR (Line Control Register)
960        alt_replbits_word(ALT_UART_LCR_ADDR(handle->location), 
961                          ALT_UART_LCR_DLS_SET_MSK
962                        | ALT_UART_LCR_STOP_SET_MSK
963                        | ALT_UART_LCR_PEN_SET_MSK
964                        | ALT_UART_LCR_EPS_SET_MSK,
965                        lcr);
966
967        break;
968
969    default:
970        return ALT_E_ERROR;
971    }
972
973    return ALT_E_SUCCESS;
974}
975
976ALT_STATUS_CODE alt_16550_line_break_enable(ALT_16550_HANDLE_t * handle)
977{
978    switch (handle->device)
979    {
980    case ALT_16550_DEVICE_SOCFPGA_UART0:
981    case ALT_16550_DEVICE_SOCFPGA_UART1:
982    case ALT_16550_DEVICE_ALTERA_16550_UART:
983        // Set the LCR::Break (Line Control Register :: Break) bit.
984        alt_setbits_word(ALT_UART_LCR_ADDR(handle->location), ALT_UART_LCR_BREAK_SET_MSK);
985        break;
986
987    default:
988        return ALT_E_ERROR;
989    }
990
991    return ALT_E_SUCCESS;
992}
993
994ALT_STATUS_CODE alt_16550_line_break_disable(ALT_16550_HANDLE_t * handle)
995{
996    switch (handle->device)
997    {
998    case ALT_16550_DEVICE_SOCFPGA_UART0:
999    case ALT_16550_DEVICE_SOCFPGA_UART1:
1000    case ALT_16550_DEVICE_ALTERA_16550_UART:
1001        // Clear the LCR::Break (Line Control Register :: Break) bit.
1002        alt_clrbits_word(ALT_UART_LCR_ADDR(handle->location), ALT_UART_LCR_BREAK_SET_MSK);
1003        break;
1004
1005    default:
1006        return ALT_E_ERROR;
1007    }
1008
1009
1010    return ALT_E_SUCCESS;
1011}
1012
1013ALT_STATUS_CODE alt_16550_line_status_get(ALT_16550_HANDLE_t * handle,
1014                                          uint32_t * status)
1015{
1016    switch (handle->device)
1017    {
1018    case ALT_16550_DEVICE_SOCFPGA_UART0:
1019    case ALT_16550_DEVICE_SOCFPGA_UART1:
1020    case ALT_16550_DEVICE_ALTERA_16550_UART:
1021        // Read the LSR (Line Status Register).
1022        *status = alt_read_word(ALT_UART_LSR_ADDR(handle->location));
1023        break;
1024    default:
1025        return ALT_E_ERROR;
1026    }
1027
1028    return ALT_E_SUCCESS;
1029}
1030
1031/////
1032
1033static ALT_STATUS_CODE alt_16550_mcr_mask_set_helper(ALT_16550_HANDLE_t * handle,
1034                                                     uint32_t setmask)
1035{
1036    switch (handle->device)
1037    {
1038    case ALT_16550_DEVICE_SOCFPGA_UART0:
1039    case ALT_16550_DEVICE_SOCFPGA_UART1:
1040    case ALT_16550_DEVICE_ALTERA_16550_UART:
1041        // Set the bit in MCR (Modem Control Register).
1042        alt_setbits_word(ALT_UART_MCR_ADDR(handle->location), setmask);
1043        break;
1044    default:
1045        return ALT_E_ERROR;
1046    }
1047
1048    return ALT_E_SUCCESS;
1049}
1050
1051static ALT_STATUS_CODE alt_16550_mcr_mask_clr_helper(ALT_16550_HANDLE_t * handle, uint32_t setmask)
1052{
1053    switch (handle->device)
1054    {
1055    case ALT_16550_DEVICE_SOCFPGA_UART0:
1056    case ALT_16550_DEVICE_SOCFPGA_UART1:
1057    case ALT_16550_DEVICE_ALTERA_16550_UART:
1058        // Clear the bit in MCR (Modem Control Register).
1059        alt_clrbits_word(ALT_UART_MCR_ADDR(handle->location), setmask);
1060        break;
1061    default:
1062        return ALT_E_ERROR;
1063    }
1064
1065    return ALT_E_SUCCESS;
1066}
1067
1068ALT_STATUS_CODE alt_16550_flowcontrol_enable(ALT_16550_HANDLE_t * handle)
1069{
1070    // Verify that the FIFO is enabled
1071    if (!(handle->fcr & ALT_UART_FCR_FIFOE_SET_MSK))
1072    {
1073        return ALT_E_ERROR;
1074    }
1075
1076    // For the Altera 16550 Compatible Soft UART, check that Hardware Flowcontrol is enabled.
1077    if (handle->device == ALT_16550_DEVICE_ALTERA_16550_UART)
1078    {
1079        // Read the CPR::AFCE_Mode (Component Parameter Register :: Auto Flow Control mode) bit.
1080        uint32_t cpr = alt_read_word(ALT_ALTERA_16550_CPR_ADDR(handle->location));
1081        if (!(ALT_ALTERA_16550_CPR_AFCE_MODE_SET_MSK & cpr))
1082        {
1083            return ALT_E_ERROR;
1084        }
1085    }
1086
1087    // Set MCR::AFCE (Modem Control Register :: Automatic FlowControl Enable) bit.
1088    return alt_16550_mcr_mask_set_helper(handle, ALT_UART_MCR_AFCE_SET_MSK);
1089}
1090
1091ALT_STATUS_CODE alt_16550_flowcontrol_disable(ALT_16550_HANDLE_t * handle)
1092{
1093    // Clear MCR::AFCE (Modem Control Register :: Automatic FlowControl Enable) bit.
1094    return alt_16550_mcr_mask_clr_helper(handle, ALT_UART_MCR_AFCE_SET_MSK);
1095}
1096
1097ALT_STATUS_CODE alt_16550_loopback_enable(ALT_16550_HANDLE_t * handle)
1098{
1099    // Loopback is not implemented in the Altera 16550 Compatible Soft UART.
1100    if (handle->device == ALT_16550_DEVICE_ALTERA_16550_UART)
1101    {
1102        return ALT_E_ERROR;
1103    }
1104
1105    // Set MCR::Loopback (Modem Control Register :: Loopback) bit.
1106    return alt_16550_mcr_mask_set_helper(handle, ALT_UART_MCR_LOOPBACK_SET_MSK);
1107}
1108
1109ALT_STATUS_CODE alt_16550_loopback_disable(ALT_16550_HANDLE_t * handle)
1110{
1111    // Clear MCR::Loopback (Modem Control Register :: Loopback) bit.
1112    return alt_16550_mcr_mask_clr_helper(handle, ALT_UART_MCR_LOOPBACK_SET_MSK);
1113}
1114
1115ALT_STATUS_CODE alt_16550_modem_enable_out1(ALT_16550_HANDLE_t * handle)
1116{
1117    // Set MCR::Out1 (Modem Control Register :: Out1) bit.
1118    return alt_16550_mcr_mask_set_helper(handle, ALT_UART_MCR_OUT1_SET_MSK);
1119}
1120
1121ALT_STATUS_CODE alt_16550_modem_disable_out1(ALT_16550_HANDLE_t * handle)
1122{
1123    // Clear MCR::Out1 (Modem Control Register :: Out1) bit.
1124    return alt_16550_mcr_mask_clr_helper(handle, ALT_UART_MCR_OUT1_SET_MSK);
1125}
1126
1127ALT_STATUS_CODE alt_16550_modem_enable_out2(ALT_16550_HANDLE_t * handle)
1128{
1129    // Set MCR::Out2 (Modem Control Register :: Out2) bit.
1130    return alt_16550_mcr_mask_set_helper(handle, ALT_UART_MCR_OUT2_SET_MSK);
1131}
1132
1133ALT_STATUS_CODE alt_16550_modem_disable_out2(ALT_16550_HANDLE_t * handle)
1134{
1135    // Clear MCR::Out2 (Modem Control Register :: Out2) bit.
1136    return alt_16550_mcr_mask_clr_helper(handle, ALT_UART_MCR_OUT2_SET_MSK);
1137}
1138
1139ALT_STATUS_CODE alt_16550_modem_enable_rts(ALT_16550_HANDLE_t * handle)
1140{
1141    // Set MCR::RTS (Modem Control Register :: Request To Send) bit.
1142    return alt_16550_mcr_mask_set_helper(handle, ALT_UART_MCR_RTS_SET_MSK);
1143}
1144
1145ALT_STATUS_CODE alt_16550_modem_disable_rts(ALT_16550_HANDLE_t * handle)
1146{
1147    // Clear MCR::RTS (Modem Control Register :: Request To Send) bit.
1148    return alt_16550_mcr_mask_clr_helper(handle, ALT_UART_MCR_RTS_SET_MSK);
1149}
1150
1151ALT_STATUS_CODE alt_16550_modem_enable_dtr(ALT_16550_HANDLE_t * handle)
1152{
1153    // Set MCR::DTR (Modem Control Register :: Data Terminal Ready) bit.
1154    return alt_16550_mcr_mask_set_helper(handle, ALT_UART_MCR_DTR_SET_MSK);
1155}
1156
1157ALT_STATUS_CODE alt_16550_modem_disable_dtr(ALT_16550_HANDLE_t * handle)
1158{
1159    // Clear MCR::DTR (Modem Control Register :: Data Terminal Ready) bit.
1160    return alt_16550_mcr_mask_clr_helper(handle, ALT_UART_MCR_DTR_SET_MSK);
1161}
1162
1163ALT_STATUS_CODE alt_16550_modem_status_get(ALT_16550_HANDLE_t * handle,
1164                                          uint32_t * status)
1165{
1166    switch (handle->device)
1167    {
1168    case ALT_16550_DEVICE_SOCFPGA_UART0:
1169    case ALT_16550_DEVICE_SOCFPGA_UART1:
1170    case ALT_16550_DEVICE_ALTERA_16550_UART:
1171        // Read the MSR (Modem Status Register).
1172        *status = alt_read_word(ALT_UART_MSR_ADDR(handle->location));
1173        break;
1174    default:
1175        return ALT_E_ERROR;
1176    }
1177
1178    return ALT_E_SUCCESS;
1179}
Note: See TracBrowser for help on using the repository browser.