1 /******************************************************************************
2 *                                                                             *
3 * License Agreement                                                           *
4 *                                                                             *
5 * Copyright (c) 2011 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 __ALTERA_AVALON_SGDMA_H__
30 #define __ALTERA_AVALON_SGDMA_H__
31 
32 #include <stddef.h>
33 #include <errno.h>
34 
35 #include "sys/alt_dev.h"
36 #include "alt_types.h"
37 #include "altera_avalon_sgdma_descriptor.h"
38 
39 #ifdef __cplusplus
40 extern "C"
41 {
42 #endif /* __cplusplus */
43 
44 /*
45  * The function alt_find_dev() is used to search the device list "list" to
46  * locate a device named "name". If a match is found, then a pointer to the
47  * device is returned, otherwise NULL is returned.
48  */
49 extern alt_dev* alt_find_dev (const char* name, alt_llist* list);
50 
51 /* Callback routine type definition */
52 typedef void (*alt_avalon_sgdma_callback)(void *context);
53 
54 /* SGDMA Device Structure */
55 typedef struct alt_sgdma_dev
56 {
57   alt_llist                 llist;               // Device linked-list entry
58   const char                *name;               // Name of SGDMA in SOPC System
59   void                      *base;               // Base address of SGDMA
60   alt_u32                   *descriptor_base;    // reserved
61   alt_u32                   next_index;          // reserved
62   alt_u32                   num_descriptors;     // reserved
63   alt_sgdma_descriptor      *current_descriptor; // reserved
64   alt_sgdma_descriptor      *next_descriptor;    // reserved
65   alt_avalon_sgdma_callback callback;            // Callback routine pointer
66   void                      *callback_context;   // Callback context pointer
67   alt_u32                   chain_control;       // Value OR'd into control reg
68 } alt_sgdma_dev;
69 
70 
71 /*******************************************************************************
72  *  Public API
73  ******************************************************************************/
74 
75 /* API for "application managed" operation */
76 int alt_avalon_sgdma_do_async_transfer(
77   alt_sgdma_dev *dev,
78   alt_sgdma_descriptor *desc);
79 
80 alt_u8 alt_avalon_sgdma_do_sync_transfer(
81   alt_sgdma_dev *dev,
82   alt_sgdma_descriptor *desc);
83 
84 void alt_avalon_sgdma_construct_mem_to_mem_desc(
85   alt_sgdma_descriptor *desc,
86   alt_sgdma_descriptor *next,
87   alt_u32              *read_addr,
88   alt_u32              *write_addr,
89   alt_u16               length,
90   int                   read_fixed,
91   int                   write_fixed);
92 
93 void alt_avalon_sgdma_construct_mem_to_mem_desc_burst(
94   alt_sgdma_descriptor *desc,
95   alt_sgdma_descriptor *next,
96   alt_u32              *read_addr,
97   alt_u32              *write_addr,
98   alt_u16               length,
99   int                   read_fixed,
100   int                   write_fixed,
101   int                   read_burst,
102   int                   write_burst);
103 
104 void alt_avalon_sgdma_construct_stream_to_mem_desc(
105   alt_sgdma_descriptor *desc,
106   alt_sgdma_descriptor *next,
107   alt_u32              *write_addr,
108   alt_u16               length_or_eop,
109   int                   write_fixed);
110 
111 void alt_avalon_sgdma_construct_stream_to_mem_desc_burst(
112   alt_sgdma_descriptor *desc,
113   alt_sgdma_descriptor *next,
114   alt_u32              *write_addr,
115   alt_u16               length_or_eop,
116   int                   write_fixed,
117   int                   write_burst);
118 
119   void alt_avalon_sgdma_construct_mem_to_stream_desc(
120   alt_sgdma_descriptor *desc,
121   alt_sgdma_descriptor *next,
122   alt_u32              *read_addr,
123   alt_u16               length,
124   int                   read_fixed,
125   int                   generate_sop,
126   int                   generate_eop,
127   alt_u8                atlantic_channel);
128 
129   void alt_avalon_sgdma_construct_mem_to_stream_desc_burst(
130   alt_sgdma_descriptor *desc,
131   alt_sgdma_descriptor *next,
132   alt_u32              *read_addr,
133   alt_u16               length,
134   int                   read_fixed,
135   int                   generate_sop,
136   int                   generate_eop,
137   int                   read_burst,
138   alt_u8                atlantic_channel);
139 
140 void alt_avalon_sgdma_register_callback(
141   alt_sgdma_dev *dev,
142   alt_avalon_sgdma_callback callback,
143   alt_u32 chain_control,
144   void *context);
145 
146 void alt_avalon_sgdma_start(alt_sgdma_dev *dev);
147 
148 void alt_avalon_sgdma_stop(alt_sgdma_dev *dev);
149 
150 int alt_avalon_sgdma_check_descriptor_status(alt_sgdma_descriptor *desc);
151 
152 alt_sgdma_dev* alt_avalon_sgdma_open (const char* name);
153 
154 void alt_avalon_sgdma_enable_desc_poll(alt_sgdma_dev *dev, alt_u32 frequency);
155 
156 void alt_avalon_sgdma_disable_desc_poll(alt_sgdma_dev *dev);
157 
158 /* Private API */
159 void alt_avalon_sgdma_construct_descriptor(
160   alt_sgdma_descriptor *desc,
161   alt_sgdma_descriptor *next,
162   alt_u32              *read_addr,
163   alt_u32              *write_addr,
164   alt_u16               length_or_eop,
165   int                   generate_eop,
166   int                   read_fixed,
167   int                   write_fixed_or_sop,
168   alt_u8                atlantic_channel);
169 
170 /* Private API */
171 void alt_avalon_sgdma_construct_descriptor_burst(
172   alt_sgdma_descriptor *desc,
173   alt_sgdma_descriptor *next,
174   alt_u32              *read_addr,
175   alt_u32              *write_addr,
176   alt_u16               length_or_eop,
177   int                   generate_eop,
178   int                   read_fixed,
179   int                   write_fixed_or_sop,
180   int                   read_burst,
181   int                   write_burst,
182   alt_u8                atlantic_channel);
183 
184 void alt_avalon_sgdma_init (alt_sgdma_dev *dev, alt_u32 ic_id, alt_u32 irq);
185 
186 /* HAL initialization macros */
187 
188 /*
189  * ALTERA_AVALON_SGDMA_INSTANCE is the macro used by alt_sys_init() to
190  * allocate any per device memory that may be required.
191  */
192 #define ALTERA_AVALON_SGDMA_INSTANCE(name, dev)                         \
193 static alt_sgdma_dev dev =                                              \
194 {                                                                       \
195   ALT_LLIST_ENTRY,                                                      \
196   name##_NAME,                                                          \
197   ((void *)(name##_BASE)),                                              \
198   ((alt_u32 *) 0x0),                                                    \
199   ((alt_u32) 0x0),                                                      \
200   ((alt_u32) 0x0),                                                      \
201   ((alt_sgdma_descriptor *) 0x0),                                       \
202   ((alt_sgdma_descriptor *) 0x0),                                       \
203   ((void *) 0x0),                                                       \
204   ((void *) 0x0),                                                       \
205   ((alt_u16) 0x0)                                                       \
206 };
207 
208 /*
209  * The macro ALTERA_AVALON_SGDMA_INIT is called by the auto-generated function
210  * alt_sys_init() to initialize a given device instance.
211  */
212 #define ALTERA_AVALON_SGDMA_INIT(name, dev)                                 \
213   if (name##_IRQ == ALT_IRQ_NOT_CONNECTED)                                  \
214   {                                                                         \
215     ALT_LINK_ERROR ("Error: Interrupt not connected for " #dev ". "         \
216                     "The Altera Avalon Scatter-Gather DMA driver requires " \
217                     "that an interrupt is connected. Please select an IRQ " \
218                     "for this device in SOPC builder.");                    \
219   }                                                                         \
220   else                                                                      \
221   {                                                                         \
222     alt_avalon_sgdma_init(&dev, name##_IRQ_INTERRUPT_CONTROLLER_ID,         \
223       name##_IRQ);                                                          \
224   }
225 
226 #ifdef __cplusplus
227 }
228 #endif /* __cplusplus */
229 
230 #endif /* __ALTERA_AVALON_SGDMA_H__ */
231