1 /******************************************************************************
\r
3 * Copyright 2013 Altera Corporation. All Rights Reserved.
\r
5 * Redistribution and use in source and binary forms, with or without
\r
6 * modification, are permitted provided that the following conditions are met:
\r
8 * 1. Redistributions of source code must retain the above copyright notice,
\r
9 * this list of conditions and the following disclaimer.
\r
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
\r
12 * this list of conditions and the following disclaimer in the documentation
\r
13 * and/or other materials provided with the distribution.
\r
15 * 3. The name of the author may not be used to endorse or promote products
\r
16 * derived from this software without specific prior written permission.
\r
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY EXPRESS OR
\r
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
\r
20 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO
\r
21 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
\r
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
\r
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
\r
24 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
\r
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
\r
26 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
\r
27 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\r
29 ******************************************************************************/
\r
31 #include "alt_16550_uart.h"
\r
32 #include "alt_clock_manager.h"
\r
33 #include "socal/alt_rstmgr.h"
\r
34 #include "socal/alt_uart.h"
\r
35 #include "socal/hps.h"
\r
36 #include "socal/socal.h"
\r
40 #define ALT_16550_HANDLE_DATA_UART_ENABLED_MSK (1UL << 31)
\r
41 #define ALT_16550_HANDLE_DATA_DIVISOR_VALUE_GET(value) (value & 0xffff)
\r
43 #define ALT_ALTERA_16550_CPR_OFST (0xF4)
\r
44 #define ALT_ALTERA_16550_CPR_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_ALTERA_16550_CPR_OFST))
\r
45 #define ALT_ALTERA_16550_CPR_FIFO_MODE_GET(value) (((value) >> 16) & 0xff)
\r
46 #define ALT_ALTERA_16550_CPR_AFCE_MODE_SET_MSK (1 << 4)
\r
50 // Remove these macros as part of case:123835.
\r
51 #define ALT_UART_IER_DLH_VALUE_SET(value) ((value) & 0xff)
\r
52 #define ALT_UART_IER_DLH_ETBEI_DLH1_SET_MSK ALT_UART_IER_DLH_ETBEI_DLHL_SET_MSK
\r
57 // Helper function which resets the UART and if requested, initializes the UART
\r
58 // to the default settings. Currently the default settings are:
\r
63 // The reset routines depends on the hardware implementation of the UART.
\r
66 // This helper is needed because the regular alt_read_word(src) essentially
\r
67 // resolves to "*(volatile uint32_t *)src". As there is no assignment, this
\r
68 // could potentially be optimized away. With the helper, the actual register
\r
69 // read should occur and be returned (and subsequently discarded).
\r
70 static inline uint32_t alt_read_word_helper(const void * addr)
\r
72 return alt_read_word(addr);
\r
76 // Helper function write the divisor in hardware.
\r
78 static ALT_STATUS_CODE alt_16550_write_divisor_helper(ALT_16550_HANDLE_t * handle,
\r
81 // Validate the divisor parameter.
\r
82 if (divisor > 0xffff)
\r
84 // This should never happen as it is verified in divisor_set.
\r
88 switch (handle->device)
\r
90 case ALT_16550_DEVICE_SOCFPGA_UART0:
\r
91 case ALT_16550_DEVICE_SOCFPGA_UART1:
\r
92 case ALT_16550_DEVICE_ALTERA_16550_UART:
\r
93 // Set LCR::DLAB (Line Control Register :: Divisor Latch Access Bit)
\r
94 alt_setbits_word(ALT_UART_LCR_ADDR(handle->location), ALT_UART_LCR_DLAB_SET_MSK);
\r
96 // Write DLL (Divisor Latch Low).
\r
97 alt_write_word(ALT_UART_RBR_THR_DLL_ADDR(handle->location), ALT_UART_RBR_THR_DLL_VALUE_SET(divisor));
\r
99 // Write DLH (Divisor Latch High).
\r
100 alt_write_word(ALT_UART_IER_DLH_ADDR(handle->location), ALT_UART_IER_DLH_VALUE_SET(divisor >> 8));
\r
102 // Clear LCR::DLAB (Line Control Register :: Divisor Latch Access Bit)
\r
103 alt_clrbits_word(ALT_UART_LCR_ADDR(handle->location), ALT_UART_LCR_DLAB_SET_MSK);
\r
108 return ALT_E_ERROR;
\r
111 // Update the enabled state in the handle data.
\r
114 handle->data |= ALT_16550_HANDLE_DATA_UART_ENABLED_MSK;
\r
118 handle->data &= ~ALT_16550_HANDLE_DATA_UART_ENABLED_MSK;
\r
121 return ALT_E_SUCCESS;
\r
125 // Helper function to reset the UART.
\r
127 static ALT_STATUS_CODE alt_16550_reset_helper(ALT_16550_HANDLE_t * handle, bool enable_init)
\r
129 switch (handle->device)
\r
131 case ALT_16550_DEVICE_SOCFPGA_UART0:
\r
132 case ALT_16550_DEVICE_SOCFPGA_UART1:
\r
133 // Write SRR::UR (Shadow Reset Register :: UART Reset)
\r
134 alt_write_word(ALT_UART_SRR_ADDR(handle->location), ALT_UART_SRR_UR_SET_MSK);
\r
136 // Read the MSR to work around case:119085.
\r
137 alt_read_word_helper(ALT_UART_MSR_ADDR(handle->location));
\r
140 case ALT_16550_DEVICE_ALTERA_16550_UART:
\r
141 alt_16550_write_divisor_helper(handle, 0); // Disable UART
\r
142 alt_16550_int_disable_all(handle); // Disable interrupts
\r
143 alt_16550_fifo_disable(handle); // Disable FIFOs
\r
144 alt_write_word(ALT_UART_MCR_ADDR(handle->location), 0); // 0 -> MCR (AFCE, LP, OUT2, OUT1, RTS, DTR)
\r
148 return ALT_E_ERROR;
\r
151 // If we are initializing (as opposed to just uninitializing)
\r
154 ALT_STATUS_CODE status;
\r
156 // Set bit IER::PTIME (Interrupt Enable Register :: Programmable THRE Mode Enable)
\r
157 alt_setbits_word(ALT_UART_IER_DLH_ADDR(handle->location), ALT_UART_IER_DLH_PTIME_DLH7_SET_MSK);
\r
159 // Set the line configuration to use 8-N-1.
\r
160 status = alt_16550_line_config_set(handle, ALT_16550_DATABITS_8,
\r
161 ALT_16550_PARITY_DISABLE,
\r
162 ALT_16550_STOPBITS_1);
\r
163 if (status != ALT_E_SUCCESS)
\r
168 uint32_t divisor = ALT_16550_HANDLE_DATA_DIVISOR_VALUE_GET(handle->data);
\r
171 // Set the default baudrate to 57600.
\r
172 status = alt_16550_baudrate_set(handle, ALT_16550_BAUDRATE_57600);
\r
173 if (status != ALT_E_SUCCESS)
\r
180 return ALT_E_SUCCESS;
\r
183 ALT_STATUS_CODE alt_16550_init(ALT_16550_DEVICE_t device,
\r
185 alt_freq_t clock_freq,
\r
186 ALT_16550_HANDLE_t * handle)
\r
188 handle->device = device;
\r
194 case ALT_16550_DEVICE_SOCFPGA_UART0:
\r
195 case ALT_16550_DEVICE_SOCFPGA_UART1:
\r
196 // The ALT_CLK_L4_SP is required for all SoCFPGA UARTs. Check that it's enabled.
\r
197 if (alt_clk_is_enabled(ALT_CLK_L4_SP) != ALT_E_TRUE)
\r
199 return ALT_E_BAD_CLK;
\r
203 ALT_STATUS_CODE status;
\r
204 status = alt_clk_freq_get(ALT_CLK_L4_SP, &handle->clock_freq);
\r
205 if (status != ALT_E_SUCCESS)
\r
210 if (device == ALT_16550_DEVICE_SOCFPGA_UART0)
\r
212 handle->location = ALT_UART0_ADDR;
\r
214 // Bring UART0 out of reset.
\r
215 alt_clrbits_word(ALT_RSTMGR_PERMODRST_ADDR, ALT_RSTMGR_PERMODRST_UART0_SET_MSK);
\r
217 else // device == ALT_16550_DEVICE_SOCFPGA_UART1
\r
219 handle->location = ALT_UART1_ADDR;
\r
221 // Bring UART1 out of reset.
\r
222 alt_clrbits_word(ALT_RSTMGR_PERMODRST_ADDR, ALT_RSTMGR_PERMODRST_UART1_SET_MSK);
\r
225 // Verify the UCR (UART Component Version)
\r
226 uint32_t ucr = alt_read_word(ALT_UART_UCV_ADDR(handle->location));
\r
227 if (ucr != ALT_UART_UCV_UART_COMPONENT_VER_RESET)
\r
229 return ALT_E_ERROR;
\r
233 case ALT_16550_DEVICE_ALTERA_16550_UART:
\r
234 handle->location = location;
\r
235 handle->clock_freq = clock_freq;
\r
238 return ALT_E_BAD_ARG;
\r
241 return alt_16550_reset_helper(handle, true);
\r
244 ALT_STATUS_CODE alt_16550_uninit(ALT_16550_HANDLE_t * handle)
\r
246 switch (handle->device)
\r
248 case ALT_16550_DEVICE_SOCFPGA_UART0:
\r
249 alt_setbits_word(ALT_RSTMGR_PERMODRST_ADDR, ALT_RSTMGR_PERMODRST_UART0_SET_MSK);
\r
250 return ALT_E_SUCCESS;
\r
251 case ALT_16550_DEVICE_SOCFPGA_UART1:
\r
252 alt_setbits_word(ALT_RSTMGR_PERMODRST_ADDR, ALT_RSTMGR_PERMODRST_UART1_SET_MSK);
\r
253 return ALT_E_SUCCESS;
\r
254 case ALT_16550_DEVICE_ALTERA_16550_UART:
\r
256 return alt_16550_reset_helper(handle, false);
\r
260 ALT_STATUS_CODE alt_16550_reset(ALT_16550_HANDLE_t * handle)
\r
262 return alt_16550_reset_helper(handle, true);
\r
265 ALT_STATUS_CODE alt_16550_enable(ALT_16550_HANDLE_t * handle)
\r
267 // Write the divisor cached in the handle data to the divisor registers.
\r
268 // This will effectively enable the UART.
\r
269 return alt_16550_write_divisor_helper(handle,
\r
270 ALT_16550_HANDLE_DATA_DIVISOR_VALUE_GET(handle->data));
\r
273 ALT_STATUS_CODE alt_16550_disable(ALT_16550_HANDLE_t * handle)
\r
275 // Write 0 to the divisor the divisor registers. This will effectively
\r
276 // disable the UART.
\r
277 return alt_16550_write_divisor_helper(handle, 0);
\r
280 ALT_STATUS_CODE alt_16550_read(ALT_16550_HANDLE_t * handle,
\r
283 // Verify that the UART is enabled
\r
284 if (!(handle->data & ALT_16550_HANDLE_DATA_UART_ENABLED_MSK))
\r
286 return ALT_E_ERROR;
\r
289 // Verify that the FIFO is disabled
\r
290 if (handle->fcr & ALT_UART_FCR_FIFOE_SET_MSK)
\r
292 return ALT_E_ERROR;
\r
295 switch (handle->device)
\r
297 case ALT_16550_DEVICE_SOCFPGA_UART0:
\r
298 case ALT_16550_DEVICE_SOCFPGA_UART1:
\r
299 case ALT_16550_DEVICE_ALTERA_16550_UART:
\r
300 // Read the RBR (Receive Buffer Register) into *item.
\r
301 *item = ALT_UART_RBR_THR_DLL_VALUE_GET(alt_read_word(ALT_UART_RBR_THR_DLL_ADDR(handle->location)));
\r
304 return ALT_E_ERROR;
\r
306 return ALT_E_SUCCESS;
\r
309 ALT_STATUS_CODE alt_16550_write(ALT_16550_HANDLE_t * handle,
\r
312 // Verify that the UART is enabled
\r
313 if (!(handle->data & ALT_16550_HANDLE_DATA_UART_ENABLED_MSK))
\r
315 return ALT_E_ERROR;
\r
318 // Verify that the FIFO is disabled
\r
319 if (handle->fcr & ALT_UART_FCR_FIFOE_SET_MSK)
\r
321 return ALT_E_ERROR;
\r
324 switch (handle->device)
\r
326 case ALT_16550_DEVICE_SOCFPGA_UART0:
\r
327 case ALT_16550_DEVICE_SOCFPGA_UART1:
\r
328 case ALT_16550_DEVICE_ALTERA_16550_UART:
\r
329 // Write the buffer into the THR (Transmit Holding Register)
\r
330 alt_write_word(ALT_UART_RBR_THR_DLL_ADDR(handle->location), item);
\r
333 return ALT_E_ERROR;
\r
336 return ALT_E_SUCCESS;
\r
341 ALT_STATUS_CODE alt_16550_fifo_enable(ALT_16550_HANDLE_t * handle)
\r
343 switch (handle->device)
\r
345 case ALT_16550_DEVICE_SOCFPGA_UART0:
\r
346 case ALT_16550_DEVICE_SOCFPGA_UART1:
\r
347 case ALT_16550_DEVICE_ALTERA_16550_UART:
\r
348 // Set FCR::FIFOE (FIFO Control Register :: FIFO Enable) bit.
\r
349 handle->fcr |= ALT_UART_FCR_FIFOE_SET_MSK;
\r
350 alt_write_word(ALT_UART_FCR_ADDR(handle->location), handle->fcr);
\r
353 return ALT_E_ERROR;
\r
356 // No need to reset / clear the FIFOs. This is done automatically when
\r
357 // FCR::FIFOE is changed.
\r
358 return ALT_E_SUCCESS;
\r
361 ALT_STATUS_CODE alt_16550_fifo_disable(ALT_16550_HANDLE_t * handle)
\r
363 switch (handle->device)
\r
365 case ALT_16550_DEVICE_SOCFPGA_UART0:
\r
366 case ALT_16550_DEVICE_SOCFPGA_UART1:
\r
367 case ALT_16550_DEVICE_ALTERA_16550_UART:
\r
368 // Clear FCR::FIFOE (FIFO Control Register :: FIFO Enable) bit.
\r
369 handle->fcr &= ~ALT_UART_FCR_FIFOE_SET_MSK;
\r
370 alt_write_word(ALT_UART_FCR_ADDR(handle->location), handle->fcr);
\r
373 return ALT_E_ERROR;
\r
376 return ALT_E_SUCCESS;
\r
379 ALT_STATUS_CODE alt_16550_fifo_read(ALT_16550_HANDLE_t * handle,
\r
383 // Verify that the UART is enabled
\r
384 if (!(handle->data & ALT_16550_HANDLE_DATA_UART_ENABLED_MSK))
\r
386 return ALT_E_ERROR;
\r
389 // Verify that the FIFO is enabled
\r
390 if (!(handle->fcr & ALT_UART_FCR_FIFOE_SET_MSK))
\r
392 return ALT_E_ERROR;
\r
395 switch (handle->device)
\r
397 case ALT_16550_DEVICE_SOCFPGA_UART0:
\r
398 case ALT_16550_DEVICE_SOCFPGA_UART1:
\r
399 case ALT_16550_DEVICE_ALTERA_16550_UART:
\r
400 // Read the RBR (Receive Buffer Register) into the buffer
\r
401 for (size_t i = 0; i < count; ++i)
\r
403 buffer[i] = ALT_UART_RBR_THR_DLL_VALUE_GET(alt_read_word(ALT_UART_RBR_THR_DLL_ADDR(handle->location)));
\r
407 return ALT_E_ERROR;
\r
410 return ALT_E_SUCCESS;
\r
413 ALT_STATUS_CODE alt_16550_fifo_write(ALT_16550_HANDLE_t * handle,
\r
414 const char * buffer,
\r
417 // Verify that the UART is enabled
\r
418 if (!(handle->data & ALT_16550_HANDLE_DATA_UART_ENABLED_MSK))
\r
420 return ALT_E_ERROR;
\r
423 // Verify that the FIFO is enabled
\r
424 if (!(handle->fcr & ALT_UART_FCR_FIFOE_SET_MSK))
\r
426 return ALT_E_ERROR;
\r
429 switch (handle->device)
\r
431 case ALT_16550_DEVICE_SOCFPGA_UART0:
\r
432 case ALT_16550_DEVICE_SOCFPGA_UART1:
\r
433 case ALT_16550_DEVICE_ALTERA_16550_UART:
\r
434 // Write the buffer into the THR (Transmit Holding Register)
\r
435 for (size_t i = 0; i < count; ++i)
\r
437 alt_write_word(ALT_UART_RBR_THR_DLL_ADDR(handle->location), buffer[i]);
\r
441 return ALT_E_ERROR;
\r
444 return ALT_E_SUCCESS;
\r
447 ALT_STATUS_CODE alt_16550_fifo_clear_rx(ALT_16550_HANDLE_t * handle)
\r
449 // Verify that the FIFO is enabled
\r
450 if (!(handle->fcr & ALT_UART_FCR_FIFOE_SET_MSK))
\r
452 return ALT_E_ERROR;
\r
455 switch (handle->device)
\r
457 case ALT_16550_DEVICE_SOCFPGA_UART0:
\r
458 case ALT_16550_DEVICE_SOCFPGA_UART1:
\r
459 // Write SRR::RFR (Shadow Reset Register :: Receiver FIFO Reset) bit.
\r
460 alt_write_word(ALT_UART_SRR_ADDR(handle->location), ALT_UART_SRR_RFR_SET_MSK);
\r
462 case ALT_16550_DEVICE_ALTERA_16550_UART:
\r
463 // Write FCR::RFIFOR (FIFO Control Register :: Receiver FIFO Reset) bit.
\r
464 alt_write_word(ALT_UART_FCR_ADDR(handle->location), handle->fcr | ALT_UART_FCR_RFIFOR_SET_MSK);
\r
467 return ALT_E_ERROR;
\r
470 return ALT_E_SUCCESS;
\r
473 ALT_STATUS_CODE alt_16550_fifo_clear_tx(ALT_16550_HANDLE_t * handle)
\r
475 // Verify that the FIFO is enabled
\r
476 if (!(handle->fcr & ALT_UART_FCR_FIFOE_SET_MSK))
\r
478 return ALT_E_ERROR;
\r
481 switch (handle->device)
\r
483 case ALT_16550_DEVICE_SOCFPGA_UART0:
\r
484 case ALT_16550_DEVICE_SOCFPGA_UART1:
\r
485 // Write SRR::XFR (Shadow Reset Register :: Xmitter FIFO Reset) bit.
\r
486 alt_write_word(ALT_UART_SRR_ADDR(handle->location), ALT_UART_SRR_XFR_SET_MSK);
\r
488 case ALT_16550_DEVICE_ALTERA_16550_UART:
\r
489 // Write FCR::XFIFOR (FIFO Control Register :: Xmitter FIFO Reset) bit.
\r
490 alt_write_word(ALT_UART_FCR_ADDR(handle->location), handle->fcr | ALT_UART_FCR_XFIFOR_SET_MSK);
\r
493 return ALT_E_ERROR;
\r
496 return ALT_E_SUCCESS;
\r
499 ALT_STATUS_CODE alt_16550_fifo_clear_all(ALT_16550_HANDLE_t * handle)
\r
501 // Verify that the FIFO is enabled
\r
502 if (!(handle->fcr & ALT_UART_FCR_FIFOE_SET_MSK))
\r
504 return ALT_E_ERROR;
\r
507 switch (handle->device)
\r
509 case ALT_16550_DEVICE_SOCFPGA_UART0:
\r
510 case ALT_16550_DEVICE_SOCFPGA_UART1:
\r
511 // Write SRR::(RFR | XFR)
\r
512 // (Shadow Reset Register :: (Receiver FIFO Reset | Xmitter FIFO Reset)) bits.
\r
513 alt_write_word(ALT_UART_SRR_ADDR(handle->location),
\r
514 ALT_UART_SRR_RFR_SET_MSK | ALT_UART_SRR_XFR_SET_MSK);
\r
516 case ALT_16550_DEVICE_ALTERA_16550_UART:
\r
517 // Write FCR::(RFIFOR |XFIFOR)
\r
518 // (FIFO Control Register :: (Receiver FIFO Reset | Xmitter FIFO Reset)) bits.
\r
519 alt_write_word(ALT_UART_FCR_ADDR(handle->location),
\r
520 handle->fcr | ALT_UART_FCR_RFIFOR_SET_MSK | ALT_UART_FCR_XFIFOR_SET_MSK);
\r
523 return ALT_E_ERROR;
\r
526 return ALT_E_SUCCESS;
\r
529 ALT_STATUS_CODE alt_16550_fifo_size_get_rx(ALT_16550_HANDLE_t * handle,
\r
532 switch (handle->device)
\r
534 case ALT_16550_DEVICE_SOCFPGA_UART0:
\r
535 case ALT_16550_DEVICE_SOCFPGA_UART1:
\r
536 // Read the CPR::FIFO_Mod (Component Parameter Register :: FIFO Mode).
\r
537 // The FIFO size is 16x this value.
\r
538 *size = ALT_UART_CPR_FIFO_MOD_GET(alt_read_word(ALT_UART_CPR_ADDR(handle->location))) << 4;
\r
540 case ALT_16550_DEVICE_ALTERA_16550_UART:
\r
541 // Altera 16550 Compatible Soft UARTs have a configurable size and is
\r
542 // stored in the CPR::FIFO_Mode (Component Parameter Register :: FIFO Depth).
\r
543 *size = ALT_ALTERA_16550_CPR_FIFO_MODE_GET(alt_read_word(ALT_ALTERA_16550_CPR_ADDR(handle->location))) << 4;
\r
546 return ALT_E_ERROR;
\r
549 return ALT_E_SUCCESS;
\r
552 ALT_STATUS_CODE alt_16550_fifo_size_get_tx(ALT_16550_HANDLE_t * handle,
\r
555 switch (handle->device)
\r
557 case ALT_16550_DEVICE_SOCFPGA_UART0:
\r
558 case ALT_16550_DEVICE_SOCFPGA_UART1:
\r
559 // Read the CPR::FIFO_Mod (Component Parameter Register :: FIFO Mode).
\r
560 // The FIFO size is 16x this value.
\r
561 *size = ALT_UART_CPR_FIFO_MOD_GET(alt_read_word(ALT_UART_CPR_ADDR(handle->location))) << 4;
\r
563 case ALT_16550_DEVICE_ALTERA_16550_UART:
\r
564 // Altera 16550 Compatible Soft UARTs have a configurable size and is
\r
565 // stored in the CPR::FIFO_Mode (Component Parameter Register :: FIFO Depth).
\r
566 // The FIFO size is 16x this value.
\r
567 *size = ALT_ALTERA_16550_CPR_FIFO_MODE_GET(alt_read_word(ALT_ALTERA_16550_CPR_ADDR(handle->location))) << 4;
\r
570 return ALT_E_ERROR;
\r
573 return ALT_E_SUCCESS;
\r
576 ALT_STATUS_CODE alt_16550_fifo_level_get_rx(ALT_16550_HANDLE_t * handle,
\r
579 // Verify that the FIFO is enabled
\r
580 if (!(handle->fcr & ALT_UART_FCR_FIFOE_SET_MSK))
\r
582 return ALT_E_ERROR;
\r
585 switch (handle->device)
\r
587 case ALT_16550_DEVICE_SOCFPGA_UART0:
\r
588 case ALT_16550_DEVICE_SOCFPGA_UART1:
\r
589 // Read RFL (Receive FIFO Level).
\r
590 *level = alt_read_word(ALT_UART_RFL_ADDR(handle->location));
\r
592 case ALT_16550_DEVICE_ALTERA_16550_UART:
\r
593 // RFL not implemented. Return 0.
\r
597 return ALT_E_ERROR;
\r
600 return ALT_E_SUCCESS;
\r
603 ALT_STATUS_CODE alt_16550_fifo_level_get_tx(ALT_16550_HANDLE_t * handle,
\r
606 // Verify that the FIFO is enabled
\r
607 if (!(handle->fcr & ALT_UART_FCR_FIFOE_SET_MSK))
\r
609 return ALT_E_ERROR;
\r
612 switch (handle->device)
\r
614 case ALT_16550_DEVICE_SOCFPGA_UART0:
\r
615 case ALT_16550_DEVICE_SOCFPGA_UART1:
\r
616 // Read TFL (Transmit FIFO Level).
\r
617 *level = alt_read_word(ALT_UART_TFL_ADDR(handle->location));
\r
619 case ALT_16550_DEVICE_ALTERA_16550_UART:
\r
620 // TFL not implemented. Return 0.
\r
624 return ALT_E_ERROR;
\r
627 return ALT_E_SUCCESS;
\r
630 ALT_STATUS_CODE alt_16550_fifo_trigger_set_rx(ALT_16550_HANDLE_t * handle,
\r
631 ALT_16550_FIFO_TRIGGER_RX_t trigger)
\r
633 // Verify that the FIFO is enabled
\r
634 if (!(handle->fcr & ALT_UART_FCR_FIFOE_SET_MSK))
\r
636 return ALT_E_ERROR;
\r
639 // Verify triggering parameter
\r
642 case ALT_16550_FIFO_TRIGGER_RX_ANY:
\r
643 case ALT_16550_FIFO_TRIGGER_RX_QUARTER_FULL:
\r
644 case ALT_16550_FIFO_TRIGGER_RX_HALF_FULL:
\r
645 case ALT_16550_FIFO_TRIGGER_RX_ALMOST_FULL:
\r
648 return ALT_E_BAD_ARG;
\r
651 switch (handle->device)
\r
653 case ALT_16550_DEVICE_SOCFPGA_UART0:
\r
654 case ALT_16550_DEVICE_SOCFPGA_UART1:
\r
655 case ALT_16550_DEVICE_ALTERA_16550_UART:
\r
656 // Update FCR::RT (FIFO Control Register :: Receiver Trigger)
\r
657 handle->fcr &= ~ALT_UART_FCR_RT_SET_MSK;
\r
658 handle->fcr |= ALT_UART_FCR_RT_SET(trigger);
\r
659 alt_write_word(ALT_UART_FCR_ADDR(handle->location), handle->fcr);
\r
662 return ALT_E_ERROR;
\r
665 return ALT_E_SUCCESS;
\r
668 ALT_STATUS_CODE alt_16550_fifo_trigger_set_tx(ALT_16550_HANDLE_t * handle,
\r
669 ALT_16550_FIFO_TRIGGER_TX_t trigger)
\r
671 // Verify that the FIFO is enabled
\r
672 if (!(handle->fcr & ALT_UART_FCR_FIFOE_SET_MSK))
\r
674 return ALT_E_ERROR;
\r
677 // Verify triggering parameter
\r
680 case ALT_16550_FIFO_TRIGGER_TX_EMPTY:
\r
681 case ALT_16550_FIFO_TRIGGER_TX_ALMOST_EMPTY:
\r
682 case ALT_16550_FIFO_TRIGGER_TX_QUARTER_FULL:
\r
683 case ALT_16550_FIFO_TRIGGER_TX_HALF_FULL:
\r
686 return ALT_E_BAD_ARG;
\r
689 switch (handle->device)
\r
691 case ALT_16550_DEVICE_SOCFPGA_UART0:
\r
692 case ALT_16550_DEVICE_SOCFPGA_UART1:
\r
693 case ALT_16550_DEVICE_ALTERA_16550_UART:
\r
694 // Update FCR::TET (FIFO Control Register :: Transmit Empty Trigger)
\r
695 handle->fcr &= ~ALT_UART_FCR_TET_SET_MSK;
\r
696 handle->fcr |= ALT_UART_FCR_TET_SET(trigger);
\r
697 alt_write_word(ALT_UART_FCR_ADDR(handle->location), handle->fcr);
\r
700 return ALT_E_ERROR;
\r
703 return ALT_E_SUCCESS;
\r
708 ALT_STATUS_CODE alt_16550_baudrate_get(ALT_16550_HANDLE_t * handle,
\r
709 uint32_t * baudrate)
\r
711 // Query the divisor cached in the handle data
\r
712 uint32_t divisor = ALT_16550_HANDLE_DATA_DIVISOR_VALUE_GET(handle->data);
\r
714 // The divisor should never be zero. It is set to allow for a baud of 57600
\r
715 // on initialization and a valid value is checked at
\r
716 // alt_16550_divisor_set(). We do not check for users altering the data in
\r
717 // the handle structure.
\r
719 // Formula for calculating the baudrate:
\r
720 // baudrate = clock / (16 * divisor)
\r
722 *baudrate = (handle->clock_freq >> 4) / divisor;
\r
724 return ALT_E_SUCCESS;
\r
727 ALT_STATUS_CODE alt_16550_baudrate_set(ALT_16550_HANDLE_t * handle,
\r
732 return ALT_E_ARG_RANGE;
\r
735 // Formula for calculating the divisor:
\r
736 // baudrate = clock / (16 * divisor)
\r
737 // => baudrate * 16 * divisor = clock
\r
738 // => divisor = clock / (baudrate * 16)
\r
739 // => divisor = (clock / 16) / baudrate
\r
741 // Add half of the denominator to address rounding errors.
\r
742 uint32_t divisor = ((handle->clock_freq + (8 * baudrate)) / (16 * baudrate));
\r
744 // Check for divisor range is in alt_16550_divisor_set().
\r
745 return alt_16550_divisor_set(handle, divisor);
\r
748 ALT_STATUS_CODE alt_16550_divisor_get(ALT_16550_HANDLE_t * handle,
\r
749 uint32_t * divisor)
\r
751 // Just read the divisor portion of the handle data.
\r
752 *divisor = ALT_16550_HANDLE_DATA_DIVISOR_VALUE_GET(handle->data);
\r
754 return ALT_E_SUCCESS;
\r
757 ALT_STATUS_CODE alt_16550_divisor_set(ALT_16550_HANDLE_t * handle,
\r
760 // Verify divisor value is in range.
\r
761 if ((divisor > 0xffff) || (divisor == 0))
\r
763 return ALT_E_ARG_RANGE;
\r
766 // Set the divisor portion of the handle data.
\r
767 handle->data &= ~(0xffff);
\r
768 handle->data |= divisor;
\r
770 // Even if the UART is enabled, don't do anything. It is documented that
\r
771 // the change will take effect when the UART move to the enabled state.
\r
773 return ALT_E_SUCCESS;
\r
778 static ALT_STATUS_CODE alt_16550_ier_mask_set_helper(ALT_16550_HANDLE_t * handle, uint32_t setmask)
\r
780 switch (handle->device)
\r
782 case ALT_16550_DEVICE_SOCFPGA_UART0:
\r
783 case ALT_16550_DEVICE_SOCFPGA_UART1:
\r
784 case ALT_16550_DEVICE_ALTERA_16550_UART:
\r
785 // Set bit in IER (Interrupt Enable Register)
\r
786 alt_setbits_word(ALT_UART_IER_DLH_ADDR(handle->location), setmask);
\r
789 return ALT_E_ERROR;
\r
792 return ALT_E_SUCCESS;
\r
795 static ALT_STATUS_CODE alt_16550_ier_mask_clr_helper(ALT_16550_HANDLE_t * handle, uint32_t setmask)
\r
797 switch (handle->device)
\r
799 case ALT_16550_DEVICE_SOCFPGA_UART0:
\r
800 case ALT_16550_DEVICE_SOCFPGA_UART1:
\r
801 case ALT_16550_DEVICE_ALTERA_16550_UART:
\r
802 // Clear bit in IER (Interrupt Enable Register)
\r
803 alt_clrbits_word(ALT_UART_IER_DLH_ADDR(handle->location), setmask);
\r
806 return ALT_E_ERROR;
\r
809 return ALT_E_SUCCESS;
\r
812 ALT_STATUS_CODE alt_16550_int_enable_rx(ALT_16550_HANDLE_t * handle)
\r
814 // Set the IER::ERBFI (Interrupt Enable Register :: Enable Receive Buffer Full Interrupt) bit.
\r
815 return alt_16550_ier_mask_set_helper(handle, ALT_UART_IER_DLH_ERBFI_DLH0_SET_MSK);
\r
818 ALT_STATUS_CODE alt_16550_int_disable_rx(ALT_16550_HANDLE_t * handle)
\r
820 // Clear the IER::ERBFI (Interrupt Enable Register :: Enable Receive Buffer Full Interrupt) bit.
\r
821 return alt_16550_ier_mask_clr_helper(handle, ALT_UART_IER_DLH_ERBFI_DLH0_SET_MSK);
\r
824 ALT_STATUS_CODE alt_16550_int_enable_tx(ALT_16550_HANDLE_t * handle)
\r
826 // Set the IER::ETBEI (Interrupt Enable Register :: Enable Transmit Buffer Empty Interrupt) bit.
\r
827 return alt_16550_ier_mask_set_helper(handle, ALT_UART_IER_DLH_ETBEI_DLH1_SET_MSK);
\r
830 ALT_STATUS_CODE alt_16550_int_disable_tx(ALT_16550_HANDLE_t * handle)
\r
832 // Clear the IER::ETBEI (Interrupt Enable Register :: Enable Transmit Buffer Empty Interrupt) bit.
\r
833 return alt_16550_ier_mask_clr_helper(handle, ALT_UART_IER_DLH_ETBEI_DLH1_SET_MSK);
\r
836 ALT_STATUS_CODE alt_16550_int_enable_line(ALT_16550_HANDLE_t * handle)
\r
838 // Set the IER::ELSI (Interrupt Enable Register :: Enable Line Status Interrupt) bit.
\r
839 return alt_16550_ier_mask_set_helper(handle, ALT_UART_IER_DLH_ELSI_DHL2_SET_MSK);
\r
842 ALT_STATUS_CODE alt_16550_int_disable_line(ALT_16550_HANDLE_t * handle)
\r
844 // Clear the IER::ELSI (Interrupt Enable Register :: Enable Line Status Interrupt) bit.
\r
845 return alt_16550_ier_mask_clr_helper(handle, ALT_UART_IER_DLH_ELSI_DHL2_SET_MSK);
\r
848 ALT_STATUS_CODE alt_16550_int_enable_modem(ALT_16550_HANDLE_t * handle)
\r
850 // Set the IER::EDSSI (Interrupt Enable Register :: Enable Modem Status Interrupt) bit.
\r
851 return alt_16550_ier_mask_set_helper(handle, ALT_UART_IER_DLH_EDSSI_DHL3_SET_MSK);
\r
854 ALT_STATUS_CODE alt_16550_int_disable_modem(ALT_16550_HANDLE_t * handle)
\r
856 // Clear the IER::EDSSI (Interrupt Enable Register :: Enable Modem Status Interrupt) bit.
\r
857 return alt_16550_ier_mask_clr_helper(handle, ALT_UART_IER_DLH_EDSSI_DHL3_SET_MSK);
\r
860 ALT_STATUS_CODE alt_16550_int_disable_all(ALT_16550_HANDLE_t * handle)
\r
862 // Clear the IER::(ERBFI | ETBEI | ELSI | EDSSI)
\r
863 // (Interrupt Enable Register :: (Enable Receive Buffer Full Interrupt |
\r
864 // Enable Transmit Buffer Empty Interrupt |
\r
865 // Enable Line Status Interrupt |
\r
866 // Enable Modem Status Interrupt)) bits
\r
867 return alt_16550_ier_mask_clr_helper(handle, ALT_UART_IER_DLH_ERBFI_DLH0_SET_MSK |
\r
868 ALT_UART_IER_DLH_ETBEI_DLH1_SET_MSK |
\r
869 ALT_UART_IER_DLH_ELSI_DHL2_SET_MSK |
\r
870 ALT_UART_IER_DLH_EDSSI_DHL3_SET_MSK);
\r
873 ALT_STATUS_CODE alt_16550_int_status_get(ALT_16550_HANDLE_t * handle,
\r
874 ALT_16550_INT_STATUS_t * status)
\r
876 switch (handle->device)
\r
878 case ALT_16550_DEVICE_SOCFPGA_UART0:
\r
879 case ALT_16550_DEVICE_SOCFPGA_UART1:
\r
880 case ALT_16550_DEVICE_ALTERA_16550_UART:
\r
881 // Read IIR::IID (Interrupt Identity Register :: Interrupt ID)
\r
882 *status = (ALT_16550_INT_STATUS_t) ALT_UART_IIR_ID_GET(alt_read_word(ALT_UART_IIR_ADDR(handle->location)));
\r
885 return ALT_E_ERROR;
\r
888 return ALT_E_SUCCESS;
\r
893 ALT_STATUS_CODE alt_16550_line_config_set(ALT_16550_HANDLE_t * handle,
\r
894 ALT_16550_DATABITS_t databits,
\r
895 ALT_16550_PARITY_t parity,
\r
896 ALT_16550_STOPBITS_t stopbits)
\r
898 // Validate the databits parameter.
\r
901 case ALT_16550_DATABITS_5:
\r
902 case ALT_16550_DATABITS_6:
\r
903 case ALT_16550_DATABITS_7:
\r
904 case ALT_16550_DATABITS_8:
\r
907 return ALT_E_ERROR;
\r
910 // Validate the parity parameter.
\r
913 case ALT_16550_PARITY_DISABLE:
\r
914 case ALT_16550_PARITY_ODD:
\r
915 case ALT_16550_PARITY_EVEN:
\r
918 return ALT_E_ERROR;
\r
921 // Validate the stopbits parameter.
\r
924 case ALT_16550_STOPBITS_1:
\r
925 case ALT_16550_STOPBITS_2:
\r
928 return ALT_E_ERROR;
\r
931 // LCR (Line Control Register) cache.
\r
934 switch (handle->device)
\r
936 case ALT_16550_DEVICE_SOCFPGA_UART0:
\r
937 case ALT_16550_DEVICE_SOCFPGA_UART1:
\r
938 case ALT_16550_DEVICE_ALTERA_16550_UART:
\r
940 // Configure the number of databits
\r
941 lcr |= ALT_UART_LCR_DLS_SET(databits);
\r
943 // Configure the number of stopbits
\r
944 lcr |= ALT_UART_LCR_STOP_SET(stopbits);
\r
946 // Configure the parity
\r
947 if (parity != ALT_16550_PARITY_DISABLE)
\r
949 // Enable parity in LCR
\r
950 lcr |= ALT_UART_LCR_PEN_SET_MSK;
\r
952 if (parity == ALT_16550_PARITY_EVEN)
\r
954 // Enable even parity in LCR; otherwise it's odd parity.
\r
955 lcr |= ALT_UART_LCR_EPS_SET_MSK;
\r
959 // Update LCR (Line Control Register)
\r
960 alt_replbits_word(ALT_UART_LCR_ADDR(handle->location),
\r
961 ALT_UART_LCR_DLS_SET_MSK
\r
962 | ALT_UART_LCR_STOP_SET_MSK
\r
963 | ALT_UART_LCR_PEN_SET_MSK
\r
964 | ALT_UART_LCR_EPS_SET_MSK,
\r
970 return ALT_E_ERROR;
\r
973 return ALT_E_SUCCESS;
\r
976 ALT_STATUS_CODE alt_16550_line_break_enable(ALT_16550_HANDLE_t * handle)
\r
978 switch (handle->device)
\r
980 case ALT_16550_DEVICE_SOCFPGA_UART0:
\r
981 case ALT_16550_DEVICE_SOCFPGA_UART1:
\r
982 case ALT_16550_DEVICE_ALTERA_16550_UART:
\r
983 // Set the LCR::Break (Line Control Register :: Break) bit.
\r
984 alt_setbits_word(ALT_UART_LCR_ADDR(handle->location), ALT_UART_LCR_BREAK_SET_MSK);
\r
988 return ALT_E_ERROR;
\r
991 return ALT_E_SUCCESS;
\r
994 ALT_STATUS_CODE alt_16550_line_break_disable(ALT_16550_HANDLE_t * handle)
\r
996 switch (handle->device)
\r
998 case ALT_16550_DEVICE_SOCFPGA_UART0:
\r
999 case ALT_16550_DEVICE_SOCFPGA_UART1:
\r
1000 case ALT_16550_DEVICE_ALTERA_16550_UART:
\r
1001 // Clear the LCR::Break (Line Control Register :: Break) bit.
\r
1002 alt_clrbits_word(ALT_UART_LCR_ADDR(handle->location), ALT_UART_LCR_BREAK_SET_MSK);
\r
1006 return ALT_E_ERROR;
\r
1010 return ALT_E_SUCCESS;
\r
1013 ALT_STATUS_CODE alt_16550_line_status_get(ALT_16550_HANDLE_t * handle,
\r
1014 uint32_t * status)
\r
1016 switch (handle->device)
\r
1018 case ALT_16550_DEVICE_SOCFPGA_UART0:
\r
1019 case ALT_16550_DEVICE_SOCFPGA_UART1:
\r
1020 case ALT_16550_DEVICE_ALTERA_16550_UART:
\r
1021 // Read the LSR (Line Status Register).
\r
1022 *status = alt_read_word(ALT_UART_LSR_ADDR(handle->location));
\r
1025 return ALT_E_ERROR;
\r
1028 return ALT_E_SUCCESS;
\r
1033 static ALT_STATUS_CODE alt_16550_mcr_mask_set_helper(ALT_16550_HANDLE_t * handle,
\r
1036 switch (handle->device)
\r
1038 case ALT_16550_DEVICE_SOCFPGA_UART0:
\r
1039 case ALT_16550_DEVICE_SOCFPGA_UART1:
\r
1040 case ALT_16550_DEVICE_ALTERA_16550_UART:
\r
1041 // Set the bit in MCR (Modem Control Register).
\r
1042 alt_setbits_word(ALT_UART_MCR_ADDR(handle->location), setmask);
\r
1045 return ALT_E_ERROR;
\r
1048 return ALT_E_SUCCESS;
\r
1051 static ALT_STATUS_CODE alt_16550_mcr_mask_clr_helper(ALT_16550_HANDLE_t * handle, uint32_t setmask)
\r
1053 switch (handle->device)
\r
1055 case ALT_16550_DEVICE_SOCFPGA_UART0:
\r
1056 case ALT_16550_DEVICE_SOCFPGA_UART1:
\r
1057 case ALT_16550_DEVICE_ALTERA_16550_UART:
\r
1058 // Clear the bit in MCR (Modem Control Register).
\r
1059 alt_clrbits_word(ALT_UART_MCR_ADDR(handle->location), setmask);
\r
1062 return ALT_E_ERROR;
\r
1065 return ALT_E_SUCCESS;
\r
1068 ALT_STATUS_CODE alt_16550_flowcontrol_enable(ALT_16550_HANDLE_t * handle)
\r
1070 // Verify that the FIFO is enabled
\r
1071 if (!(handle->fcr & ALT_UART_FCR_FIFOE_SET_MSK))
\r
1073 return ALT_E_ERROR;
\r
1076 // For the Altera 16550 Compatible Soft UART, check that Hardware Flowcontrol is enabled.
\r
1077 if (handle->device == ALT_16550_DEVICE_ALTERA_16550_UART)
\r
1079 // Read the CPR::AFCE_Mode (Component Parameter Register :: Auto Flow Control mode) bit.
\r
1080 uint32_t cpr = alt_read_word(ALT_ALTERA_16550_CPR_ADDR(handle->location));
\r
1081 if (!(ALT_ALTERA_16550_CPR_AFCE_MODE_SET_MSK & cpr))
\r
1083 return ALT_E_ERROR;
\r
1087 // Set MCR::AFCE (Modem Control Register :: Automatic FlowControl Enable) bit.
\r
1088 return alt_16550_mcr_mask_set_helper(handle, ALT_UART_MCR_AFCE_SET_MSK);
\r
1091 ALT_STATUS_CODE alt_16550_flowcontrol_disable(ALT_16550_HANDLE_t * handle)
\r
1093 // Clear MCR::AFCE (Modem Control Register :: Automatic FlowControl Enable) bit.
\r
1094 return alt_16550_mcr_mask_clr_helper(handle, ALT_UART_MCR_AFCE_SET_MSK);
\r
1097 ALT_STATUS_CODE alt_16550_loopback_enable(ALT_16550_HANDLE_t * handle)
\r
1099 // Loopback is not implemented in the Altera 16550 Compatible Soft UART.
\r
1100 if (handle->device == ALT_16550_DEVICE_ALTERA_16550_UART)
\r
1102 return ALT_E_ERROR;
\r
1105 // Set MCR::Loopback (Modem Control Register :: Loopback) bit.
\r
1106 return alt_16550_mcr_mask_set_helper(handle, ALT_UART_MCR_LOOPBACK_SET_MSK);
\r
1109 ALT_STATUS_CODE alt_16550_loopback_disable(ALT_16550_HANDLE_t * handle)
\r
1111 // Clear MCR::Loopback (Modem Control Register :: Loopback) bit.
\r
1112 return alt_16550_mcr_mask_clr_helper(handle, ALT_UART_MCR_LOOPBACK_SET_MSK);
\r
1115 ALT_STATUS_CODE alt_16550_modem_enable_out1(ALT_16550_HANDLE_t * handle)
\r
1117 // Set MCR::Out1 (Modem Control Register :: Out1) bit.
\r
1118 return alt_16550_mcr_mask_set_helper(handle, ALT_UART_MCR_OUT1_SET_MSK);
\r
1121 ALT_STATUS_CODE alt_16550_modem_disable_out1(ALT_16550_HANDLE_t * handle)
\r
1123 // Clear MCR::Out1 (Modem Control Register :: Out1) bit.
\r
1124 return alt_16550_mcr_mask_clr_helper(handle, ALT_UART_MCR_OUT1_SET_MSK);
\r
1127 ALT_STATUS_CODE alt_16550_modem_enable_out2(ALT_16550_HANDLE_t * handle)
\r
1129 // Set MCR::Out2 (Modem Control Register :: Out2) bit.
\r
1130 return alt_16550_mcr_mask_set_helper(handle, ALT_UART_MCR_OUT2_SET_MSK);
\r
1133 ALT_STATUS_CODE alt_16550_modem_disable_out2(ALT_16550_HANDLE_t * handle)
\r
1135 // Clear MCR::Out2 (Modem Control Register :: Out2) bit.
\r
1136 return alt_16550_mcr_mask_clr_helper(handle, ALT_UART_MCR_OUT2_SET_MSK);
\r
1139 ALT_STATUS_CODE alt_16550_modem_enable_rts(ALT_16550_HANDLE_t * handle)
\r
1141 // Set MCR::RTS (Modem Control Register :: Request To Send) bit.
\r
1142 return alt_16550_mcr_mask_set_helper(handle, ALT_UART_MCR_RTS_SET_MSK);
\r
1145 ALT_STATUS_CODE alt_16550_modem_disable_rts(ALT_16550_HANDLE_t * handle)
\r
1147 // Clear MCR::RTS (Modem Control Register :: Request To Send) bit.
\r
1148 return alt_16550_mcr_mask_clr_helper(handle, ALT_UART_MCR_RTS_SET_MSK);
\r
1151 ALT_STATUS_CODE alt_16550_modem_enable_dtr(ALT_16550_HANDLE_t * handle)
\r
1153 // Set MCR::DTR (Modem Control Register :: Data Terminal Ready) bit.
\r
1154 return alt_16550_mcr_mask_set_helper(handle, ALT_UART_MCR_DTR_SET_MSK);
\r
1157 ALT_STATUS_CODE alt_16550_modem_disable_dtr(ALT_16550_HANDLE_t * handle)
\r
1159 // Clear MCR::DTR (Modem Control Register :: Data Terminal Ready) bit.
\r
1160 return alt_16550_mcr_mask_clr_helper(handle, ALT_UART_MCR_DTR_SET_MSK);
\r
1163 ALT_STATUS_CODE alt_16550_modem_status_get(ALT_16550_HANDLE_t * handle,
\r
1164 uint32_t * status)
\r
1166 switch (handle->device)
\r
1168 case ALT_16550_DEVICE_SOCFPGA_UART0:
\r
1169 case ALT_16550_DEVICE_SOCFPGA_UART1:
\r
1170 case ALT_16550_DEVICE_ALTERA_16550_UART:
\r
1171 // Read the MSR (Modem Status Register).
\r
1172 *status = alt_read_word(ALT_UART_MSR_ADDR(handle->location));
\r
1175 return ALT_E_ERROR;
\r
1178 return ALT_E_SUCCESS;
\r