summaryrefslogtreecommitdiff
path: root/bsps/include/grlib/ambapp.h
blob: 3c3d3e9e3ef6edb3d7d72d5e7a561b4bc82d1fd4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
/**
 * @file
 * @ingroup amba
 */

/*
 *  COPYRIGHT (c) 2009.
 *  Aeroflex Gaisler.
 *
 *  The license and distribution terms for this file may be
 *  found in the file LICENSE in this distribution or at
 *  http://www.rtems.org/license/LICENSE.
 */

#ifndef __AMBAPP_H__
#define __AMBAPP_H__

/**
 * @defgroup amba AMBA
 *
 * @ingroup RTEMSBSPsSharedGRLIB
 *
 * @brief AMBA Plug & Play routines
 *
 * @{
 */

/* Include VENDOR and DEVICE definitions */
#include "ambapp_ids.h"

#ifdef __cplusplus
extern "C" {
#endif

/* Max supported AHB buses */
#define AHB_BUS_MAX 6

#define AMBAPP_FLAG_FFACT_DIR	0x100	/* Frequency factor direction, 0=down, 1=up */
#define AMBAPP_FLAG_FFACT	0x0f0	/* Frequency factor against top bus */
#define AMBAPP_FLAG_MBUS	0x00c
#define AMBAPP_FLAG_SBUS	0x003

/* Get APB or AHB information from a AMBA device */
#define DEV_TO_APB(adev) ((struct ambapp_apb_info *)((adev)->devinfo))
#define DEV_TO_AHB(adev) ((struct ambapp_ahb_info *)((adev)->devinfo))
#define DEV_TO_COMMON(adev) (((adev)->devinfo))

struct ambapp_common_info {
	unsigned char irq;
	unsigned char ver;
	unsigned char ahbidx;	/* AHB Bus Index */
};

struct ambapp_apb_info {
	struct ambapp_common_info common;

	/* APB SPECIFIC */
	unsigned int start;
	unsigned int mask;
};

struct ambapp_ahb_info {
	struct ambapp_common_info common;

	/* AHB SPECIFIC */
	unsigned int start[4];
	unsigned int mask[4];
	char type[4];		/* type[N] Determine type of start[N]-mask[N],
				 * 2=AHB Memory Space, 3=AHB I/O Space */
	unsigned int custom[3];
};

struct ambapp_dev {
	struct ambapp_dev *next;	/* Next */
	struct ambapp_dev *prev;	/* Previous Device. If (this ==
					 * rev->child) prev is bus bridge */
	struct ambapp_dev *children;	/* Points to first device on sub-bus */
	void *owner;			/* Owner of this AMBA device */
	unsigned char dev_type;		/* AHB MST, AHB SLV or APB SLV*/
	unsigned char vendor;		/* Vendor ID */
	unsigned short device;		/* Device ID */

	/* Device info (APB/AHB dep. on type) */
	struct ambapp_common_info devinfo[0];
};

/* Describes a complete AMBA Core. Each device may consist of 3 interfaces */
struct ambapp_core {
	char			irq;		/* irq=-1 indicate no IRQ */
	unsigned char		vendor;
	unsigned short		device;
	int			index;		/* Core index */
	struct ambapp_ahb_info	*ahb_mst;
	struct ambapp_ahb_info	*ahb_slv;
	struct ambapp_apb_info	*apb_slv;
};

struct ambapp_ahb_bus {
	unsigned int ioarea;	/* AHB Bus IOAREA */
	unsigned int freq_hz;	/* Frequency of AHB Bus */
	struct ambapp_dev *bridge;/* Bridge Device on Parent AHB Bus */
	struct ambapp_dev *dev;	/* First Device on AHB Bus */
};

struct ambapp_mmap {
	unsigned int		size;
	unsigned int		local_adr;
	unsigned int		remote_adr;
};

/* Complete AMBA PnP information */
struct ambapp_bus {
	struct ambapp_dev	*root;			/* AHB/APB Device Tree*/
	struct ambapp_mmap	*mmaps;			/* Memory MAP Array */
	struct ambapp_ahb_bus	ahbs[AHB_BUS_MAX];	/* AHB Buses */
};

/* 
 * Return values
 *  0 - continue
 *  1 - stop scanning
 */
typedef int (*ambapp_func_t)(struct ambapp_dev *dev, int index, void *arg);

#define DEV_IS_FREE(dev) (dev->owner == NULL)
#define DEV_IS_ALLOCATED(dev) (dev->owner != NULL)

/* Options to ambapp_for_each */
#define OPTIONS_AHB_MSTS	0x00000001
#define OPTIONS_AHB_SLVS	0x00000002
#define OPTIONS_APB_SLVS	0x00000004
#define OPTIONS_ALL_DEVS	(OPTIONS_AHB_MSTS|OPTIONS_AHB_SLVS|OPTIONS_APB_SLVS)

#define OPTIONS_FREE		0x00000010
#define OPTIONS_ALLOCATED	0x00000020
#define OPTIONS_ALL		(OPTIONS_FREE|OPTIONS_ALLOCATED)

/* Depth first search, Defualt is breath first search. */
#define OPTIONS_DEPTH_FIRST	0x00000100

#define DEV_AHB_NONE 0
#define DEV_AHB_MST  1
#define DEV_AHB_SLV  2
#define DEV_APB_SLV 3

/* Structures used to access Plug&Play information directly */
struct ambapp_pnp_ahb {
	const unsigned int	id;		/* VENDOR, DEVICE, VER, IRQ, */
	const unsigned int	custom[3];
	const unsigned int	mbar[4];	/* MASK, ADDRESS, TYPE, CACHABLE/PREFETCHABLE */
};

struct ambapp_pnp_apb {
	const unsigned int	id;		/* VENDOR, DEVICE, VER, IRQ, */
	const unsigned int	iobar;		/* MASK, ADDRESS, TYPE, CACHABLE/PREFETCHABLE */
};

#define ambapp_pnp_vendor(id) (((id) >> 24) & 0xff)
#define ambapp_pnp_device(id) (((id) >> 12) & 0xfff)
#define ambapp_pnp_ver(id) (((id)>>5) & 0x1f)
#define ambapp_pnp_irq(id) ((id) & 0x1f)

#define ambapp_pnp_start(mbar)  (((mbar) & 0xfff00000) & (((mbar) & 0xfff0) << 16)) 
#define ambapp_pnp_mbar_mask(mbar) (((mbar)>>4) & 0xfff)
#define ambapp_pnp_mbar_type(mbar) ((mbar) & 0xf)

#define ambapp_pnp_apb_start(iobar, base) ((base) | ((((iobar) & 0xfff00000)>>12) & (((iobar) & 0xfff0)<<4)) )
#define ambapp_pnp_apb_mask(iobar) ((~(ambapp_pnp_mbar_mask(iobar)<<8) & 0x000fffff) + 1)

#define AMBA_TYPE_AHBIO_ADDR(addr,base_ioarea) ((unsigned int)(base_ioarea) | ((addr) >> 12))

#define AMBA_TYPE_APBIO 0x1
#define AMBA_TYPE_MEM   0x2
#define AMBA_TYPE_AHBIO 0x3

/* Copy Data from AMBA PnP I/O Area */
typedef void *(*ambapp_memcpy_t)(
	void *dest,		/* Destination RAM copy */
	const void *src,	/* Source AMBA PnP Address to copy from */
	int n,			/* Number of bytes to be copied */
	struct ambapp_bus *abus	/* Optional AMBA Bus pointer */
	);

/* Scan a AMBA Plug & Play bus and create all device structures describing the 
 * the devices. The devices will form a tree, where every node describes one
 * interface. The resulting tree is placed in the location pointed to by root.
 *
 * Since it the tree is located in RAM it is easier to work with AMBA buses
 * that is located over PCI and SpaceWire etc.
 *
 * \param ioarea   The IO-AREA where Plug & Play information can be found.
 * \param parent   Used internally when recursing down a bridge. Set to NULL.
 * \param mmaps    Is used to perform address translation if needed.
 * \param root     Resulting device node tree root is stored here.
 *
 */
extern int ambapp_scan(
	struct ambapp_bus *abus,
	unsigned int ioarea,
	ambapp_memcpy_t memfunc,
	struct ambapp_mmap *mmaps
	);

/* Initialize the frequency [Hz] of all AHB Buses from knowing the frequency
 * of one particular APB/AHB Device.
 */
extern void ambapp_freq_init(
	struct ambapp_bus *abus,
	struct ambapp_dev *dev,
	unsigned int freq);

/* Returns the frequency [Hz] of a AHB/APB device */
extern unsigned int ambapp_freq_get(
	struct ambapp_bus *abus,
	struct ambapp_dev *dev);

/* Iterates through all AMBA devices previously found, it calls func 
 * once for every device that match the search arguments.
 *
 * SEARCH OPTIONS
 * All search options must be fulfilled, type of devices searched (options)
 * and AMBA Plug&Play ID [VENDOR,DEVICE], before func() is called. The options
 * can be use to search only for AMBA APB or AHB Slaves or AHB Masters for
 * example. Note that when VENDOR=-1 or DEVICE=-1 it will match any vendor or
 * device ID, this means setting both VENDOR and DEVICE to -1 will result in
 * calling all devices matches the options argument.
 *
 * \param abus     AMBAPP Bus to search
 * \param options  Search options, see OPTIONS_* above
 * \param vendor   AMBAPP VENDOR ID to search for
 * \param device   AMBAPP DEVICE ID to search for
 * \param func     Function called for every device matching search options
 * \param arg      Optional argument passed on to func
 *
 * func return value affects the search, returning a non-zero value will
 * stop the search and ambapp_for_each will return immediately returning the
 * same non-zero value.
 *
 * Return Values
 *  0 - all devices was scanned
 *  non-zero - stopped by user function returning the non-zero value
 */
extern int ambapp_for_each(
	struct ambapp_bus *abus,
	unsigned int options,
	int vendor,
	int device,
	ambapp_func_t func,
	void *arg);

/* Helper function for ambapp_for_each(), find a device by index. If pcount
 * is NULL the first device is returned, else pcount is interpreted as index
 * by decrementing the value until zero is reaced: *count=0 first device,
 * *count=1 second device etc.
 *
 * The matching device is returned, which will stop the ambapp_for_each search.
 * If zero is returned from ambapp_for_each no device matching the index was
 * found
 */
extern int ambapp_find_by_idx(struct ambapp_dev *dev, int index, void *pcount);

/* Get number of devices matching the options/vendor/device arguments, the
 * arguments are passed onto ambapp_for_each().
 */
extern int ambapp_dev_count(struct ambapp_bus *abus, unsigned int options,
				int vendor, int device);

/* Print short information about devices on the AMBA bus onto the console */
extern void ambapp_print(struct ambapp_bus *abus, int show_depth);

/* Mark a device taken (allocate), Owner field is set with owner Data. Returns
 * -1 if device has already been allocated.
 */
extern int ambapp_alloc_dev(struct ambapp_dev *dev, void *owner);

/* Owner field is cleared, which indicates that device is not allocated */
extern void ambapp_free_dev(struct ambapp_dev *dev);

/* Find AHB/APB Bridge or AHB/AHB Bridge Parent */
extern struct ambapp_dev *ambapp_find_parent(struct ambapp_dev *dev);

/* Returns bus depth (number of sub AHB buses) of device from root bus */
extern int ambapp_depth(struct ambapp_dev *dev);

/* Get Device Name from AMBA PnP name database */
extern char *ambapp_device_id2str(int vendor, int id);

/* Get Vendor Name from AMBA PnP name database */
extern char *ambapp_vendor_id2str(int vendor);

/* Set together VENDOR_DEVICE Name from AMBA PnP name database. Return length
 * of C-string stored in buf not including string termination '\0'.
 */
extern int ambapp_vendev_id2str(int vendor, int id, char *buf);

/* Help functions for backwards compability */

extern int ambapp_find_apbslv(
	struct ambapp_bus *abus,
	int vendor,
	int device,
	struct ambapp_apb_info *dev);

extern int ambapp_find_apbslv_next(
	struct ambapp_bus *abus,
	int vendor,
	int device,
	struct ambapp_apb_info *dev,
	int index);

extern int ambapp_find_apbslvs_next(
	struct ambapp_bus *abus,
	int vendor,
	int device,
	struct ambapp_apb_info *dev,
	int index,
	int maxno);

extern int ambapp_find_apbslvs(
	struct ambapp_bus *abus,
	int vendor,
	int device,
	struct ambapp_apb_info *dev,
	int maxno);

extern int ambapp_find_ahbslv(
	struct ambapp_bus *abus,
	int vendor,
	int device,
	struct ambapp_ahb_info *dev);

extern int ambapp_find_ahbslv_next(
	struct ambapp_bus *abus,
	int vendor,
	int device,
	struct ambapp_ahb_info *dev,
	int index);

extern int ambapp_find_ahbslvs_next(
	struct ambapp_bus *abus,
	int vendor,
	int device,
	struct ambapp_ahb_info *dev,
	int index,
	int maxno);

extern int ambapp_find_ahbslvs(
	struct ambapp_bus *abus,
	int vendor,
	int device,
	struct ambapp_ahb_info *dev,
	int maxno);


extern int ambapp_get_number_ahbslv_devices(
	struct ambapp_bus *abus,
	int vendor,
	int device);

extern int ambapp_get_number_apbslv_devices(
	struct ambapp_bus *abus,
	int vendor,
	int device);

#ifdef __cplusplus
}
#endif

/** @} */

#endif