blob: efd41ae0a81df109a315a69781c9219ea902c39d [file] [log] [blame]
Daniel Hellstromb552dbe2008-03-26 22:51:29 +01001/* Gaisler AMBA Plug&Play bus scanning. Functions
2 * ending on _nomem is inteded to be used only during
3 * initialization, only registers are used (no ram).
4 *
5 * (C) Copyright 2007
6 * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com
7 *
8 * See file CREDITS for list of people who contributed to this
9 * project.
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License as
13 * published by the Free Software Foundation; either version 2 of
14 * the License, or (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
24 * MA 02111-1307 USA
25 */
26
27#include <common.h>
28#include <command.h>
29#include <ambapp.h>
30
Daniel Hellstromfeb0c262008-03-26 23:00:38 +010031#if defined(CONFIG_CMD_AMBAPP)
32extern void ambapp_print_apb(apbctrl_pp_dev * apb,
33 ambapp_ahbdev * apbmst, int index);
34extern void ambapp_print_ahb(ahbctrl_pp_dev * ahb, int index);
35extern int ambapp_apb_print;
36extern int ambapp_ahb_print;
37#endif
38
Daniel Hellstromb552dbe2008-03-26 22:51:29 +010039static int ambapp_apb_scan(unsigned int vendor, /* Plug&Play Vendor ID */
40 unsigned int driver, /* Plug&Play Device ID */
41 ambapp_apbdev * dev, /* Result(s) is placed here */
42 int index, /* Index of device to start copying Plug&Play
43 * info into dev
44 */
45 int max_cnt /* Maximal count that dev can hold, if dev
46 * is NULL function will stop scanning after
47 * max_cnt devices are found.
48 */
49 )
50{
51 int i, cnt = 0;
52 unsigned int apbmst_base;
53 ambapp_ahbdev apbmst;
54 apbctrl_pp_dev *apb;
55
56 if (max_cnt == 0)
57 return 0;
58
59 /* Get AMBA APB Master */
60 if (ambapp_ahbslv_first(VENDOR_GAISLER, GAISLER_APBMST, &apbmst) != 1) {
61 return 0;
62 }
63
64 /* Get APB CTRL Plug&Play info area */
65 apbmst_base = apbmst.address[0] & LEON3_IO_AREA;
66 apb = (apbctrl_pp_dev *) (apbmst_base | LEON3_CONF_AREA);
67
68 for (i = 0; i < LEON3_APB_SLAVES; i++) {
Daniel Hellstromfeb0c262008-03-26 23:00:38 +010069#if defined(CONFIG_CMD_AMBAPP)
70 if (ambapp_apb_print && amba_vendor(apb->conf)
71 && amba_device(apb->conf)) {
72 ambapp_print_apb(apb, &apbmst, i);
73 }
74#endif
Daniel Hellstromb552dbe2008-03-26 22:51:29 +010075 if ((amba_vendor(apb->conf) == vendor) &&
76 (amba_device(apb->conf) == driver) && ((index < 0)
77 || (index-- == 0))) {
78 /* Convert Plug&Play info into a more readable format */
79 cnt++;
80 if (dev) {
81 dev->irq = amba_irq(apb->conf);
82 dev->ver = amba_ver(apb->conf);
83 dev->address =
84 (apbmst_base |
85 (((apb->
86 bar & 0xfff00000) >> 12))) & (((apb->
87 bar &
88 0x0000fff0)
89 << 4) |
90 0xfff00000);
91 dev++;
92 }
93 /* found max devices? */
94 if (cnt >= max_cnt)
95 return cnt;
96 }
97 /* Get next Plug&Play entry */
98 apb++;
99 }
100 return cnt;
101}
102
103unsigned int ambapp_apb_next_nomem(register unsigned int vendor, /* Plug&Play Vendor ID */
104 register unsigned int driver, /* Plug&Play Device ID */
105 register int index)
106{
107 register int i;
108 register ahbctrl_pp_dev *apbmst;
109 register apbctrl_pp_dev *apb;
110 register unsigned int apbmst_base;
111
112 /* APBMST is a AHB Slave */
113 apbmst = ambapp_ahb_next_nomem(VENDOR_GAISLER, GAISLER_APBMST, 1, 0);
114 if (!apbmst)
115 return 0;
116
117 apbmst_base = amba_membar_start(apbmst->bars[0]);
118 if (amba_membar_type(apbmst->bars[0]) == AMBA_TYPE_AHBIO)
119 apbmst_base = AMBA_TYPE_AHBIO_ADDR(apbmst_base);
120 apbmst_base &= LEON3_IO_AREA;
121
122 /* Find the vendor/driver device on the first APB bus */
123 apb = (apbctrl_pp_dev *) (apbmst_base | LEON3_CONF_AREA);
124
125 for (i = 0; i < LEON3_APB_SLAVES; i++) {
126 if ((amba_vendor(apb->conf) == vendor) &&
127 (amba_device(apb->conf) == driver) && ((index < 0)
128 || (index-- == 0))) {
129 /* Convert Plug&Play info info a more readable format */
130 return (apbmst_base | (((apb->bar & 0xfff00000) >> 12)))
131 & (((apb->bar & 0x0000fff0) << 4) | 0xfff00000);
132 }
133 /* Get next Plug&Play entry */
134 apb++;
135 }
136 return 0;
137}
138
139/****************************** APB SLAVES ******************************/
140
141int ambapp_apb_count(unsigned int vendor, unsigned int driver)
142{
143 return ambapp_apb_scan(vendor, driver, NULL, 0, LEON3_APB_SLAVES);
144}
145
146int ambapp_apb_first(unsigned int vendor,
147 unsigned int driver, ambapp_apbdev * dev)
148{
149 return ambapp_apb_scan(vendor, driver, dev, 0, 1);
150}
151
152int ambapp_apb_next(unsigned int vendor,
153 unsigned int driver, ambapp_apbdev * dev, int index)
154{
155 return ambapp_apb_scan(vendor, driver, dev, index, 1);
156}
157
158int ambapp_apbs_first(unsigned int vendor,
159 unsigned int driver, ambapp_apbdev * dev, int max_cnt)
160{
161 return ambapp_apb_scan(vendor, driver, dev, 0, max_cnt);
162}
163
164enum {
165 AHB_SCAN_MASTER = 0,
166 AHB_SCAN_SLAVE = 1
167};
168
169/* Scan AMBA Plug&Play bus for AMBA AHB Masters or AHB Slaves
170 * for a certain matching Vendor and Device ID.
171 *
172 * Return number of devices found.
173 *
174 * Compact edition...
175 */
176static int ambapp_ahb_scan(unsigned int vendor, /* Plug&Play Vendor ID */
177 unsigned int driver, /* Plug&Play Device ID */
178 ambapp_ahbdev * dev, /* Result(s) is placed here */
179 int index, /* Index of device to start copying Plug&Play
180 * info into dev
181 */
182 int max_cnt, /* Maximal count that dev can hold, if dev
183 * is NULL function will stop scanning after
184 * max_cnt devices are found.
185 */
186 int type /* Selectes what type of devices to scan.
187 * 0=AHB Masters
188 * 1=AHB Slaves
189 */
190 )
191{
192 int i, j, cnt = 0, max_pp_devs;
193 unsigned int addr;
194 ahbctrl_info *info = (ahbctrl_info *) (LEON3_IO_AREA | LEON3_CONF_AREA);
195 ahbctrl_pp_dev *ahb;
196
197 if (max_cnt == 0)
198 return 0;
199
200 if (type == 0) {
201 max_pp_devs = LEON3_AHB_MASTERS;
202 ahb = info->masters;
203 } else {
204 max_pp_devs = LEON3_AHB_SLAVES;
205 ahb = info->slaves;
206 }
207
208 for (i = 0; i < max_pp_devs; i++) {
Daniel Hellstromfeb0c262008-03-26 23:00:38 +0100209#if defined(CONFIG_CMD_AMBAPP)
210 if (ambapp_ahb_print && amba_vendor(ahb->conf) &&
211 amba_device(ahb->conf)) {
212 ambapp_print_ahb(ahb, i);
213 }
214#endif
Daniel Hellstromb552dbe2008-03-26 22:51:29 +0100215 if ((amba_vendor(ahb->conf) == vendor) &&
216 (amba_device(ahb->conf) == driver) &&
217 ((index < 0) || (index-- == 0))) {
218 /* Convert Plug&Play info info a more readable format */
219 cnt++;
220 if (dev) {
221 dev->irq = amba_irq(ahb->conf);
222 dev->ver = amba_ver(ahb->conf);
223 dev->userdef[0] = ahb->userdef[0];
224 dev->userdef[1] = ahb->userdef[1];
225 dev->userdef[2] = ahb->userdef[2];
226 for (j = 0; j < 4; j++) {
227 addr = amba_membar_start(ahb->bars[j]);
228 if (amba_membar_type(ahb->bars[j]) ==
229 AMBA_TYPE_AHBIO)
230 addr =
231 AMBA_TYPE_AHBIO_ADDR(addr);
232 dev->address[j] = addr;
233 }
234 dev++;
235 }
236 /* found max devices? */
237 if (cnt >= max_cnt)
238 return cnt;
239 }
240 /* Get next Plug&Play entry */
241 ahb++;
242 }
243 return cnt;
244}
245
246unsigned int ambapp_ahb_get_info(ahbctrl_pp_dev * ahb, int info)
247{
248 register unsigned int ret;
249
250 if (!ahb)
251 return 0;
252
253 switch (info) {
254 default:
255 info = 0;
256 case 0:
257 case 1:
258 case 2:
259 case 3:
260 /* Get Address from PnP Info */
261 ret = amba_membar_start(ahb->bars[info]);
262 if (amba_membar_type(ahb->bars[info]) == AMBA_TYPE_AHBIO)
263 ret = AMBA_TYPE_AHBIO_ADDR(ret);
264 return ret;
265 }
266 return 0;
267
268}
269
270ahbctrl_pp_dev *ambapp_ahb_next_nomem(register unsigned int vendor, /* Plug&Play Vendor ID */
271 register unsigned int driver, /* Plug&Play Device ID */
272 register unsigned int opts, /* 1=slave, 0=master */
273 register int index)
274{
275 register ahbctrl_pp_dev *ahb;
276 register ahbctrl_info *info =
277 (ahbctrl_info *) (LEON3_IO_AREA | LEON3_CONF_AREA);
278 register int i;
279 register int max_pp_devs;
280
281 if (opts == 0) {
282 max_pp_devs = LEON3_AHB_MASTERS;
283 ahb = info->masters;
284 } else {
285 max_pp_devs = LEON3_AHB_SLAVES;
286 ahb = info->slaves;
287 }
288
289 for (i = 0; i < max_pp_devs; i++) {
290 if ((amba_vendor(ahb->conf) == vendor) &&
291 (amba_device(ahb->conf) == driver) &&
292 ((index < 0) || (index-- == 0))) {
293 /* Convert Plug&Play info info a more readable format */
294 return ahb;
295 }
296 /* Get next Plug&Play entry */
297 ahb++;
298 }
299 return 0;
300}
301
302/****************************** AHB MASTERS ******************************/
303int ambapp_ahbmst_count(unsigned int vendor, unsigned int driver)
304{
305 /* Get number of devices of this vendor&device ID */
306 return ambapp_ahb_scan(vendor, driver, NULL, 0, LEON3_AHB_MASTERS,
307 AHB_SCAN_MASTER);
308}
309
310int ambapp_ahbmst_first(unsigned int vendor, unsigned int driver,
311 ambapp_ahbdev * dev)
312{
313 /* find first device of this */
314 return ambapp_ahb_scan(vendor, driver, dev, 0, 1, AHB_SCAN_MASTER);
315}
316
317int ambapp_ahbmst_next(unsigned int vendor,
318 unsigned int driver, ambapp_ahbdev * dev, int index)
319{
320 /* find first device of this */
321 return ambapp_ahb_scan(vendor, driver, dev, index, 1, AHB_SCAN_MASTER);
322}
323
324int ambapp_ahbmsts_first(unsigned int vendor,
325 unsigned int driver, ambapp_ahbdev * dev, int max_cnt)
326{
327 /* find first device of this */
328 return ambapp_ahb_scan(vendor, driver, dev, 0, max_cnt,
329 AHB_SCAN_MASTER);
330}
331
332/****************************** AHB SLAVES ******************************/
333int ambapp_ahbslv_count(unsigned int vendor, unsigned int driver)
334{
335 /* Get number of devices of this vendor&device ID */
336 return ambapp_ahb_scan(vendor, driver, NULL, 0, LEON3_AHB_SLAVES,
337 AHB_SCAN_SLAVE);
338}
339
340int ambapp_ahbslv_first(unsigned int vendor, unsigned int driver,
341 ambapp_ahbdev * dev)
342{
343 /* find first device of this */
344 return ambapp_ahb_scan(vendor, driver, dev, 0, 1, AHB_SCAN_SLAVE);
345}
346
347int ambapp_ahbslv_next(unsigned int vendor,
348 unsigned int driver, ambapp_ahbdev * dev, int index)
349{
350 /* find first device of this */
351 return ambapp_ahb_scan(vendor, driver, dev, index, 1, AHB_SCAN_SLAVE);
352}
353
354int ambapp_ahbslvs_first(unsigned int vendor,
355 unsigned int driver, ambapp_ahbdev * dev, int max_cnt)
356{
357 /* find first device of this */
358 return ambapp_ahb_scan(vendor, driver, dev, 0, max_cnt, AHB_SCAN_SLAVE);
359}