source: rtems/bsps/arm/altera-cyclone-v/contrib/hwlib/src/hwmgr/alt_16550_uart.c @ 9d41fca

5
Last change on this file since 9d41fca was 9d41fca, checked in by Sebastian Huber <sebastian.huber@…>, on 02/27/19 at 10:39:29

bsp/altera-cyclone-v: Adjust Doxygen file groups

Update #3707.

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