sparc: leon3: Reimplemented AMBA Plug&Play scanning routines.

Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
diff --git a/arch/sparc/cpu/leon3/ambapp.c b/arch/sparc/cpu/leon3/ambapp.c
index a30d1f2..bb81338 100644
--- a/arch/sparc/cpu/leon3/ambapp.c
+++ b/arch/sparc/cpu/leon3/ambapp.c
@@ -1,343 +1,315 @@
-/* Gaisler AMBA Plug&Play bus scanning. Functions
- * ending on _nomem is inteded to be used only during
- * initialization, only registers are used (no ram).
+/* GRLIB AMBA Plug&Play information scanning, relies on assembler
+ * routines.
  *
- * (C) Copyright 2007
- * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com
+ * (C) Copyright 2010, 2015
+ * Daniel Hellstrom, Cobham Gaisler, daniel@gaisler.com.
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
+/* #define DEBUG */
+
 #include <common.h>
-#include <command.h>
 #include <ambapp.h>
+#include <config.h>
 
-#if defined(CONFIG_CMD_AMBAPP)
-extern void ambapp_print_apb(apbctrl_pp_dev * apb,
-			     ambapp_ahbdev * apbmst, int index);
-extern void ambapp_print_ahb(ahbctrl_pp_dev * ahb, int index);
-extern int ambapp_apb_print;
-extern int ambapp_ahb_print;
-#endif
+/************ C INTERFACE OF ASSEMBLER SCAN ROUTINES ************/
+struct ambapp_find_apb_info {
+	/* Address of APB device Plug&Play information */
+	struct ambapp_pnp_apb	*pnp;
+	/* AHB Bus index of where the APB-Master Bridge device was found */
+	int			ahb_bus_index;
+	int			dec_index;
+};
+
+struct ambapp_find_ahb_info {
+	/* Address of AHB device Plug&Play information */
+	struct ambapp_pnp_ahb	*pnp;
+	/* AHB Bus index of where the AHB device was found */
+	int			ahb_bus_index;
+	int			dec_index;
+};
 
-static int ambapp_apb_scan(unsigned int vendor,	/* Plug&Play Vendor ID */
-			   unsigned int driver,	/* Plug&Play Device ID */
-			   ambapp_apbdev * dev,	/* Result(s) is placed here */
-			   int index,	/* Index of device to start copying Plug&Play
-					 * info into dev
-					 */
-			   int max_cnt	/* Maximal count that dev can hold, if dev
-					 * is NULL function will stop scanning after
-					 * max_cnt devices are found.
-					 */
-    )
+extern void ambapp_find_buses(unsigned int ioarea, struct ambapp_bus *abus);
+
+extern int ambapp_find_apb(struct ambapp_bus *abus, unsigned int dev_vend,
+	int index, struct ambapp_find_apb_info *result);
+
+extern int ambapp_find_ahb(struct ambapp_bus *abus, unsigned int dev_vend,
+	int index, int type, struct ambapp_find_ahb_info *result);
+
+/************ C ROUTINES USED BY U-BOOT AMBA CORE DRIVERS ************/
+struct ambapp_bus ambapp_plb;
+
+void ambapp_bus_init(
+	unsigned int ioarea,
+	unsigned int freq,
+	struct ambapp_bus *abus)
 {
-	int i, cnt = 0;
-	unsigned int apbmst_base;
-	ambapp_ahbdev apbmst;
-	apbctrl_pp_dev *apb;
+	int i;
 
-	if (max_cnt == 0)
-		return 0;
+	ambapp_find_buses(ioarea, abus);
+	for (i = 0; i < 6; i++)
+		if (abus->ioareas[i] == 0)
+			break;
+	abus->buses = i;
+	abus->freq = freq;
+}
 
-	/* Get AMBA APB Master */
-	if (ambapp_ahbslv_first(VENDOR_GAISLER, GAISLER_APBMST, &apbmst) != 1) {
-		return 0;
-	}
+/* Parse APB PnP Information */
+void ambapp_apb_parse(struct ambapp_find_apb_info *info, ambapp_apbdev *dev)
+{
+	struct ambapp_pnp_apb *apb = info->pnp;
+	unsigned int apbbase = (unsigned int)apb & 0xfff00000;
+
+	dev->vendor = amba_vendor(apb->id);
+	dev->device = amba_device(apb->id);
+	dev->irq = amba_irq(apb->id);
+	dev->ver = amba_ver(apb->id);
+	dev->address = (apbbase | (((apb->iobar & 0xfff00000) >> 12))) &
+			(((apb->iobar &	0x0000fff0) << 4) | 0xfff00000);
+	dev->mask = amba_apb_mask(apb->iobar);
+	dev->ahb_bus_index = info->ahb_bus_index - 1;
+}
 
