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).
6 * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com
8 * See file CREDITS for list of people who contributed to this
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.
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.
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,
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
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.
44 unsigned int apbmst_base;
51 /* Get AMBA APB Master */
52 if (ambapp_ahbslv_first(VENDOR_GAISLER, GAISLER_APBMST, &apbmst) != 1) {
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);
60 for (i = 0; i < LEON3_APB_SLAVES; i++) {
61 if ((amba_vendor(apb->conf) == vendor) &&
62 (amba_device(apb->conf) == driver) && ((index < 0)
64 /* Convert Plug&Play info into a more readable format */
67 dev->irq = amba_irq(apb->conf);
68 dev->ver = amba_ver(apb->conf);
72 bar & 0xfff00000) >> 12))) & (((apb->
79 /* found max devices? */
83 /* Get next Plug&Play entry */
89 unsigned int ambapp_apb_next_nomem(register unsigned int vendor, /* Plug&Play Vendor ID */
90 register unsigned int driver, /* Plug&Play Device ID */
94 register ahbctrl_pp_dev *apbmst;
95 register apbctrl_pp_dev *apb;
96 register unsigned int apbmst_base;
98 /* APBMST is a AHB Slave */
99 apbmst = ambapp_ahb_next_nomem(VENDOR_GAISLER, GAISLER_APBMST, 1, 0);
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;
108 /* Find the vendor/driver device on the first APB bus */
109 apb = (apbctrl_pp_dev *) (apbmst_base | LEON3_CONF_AREA);
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);
119 /* Get next Plug&Play entry */
125 /****************************** APB SLAVES ******************************/
127 int ambapp_apb_count(unsigned int vendor, unsigned int driver)
129 return ambapp_apb_scan(vendor, driver, NULL, 0, LEON3_APB_SLAVES);
132 int ambapp_apb_first(unsigned int vendor,
133 unsigned int driver, ambapp_apbdev * dev)
135 return ambapp_apb_scan(vendor, driver, dev, 0, 1);
138 int ambapp_apb_next(unsigned int vendor,
139 unsigned int driver, ambapp_apbdev * dev, int index)
141 return ambapp_apb_scan(vendor, driver, dev, index, 1);
144 int ambapp_apbs_first(unsigned int vendor,
145 unsigned int driver, ambapp_apbdev * dev, int max_cnt)
147 return ambapp_apb_scan(vendor, driver, dev, 0, max_cnt);
155 /* Scan AMBA Plug&Play bus for AMBA AHB Masters or AHB Slaves
156 * for a certain matching Vendor and Device ID.
158 * Return number of devices found.
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
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.
172 int type /* Selectes what type of devices to scan.
178 int i, j, cnt = 0, max_pp_devs;
180 ahbctrl_info *info = (ahbctrl_info *) (LEON3_IO_AREA | LEON3_CONF_AREA);
187 max_pp_devs = LEON3_AHB_MASTERS;
190 max_pp_devs = LEON3_AHB_SLAVES;
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 */
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]) ==
211 AMBA_TYPE_AHBIO_ADDR(addr);
212 dev->address[j] = addr;
216 /* found max devices? */
220 /* Get next Plug&Play entry */
226 unsigned int ambapp_ahb_get_info(ahbctrl_pp_dev * ahb, int info)
228 register unsigned int ret;
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);
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 */
255 register ahbctrl_pp_dev *ahb;
256 register ahbctrl_info *info =
257 (ahbctrl_info *) (LEON3_IO_AREA | LEON3_CONF_AREA);
259 register int max_pp_devs;
262 max_pp_devs = LEON3_AHB_MASTERS;
265 max_pp_devs = LEON3_AHB_SLAVES;
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 */
276 /* Get next Plug&Play entry */
282 /****************************** AHB MASTERS ******************************/
283 int ambapp_ahbmst_count(unsigned int vendor, unsigned int driver)
285 /* Get number of devices of this vendor&device ID */
286 return ambapp_ahb_scan(vendor, driver, NULL, 0, LEON3_AHB_MASTERS,
290 int ambapp_ahbmst_first(unsigned int vendor, unsigned int driver,
293 /* find first device of this */
294 return ambapp_ahb_scan(vendor, driver, dev, 0, 1, AHB_SCAN_MASTER);
297 int ambapp_ahbmst_next(unsigned int vendor,
298 unsigned int driver, ambapp_ahbdev * dev, int index)
300 /* find first device of this */
301 return ambapp_ahb_scan(vendor, driver, dev, index, 1, AHB_SCAN_MASTER);
304 int ambapp_ahbmsts_first(unsigned int vendor,
305 unsigned int driver, ambapp_ahbdev * dev, int max_cnt)
307 /* find first device of this */
308 return ambapp_ahb_scan(vendor, driver, dev, 0, max_cnt,
312 /****************************** AHB SLAVES ******************************/
313 int ambapp_ahbslv_count(unsigned int vendor, unsigned int driver)
315 /* Get number of devices of this vendor&device ID */
316 return ambapp_ahb_scan(vendor, driver, NULL, 0, LEON3_AHB_SLAVES,
320 int ambapp_ahbslv_first(unsigned int vendor, unsigned int driver,
323 /* find first device of this */
324 return ambapp_ahb_scan(vendor, driver, dev, 0, 1, AHB_SCAN_SLAVE);
327 int ambapp_ahbslv_next(unsigned int vendor,
328 unsigned int driver, ambapp_ahbdev * dev, int index)
330 /* find first device of this */
331 return ambapp_ahb_scan(vendor, driver, dev, index, 1, AHB_SCAN_SLAVE);
334 int ambapp_ahbslvs_first(unsigned int vendor,
335 unsigned int driver, ambapp_ahbdev * dev, int max_cnt)
337 /* find first device of this */
338 return ambapp_ahb_scan(vendor, driver, dev, 0, max_cnt, AHB_SCAN_SLAVE);