SPARC: Added support for SPARC LEON3 SOC processor.
[oweals/u-boot.git] / 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  * 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 static 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
89 unsigned 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
127 int ambapp_apb_count(unsigned int vendor, unsigned int driver)
128 {
129         return ambapp_apb_scan(vendor, driver, NULL, 0, LEON3_APB_SLAVES);
130 }
131
132 int 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
138 int 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
144 int 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
150 enum {
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  */
162 static 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
226 unsigned 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
250 ahbctrl_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 ******************************/
283 int 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
290 int 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
297 int 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
304 int 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 ******************************/
313 int 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
320 int 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
327 int 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
334 int 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 }