Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / u-boot / arch / sparc / cpu / leon3 / ambapp.c
diff --git a/qemu/roms/u-boot/arch/sparc/cpu/leon3/ambapp.c b/qemu/roms/u-boot/arch/sparc/cpu/leon3/ambapp.c
new file mode 100644 (file)
index 0000000..a30d1f2
--- /dev/null
@@ -0,0 +1,343 @@
+/* Gaisler AMBA Plug&Play bus scanning. Functions
+ * ending on _nomem is inteded to be used only during
+ * initialization, only registers are used (no ram).
+ *
+ * (C) Copyright 2007
+ * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <command.h>
+#include <ambapp.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
+
+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.
+                                        */
+    )
+{
+       int i, cnt = 0;
+       unsigned int apbmst_base;
+       ambapp_ahbdev apbmst;
+       apbctrl_pp_dev *apb;
+
+       if (max_cnt == 0)
+               return 0;
+
+       /* Get AMBA APB Master */
+       if (ambapp_ahbslv_first(VENDOR_GAISLER, GAISLER_APBMST, &apbmst) != 1) {
+               return 0;
+       }
+
+       /* Get APB CTRL Plug&Play info area */
+       apbmst_base = apbmst.address[0] & LEON3_IO_AREA;
+       apb = (apbctrl_pp_dev *) (apbmst_base | LEON3_CONF_AREA);
+
+       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;
+               }
+               /* Get next Plug&Play entry */
+               apb++;
+       }
+       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)
+{
+       register int i;
+       register ahbctrl_pp_dev *apbmst;
+       register apbctrl_pp_dev *apb;
+       register unsigned int apbmst_base;
+
+       /* APBMST is a AHB Slave */
+       apbmst = ambapp_ahb_next_nomem(VENDOR_GAISLER, GAISLER_APBMST, 1, 0);
+       if (!apbmst)
+               return 0;
+
+       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;
+
+       /* Find the vendor/driver device on the first APB bus */
+       apb = (apbctrl_pp_dev *) (apbmst_base | LEON3_CONF_AREA);
+
+       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;
+}
+
+/****************************** APB SLAVES ******************************/
+
+int ambapp_apb_count(unsigned int vendor, unsigned int driver)
+{
+       return ambapp_apb_scan(vendor, driver, NULL, 0, LEON3_APB_SLAVES);
+}
+
+int ambapp_apb_first(unsigned int vendor,
+                    unsigned int driver, ambapp_apbdev * dev)
+{
+       return ambapp_apb_scan(vendor, driver, dev, 0, 1);
+}
+
+int ambapp_apb_next(unsigned int vendor,
+                   unsigned int driver, ambapp_apbdev * dev, int index)
+{
+       return ambapp_apb_scan(vendor, driver, dev, index, 1);
+}
+
+int ambapp_apbs_first(unsigned int vendor,
+                     unsigned int driver, ambapp_apbdev * dev, int max_cnt)
+{
+       return ambapp_apb_scan(vendor, driver, dev, 0, max_cnt);
+}
+
+enum {
+       AHB_SCAN_MASTER = 0,
+       AHB_SCAN_SLAVE = 1
+};
+
+/* 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.
+ *
+ * Compact edition...
+ */
+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
+                                        */
+    )
+{
+       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;
+
+       if (max_cnt == 0)
+               return 0;
+
+       if (type == 0) {
+               max_pp_devs = LEON3_AHB_MASTERS;
+               ahb = info->masters;
+       } else {
+               max_pp_devs = LEON3_AHB_SLAVES;
+               ahb = info->slaves;
+       }
+
+       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;
+}
+
+unsigned int ambapp_ahb_get_info(ahbctrl_pp_dev * ahb, int info)
+{
+       register unsigned int ret;
+
+       if (!ahb)
+               return 0;
+
+       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;
+
+}
+
+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;
+
+       if (opts == 0) {
+               max_pp_devs = LEON3_AHB_MASTERS;
+               ahb = info->masters;
+       } else {
+               max_pp_devs = LEON3_AHB_SLAVES;
+               ahb = info->slaves;
+       }
+
+       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 next Plug&Play entry */
+               ahb++;
+       }
+       return 0;
+}
+
+/****************************** 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);
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+/****************************** 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);
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}