1 /******************************************************************************
2 *                                                                             *
3 * License Agreement                                                           *
4 *                                                                             *
5 * Copyright (c) 2006 Altera Corporation, San Jose, California, USA.           *
6 * All rights reserved.                                                        *
7 *                                                                             *
8 * Permission is hereby granted, free of charge, to any person obtaining a     *
9 * copy of this software and associated documentation files (the "Software"),  *
10 * to deal in the Software without restriction, including without limitation   *
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,    *
12 * and/or sell copies of the Software, and to permit persons to whom the       *
13 * Software is furnished to do so, subject to the following conditions:        *
14 *                                                                             *
15 * The above copyright notice and this permission notice shall be included in  *
16 * all copies or substantial portions of the Software.                         *
17 *                                                                             *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  *
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,    *
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER      *
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING     *
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER         *
24 * DEALINGS IN THE SOFTWARE.                                                   *
25 *                                                                             *
26 *                                                                             *
27 ******************************************************************************/
28 
29 #ifndef __ALT_AVALON_UART_H__
30 #define __ALT_AVALON_UART_H__
31 
32 #include <stddef.h>
33 #include <sys/termios.h>
34 
35 #include "sys/alt_warning.h"
36 
37 #include "os/alt_sem.h"
38 #include "os/alt_flag.h"
39 #include "alt_types.h"
40 
41 #ifdef __cplusplus
42 extern "C"
43 {
44 #endif /* __cplusplus */
45 
46 #if defined(ALT_USE_SMALL_DRIVERS) || defined(ALTERA_AVALON_UART_SMALL)
47 
48 /*
49  ***********************************************************************
50  *********************** SMALL DRIVER **********************************
51  ***********************************************************************
52  */
53 
54 /*
55  * State structure definition. Each instance of the driver uses one
56  * of these structures to hold its associated state.
57  */
58 
59 typedef struct altera_avalon_uart_state_s
60 {
61     unsigned int        base;
62 } altera_avalon_uart_state;
63 
64 /*
65  * The macro ALTERA_AVALON_UART_STATE_INSTANCE is used by the
66  * auto-generated file alt_sys_init.c to create an instance of this
67  * device driver state.
68  */
69 
70 #define ALTERA_AVALON_UART_STATE_INSTANCE(name, state)   \
71   altera_avalon_uart_state state =                  \
72     {                                               \
73       name##_BASE                                   \
74     }
75 
76 /*
77  * The macro ALTERA_AVALON_UART_STATE_INIT is used by the auto-generated file
78  * alt_sys_init.c to initialize an instance of the device driver state.
79  */
80 
81 #define ALTERA_AVALON_UART_STATE_INIT(name, state)
82 
83 #else /* fast driver */
84 
85 /*
86  **********************************************************************
87  *********************** FAST DRIVER **********************************
88  **********************************************************************
89  */
90 
91 /*
92  * ALT_AVALON_UART_READ_RDY and ALT_AVALON_UART_WRITE_RDY are the bitmasks
93  * that define uC/OS-II event flags that are releated to this device.
94  *
95  * ALT_AVALON_UART_READY_RDY indicates that there is read data in the buffer
96  * ready to be processed. ALT_UART_WRITE_RDY indicates that the transmitter is
97  * ready for more data.
98  */
99 
100 #define ALT_UART_READ_RDY  0x1
101 #define ALT_UART_WRITE_RDY 0x2
102 
103 /*
104  * ALT_AVALON_UART_BUF_LEN is the length of the circular buffers used to hold
105  * pending transmit and receive data. This value must be a power of two.
106  */
107 
108 #define ALT_AVALON_UART_BUF_LEN (64)
109 
110 /*
111  * ALT_AVALON_UART_BUF_MSK is used as an internal convenience for detecting
112  * the end of the arrays used to implement the transmit and receive buffers.
113  */
114 
115 #define ALT_AVALON_UART_BUF_MSK (ALT_AVALON_UART_BUF_LEN - 1)
116 
117 /*
118  * This is somewhat of an ugly hack, but we need some mechanism for
119  * representing the non-standard 9 bit mode provided by this UART. In this
120  * case we abscond with the 5 bit mode setting. The value CS5 is defined in
121  * termios.h.
122  */
123 
124 #define CS9 CS5
125 
126 /*
127  * The value ALT_AVALON_UART_FB is a value set in the devices flag field to
128  * indicate that the device has a fixed baud rate; i.e. if this flag is set
129  * software can not control the baud rate of the device.
130  */
131 
132 #define ALT_AVALON_UART_FB 0x1
133 
134 /*
135  * The value ALT_AVALON_UART_FC is a value set in the device flag field to
136  * indicate the the device is using flow control, i.e. the driver must
137  * throttle on transmit if the nCTS pin is low.
138  */
139 
140 #define ALT_AVALON_UART_FC 0x2
141 
142 /*
143  * The altera_avalon_uart_state structure is used to hold device specific data.
144  * This includes the transmit and receive buffers.
145  *
146  * An instance of this structure is created in the auto-generated
147  * alt_sys_init.c file for each UART listed in the systems PTF file. This is
148  * done using the ALTERA_AVALON_UART_STATE_INSTANCE macro given below.
149  */
150 
151 typedef struct altera_avalon_uart_state_s
152 {
153   void*            base;            /* The base address of the device */
154   alt_u32          ctrl;            /* Shadow value of the control register */
155   volatile alt_u32 rx_start;        /* Start of the pending receive data */
156   volatile alt_u32 rx_end;          /* End of the pending receive data */
157   volatile alt_u32 tx_start;        /* Start of the pending transmit data */
158   volatile alt_u32 tx_end;          /* End of the pending transmit data */
159 #ifdef ALTERA_AVALON_UART_USE_IOCTL
160   struct termios termios;           /* Current device configuration */
161   alt_u32          freq;            /* Current baud rate */
162 #endif
163   alt_u32          flags;           /* Configuation flags */
164   ALT_FLAG_GRP     (events)         /* Event flags used for
165                                      * foreground/background in mult-threaded
166                                      * mode */
167   ALT_SEM          (read_lock)      /* Semaphore used to control access to the
168                                      * read buffer in multi-threaded mode */
169   ALT_SEM          (write_lock)     /* Semaphore used to control access to the
170                                      * write buffer in multi-threaded mode */
171   volatile alt_u8  rx_buf[ALT_AVALON_UART_BUF_LEN]; /* The receive buffer */
172   volatile alt_u8  tx_buf[ALT_AVALON_UART_BUF_LEN]; /* The transmit buffer */
173 } altera_avalon_uart_state;
174 
175 /*
176  * Conditionally define the data structures used to process ioctl requests.
177  * The following macros are defined for use in creating a device instance:
178  *
179  * ALTERA_AVALON_UART_TERMIOS - Initialise the termios structure used to
180  *                              describe the UART configuration.
181  * ALTERA_AVALON_UART_FREQ    - Initialise the 'freq' field of the device
182  *                              structure, if the field exists.
183  * ALTERA_AVALON_UART_IOCTL   - Initialise the 'ioctl' field of the device
184  *                              callback structure, if ioctls are enabled.
185  */
186 
187 #ifdef ALTERA_AVALON_UART_USE_IOCTL
188 
189 #define ALTERA_AVALON_UART_TERMIOS(stop_bits,               \
190                                    parity,                  \
191                                    odd_parity,              \
192                                    data_bits,               \
193                                    ctsrts,                  \
194                                    baud)                    \
195 {                                                           \
196   0,                                                        \
197   0,                                                        \
198   ((stop_bits == 2) ? CSTOPB: 0)      |                     \
199     ((parity) ? PARENB: 0)            |                     \
200     ((odd_parity) ? PAODD: 0)         |                     \
201     ((data_bits == 7) ? CS7: (data_bits == 9) ? CS9: CS8) | \
202     ((ctsrts) ? CRTSCTS : 0),                               \
203   0,                                                        \
204   0,                                                        \
205   {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},                  \
206   baud,                                                     \
207   baud                                                      \
208 },
209 #define ALTERA_AVALON_UART_FREQ(name) name##_FREQ,
210 
211 #else /* !ALTERA_AVALON_UART_USE_IOCTL */
212 
213 #define ALTERA_AVALON_UART_TERMIOS(stop_bits,  \
214                                    parity,     \
215                                    odd_parity, \
216                                    data_bits,  \
217                                    ctsrts,     \
218                                    baud)
219 #define ALTERA_AVALON_UART_FREQ(name)
220 
221 #endif /* ALTERA_AVALON_UART_USE_IOCTL */
222 
223 /*
224  * The macro ALTERA_AVALON_UART_INSTANCE is used by the auto-generated file
225  * alt_sys_init.c to create an instance of this device driver state.
226  */
227 
228 #define ALTERA_AVALON_UART_STATE_INSTANCE(name, state) \
229   altera_avalon_uart_state state =                     \
230    {                                                   \
231      (void*) name##_BASE,                              \
232      0,                                                \
233      0,                                                \
234      0,                                                \
235      0,                                                \
236      0,                                                \
237      ALTERA_AVALON_UART_TERMIOS(name##_STOP_BITS,      \
238                                (name##_PARITY == 'N'), \
239                                (name##_PARITY == 'O'), \
240                                name##_DATA_BITS,       \
241                                name##_USE_CTS_RTS,     \
242                                name##_BAUD)            \
243      ALTERA_AVALON_UART_FREQ(name)                     \
244      (name##_FIXED_BAUD ? ALT_AVALON_UART_FB : 0) |    \
245        (name##_USE_CTS_RTS ? ALT_AVALON_UART_FC : 0)   \
246    }
247 
248 /*
249  * altera_avalon_uart_init() is called by the auto-generated function
250  * alt_sys_init() for each UART in the system. This is done using the
251  * ALTERA_AVALON_UART_INIT macro given below.
252  *
253  * This function is responsible for performing all the run time initilisation
254  * for a device instance, i.e. registering the interrupt handler, and
255  * regestering the device with the system.
256  */
257 extern void altera_avalon_uart_init(altera_avalon_uart_state* sp,
258                                     alt_u32 irq_controller_id, alt_u32 irq);
259 
260 /*
261  * The macro ALTERA_AVALON_UART_STATE_INIT is used by the auto-generated file
262  * alt_sys_init.c to initialize an instance of the device driver state.
263  *
264  * This macro performs a sanity check to ensure that the interrupt has been
265  * connected for this device. If not, then an apropriate error message is
266  * generated at build time.
267  */
268 
269 #define ALTERA_AVALON_UART_STATE_INIT(name, state)                         \
270   if (name##_IRQ == ALT_IRQ_NOT_CONNECTED)                                 \
271   {                                                                        \
272     ALT_LINK_ERROR ("Error: Interrupt not connected for " #name ". "       \
273                     "You have selected the interrupt driven version of "   \
274                     "the ALTERA Avalon UART driver, but the interrupt is " \
275                     "not connected for this device. You can select a "     \
276                     "polled mode driver by checking the 'small driver' "   \
277                     "option in the HAL configuration window, or by "       \
278                     "using the -DALTERA_AVALON_UART_SMALL preprocessor "   \
279                     "flag.");                                              \
280   }                                                                        \
281   else                                                                     \
282   {                                                                        \
283     altera_avalon_uart_init(&state, name##_IRQ_INTERRUPT_CONTROLLER_ID,    \
284       name##_IRQ);                                                         \
285   }
286 
287 #endif /* small driver */
288 
289 /*
290  * Include in case non-direct version of driver required.
291  */
292 #include "altera_avalon_uart_fd.h"
293 
294 /*
295  * Map alt_sys_init macros to direct or non-direct versions.
296  */
297 #ifdef ALT_USE_DIRECT_DRIVERS
298 
299 #define ALTERA_AVALON_UART_INSTANCE(name, state) \
300    ALTERA_AVALON_UART_STATE_INSTANCE(name, state)
301 #define ALTERA_AVALON_UART_INIT(name, state) \
302    ALTERA_AVALON_UART_STATE_INIT(name, state)
303 
304 #else /* !ALT_USE_DIRECT_DRIVERS */
305 
306 #define ALTERA_AVALON_UART_INSTANCE(name, dev) \
307    ALTERA_AVALON_UART_DEV_INSTANCE(name, dev)
308 #define ALTERA_AVALON_UART_INIT(name, dev) \
309    ALTERA_AVALON_UART_DEV_INIT(name, dev)
310 
311 #endif /* ALT_USE_DIRECT_DRIVERS */
312 
313 #ifdef __cplusplus
314 }
315 #endif /* __cplusplus */
316 
317 #endif /* __ALT_AVALON_UART_H__ */
318