1 | /** |
---|
2 | * @file |
---|
3 | * @ingroup sparc_bsp |
---|
4 | * @defgroup amba AMBA |
---|
5 | * @ingroup amba |
---|
6 | * @brief AMBA Plug &Play routines |
---|
7 | */ |
---|
8 | |
---|
9 | /* |
---|
10 | * COPYRIGHT (c) 2009. |
---|
11 | * Aeroflex Gaisler. |
---|
12 | * |
---|
13 | * The license and distribution terms for this file may be |
---|
14 | * found in the file LICENSE in this distribution or at |
---|
15 | * http://www.rtems.org/license/LICENSE. |
---|
16 | */ |
---|
17 | |
---|
18 | #ifndef __AMBAPP_H__ |
---|
19 | #define __AMBAPP_H__ |
---|
20 | |
---|
21 | /* Include VENDOR and DEVICE definitions */ |
---|
22 | #include <ambapp_ids.h> |
---|
23 | |
---|
24 | #ifdef __cplusplus |
---|
25 | extern "C" { |
---|
26 | #endif |
---|
27 | |
---|
28 | /* Max supported AHB buses */ |
---|
29 | #define AHB_BUS_MAX 6 |
---|
30 | |
---|
31 | struct ambapp_dev; |
---|
32 | struct ambapp_core; |
---|
33 | struct ambapp_apb_info; |
---|
34 | struct ambapp_ahb_info; |
---|
35 | |
---|
36 | struct ambapp_dev { |
---|
37 | struct ambapp_dev *next; /* Next */ |
---|
38 | struct ambapp_dev *prev; /* Previous Device. If (this == |
---|
39 | * rev->child) prev is bus bridge */ |
---|
40 | struct ambapp_dev *children; /* Points to first device on sub-bus */ |
---|
41 | void *owner; /* Owner of this AMBA device */ |
---|
42 | unsigned char dev_type; /* AHB MST, AHB SLV or APB SLV*/ |
---|
43 | unsigned char vendor; /* Vendor ID */ |
---|
44 | unsigned short device; /* Device ID */ |
---|
45 | int devinfo[0]; /* Device info (APB/AHB dep. on type) */ |
---|
46 | }; |
---|
47 | |
---|
48 | #define AMBAPP_FLAG_FFACT_DIR 0x100 /* Frequency factor direction, 0=down, 1=up */ |
---|
49 | #define AMBAPP_FLAG_FFACT 0x0f0 /* Frequency factor against top bus */ |
---|
50 | #define AMBAPP_FLAG_MBUS 0x00c |
---|
51 | #define AMBAPP_FLAG_SBUS 0x003 |
---|
52 | |
---|
53 | /* Get APB or AHB information from a AMBA device */ |
---|
54 | #define DEV_TO_APB(adev) ((struct ambapp_apb_info *)((adev)->devinfo)) |
---|
55 | #define DEV_TO_AHB(adev) ((struct ambapp_ahb_info *)((adev)->devinfo)) |
---|
56 | #define DEV_TO_COMMON(adev) ((struct ambapp_common_info *)((adev)->devinfo)) |
---|
57 | /* Convert address of ambapp_apb_info/ambapp_ahb_info into ambapp_dev */ |
---|
58 | #define APB_TO_DEV(apb_info) ((struct ambapp_dev *)(unsigned int(apb_info) - \ |
---|
59 | offsetof(struct ambapp_dev, devinfo))) |
---|
60 | #define AHB_TO_DEV(ahb_info) ((struct ambapp_dev *)(unsigned int(ahb_info) - \ |
---|
61 | offsetof(struct ambapp_dev, devinfo))) |
---|
62 | |
---|
63 | struct ambapp_common_info { |
---|
64 | unsigned char irq; |
---|
65 | unsigned char ver; |
---|
66 | unsigned char ahbidx; /* AHB Bus Index */ |
---|
67 | }; |
---|
68 | |
---|
69 | struct ambapp_apb_info { |
---|
70 | /* COMMON */ |
---|
71 | unsigned char irq; |
---|
72 | unsigned char ver; |
---|
73 | unsigned char ahbidx; /* AHB Bus Index */ |
---|
74 | |
---|
75 | /* APB SPECIFIC */ |
---|
76 | unsigned int start; |
---|
77 | unsigned int mask; |
---|
78 | }; |
---|
79 | |
---|
80 | struct ambapp_ahb_info { |
---|
81 | /* COMMON */ |
---|
82 | unsigned char irq; |
---|
83 | unsigned char ver; |
---|
84 | unsigned char ahbidx; /* AHB Bus Index */ |
---|
85 | |
---|
86 | /* AHB SPECIFIC */ |
---|
87 | unsigned int start[4]; |
---|
88 | unsigned int mask[4]; |
---|
89 | char type[4]; /* type[N] Determine type of start[N]-mask[N], |
---|
90 | * 2=AHB Memory Space, 3=AHB I/O Space */ |
---|
91 | unsigned int custom[3]; |
---|
92 | }; |
---|
93 | |
---|
94 | /* Describes a complete AMBA Core. Each device may consist of 3 interfaces */ |
---|
95 | struct ambapp_core { |
---|
96 | char irq; /* irq=-1 indicate no IRQ */ |
---|
97 | unsigned char vendor; |
---|
98 | unsigned short device; |
---|
99 | int index; /* Core index */ |
---|
100 | struct ambapp_ahb_info *ahb_mst; |
---|
101 | struct ambapp_ahb_info *ahb_slv; |
---|
102 | struct ambapp_apb_info *apb_slv; |
---|
103 | }; |
---|
104 | |
---|
105 | struct ambapp_ahb_bus { |
---|
106 | unsigned int ioarea; /* AHB Bus IOAREA */ |
---|
107 | unsigned int freq_hz; /* Frequency of AHB Bus */ |
---|
108 | struct ambapp_dev *bridge;/* Bridge Device on Parent AHB Bus */ |
---|
109 | struct ambapp_dev *dev; /* First Device on AHB Bus */ |
---|
110 | }; |
---|
111 | |
---|
112 | struct ambapp_mmap { |
---|
113 | unsigned int size; |
---|
114 | unsigned int local_adr; |
---|
115 | unsigned int remote_adr; |
---|
116 | }; |
---|
117 | |
---|
118 | /* Complete AMBA PnP information */ |
---|
119 | struct ambapp_bus { |
---|
120 | struct ambapp_dev *root; /* AHB/APB Device Tree*/ |
---|
121 | struct ambapp_mmap *mmaps; /* Memory MAP Array */ |
---|
122 | struct ambapp_ahb_bus ahbs[AHB_BUS_MAX]; /* AHB Buses */ |
---|
123 | }; |
---|
124 | |
---|
125 | /* |
---|
126 | * Return values |
---|
127 | * 0 - continue |
---|
128 | * 1 - stop scanning |
---|
129 | */ |
---|
130 | typedef int (*ambapp_func_t)(struct ambapp_dev *dev, int index, void *arg); |
---|
131 | |
---|
132 | #define DEV_IS_FREE(dev) (dev->owner == NULL) |
---|
133 | #define DEV_IS_ALLOCATED(dev) (dev->owner != NULL) |
---|
134 | |
---|
135 | /* Options to ambapp_for_each */ |
---|
136 | #define OPTIONS_AHB_MSTS 0x00000001 |
---|
137 | #define OPTIONS_AHB_SLVS 0x00000002 |
---|
138 | #define OPTIONS_APB_SLVS 0x00000004 |
---|
139 | #define OPTIONS_ALL_DEVS (OPTIONS_AHB_MSTS|OPTIONS_AHB_SLVS|OPTIONS_APB_SLVS) |
---|
140 | |
---|
141 | #define OPTIONS_FREE 0x00000010 |
---|
142 | #define OPTIONS_ALLOCATED 0x00000020 |
---|
143 | #define OPTIONS_ALL (OPTIONS_FREE|OPTIONS_ALLOCATED) |
---|
144 | |
---|
145 | /* Depth first search, Defualt is breath first search. */ |
---|
146 | #define OPTIONS_DEPTH_FIRST 0x00000100 |
---|
147 | |
---|
148 | #define DEV_AHB_NONE 0 |
---|
149 | #define DEV_AHB_MST 1 |
---|
150 | #define DEV_AHB_SLV 2 |
---|
151 | #define DEV_APB_SLV 3 |
---|
152 | |
---|
153 | /* Structures used to access Plug&Play information directly */ |
---|
154 | struct ambapp_pnp_ahb { |
---|
155 | const unsigned int id; /* VENDOR, DEVICE, VER, IRQ, */ |
---|
156 | const unsigned int custom[3]; |
---|
157 | const unsigned int mbar[4]; /* MASK, ADDRESS, TYPE, CACHABLE/PREFETCHABLE */ |
---|
158 | }; |
---|
159 | |
---|
160 | struct ambapp_pnp_apb { |
---|
161 | const unsigned int id; /* VENDOR, DEVICE, VER, IRQ, */ |
---|
162 | const unsigned int iobar; /* MASK, ADDRESS, TYPE, CACHABLE/PREFETCHABLE */ |
---|
163 | }; |
---|
164 | |
---|
165 | #define ambapp_pnp_vendor(id) (((id) >> 24) & 0xff) |
---|
166 | #define ambapp_pnp_device(id) (((id) >> 12) & 0xfff) |
---|
167 | #define ambapp_pnp_ver(id) (((id)>>5) & 0x1f) |
---|
168 | #define ambapp_pnp_irq(id) ((id) & 0x1f) |
---|
169 | |
---|
170 | #define ambapp_pnp_start(mbar) (((mbar) & 0xfff00000) & (((mbar) & 0xfff0) << 16)) |
---|
171 | #define ambapp_pnp_mbar_mask(mbar) (((mbar)>>4) & 0xfff) |
---|
172 | #define ambapp_pnp_mbar_type(mbar) ((mbar) & 0xf) |
---|
173 | |
---|
174 | #define ambapp_pnp_apb_start(iobar, base) ((base) | ((((iobar) & 0xfff00000)>>12) & (((iobar) & 0xfff0)<<4)) ) |
---|
175 | #define ambapp_pnp_apb_mask(iobar) ((~(ambapp_pnp_mbar_mask(iobar)<<8) & 0x000fffff) + 1) |
---|
176 | |
---|
177 | #define AMBA_TYPE_AHBIO_ADDR(addr,base_ioarea) ((unsigned int)(base_ioarea) | ((addr) >> 12)) |
---|
178 | |
---|
179 | #define AMBA_TYPE_APBIO 0x1 |
---|
180 | #define AMBA_TYPE_MEM 0x2 |
---|
181 | #define AMBA_TYPE_AHBIO 0x3 |
---|
182 | |
---|
183 | /* Copy Data from AMBA PnP I/O Area */ |
---|
184 | typedef void *(*ambapp_memcpy_t)( |
---|
185 | void *dest, /* Destination RAM copy */ |
---|
186 | const void *src, /* Source AMBA PnP Address to copy from */ |
---|
187 | int n, /* Number of bytes to be copied */ |
---|
188 | struct ambapp_bus *abus /* Optional AMBA Bus pointer */ |
---|
189 | ); |
---|
190 | |
---|
191 | /* Scan a AMBA Plug & Play bus and create all device structures describing the |
---|
192 | * the devices. The devices will form a tree, where every node describes one |
---|
193 | * interface. The resulting tree is placed in the location pointed to by root. |
---|
194 | * |
---|
195 | * Since it the tree is located in RAM it is easier to work with AMBA buses |
---|
196 | * that is located over PCI and SpaceWire etc. |
---|
197 | * |
---|
198 | * \param ioarea The IO-AREA where Plug & Play information can be found. |
---|
199 | * \param parent Used internally when recursing down a bridge. Set to NULL. |
---|
200 | * \param mmaps Is used to perform address translation if needed. |
---|
201 | * \param root Resulting device node tree root is stored here. |
---|
202 | * |
---|
203 | */ |
---|
204 | extern int ambapp_scan( |
---|
205 | struct ambapp_bus *abus, |
---|
206 | unsigned int ioarea, |
---|
207 | ambapp_memcpy_t memfunc, |
---|
208 | struct ambapp_mmap *mmaps |
---|
209 | ); |
---|
210 | |
---|
211 | /* Initialize the frequency [Hz] of all AHB Buses from knowing the frequency |
---|
212 | * of one particular APB/AHB Device. |
---|
213 | */ |
---|
214 | extern void ambapp_freq_init( |
---|
215 | struct ambapp_bus *abus, |
---|
216 | struct ambapp_dev *dev, |
---|
217 | unsigned int freq); |
---|
218 | |
---|
219 | /* Returns the frequency [Hz] of a AHB/APB device */ |
---|
220 | extern unsigned int ambapp_freq_get( |
---|
221 | struct ambapp_bus *abus, |
---|
222 | struct ambapp_dev *dev); |
---|
223 | |
---|
224 | /* Iterates through all AMBA devices previously found, it calls func |
---|
225 | * once for every device that match the search arguments. |
---|
226 | * |
---|
227 | * SEARCH OPTIONS |
---|
228 | * All search options must be fulfilled, type of devices searched (options) |
---|
229 | * and AMBA Plug&Play ID [VENDOR,DEVICE], before func() is called. The options |
---|
230 | * can be use to search only for AMBA APB or AHB Slaves or AHB Masters for |
---|
231 | * example. Note that when VENDOR=-1 or DEVICE=-1 it will match any vendor or |
---|
232 | * device ID, this means setting both VENDOR and DEVICE to -1 will result in |
---|
233 | * calling all devices matches the options argument. |
---|
234 | * |
---|
235 | * \param abus AMBAPP Bus to search |
---|
236 | * \param options Search options, see OPTIONS_* above |
---|
237 | * \param vendor AMBAPP VENDOR ID to search for |
---|
238 | * \param device AMBAPP DEVICE ID to search for |
---|
239 | * \param func Function called for every device matching search options |
---|
240 | * \param arg Optional argument passed on to func |
---|
241 | * |
---|
242 | * func return value affects the search, returning a non-zero value will |
---|
243 | * stop the search and ambapp_for_each will return immediately returning the |
---|
244 | * same non-zero value. |
---|
245 | * |
---|
246 | * Return Values |
---|
247 | * 0 - all devices was scanned |
---|
248 | * non-zero - stopped by user function returning the non-zero value |
---|
249 | */ |
---|
250 | extern int ambapp_for_each( |
---|
251 | struct ambapp_bus *abus, |
---|
252 | unsigned int options, |
---|
253 | int vendor, |
---|
254 | int device, |
---|
255 | ambapp_func_t func, |
---|
256 | void *arg); |
---|
257 | |
---|
258 | /* Helper function for ambapp_for_each(), find a device by index. If pcount |
---|
259 | * is NULL the first device is returned, else pcount is interpreted as index |
---|
260 | * by decrementing the value until zero is reaced: *count=0 first device, |
---|
261 | * *count=1 second device etc. |
---|
262 | * |
---|
263 | * The matching device is returned, which will stop the ambapp_for_each search. |
---|
264 | * If zero is returned from ambapp_for_each no device matching the index was |
---|
265 | * found |
---|
266 | */ |
---|
267 | extern int ambapp_find_by_idx(struct ambapp_dev *dev, int index, void *pcount); |
---|
268 | |
---|
269 | /* Get number of devices matching the options/vendor/device arguments, the |
---|
270 | * arguments are passed onto ambapp_for_each(). |
---|
271 | */ |
---|
272 | extern int ambapp_dev_count(struct ambapp_bus *abus, unsigned int options, |
---|
273 | int vendor, int device); |
---|
274 | |
---|
275 | /* Print short information about devices on the AMBA bus onto the console */ |
---|
276 | extern void ambapp_print(struct ambapp_bus *abus, int show_depth); |
---|
277 | |
---|
278 | /* Mark a device taken (allocate), Owner field is set with owner Data. Returns |
---|
279 | * -1 if device has already been allocated. |
---|
280 | */ |
---|
281 | extern int ambapp_alloc_dev(struct ambapp_dev *dev, void *owner); |
---|
282 | |
---|
283 | /* Owner field is cleared, which indicates that device is not allocated */ |
---|
284 | extern void ambapp_free_dev(struct ambapp_dev *dev); |
---|
285 | |
---|
286 | /* Find AHB/APB Bridge or AHB/AHB Bridge Parent */ |
---|
287 | extern struct ambapp_dev *ambapp_find_parent(struct ambapp_dev *dev); |
---|
288 | |
---|
289 | /* Returns bus depth (number of sub AHB buses) of device from root bus */ |
---|
290 | extern int ambapp_depth(struct ambapp_dev *dev); |
---|
291 | |
---|
292 | /* Get Device Name from AMBA PnP name database */ |
---|
293 | extern char *ambapp_device_id2str(int vendor, int id); |
---|
294 | |
---|
295 | /* Get Vendor Name from AMBA PnP name database */ |
---|
296 | extern char *ambapp_vendor_id2str(int vendor); |
---|
297 | |
---|
298 | /* Set together VENDOR_DEVICE Name from AMBA PnP name database. Return length |
---|
299 | * of C-string stored in buf not including string termination '\0'. |
---|
300 | */ |
---|
301 | extern int ambapp_vendev_id2str(int vendor, int id, char *buf); |
---|
302 | |
---|
303 | /* Help functions for backwards compability */ |
---|
304 | |
---|
305 | extern int ambapp_find_apbslv( |
---|
306 | struct ambapp_bus *abus, |
---|
307 | int vendor, |
---|
308 | int device, |
---|
309 | struct ambapp_apb_info *dev); |
---|
310 | |
---|
311 | extern int ambapp_find_apbslv_next( |
---|
312 | struct ambapp_bus *abus, |
---|
313 | int vendor, |
---|
314 | int device, |
---|
315 | struct ambapp_apb_info *dev, |
---|
316 | int index); |
---|
317 | |
---|
318 | extern int ambapp_find_apbslvs_next( |
---|
319 | struct ambapp_bus *abus, |
---|
320 | int vendor, |
---|
321 | int device, |
---|
322 | struct ambapp_apb_info *dev, |
---|
323 | int index, |
---|
324 | int maxno); |
---|
325 | |
---|
326 | extern int ambapp_find_apbslvs( |
---|
327 | struct ambapp_bus *abus, |
---|
328 | int vendor, |
---|
329 | int device, |
---|
330 | struct ambapp_apb_info *dev, |
---|
331 | int maxno); |
---|
332 | |
---|
333 | extern int ambapp_find_ahbslv( |
---|
334 | struct ambapp_bus *abus, |
---|
335 | int vendor, |
---|
336 | int device, |
---|
337 | struct ambapp_ahb_info *dev); |
---|
338 | |
---|
339 | extern int ambapp_find_ahbslv_next( |
---|
340 | struct ambapp_bus *abus, |
---|
341 | int vendor, |
---|
342 | int device, |
---|
343 | struct ambapp_ahb_info *dev, |
---|
344 | int index); |
---|
345 | |
---|
346 | extern int ambapp_find_ahbslvs_next( |
---|
347 | struct ambapp_bus *abus, |
---|
348 | int vendor, |
---|
349 | int device, |
---|
350 | struct ambapp_ahb_info *dev, |
---|
351 | int index, |
---|
352 | int maxno); |
---|
353 | |
---|
354 | extern int ambapp_find_ahbslvs( |
---|
355 | struct ambapp_bus *abus, |
---|
356 | int vendor, |
---|
357 | int device, |
---|
358 | struct ambapp_ahb_info *dev, |
---|
359 | int maxno); |
---|
360 | |
---|
361 | |
---|
362 | extern int ambapp_get_number_ahbslv_devices( |
---|
363 | struct ambapp_bus *abus, |
---|
364 | int vendor, |
---|
365 | int device); |
---|
366 | |
---|
367 | extern int ambapp_get_number_apbslv_devices( |
---|
368 | struct ambapp_bus *abus, |
---|
369 | int vendor, |
---|
370 | int device); |
---|
371 | |
---|
372 | #ifdef __cplusplus |
---|
373 | } |
---|
374 | #endif |
---|
375 | |
---|
376 | #endif |
---|