-	/* Get APB CTRL Plug&Play info area */
-	apbmst_base = apbmst.address[0] & LEON3_IO_AREA;
-	apb = (apbctrl_pp_dev *) (apbmst_base | LEON3_CONF_AREA);
+/* Parse AHB PnP information */
+void ambapp_ahb_parse(struct ambapp_find_ahb_info *info, ambapp_ahbdev *dev)
+{
+	struct ambapp_pnp_ahb *ahb = info->pnp;
+	unsigned int ahbbase = (unsigned int)ahb & 0xfff00000;
+	int i, type;
+	unsigned int addr, mask, mbar;
 
-	for (i = 0; i < LEON3_APB_SLAVES; i++) {
-#if defined(CONFIG_CMD_AMBAPP)
-		if (ambapp_apb_print && amba_vendor(apb->conf)
-		    && amba_device(apb->conf)) {
-			ambapp_print_apb(apb, &apbmst, i);
-		}
-#endif
-		if ((amba_vendor(apb->conf) == vendor) &&
-		    (amba_device(apb->conf) == driver) && ((index < 0)
-							   || (index-- == 0))) {
-			/* Convert Plug&Play info into a more readable format */
-			cnt++;
-			if (dev) {
-				dev->irq = amba_irq(apb->conf);
-				dev->ver = amba_ver(apb->conf);
-				dev->address =
-				    (apbmst_base |
-				     (((apb->
-					bar & 0xfff00000) >> 12))) & (((apb->
-									bar &
-									0x0000fff0)
-								       << 4) |
-								      0xfff00000);
-				dev++;
-			}
-			/* found max devices? */
-			if (cnt >= max_cnt)
-				return cnt;
+	dev->vendor = amba_vendor(ahb->id);
+	dev->device = amba_device(ahb->id);
+	dev->irq = amba_irq(ahb->id);
+	dev->ver = amba_ver(ahb->id);
+	dev->userdef[0] = ahb->custom[0];
+	dev->userdef[1] = ahb->custom[1];
+	dev->userdef[2] = ahb->custom[2];
+	dev->ahb_bus_index = info->ahb_bus_index - 1;
+	for (i = 0; i < 4; i++) {
+		mbar = ahb->mbar[i];
+		addr = amba_membar_start(mbar);
+		type = amba_membar_type(mbar);
+		if (type == AMBA_TYPE_AHBIO) {
+			addr = amba_ahbio_adr(addr, ahbbase);
+			mask = (((unsigned int)
+				(amba_membar_mask((~mbar))<<8)|0xff))+1;
+		} else {
+			/* AHB memory area, absolute address */
+			mask = (~((unsigned int)
+				(amba_membar_mask(mbar)<<20)))+1;
 		}
-		/* Get next Plug&Play entry */
-		apb++;
+		dev->address[i] = addr;
+		dev->mask[i] = mask;
+		dev->type[i] = type;
 	}
-	return cnt;
 }
 
-unsigned int ambapp_apb_next_nomem(register unsigned int vendor,	/* Plug&Play Vendor ID */
-				   register unsigned int driver,	/* Plug&Play Device ID */
-				   register int index)
+int ambapp_apb_find(struct ambapp_bus *abus, int vendor, int device,
+	int index, ambapp_apbdev *dev)
 {
-	register int i;
-	register ahbctrl_pp_dev *apbmst;
-	register apbctrl_pp_dev *apb;
-	register unsigned int apbmst_base;
+	unsigned int devid = AMBA_PNP_ID(vendor, device);
+	int found;
+	struct ambapp_find_apb_info apbdev;
 
-	/* APBMST is a AHB Slave */
-	apbmst = ambapp_ahb_next_nomem(VENDOR_GAISLER, GAISLER_APBMST, 1, 0);
-	if (!apbmst)
-		return 0;
+	found = ambapp_find_apb(abus, devid, index, &apbdev);
+	if (found == 1)
+		ambapp_apb_parse(&apbdev, dev);
 
-	apbmst_base = amba_membar_start(apbmst->bars[0]);
-	if (amba_membar_type(apbmst->bars[0]) == AMBA_TYPE_AHBIO)
-		apbmst_base = AMBA_TYPE_AHBIO_ADDR(apbmst_base);
-	apbmst_base &= LEON3_IO_AREA;
+	return found;
+}
 
-	/* Find the vendor/driver device on the first APB bus */
-	apb = (apbctrl_pp_dev *) (apbmst_base | LEON3_CONF_AREA);
+int ambapp_apb_count(struct ambapp_bus *abus, int vendor, int device)
+{
+	unsigned int devid = AMBA_PNP_ID(vendor, device);
+	int found;
+	struct ambapp_find_apb_info apbdev;
 
-	for (i = 0; i < LEON3_APB_SLAVES; i++) {
-		if ((amba_vendor(apb->conf) == vendor) &&
-		    (amba_device(apb->conf) == driver) && ((index < 0)
-							   || (index-- == 0))) {
-			/* Convert Plug&Play info info a more readable format */
-			return (apbmst_base | (((apb->bar & 0xfff00000) >> 12)))
-			    & (((apb->bar & 0x0000fff0) << 4) | 0xfff00000);
-		}
-		/* Get next Plug&Play entry */
-		apb++;
-	}
-	return 0;
+	found = ambapp_find_apb(abus, devid, 63, &apbdev);
+	if (found == 1)
+		return 64;
+	else
+		return 63 - apbdev.dec_index;
 }
 
-/****************************** APB SLAVES ******************************/
+int ambapp_ahb_find(struct ambapp_bus *abus, int vendor, int device,
+	int index, ambapp_ahbdev *dev, int type)
+{
+	int found;
+	struct ambapp_find_ahb_info ahbdev;
+	unsigned int devid = AMBA_PNP_ID(vendor, device);
 
-int ambapp_apb_count(unsigned int vendor, unsigned int driver)
+	found = ambapp_find_ahb(abus, devid, index, type, &ahbdev);
+	if (found == 1)
+		ambapp_ahb_parse(&ahbdev, dev);
+
+	return found;
+}
+
+int ambapp_ahbmst_find(struct ambapp_bus *abus, int vendor, int device,
+	int index, ambapp_ahbdev *dev)
 {
-	return ambapp_apb_scan(vendor, driver, NULL, 0, LEON3_APB_SLAVES);
+	return ambapp_ahb_find(abus, vendor, device, index, dev, DEV_AHB_MST);
 }
 
-int ambapp_apb_first(unsigned int vendor,
-		     unsigned int driver, ambapp_apbdev * dev)
+int ambapp_ahbslv_find(struct ambapp_bus *abus, int vendor, int device,
+	int index, ambapp_ahbdev *dev)
 {
-	return ambapp_apb_scan(vendor, driver, dev, 0, 1);
+	return ambapp_ahb_find(abus, vendor, device, index, dev, DEV_AHB_SLV);
 }
 
-int ambapp_apb_next(unsigned int vendor,
-		    unsigned int driver, ambapp_apbdev * dev, int index)
+int ambapp_ahb_count(struct ambapp_bus *abus, int vendor, int device, int type)
 {
-	return ambapp_apb_scan(vendor, driver, dev, index, 1);
+	int found;
+	struct ambapp_find_ahb_info ahbdev;
+	unsigned int devid = AMBA_PNP_ID(vendor, device);
+
+	found = ambapp_find_ahb(abus, devid, 63, type, &ahbdev);
+	if (found == 1)
+		return 64;
+	else
+		return 63 - ahbdev.dec_index;
 }
 
-int ambapp_apbs_first(unsigned int vendor,
-		      unsigned int driver, ambapp_apbdev * dev, int max_cnt)
+int ambapp_ahbmst_count(struct ambapp_bus *abus, int vendor, int device)
 {
-	return ambapp_apb_scan(vendor, driver, dev, 0, max_cnt);
+	return ambapp_ahb_count(abus, vendor, device, DEV_AHB_MST);
 }
 
-enum {
-	AHB_SCAN_MASTER = 0,
-	AHB_SCAN_SLAVE = 1
-};
+int ambapp_ahbslv_count(struct ambapp_bus *abus, int vendor, int device)
+{
+	return ambapp_ahb_count(abus, vendor, device, DEV_AHB_SLV);
+}
 
-/* Scan AMBA Plug&Play bus for AMBA AHB Masters or AHB Slaves
- * for a certain matching Vendor and Device ID.
- *
- * Return number of devices found.
+/* The define CONFIG_SYS_GRLIB_SINGLE_BUS may be defined on GRLIB systems
+ * where only one AHB Bus is available - no bridges are present. This option
+ * is available only to reduce the footprint.
  *
- * Compact edition...
+ * Defining this on a multi-bus GRLIB system may also work depending on the
+ * design.
+ */
+
+#ifndef CONFIG_SYS_GRLIB_SINGLE_BUS
+
+/* GAISLER AHB2AHB Version 1 Bridge Definitions */
+#define AHB2AHB_V1_FLAG_FFACT     0x0f0	/* Frequency factor against top bus */
+#define AHB2AHB_V1_FLAG_FFACT_DIR 0x100	/* Factor direction, 0=down, 1=up */
+#define AHB2AHB_V1_FLAG_MBUS      0x00c	/* Master bus number mask */
+#define AHB2AHB_V1_FLAG_SBUS      0x003	/* Slave bus number mask */
+
+/* Get Parent bus frequency. Note that since we go from a "child" bus
+ * to a parent bus, the frequency factor direction is inverted.
  */
-static int ambapp_ahb_scan(unsigned int vendor,	/* Plug&Play Vendor ID */
-			   unsigned int driver,	/* Plug&Play Device ID */
-			   ambapp_ahbdev * dev,	/* Result(s) is placed here */
-			   int index,	/* Index of device to start copying Plug&Play
-					 * info into dev
-					 */
-			   int max_cnt,	/* Maximal count that dev can hold, if dev
-					 * is NULL function will stop scanning after
-					 * max_cnt devices are found.
-					 */
-			   int type	/* Selectes what type of devices to scan.
-					 * 0=AHB Masters
-					 * 1=AHB Slaves
-					 */
-    )
+unsigned int gaisler_ahb2ahb_v1_freq(ambapp_ahbdev *ahb, unsigned int freq)
 {
-	int i, j, cnt = 0, max_pp_devs;
-	unsigned int addr;
-	ahbctrl_info *info = (ahbctrl_info *) (LEON3_IO_AREA | LEON3_CONF_AREA);
-	ahbctrl_pp_dev *ahb;
+	int dir;
+	unsigned char ffact;
 
-	if (max_cnt == 0)
-		return 0;
+	/* Get division/multiple factor */
+	ffact = (ahb->userdef[0] & AHB2AHB_V1_FLAG_FFACT) >> 4;
+	if (ffact != 0) {
+		dir = ahb->userdef[0] & AHB2AHB_V1_FLAG_FFACT_DIR;
 
-	if (type == 0) {
-		max_pp_devs = LEON3_AHB_MASTERS;
-		ahb = info->masters;
-	} else {
-		max_pp_devs = LEON3_AHB_SLAVES;
-		ahb = info->slaves;
+		/* Calculate frequency by dividing or
+		 * multiplying system frequency
+		 */
+		if (dir)
+			freq = freq * ffact;
+		else
+			freq = freq / ffact;
 	}
 
-	for (i = 0; i < max_pp_devs; i++) {
-#if defined(CONFIG_CMD_AMBAPP)
-		if (ambapp_ahb_print && amba_vendor(ahb->conf) &&
-		    amba_device(ahb->conf)) {
-			ambapp_print_ahb(ahb, i);
-		}
-#endif
-		if ((amba_vendor(ahb->conf) == vendor) &&
-		    (amba_device(ahb->conf) == driver) &&
-		    ((index < 0) || (index-- == 0))) {
-			/* Convert Plug&Play info info a more readable format */
-			cnt++;
-			if (dev) {
-				dev->irq = amba_irq(ahb->conf);
-				dev->ver = amba_ver(ahb->conf);
-				dev->userdef[0] = ahb->userdef[0];
-				dev->userdef[1] = ahb->userdef[1];
-				dev->userdef[2] = ahb->userdef[2];
-				for (j = 0; j < 4; j++) {
-					addr = amba_membar_start(ahb->bars[j]);
-					if (amba_membar_type(ahb->bars[j]) ==
-					    AMBA_TYPE_AHBIO)
-						addr =
-						    AMBA_TYPE_AHBIO_ADDR(addr);
-					dev->address[j] = addr;
-				}
-				dev++;
-			}
-			/* found max devices? */
-			if (cnt >= max_cnt)
-				return cnt;
-		}
-		/* Get next Plug&Play entry */
-		ahb++;
-	}
-	return cnt;
+	return freq;
 }
 
-unsigned int ambapp_ahb_get_info(ahbctrl_pp_dev * ahb, int info)
+/* AHB2AHB and L2CACHE ver 2 is not supported yet. */
+unsigned int gaisler_ahb2ahb_v2_freq(ambapp_ahbdev *ahb, unsigned int freq)
 {
-	register unsigned int ret;
+	panic("gaisler_ahb2ahb_v2_freq: AHB2AHB ver 2 not supported\n");
+	return -1;
+}
+#endif
 
-	if (!ahb)
-		return 0;
+/* Return the frequency of a AHB bus identified by index found
+ * note that this is not the AHB Bus number.
+ */
+unsigned int ambapp_bus_freq(struct ambapp_bus *abus, int ahb_bus_index)
+{
+	unsigned int freq = abus->freq;
+#ifndef CONFIG_SYS_GRLIB_SINGLE_BUS
+	unsigned int ioarea, ioarea_parent, bridge_pnp_ofs;
+	struct ambapp_find_ahb_info ahbinfo;
+	ambapp_ahbdev ahb;
+	int parent;
 
-	switch (info) {
-	default:
-		info = 0;
-	case 0:
-	case 1:
-	case 2:
-	case 3:
-		/* Get Address from PnP Info */
-		ret = amba_membar_start(ahb->bars[info]);
-		if (amba_membar_type(ahb->bars[info]) == AMBA_TYPE_AHBIO)
-			ret = AMBA_TYPE_AHBIO_ADDR(ret);
-		return ret;
-	}
-	return 0;
+	debug("ambapp_bus_freq: get freq on bus %d\n", ahb_bus_index);
 
-}
+	while (ahb_bus_index != 0) {
+		debug("  BUS[0]: 0x%08x\n", abus->ioareas[0]);
+		debug("  BUS[1]: 0x%08x\n", abus->ioareas[1]);
+		debug("  BUS[2]: 0x%08x\n", abus->ioareas[2]);
+		debug("  BUS[3]: 0x%08x\n", abus->ioareas[3]);
+		debug("  BUS[4]: 0x%08x\n", abus->ioareas[4]);
+		debug("  BUS[5]: 0x%08x\n", abus->ioareas[5]);
 
-ahbctrl_pp_dev *ambapp_ahb_next_nomem(register unsigned int vendor,	/* Plug&Play Vendor ID */
-				      register unsigned int driver,	/* Plug&Play Device ID */
-				      register unsigned int opts,	/* 1=slave, 0=master */
-				      register int index)
-{
-	register ahbctrl_pp_dev *ahb;
-	register ahbctrl_info *info =
-	    (ahbctrl_info *) (LEON3_IO_AREA | LEON3_CONF_AREA);
-	register int i;
-	register int max_pp_devs;
+		/* Get I/O area of AHB bus */
+		ioarea = abus->ioareas[ahb_bus_index];
 
-	if (opts == 0) {
-		max_pp_devs = LEON3_AHB_MASTERS;
-		ahb = info->masters;
-	} else {
-		max_pp_devs = LEON3_AHB_SLAVES;
-		ahb = info->slaves;
-	}
+		printf("  IOAREA: 0x%08x\n", ioarea);
 
-	for (i = 0; i < max_pp_devs; i++) {
-		if ((amba_vendor(ahb->conf) == vendor) &&
-		    (amba_device(ahb->conf) == driver) &&
-		    ((index < 0) || (index-- == 0))) {
-			/* Convert Plug&Play info info a more readable format */
-			return ahb;
+		/* Get parent bus */
+		parent = (ioarea & 0x7);
+		if (parent == 0) {
+			panic("%s: parent=0 indicates no parent! Stopping.\n",
+				__func__);
+			return -1;
 		}
-		/* Get next Plug&Play entry */
-		ahb++;
-	}
-	return 0;
-}
+		parent = parent - 1;
+		bridge_pnp_ofs = ioarea & 0x7e0;
 
-/****************************** AHB MASTERS ******************************/
-int ambapp_ahbmst_count(unsigned int vendor, unsigned int driver)
-{
-	/* Get number of devices of this vendor&device ID */
-	return ambapp_ahb_scan(vendor, driver, NULL, 0, LEON3_AHB_MASTERS,
-			       AHB_SCAN_MASTER);
-}
+		debug("  PARENT: %d\n", parent);
+		debug("  BRIDGE_OFS: 0x%08x\n", bridge_pnp_ofs);
 
-int ambapp_ahbmst_first(unsigned int vendor, unsigned int driver,
-			ambapp_ahbdev * dev)
-{
-	/* find first device of this */
-	return ambapp_ahb_scan(vendor, driver, dev, 0, 1, AHB_SCAN_MASTER);
-}
+		/* Get AHB/AHB bridge PnP address */
+		ioarea_parent = (abus->ioareas[parent] & 0xfff00000) |
+				AMBA_CONF_AREA | AMBA_AHB_SLAVE_CONF_AREA;
+		ahbinfo.pnp = (struct ambapp_pnp_ahb *)
+				(ioarea_parent | bridge_pnp_ofs);
 
-int ambapp_ahbmst_next(unsigned int vendor,
-		       unsigned int driver, ambapp_ahbdev * dev, int index)
-{
-	/* find first device of this */
-	return ambapp_ahb_scan(vendor, driver, dev, index, 1, AHB_SCAN_MASTER);
-}
+		debug("  IOAREA PARENT: 0x%08x\n", ioarea_parent);
+		debug("  BRIDGE PNP: 0x%p\n", ahbinfo.pnp);
 
-int ambapp_ahbmsts_first(unsigned int vendor,
-			 unsigned int driver, ambapp_ahbdev * dev, int max_cnt)
-{
-	/* find first device of this */
-	return ambapp_ahb_scan(vendor, driver, dev, 0, max_cnt,
-			       AHB_SCAN_MASTER);
-}
+		/* Parse the AHB information */
+		ahbinfo.ahb_bus_index = parent;
+		ambapp_ahb_parse(&ahbinfo, &ahb);
 
-/****************************** AHB SLAVES ******************************/
-int ambapp_ahbslv_count(unsigned int vendor, unsigned int driver)
-{
-	/* Get number of devices of this vendor&device ID */
-	return ambapp_ahb_scan(vendor, driver, NULL, 0, LEON3_AHB_SLAVES,
-			       AHB_SCAN_SLAVE);
-}
+		debug("  BRIDGE ID: VENDOR=%d(0x%x), DEVICE=%d(0x%x)\n",
+			ahb.vendor, ahb.vendor, ahb.device, ahb.device);
 
-int ambapp_ahbslv_first(unsigned int vendor, unsigned int driver,
-			ambapp_ahbdev * dev)
-{
-	/* find first device of this */
-	return ambapp_ahb_scan(vendor, driver, dev, 0, 1, AHB_SCAN_SLAVE);
-}
+		/* Different bridges may convert frequency differently */
+		if ((ahb.vendor == VENDOR_GAISLER) &&
+			((ahb.device == GAISLER_AHB2AHB) ||
+			(ahb.device == GAISLER_L2CACHE))) {
+			/* Get new frequency */
+			if (ahb.ver > 1)
+				freq = gaisler_ahb2ahb_v2_freq(&ahb, freq);
+			else
+				freq = gaisler_ahb2ahb_v1_freq(&ahb, freq);
 
-int ambapp_ahbslv_next(unsigned int vendor,
-		       unsigned int driver, ambapp_ahbdev * dev, int index)
-{
-	/* find first device of this */
-	return ambapp_ahb_scan(vendor, driver, dev, index, 1, AHB_SCAN_SLAVE);
-}
+			debug("  NEW FREQ: %dHz\n", freq);
+		} else {
+			panic("%s: unsupported AMBA bridge\n", __func__);
+			return -1;
+		}
 
-int ambapp_ahbslvs_first(unsigned int vendor,
-			 unsigned int driver, ambapp_ahbdev * dev, int max_cnt)
-{
-	/* find first device of this */
-	return ambapp_ahb_scan(vendor, driver, dev, 0, max_cnt, AHB_SCAN_SLAVE);
+		/* Step upwards towards system top bus */
+		ahb_bus_index = parent;
+	}
+#endif
+
+	debug("ambapp_bus_freq: %dHz\n", freq);
+
+	return freq;
 }