summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/sparc/shared/drvmgr
diff options
context:
space:
mode:
authorDaniel Hellstrom <daniel@gaisler.com>2011-12-20 12:28:32 +0100
committerDaniel Hellstrom <daniel@gaisler.com>2015-04-17 01:10:17 +0200
commit3e3fb0d40b8bdfda8ecce3c07c186d6468fbfb71 (patch)
tree1143a4cfd70b6601ae235b167d21857df15033cc /c/src/lib/libbsp/sparc/shared/drvmgr
parentLEON: replaced old BSP PCI layer with new generic libpci PCI layer (diff)
downloadrtems-3e3fb0d40b8bdfda8ecce3c07c186d6468fbfb71.tar.bz2
LEON2: added support for LEON2-GRLIB systems
In some non-standard designs GRLIB peripherals are used together LEON2. This patch adds a GRLIB amba Plug&Play driver so that AMBA devices can be found from Plug&Play the same way as with the LEON3 BSP. The user is required to add an AMBA-PnP device entry into the LEON2 bus configuration, so that the driver manager unite this driver with the "fake" device and start scanning after AMBA PnP devices.
Diffstat (limited to 'c/src/lib/libbsp/sparc/shared/drvmgr')
-rw-r--r--c/src/lib/libbsp/sparc/shared/drvmgr/ambapp_bus_leon2.c265
1 files changed, 265 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/sparc/shared/drvmgr/ambapp_bus_leon2.c b/c/src/lib/libbsp/sparc/shared/drvmgr/ambapp_bus_leon2.c
new file mode 100644
index 0000000000..12034dca97
--- /dev/null
+++ b/c/src/lib/libbsp/sparc/shared/drvmgr/ambapp_bus_leon2.c
@@ -0,0 +1,265 @@
+/* LEON2 GRLIB AMBA Plug & Play bus driver.
+ *
+ * COPYRIGHT (c) 2008.
+ * Cobham Gaisler AB.
+ *
+ * This is driver is a wrapper for the general AMBA Plug & Play bus
+ * driver. This is a bus driver for LEON2-GRLIB systems providing a
+ * AMBA Plug & Play bus, the parent bus must be a LEON2 hardcoded
+ * Bus. All IRQs must be routed to this bus driver in order for IRQs
+ * to work. The PnP information is used to extract IRQs and base
+ * register addresses.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#include <bsp.h>
+
+#ifdef LEON2
+#include <stdlib.h>
+#include <stdio.h>
+#include <libcpu/access.h>
+#include <drvmgr/drvmgr.h>
+#include <drvmgr/ambapp_bus.h>
+#include <drvmgr/leon2_amba_bus.h>
+
+#define DBG(args...)
+
+int ambapp_leon2_int_register(
+ struct drvmgr_dev *dev,
+ int index,
+ const char *info,
+ drvmgr_isr isr,
+ void *arg);
+int ambapp_leon2_int_unregister(
+ struct drvmgr_dev *dev,
+ int index,
+ drvmgr_isr isr,
+ void *arg);
+int ambapp_leon2_int_clear(
+ struct drvmgr_dev *dev,
+ int index);
+int ambapp_leon2_int_mask(
+ struct drvmgr_dev *dev,
+ int irq);
+int ambapp_leon2_int_unmask(
+ struct drvmgr_dev *dev,
+ int irq);
+int ambapp_leon2_get_params(
+ struct drvmgr_dev *dev,
+ struct drvmgr_bus_params *params);
+
+int ambapp_leon2_init1(struct drvmgr_dev *dev);
+int ambapp_leon2_init2(struct drvmgr_dev *dev);
+int ambapp_leon2_remove(struct drvmgr_dev *dev);
+void ambapp_leon2_register(void);
+
+/* READ/WRITE access to SpaceWire target over RMAP */
+void *ambapp_leon2_rw_arg(struct drvmgr_dev *dev);
+
+struct ambappl2_priv {
+ struct ambapp_bus abus;
+ struct ambapp_config config;
+};
+
+struct ambapp_ops ambapp_leon2_ops = {
+ .int_register = ambapp_leon2_int_register,
+ .int_unregister = ambapp_leon2_int_unregister,
+ .int_clear = ambapp_leon2_int_clear,
+ .int_mask = ambapp_leon2_int_mask,
+ .int_unmask = ambapp_leon2_int_unmask,
+ .get_params = ambapp_leon2_get_params
+};
+
+struct drvmgr_func ambapp_leon2_funcs[] = {
+ DRVMGR_FUNC(AMBAPP_RW_ARG, ambapp_leon2_rw_arg),
+
+ DRVMGR_FUNC(AMBAPP_R8, _ld8),
+ DRVMGR_FUNC(AMBAPP_R16, _ld16),
+ DRVMGR_FUNC(AMBAPP_R32, _ld32),
+ DRVMGR_FUNC(AMBAPP_R64, _ld64),
+
+ DRVMGR_FUNC(AMBAPP_W8, _st8),
+ DRVMGR_FUNC(AMBAPP_W16, _st16),
+ DRVMGR_FUNC(AMBAPP_W32, _st32),
+ DRVMGR_FUNC(AMBAPP_W64, _st64),
+
+ DRVMGR_FUNC(AMBAPP_RMEM, memcpy),
+ DRVMGR_FUNC(AMBAPP_WMEM, memcpy),
+
+ DRVMGR_FUNC_END
+};
+
+struct drvmgr_drv_ops ambapp_ops = {
+ .init = {ambapp_leon2_init1, ambapp_leon2_init2, NULL, NULL},
+ .remove = ambapp_leon2_remove,
+ .info = NULL,
+};
+
+struct leon2_amba_dev_id ambapp_leon2_ids[] = {
+ {LEON2_AMBA_AMBAPP_ID},
+ {0}
+};
+
+struct leon2_amba_drv_info ambapp_bus_drv_leon2 = {
+ {
+ DRVMGR_OBJ_DRV, /* Driver */
+ NULL, /* Next driver */
+ NULL, /* Device list */
+ DRIVER_LEON2_AMBA_AMBAPP, /* Driver ID */
+ "AMBAPP_LEON2_DRV", /* Driver Name */
+ DRVMGR_BUS_TYPE_LEON2_AMBA, /* Bus Type */
+ &ambapp_ops,
+ NULL, /* Funcs */
+ 0,
+ sizeof(struct ambappl2_priv), /* Let DrvMgr allocate priv */
+ },
+ &ambapp_leon2_ids[0]
+};
+
+void ambapp_leon2_register(void)
+{
+ drvmgr_drv_register(&ambapp_bus_drv_leon2.general);
+}
+
+/* Function called from a hard configuration */
+int ambapp_leon2_init1(struct drvmgr_dev *dev)
+{
+ union drvmgr_key_value *value;
+ struct ambappl2_priv *priv = dev->priv;
+ struct leon2_amba_dev_info *devinfo;
+ struct ambapp_config *config;
+ unsigned int ioarea;
+ unsigned int freq_hz;
+ LEON_Register_Map *regs;
+
+ dev->name = "LEON2 AMBA PnP";
+
+ if (!priv)
+ return DRVMGR_NOMEM;
+
+ config = &priv->config;
+ config->abus = &priv->abus;
+ config->ops = &ambapp_leon2_ops;
+ config->maps_up = DRVMGR_TRANSLATE_ONE2ONE;
+ config->maps_down = DRVMGR_TRANSLATE_ONE2ONE;
+ config->funcs = ambapp_leon2_funcs;
+ config->bus_type = DRVMGR_BUS_TYPE_LEON2_AMBA;
+
+ /* Get AMBA PnP Area from REG0 */
+ devinfo = (struct leon2_amba_dev_info *)dev->businfo;
+ ioarea = devinfo->reg_base;
+
+ /* Scan AMBA PnP Bus. ABUS has already been cleared with memset() */
+ ambapp_scan(&priv->abus, ioarea, NULL, NULL);
+
+ /* Try to get Configuration from resource configuration */
+
+ value = drvmgr_dev_key_get(dev, "busFreq", KEY_TYPE_INT);
+ if (value) {
+ /* Set frequency of AMBA bus if specified by user. The frequency
+ * must be for AHB bus which IOAREA matches (AHB bus 0).
+ */
+ freq_hz = value->i;
+ } else {
+ /* Get Bus/LEON2 Frequency from timer prescaler,
+ * the hardcoded address is used to get to timer
+ */
+ regs = (LEON_Register_Map *) 0x80000000;
+ freq_hz = (regs->Scaler_Reload + 1) * 1000 * 1000;
+ }
+ /* Note that this can be overrided by a driver on the AMBA PnP bus.*/
+ ambapp_freq_init(&priv->abus, NULL, freq_hz);
+
+ value = drvmgr_dev_key_get(dev, "drvRes", KEY_TYPE_POINTER);
+ if (!value) {
+ DBG("ambapp_leon2_init1: Failed getting resource drvRes\n");
+ config->resources = NULL;
+ } else {
+ DBG("ambapp_leon2_init1: drvRes: 0x%08x\n", (unsigned int)value->ptr);
+ config->resources = (struct drvmgr_bus_res *)value->ptr;
+ }
+
+ /* Initialize the AMBA Bus */
+ return ambapp_bus_register(dev, config);
+}
+
+int ambapp_leon2_init2(struct drvmgr_dev *dev)
+{
+ return 0;
+}
+
+int ambapp_leon2_remove(struct drvmgr_dev *dev)
+{
+ return 0;
+}
+
+void *ambapp_leon2_rw_arg(struct drvmgr_dev *dev)
+{
+ return dev; /* No argument really needed, by for debug */
+}
+
+int ambapp_leon2_int_register
+ (
+ struct drvmgr_dev *dev,
+ int index,
+ const char *info,
+ drvmgr_isr isr,
+ void *arg
+ )
+{
+ /* Let LEON2 bus handle interrupt requests */
+ return drvmgr_interrupt_register(dev->parent->dev, index, info, isr, arg);
+}
+
+int ambapp_leon2_int_unregister
+ (
+ struct drvmgr_dev *dev,
+ int index,
+ drvmgr_isr isr,
+ void *arg
+ )
+{
+ /* Let LEON2 bus handle interrupt requests */
+ return drvmgr_interrupt_unregister(dev->parent->dev, index, isr, arg);
+}
+
+int ambapp_leon2_int_clear
+ (
+ struct drvmgr_dev *dev,
+ int index
+ )
+{
+ /* Let LEON2 bus handle interrupt requests */
+ return drvmgr_interrupt_clear(dev->parent->dev, index);
+}
+
+int ambapp_leon2_int_mask
+ (
+ struct drvmgr_dev *dev,
+ int index
+ )
+{
+ /* Let LEON2 bus handle interrupt requests */
+ return drvmgr_interrupt_mask(dev->parent->dev, index);
+}
+
+int ambapp_leon2_int_unmask
+ (
+ struct drvmgr_dev *dev,
+ int index
+ )
+{
+ /* Let LEON2 bus handle interrupt requests */
+ return drvmgr_interrupt_unmask(dev->parent->dev, index);
+}
+
+int ambapp_leon2_get_params(struct drvmgr_dev *dev, struct drvmgr_bus_params *params)
+{
+ params->dev_prefix = "";
+ return 0;
+}
+
+#endif