1 /* 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 
31 #if defined(CONFIG_CMD_AMBAPP)
32 extern void ambapp_print_apb(apbctrl_pp_dev * apb,
33 			     ambapp_ahbdev * apbmst, int index);
34 extern void ambapp_print_ahb(ahbctrl_pp_dev * ahb, int index);
35 extern int ambapp_apb_print;
36 extern int ambapp_ahb_print;
37 #endif
38 
ambapp_apb_scan(unsigned int vendor,unsigned int driver,ambapp_apbdev * dev,int index,int max_cnt)39 static 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++) {
69 #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
75 		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 
ambapp_apb_next_nomem(register unsigned int vendor,register unsigned int driver,register int index)103 unsigned 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 
ambapp_apb_count(unsigned int vendor,unsigned int driver)141 int ambapp_apb_count(unsigned int vendor, unsigned int driver)
142 {
143 	return ambapp_apb_scan(vendor, driver, NULL, 0, LEON3_APB_SLAVES);
144 }
145 
ambapp_apb_first(unsigned int vendor,unsigned int driver,ambapp_apbdev * dev)146 int 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 
ambapp_apb_next(unsigned int vendor,unsigned int driver,ambapp_apbdev * dev,int index)152 int 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 
ambapp_apbs_first(unsigned int vendor,unsigned int driver,ambapp_apbdev * dev,int max_cnt)158 int 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 
164 enum {
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  */
ambapp_ahb_scan(unsigned int vendor,unsigned int driver,ambapp_ahbdev * dev,int index,int max_cnt,int type)176 static 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++) {
209 #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
215 		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 
ambapp_ahb_get_info(ahbctrl_pp_dev * ahb,int info)246 unsigned 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 
ambapp_ahb_next_nomem(register unsigned int vendor,register unsigned int driver,register unsigned int opts,register int index)270 ahbctrl_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 ******************************/
ambapp_ahbmst_count(unsigned int vendor,unsigned int driver)303 int 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 
ambapp_ahbmst_first(unsigned int vendor,unsigned int driver,ambapp_ahbdev * dev)310 int 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 
ambapp_ahbmst_next(unsigned int vendor,unsigned int driver,ambapp_ahbdev * dev,int index)317 int 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 
ambapp_ahbmsts_first(unsigned int vendor,unsigned int driver,ambapp_ahbdev * dev,int max_cnt)324 int 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 ******************************/
ambapp_ahbslv_count(unsigned int vendor,unsigned int driver)333 int 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 
ambapp_ahbslv_first(unsigned int vendor,unsigned int driver,ambapp_ahbdev * dev)340 int 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 
ambapp_ahbslv_next(unsigned int vendor,unsigned int driver,ambapp_ahbdev * dev,int index)347 int 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 
ambapp_ahbslvs_first(unsigned int vendor,unsigned int driver,ambapp_ahbdev * dev,int max_cnt)354 int 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 }
360