blob: 60ff1a2aefc8553346f121287f83a8bb4d811901 [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
31static int ambapp_apb_scan(unsigned int vendor, /* Plug&Play Vendor ID */
32 unsigned int driver, /* Plug&Play Device ID */
33 ambapp_apbdev * dev, /* Result(s) is placed here */
34 int index, /* Index of device to start copying Plug&Play
35 * info into dev
36 */
37 int max_cnt /* Maximal count that dev can hold, if dev
38 * is NULL function will stop scanning after
39 * max_cnt devices are found.
40 */
41 )
42{
43 int i, cnt = 0;
44 unsigned int apbmst_base;
45 ambapp_ahbdev apbmst;
46 apbctrl_pp_dev *apb;
47
48 if (max_cnt == 0)
49 return 0;
50
51 /* Get AMBA APB Master */
52 if (ambapp_ahbslv_first(VENDOR_GAISLER, GAISLER_APBMST, &apbmst) != 1) {
53 return 0;
54 }
55
56 /* Get APB CTRL Plug&Play info area */
57 apbmst_base = apbmst.address[0] & LEON3_IO_AREA;
58 apb = (apbctrl_pp_dev *) (apbmst_base | LEON3_CONF_AREA);
59
60 for (i = 0; i < LEON3_APB_SLAVES; i++) {
61 if ((amba_vendor(apb->conf) == vendor) &&
62 (amba_device(apb->conf) == driver) && ((index < 0)
63 || (index-- == 0))) {
64 /* Convert Plug&Play info into a more readable format */
65 cnt++;
66 if (dev) {
67 dev->irq = amba_irq(apb->conf);
68 dev->ver = amba_ver(apb->conf);
69 dev->address =
70 (apbmst_base |
71 (((apb->
72 bar & 0xfff00000) >> 12))) & (((apb->
73 bar &
74 0x0000fff0)
75 << 4) |
76 0xfff00000);
77 dev++;
78 }
79 /* found max devices? */
80 if (cnt >= max_cnt)
81 return cnt;
82 }
83 /* Get next Plug&Play entry */
84 apb++;
85 }
86 return cnt;
87}
88
89unsigned int ambapp_apb_next_nomem(register unsigned int vendor, /* Plug&Play Vendor ID */
90 register unsigned int driver, /* Plug&Play Device ID */
91 register int index)
92{
93 register int i;
94 register ahbctrl_pp_dev *apbmst;
95 register apbctrl_pp_dev *apb;
96 register unsigned int apbmst_base;
97
98 /* APBMST is a AHB Slave */
99 apbmst = ambapp_ahb_next_nomem(VENDOR_GAISLER, GAISLER_APBMST, 1, 0);
100 if (!apbmst)
101 return 0;
102
103 apbmst_base = amba_membar_start(apbmst->bars[0]);
104 if (amba_membar_type(apbmst->bars[0]) == AMBA_TYPE_AHBIO)
105 apbmst_base = AMBA_TYPE_AHBIO_ADDR(apbmst_base);
106 apbmst_base &= LEON3_IO_AREA;
107
108 /* Find the vendor/driver device on the first APB bus */
109 apb = (apbctrl_pp_dev *) (apbmst_base | LEON3_CONF_AREA);
110
111 for (i = 0; i < LEON3_APB_SLAVES; i++) {
112 if ((amba_vendor(apb->conf) == vendor) &&
113 (amba_device(apb->conf) == driver) && ((index < 0)
114 || (index-- == 0))) {
115 /* Convert Plug&Play info info a more readable format */
116 return (apbmst_base | (((apb->bar & 0xfff00000) >> 12)))
117 & (((apb->bar & 0x0000fff0) << 4) | 0xfff00000);
118 }
119 /* Get next Plug&Play entry */
120 apb++;
121 }
122 return 0;
123}
124
125/****************************** APB SLAVES ******************************/
126
127int ambapp_apb_count(unsigned int vendor, unsigned int driver)
128{
129 return ambapp_apb_scan(vendor, driver, NULL, 0, LEON3_APB_SLAVES);
130}
131
132int ambapp_apb_first(unsigned int vendor,
133 unsigned int driver, ambapp_apbdev * dev)
134{
135 return ambapp_apb_scan(vendor, driver, dev, 0, 1);
136}
137
138int ambapp_apb_next(unsigned int vendor,
139 unsigned int driver, ambapp_apbdev * dev, int index)
140{
141 return ambapp_apb_scan(vendor, driver, dev, index, 1);
142}
143
144int ambapp_apbs_first(unsigned int vendor,
145 unsigned int driver, ambapp_apbdev * dev, int max_cnt)
146{
147 return ambapp_apb_scan(vendor, driver, dev, 0, max_cnt);
148}
149
150enum {
151 AHB_SCAN_MASTER = 0,
152 AHB_SCAN_SLAVE = 1
153};
154
155/* Scan AMBA Plug&Play bus for AMBA AHB Masters or AHB Slaves
156 * for a certain matching Vendor and Device ID.
157 *
158 * Return number of devices found.
159 *
160 * Compact edition...
161 */
162static int ambapp_ahb_scan(unsigned int vendor, /* Plug&Play Vendor ID */
163 unsigned int driver, /* Plug&Play Device ID */
164 ambapp_ahbdev * dev, /* Result(s) is placed here */
165 int index, /* Index of device to start copying Plug&Play
166 * info into dev
167 */
168 int max_cnt, /* Maximal count that dev can hold, if dev
169 * is NULL function will stop scanning after
170 * max_cnt devices are found.
171 */
172 int type /* Selectes what type of devices to scan.
173 * 0=AHB Masters
174 * 1=AHB Slaves
175 */
176 )
177{
178 int i, j, cnt = 0, max_pp_devs;
179 unsigned int addr;
180 ahbctrl_info *info = (ahbctrl_info *) (LEON3_IO_AREA | LEON3_CONF_AREA);
181 ahbctrl_pp_dev *ahb;
182
183 if (max_cnt == 0)
184 return 0;
185
186 if (type == 0) {
187 max_pp_devs = LEON3_AHB_MASTERS;
188 ahb = info->masters;
189 } else {
190 max_pp_devs = LEON3_AHB_SLAVES;
191 ahb = info->slaves;
192 }
193
194 for (i = 0; i < max_pp_devs; i++) {
195 if ((amba_vendor(ahb->conf) == vendor) &&
196 (amba_device(ahb->conf) == driver) &&
197 ((index < 0) || (index-- == 0))) {
198 /* Convert Plug&Play info info a more readable format */
199 cnt++;
200 if (dev) {
201 dev->irq = amba_irq(ahb->conf);
202 dev->ver = amba_ver(ahb->conf);
203 dev->userdef[0] = ahb->userdef[0];
204 dev->userdef[1] = ahb->userdef[1];
205 dev->userdef[2] = ahb->userdef[2];
206 for (j = 0; j < 4; j++) {
207 addr = amba_membar_start(ahb->bars[j]);
208 if (amba_membar_type(ahb->bars[j]) ==
209 AMBA_TYPE_AHBIO)
210 addr =
211 AMBA_TYPE_AHBIO_ADDR(addr);
212 dev->address[j] = addr;
213 }
214 dev++;
215 }
216 /* found max devices? */
217 if (cnt >= max_cnt)
218 return cnt;
219 }
220 /* Get next Plug&Play entry */
221 ahb++;
222 }
223 return cnt;
224}
225
226unsigned int ambapp_ahb_get_info(ahbctrl_pp_dev * ahb, int info)
227{
228 register unsigned int ret;
229
230 if (!ahb)
231 return 0;
232
233 switch (info) {
234 default:
235 info = 0;
236 case 0:
237 case 1:
238 case 2:
239 case 3:
240 /* Get Address from PnP Info */
241 ret = amba_membar_start(ahb->bars[info]);
242 if (amba_membar_type(ahb->bars[info]) == AMBA_TYPE_AHBIO)
243 ret = AMBA_TYPE_AHBIO_ADDR(ret);
244 return ret;
245 }
246 return 0;
247
248}
249
250ahbctrl_pp_dev *ambapp_ahb_next_nomem(register unsigned int vendor, /* Plug&Play Vendor ID */
251 register unsigned int driver, /* Plug&Play Device ID */
252 register unsigned int opts, /* 1=slave, 0=master */
253 register int index)
254{
255 register ahbctrl_pp_dev *ahb;
256 register ahbctrl_info *info =
257 (ahbctrl_info *) (LEON3_IO_AREA | LEON3_CONF_AREA);
258 register int i;
259 register int max_pp_devs;
260
261 if (opts == 0) {
262 max_pp_devs = LEON3_AHB_MASTERS;
263 ahb = info->masters;
264 } else {
265 max_pp_devs = LEON3_AHB_SLAVES;
266 ahb = info->slaves;
267 }
268
269 for (i = 0; i < max_pp_devs; i++) {
270 if ((amba_vendor(ahb->conf) == vendor) &&
271 (amba_device(ahb->conf) == driver) &&
272 ((index < 0) || (index-- == 0))) {
273 /* Convert Plug&Play info info a more readable format */
274 return ahb;
275 }
276 /* Get next Plug&Play entry */
277 ahb++;
278 }
279 return 0;
280}
281
282/****************************** AHB MASTERS ******************************/
283int ambapp_ahbmst_count(unsigned int vendor, unsigned int driver)
284{
285 /* Get number of devices of this vendor&device ID */
286 return ambapp_ahb_scan(vendor, driver, NULL, 0, LEON3_AHB_MASTERS,
287 AHB_SCAN_MASTER);
288}
289
290int ambapp_ahbmst_first(unsigned int vendor, unsigned int driver,
291 ambapp_ahbdev * dev)
292{
293 /* find first device of this */
294 return ambapp_ahb_scan(vendor, driver, dev, 0, 1, AHB_SCAN_MASTER);
295}
296
297int ambapp_ahbmst_next(unsigned int vendor,
298 unsigned int driver, ambapp_ahbdev * dev, int index)
299{
300 /* find first device of this */
301 return ambapp_ahb_scan(vendor, driver, dev, index, 1, AHB_SCAN_MASTER);
302}
303
304int ambapp_ahbmsts_first(unsigned int vendor,
305 unsigned int driver, ambapp_ahbdev * dev, int max_cnt)
306{
307 /* find first device of this */
308 return ambapp_ahb_scan(vendor, driver, dev, 0, max_cnt,
309 AHB_SCAN_MASTER);
310}
311
312/****************************** AHB SLAVES ******************************/
313int ambapp_ahbslv_count(unsigned int vendor, unsigned int driver)
314{
315 /* Get number of devices of this vendor&device ID */
316 return ambapp_ahb_scan(vendor, driver, NULL, 0, LEON3_AHB_SLAVES,
317 AHB_SCAN_SLAVE);
318}
319
320int ambapp_ahbslv_first(unsigned int vendor, unsigned int driver,
321 ambapp_ahbdev * dev)
322{
323 /* find first device of this */
324 return ambapp_ahb_scan(vendor, driver, dev, 0, 1, AHB_SCAN_SLAVE);
325}
326
327int ambapp_ahbslv_next(unsigned int vendor,
328 unsigned int driver, ambapp_ahbdev * dev, int index)
329{
330 /* find first device of this */
331 return ambapp_ahb_scan(vendor, driver, dev, index, 1, AHB_SCAN_SLAVE);
332}
333
334int ambapp_ahbslvs_first(unsigned int vendor,
335 unsigned int driver, ambapp_ahbdev * dev, int max_cnt)
336{
337 /* find first device of this */
338 return ambapp_ahb_scan(vendor, driver, dev, 0, max_cnt, AHB_SCAN_SLAVE);
339}