1 /* GRLIB AMBA Plug&Play information scanning, relies on assembler
4 * (C) Copyright 2010, 2015
5 * Daniel Hellstrom, Cobham Gaisler, daniel@gaisler.com.
7 * SPDX-License-Identifier: GPL-2.0+
16 /************ C INTERFACE OF ASSEMBLER SCAN ROUTINES ************/
17 struct ambapp_find_apb_info {
18 /* Address of APB device Plug&Play information */
19 struct ambapp_pnp_apb *pnp;
20 /* AHB Bus index of where the APB-Master Bridge device was found */
25 struct ambapp_find_ahb_info {
26 /* Address of AHB device Plug&Play information */
27 struct ambapp_pnp_ahb *pnp;
28 /* AHB Bus index of where the AHB device was found */
33 extern void ambapp_find_buses(unsigned int ioarea, struct ambapp_bus *abus);
35 extern int ambapp_find_apb(struct ambapp_bus *abus, unsigned int dev_vend,
36 int index, struct ambapp_find_apb_info *result);
38 extern int ambapp_find_ahb(struct ambapp_bus *abus, unsigned int dev_vend,
39 int index, int type, struct ambapp_find_ahb_info *result);
41 /************ C ROUTINES USED BY U-BOOT AMBA CORE DRIVERS ************/
42 struct ambapp_bus ambapp_plb;
47 struct ambapp_bus *abus)
51 ambapp_find_buses(ioarea, abus);
52 for (i = 0; i < 6; i++)
53 if (abus->ioareas[i] == 0)
59 /* Parse APB PnP Information */
60 void ambapp_apb_parse(struct ambapp_find_apb_info *info, ambapp_apbdev *dev)
62 struct ambapp_pnp_apb *apb = info->pnp;
63 unsigned int apbbase = (unsigned int)apb & 0xfff00000;
65 dev->vendor = amba_vendor(apb->id);
66 dev->device = amba_device(apb->id);
67 dev->irq = amba_irq(apb->id);
68 dev->ver = amba_ver(apb->id);
69 dev->address = (apbbase | (((apb->iobar & 0xfff00000) >> 12))) &
70 (((apb->iobar & 0x0000fff0) << 4) | 0xfff00000);
71 dev->mask = amba_apb_mask(apb->iobar);
72 dev->ahb_bus_index = info->ahb_bus_index - 1;
75 /* Parse AHB PnP information */
76 void ambapp_ahb_parse(struct ambapp_find_ahb_info *info, ambapp_ahbdev *dev)
78 struct ambapp_pnp_ahb *ahb = info->pnp;
79 unsigned int ahbbase = (unsigned int)ahb & 0xfff00000;
81 unsigned int addr, mask, mbar;
83 dev->vendor = amba_vendor(ahb->id);
84 dev->device = amba_device(ahb->id);
85 dev->irq = amba_irq(ahb->id);
86 dev->ver = amba_ver(ahb->id);
87 dev->userdef[0] = ahb->custom[0];
88 dev->userdef[1] = ahb->custom[1];
89 dev->userdef[2] = ahb->custom[2];
90 dev->ahb_bus_index = info->ahb_bus_index - 1;
91 for (i = 0; i < 4; i++) {
93 addr = amba_membar_start(mbar);
94 type = amba_membar_type(mbar);
95 if (type == AMBA_TYPE_AHBIO) {
96 addr = amba_ahbio_adr(addr, ahbbase);
97 mask = (((unsigned int)
98 (amba_membar_mask((~mbar))<<8)|0xff))+1;
100 /* AHB memory area, absolute address */
101 mask = (~((unsigned int)
102 (amba_membar_mask(mbar)<<20)))+1;
104 dev->address[i] = addr;
110 int ambapp_apb_find(struct ambapp_bus *abus, int vendor, int device,
111 int index, ambapp_apbdev *dev)
113 unsigned int devid = AMBA_PNP_ID(vendor, device);
115 struct ambapp_find_apb_info apbdev;
117 found = ambapp_find_apb(abus, devid, index, &apbdev);
119 ambapp_apb_parse(&apbdev, dev);
124 int ambapp_apb_count(struct ambapp_bus *abus, int vendor, int device)
126 unsigned int devid = AMBA_PNP_ID(vendor, device);
128 struct ambapp_find_apb_info apbdev;
130 found = ambapp_find_apb(abus, devid, 63, &apbdev);
134 return 63 - apbdev.dec_index;
137 int ambapp_ahb_find(struct ambapp_bus *abus, int vendor, int device,
138 int index, ambapp_ahbdev *dev, int type)
141 struct ambapp_find_ahb_info ahbdev;
142 unsigned int devid = AMBA_PNP_ID(vendor, device);
144 found = ambapp_find_ahb(abus, devid, index, type, &ahbdev);
146 ambapp_ahb_parse(&ahbdev, dev);
151 int ambapp_ahbmst_find(struct ambapp_bus *abus, int vendor, int device,
152 int index, ambapp_ahbdev *dev)
154 return ambapp_ahb_find(abus, vendor, device, index, dev, DEV_AHB_MST);
157 int ambapp_ahbslv_find(struct ambapp_bus *abus, int vendor, int device,
158 int index, ambapp_ahbdev *dev)
160 return ambapp_ahb_find(abus, vendor, device, index, dev, DEV_AHB_SLV);
163 int ambapp_ahb_count(struct ambapp_bus *abus, int vendor, int device, int type)
166 struct ambapp_find_ahb_info ahbdev;
167 unsigned int devid = AMBA_PNP_ID(vendor, device);
169 found = ambapp_find_ahb(abus, devid, 63, type, &ahbdev);
173 return 63 - ahbdev.dec_index;
176 int ambapp_ahbmst_count(struct ambapp_bus *abus, int vendor, int device)
178 return ambapp_ahb_count(abus, vendor, device, DEV_AHB_MST);
181 int ambapp_ahbslv_count(struct ambapp_bus *abus, int vendor, int device)
183 return ambapp_ahb_count(abus, vendor, device, DEV_AHB_SLV);
186 /* The define CONFIG_SYS_GRLIB_SINGLE_BUS may be defined on GRLIB systems
187 * where only one AHB Bus is available - no bridges are present. This option
188 * is available only to reduce the footprint.
190 * Defining this on a multi-bus GRLIB system may also work depending on the
194 #ifndef CONFIG_SYS_GRLIB_SINGLE_BUS
196 /* GAISLER AHB2AHB Version 1 Bridge Definitions */
197 #define AHB2AHB_V1_FLAG_FFACT 0x0f0 /* Frequency factor against top bus */
198 #define AHB2AHB_V1_FLAG_FFACT_DIR 0x100 /* Factor direction, 0=down, 1=up */
199 #define AHB2AHB_V1_FLAG_MBUS 0x00c /* Master bus number mask */
200 #define AHB2AHB_V1_FLAG_SBUS 0x003 /* Slave bus number mask */
202 /* Get Parent bus frequency. Note that since we go from a "child" bus
203 * to a parent bus, the frequency factor direction is inverted.
205 unsigned int gaisler_ahb2ahb_v1_freq(ambapp_ahbdev *ahb, unsigned int freq)
210 /* Get division/multiple factor */
211 ffact = (ahb->userdef[0] & AHB2AHB_V1_FLAG_FFACT) >> 4;
213 dir = ahb->userdef[0] & AHB2AHB_V1_FLAG_FFACT_DIR;
215 /* Calculate frequency by dividing or
216 * multiplying system frequency
227 /* AHB2AHB and L2CACHE ver 2 is not supported yet. */
228 unsigned int gaisler_ahb2ahb_v2_freq(ambapp_ahbdev *ahb, unsigned int freq)
230 panic("gaisler_ahb2ahb_v2_freq: AHB2AHB ver 2 not supported\n");
235 /* Return the frequency of a AHB bus identified by index found
236 * note that this is not the AHB Bus number.
238 unsigned int ambapp_bus_freq(struct ambapp_bus *abus, int ahb_bus_index)
240 unsigned int freq = abus->freq;
241 #ifndef CONFIG_SYS_GRLIB_SINGLE_BUS
242 unsigned int ioarea, ioarea_parent, bridge_pnp_ofs;
243 struct ambapp_find_ahb_info ahbinfo;
247 debug("ambapp_bus_freq: get freq on bus %d\n", ahb_bus_index);
249 while (ahb_bus_index != 0) {
250 debug(" BUS[0]: 0x%08x\n", abus->ioareas[0]);
251 debug(" BUS[1]: 0x%08x\n", abus->ioareas[1]);
252 debug(" BUS[2]: 0x%08x\n", abus->ioareas[2]);
253 debug(" BUS[3]: 0x%08x\n", abus->ioareas[3]);
254 debug(" BUS[4]: 0x%08x\n", abus->ioareas[4]);
255 debug(" BUS[5]: 0x%08x\n", abus->ioareas[5]);
257 /* Get I/O area of AHB bus */
258 ioarea = abus->ioareas[ahb_bus_index];
260 printf(" IOAREA: 0x%08x\n", ioarea);
263 parent = (ioarea & 0x7);
265 panic("%s: parent=0 indicates no parent! Stopping.\n",
270 bridge_pnp_ofs = ioarea & 0x7e0;
272 debug(" PARENT: %d\n", parent);
273 debug(" BRIDGE_OFS: 0x%08x\n", bridge_pnp_ofs);
275 /* Get AHB/AHB bridge PnP address */
276 ioarea_parent = (abus->ioareas[parent] & 0xfff00000) |
277 AMBA_CONF_AREA | AMBA_AHB_SLAVE_CONF_AREA;
278 ahbinfo.pnp = (struct ambapp_pnp_ahb *)
279 (ioarea_parent | bridge_pnp_ofs);
281 debug(" IOAREA PARENT: 0x%08x\n", ioarea_parent);
282 debug(" BRIDGE PNP: 0x%p\n", ahbinfo.pnp);
284 /* Parse the AHB information */
285 ahbinfo.ahb_bus_index = parent;
286 ambapp_ahb_parse(&ahbinfo, &ahb);
288 debug(" BRIDGE ID: VENDOR=%d(0x%x), DEVICE=%d(0x%x)\n",
289 ahb.vendor, ahb.vendor, ahb.device, ahb.device);
291 /* Different bridges may convert frequency differently */
292 if ((ahb.vendor == VENDOR_GAISLER) &&
293 ((ahb.device == GAISLER_AHB2AHB) ||
294 (ahb.device == GAISLER_L2CACHE))) {
295 /* Get new frequency */
297 freq = gaisler_ahb2ahb_v2_freq(&ahb, freq);
299 freq = gaisler_ahb2ahb_v1_freq(&ahb, freq);
301 debug(" NEW FREQ: %dHz\n", freq);
303 panic("%s: unsupported AMBA bridge\n", __func__);
307 /* Step upwards towards system top bus */
308 ahb_bus_index = parent;
312 debug("ambapp_bus_freq: %dHz\n", freq);