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