]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/sparc/cpu/leon3/ambapp.c
mxc_ipuv3: fix memory alignment of framebuffer
[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  * 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
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
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
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
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
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
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  */
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
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
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 ******************************/
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
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
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
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 ******************************/
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
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
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
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 }