[PATCH 015/111] LEON2: implemented AMBA Bus Driver for Driver Manager

Daniel Hellstrom daniel at gaisler.com
Thu Feb 26 16:38:17 UTC 2015


---
 c/src/lib/libbsp/sparc/Makefile.am                 |    2 +
 c/src/lib/libbsp/sparc/leon2/Makefile.am           |    7 +
 c/src/lib/libbsp/sparc/leon2/include/bsp.h         |    7 +
 c/src/lib/libbsp/sparc/leon2/preinstall.am         |   13 +
 .../lib/libbsp/sparc/leon2/startup/bsppredriver.c  |   70 +++
 .../libbsp/sparc/shared/drvmgr/leon2_amba_bus.c    |  459 ++++++++++++++++++++
 .../sparc/shared/include/drvmgr/leon2_amba_bus.h   |   95 ++++
 7 files changed, 653 insertions(+), 0 deletions(-)
 create mode 100644 c/src/lib/libbsp/sparc/shared/drvmgr/leon2_amba_bus.c
 create mode 100644 c/src/lib/libbsp/sparc/shared/include/drvmgr/leon2_amba_bus.h

diff --git a/c/src/lib/libbsp/sparc/Makefile.am b/c/src/lib/libbsp/sparc/Makefile.am
index eb20f37..59a212c 100644
--- a/c/src/lib/libbsp/sparc/Makefile.am
+++ b/c/src/lib/libbsp/sparc/Makefile.am
@@ -76,9 +76,11 @@ EXTRA_DIST += shared/include/i2cmst.h
 # Driver Manager
 EXTRA_DIST += shared/drvmgr/ambapp_bus.c
 EXTRA_DIST += shared/drvmgr/ambapp_bus_grlib.c
+EXTRA_DIST += shared/drvmgr/leon2_amba_bus.c
 
 EXTRA_DIST += shared/include/drvmgr/ambapp_bus_grlib.h
 EXTRA_DIST += shared/include/drvmgr/ambapp_bus.h
+EXTRA_DIST += shared/include/drvmgr/leon2_amba_bus.h
 
 include $(top_srcdir)/../../../automake/subdirs.am
 include $(top_srcdir)/../../../automake/local.am
diff --git a/c/src/lib/libbsp/sparc/leon2/Makefile.am b/c/src/lib/libbsp/sparc/leon2/Makefile.am
index efcb286..bb30517 100644
--- a/c/src/lib/libbsp/sparc/leon2/Makefile.am
+++ b/c/src/lib/libbsp/sparc/leon2/Makefile.am
@@ -131,6 +131,13 @@ libbsp_a_SOURCES += ../../sparc/shared/i2c/i2cmst.c
 # timer
 libbsp_a_SOURCES += timer/timer.c
 
+# Driver Manager
+include_drvmgrdir = $(includedir)/drvmgr
+include_drvmgr_HEADERS = ../../sparc/shared/include/drvmgr/ambapp_bus.h
+include_drvmgr_HEADERS += ../../sparc/shared/include/drvmgr/leon2_amba_bus.h
+libbsp_a_SOURCES += ../../sparc/shared/drvmgr/ambapp_bus.c
+libbsp_a_SOURCES += ../../sparc/shared/drvmgr/leon2_amba_bus.c
+
 if HAS_SMP
 libbsp_a_SOURCES += ../../shared/bspsmp.c
 libbsp_a_SOURCES += ../../shared/bspsmpgetcurrentprocessor.c
diff --git a/c/src/lib/libbsp/sparc/leon2/include/bsp.h b/c/src/lib/libbsp/sparc/leon2/include/bsp.h
index 48c4b68..dce8bea 100644
--- a/c/src/lib/libbsp/sparc/leon2/include/bsp.h
+++ b/c/src/lib/libbsp/sparc/leon2/include/bsp.h
@@ -220,6 +220,13 @@ int cchip1_register(void);
 /* AT697 has PCI defined as big endian */
 #define BSP_PCI_BIG_ENDIAN
 
+/* Common driver build-time configurations. On small systems undefine
+ * [DRIVER]_INFO_AVAIL to avoid info routines get dragged in. It is good
+ * for debugging and printing information about the system, but makes the
+ * image bigger.
+ */
+#define AMBAPPBUS_INFO_AVAIL          /* AMBAPP Bus driver */
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/c/src/lib/libbsp/sparc/leon2/preinstall.am b/c/src/lib/libbsp/sparc/leon2/preinstall.am
index a3bcae5..7260f63 100644
--- a/c/src/lib/libbsp/sparc/leon2/preinstall.am
+++ b/c/src/lib/libbsp/sparc/leon2/preinstall.am
@@ -173,3 +173,16 @@ $(PROJECT_INCLUDE)/i2cmst.h: ../../sparc/shared/include/i2cmst.h $(PROJECT_INCLU
 	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/i2cmst.h
 PREINSTALL_FILES += $(PROJECT_INCLUDE)/i2cmst.h
 
+$(PROJECT_INCLUDE)/drvmgr/$(dirstamp):
+	@$(MKDIR_P) $(PROJECT_INCLUDE)/drvmgr
+	@: > $(PROJECT_INCLUDE)/drvmgr/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/drvmgr/$(dirstamp)
+
+$(PROJECT_INCLUDE)/drvmgr/ambapp_bus.h: ../../sparc/shared/include/drvmgr/ambapp_bus.h $(PROJECT_INCLUDE)/drvmgr/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/drvmgr/ambapp_bus.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/drvmgr/ambapp_bus.h
+
+$(PROJECT_INCLUDE)/drvmgr/leon2_amba_bus.h: ../../sparc/shared/include/drvmgr/leon2_amba_bus.h $(PROJECT_INCLUDE)/drvmgr/$(dirstamp)
+	$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/drvmgr/leon2_amba_bus.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/drvmgr/leon2_amba_bus.h
+
diff --git a/c/src/lib/libbsp/sparc/leon2/startup/bsppredriver.c b/c/src/lib/libbsp/sparc/leon2/startup/bsppredriver.c
index 58493df..260c57f 100644
--- a/c/src/lib/libbsp/sparc/leon2/startup/bsppredriver.c
+++ b/c/src/lib/libbsp/sparc/leon2/startup/bsppredriver.c
@@ -17,10 +17,80 @@
 #include <bsp.h>
 #include <bsp/bootcard.h>
 
+/* If RTEMS_DRVMGR_STARTUP is defined extra code is added that
+ * registers the LEON2 AMBA bus driver as root driver into the
+ * driver manager.
+ *
+ * The structues here are declared weak so that the user can override
+ * the configuration and add custom cores in the RTEMS project.
+ */
+#ifdef RTEMS_DRVMGR_STARTUP
+#include <drvmgr/leon2_amba_bus.h>
+
+/* All drivers included by BSP, this is overridden by the user by including
+ * the devmgr_confdefs.h. No specifc drivers needed by BSP since IRQ/TIMER/UART
+ * is not drvmgr drivers.
+ */
+struct drvmgr_drv_reg_func drvmgr_drivers[] __attribute__((weak)) =
+{
+  {NULL} /* End array with NULL */
+};
+
+/* Defines what cores are avilable on the bus in addition to the standard
+ * LEON2 peripherals.
+ */
+struct leon2_core leon2_amba_custom_cores[] __attribute__((weak)) =
+{
+  EMPTY_LEON2_CORE
+};
+
+/* Configure LEON2 Root bus driver */
+struct leon2_bus leon2_bus_config __attribute__((weak)) =
+{
+  &leon2_std_cores[0], /* The standard cores, defined by driver */
+  &leon2_amba_custom_cores[0],   /* custom cores, defined by us */
+  DRVMGR_TRANSLATE_ONE2ONE,
+  DRVMGR_TRANSLATE_ONE2ONE,
+};
+
+/* Driver resources on LEON2 AMBA bus. Used to set options for particular
+ * LEON2 cores, it is up to the driver to look at the configuration paramters
+ * once started.
+ */
+struct drvmgr_bus_res leon2_amba_res __attribute__((weak)) =
+{
+  .next = NULL,
+  .resource = {
+    RES_EMPTY
+  },
+};
+
+/*
+ *  bsp_driver_level_hook
+ *
+ *  BSP driver level hook. Called just after drivers have reached initialization
+ *  level 'level' (1,2,3,4). See exinit.c for meaning of the every level.
+ */
+void bsp_driver_level_hook( int level )
+{
+}
+
+#endif
+
+/*
+ *  bsp_predriver_hook
+ *
+ *  BSP predriver hook. Called just before drivers are initialized.
+ *  Is used to initialize shared interrupt handling.
+ */
 void bsp_predriver_hook( void )
 {
   /* Initialize shared interrupt handling, must be done after IRQ
    * controller has been found and initialized.
    */
   BSP_shared_interrupt_init();
+
+#ifdef RTEMS_DRVMGR_STARTUP
+  leon2_root_register(&leon2_bus_config, &leon2_amba_res);
+#endif
 }
diff --git a/c/src/lib/libbsp/sparc/shared/drvmgr/leon2_amba_bus.c b/c/src/lib/libbsp/sparc/shared/drvmgr/leon2_amba_bus.c
new file mode 100644
index 0000000..f4ff89f
--- /dev/null
+++ b/c/src/lib/libbsp/sparc/shared/drvmgr/leon2_amba_bus.c
@@ -0,0 +1,459 @@
+/*  LEON2 Hardcoded bus driver.
+ *
+ *  COPYRIGHT (c) 2008.
+ *  Cobham Gaisler AB.
+ *
+ *  Bus driver for a hardcoded setup. LEON2 systems have some
+ *  cores always present, here called "Standard Cores". In 
+ *  addtion to the standard cores there are often extra cores
+ *  that can be defined using the "Custom Cores" mechanism.
+ *
+ *  A Core is described by assigning a base register and 
+ *  IRQ0..IRQ15 using the leon2_core structure.
+ *
+ *  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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <drvmgr/drvmgr.h>
+#include <drvmgr/leon2_amba_bus.h>
+
+#include <bsp.h>
+
+#define DBG(args...)
+/*#define DBG(args...) printk(args)*/
+
+struct drvmgr_drv leon2_bus_drv;
+
+int leon2_amba_bus_init1(struct drvmgr_bus *bus);
+int leon2_amba_unite(struct drvmgr_drv *drv, struct drvmgr_dev *dev);
+int leon2_amba_int_register(
+	struct drvmgr_dev *dev,
+	int index,
+	const char *info,
+	drvmgr_isr isr,
+	void *arg);
+int leon2_amba_int_unregister(
+	struct drvmgr_dev *dev,
+	int index,
+	drvmgr_isr isr,
+	void *arg);
+int leon2_amba_int_clear(
+	struct drvmgr_dev *dev,
+	int index);
+int leon2_amba_int_mask(
+	struct drvmgr_dev *dev,
+	int index);
+int leon2_amba_int_unmask(
+	struct drvmgr_dev *dev,
+	int index);
+
+/* LEON2 bus operations */
+struct drvmgr_bus_ops leon2_amba_bus_ops =
+{
+	.init = {
+		leon2_amba_bus_init1,
+		NULL,
+		NULL,
+		NULL
+	},
+	.remove = NULL,
+	.unite		= leon2_amba_unite,
+	.int_register	= leon2_amba_int_register,
+	.int_unregister	= leon2_amba_int_unregister,
+	.int_clear	= leon2_amba_int_clear,
+	.int_mask	= leon2_amba_int_mask,
+	.int_unmask	= leon2_amba_int_unmask,
+	.get_params	= NULL,
+};
+
+struct leon2_isr_handler {
+	void (*handler)(int irq, void *arg);
+	void *arg;
+};
+
+/* Interrupt handlers */
+struct leon2_isr_handler leon2_isrs[16];
+
+/* Standard LEON2 configuration */
+
+struct drvmgr_key leon2_timers[] =
+{
+	{"REG0", KEY_TYPE_INT, {0x80000040}},
+	{"IRQ0", KEY_TYPE_INT, {8}},
+	{"IRQ1", KEY_TYPE_INT, {9}},
+	KEY_EMPTY
+};
+
+struct drvmgr_key leon2_uart1[] =
+{
+	{"REG0", KEY_TYPE_INT, {0x80000070}},
+	{"IRQ0", KEY_TYPE_INT, {3}},
+	KEY_EMPTY
+};
+
+struct drvmgr_key leon2_uart2[] =
+{
+	{"REG0", KEY_TYPE_INT, {0x80000080}},
+	{"IRQ0", KEY_TYPE_INT, {2}},
+	KEY_EMPTY
+};
+
+struct drvmgr_key leon2_irqctrl[] =
+{
+	{"REG0", KEY_TYPE_INT, {0x80000090}},
+	KEY_EMPTY
+};
+
+struct drvmgr_key leon2_gpio0[] =
+{
+	{"REG0", KEY_TYPE_INT, {0x800000A0}},
+	{"IRQ0", KEY_TYPE_INT, {4}},
+	{"IRQ1", KEY_TYPE_INT, {5}},
+	{"IRQ2", KEY_TYPE_INT, {6}},
+	{"IRQ3", KEY_TYPE_INT, {7}},
+	KEY_EMPTY
+};
+
+struct leon2_core leon2_std_cores[] = 
+{
+	{{LEON2_AMBA_TIMER_ID}, "Timers", &leon2_timers[0]},
+	{{LEON2_AMBA_UART_ID}, "Uart1", &leon2_uart1[0]},
+	{{LEON2_AMBA_UART_ID}, "Uart2", &leon2_uart2[0]},
+	{{LEON2_AMBA_IRQCTRL_ID}, "IRQCtrl", &leon2_irqctrl[0]},
+	{{LEON2_AMBA_GPIO_ID}, "GPIO", &leon2_gpio0[0]},
+	EMPTY_LEON2_CORE
+};
+
+static struct leon2_bus *leon2_bus_config = NULL;
+static struct drvmgr_bus_res *leon2_bus_res = NULL;
+
+int leon2_root_register(struct leon2_bus *bus_config, struct drvmgr_bus_res *resources)
+{
+	/* Save the configuration for later */
+	leon2_bus_config = bus_config;
+	leon2_bus_res = resources;
+
+	/* Register root device driver */
+	drvmgr_root_drv_register(&leon2_bus_drv);
+
+	return 0;
+}
+
+int leon2_amba_dev_register(struct drvmgr_bus *bus, struct leon2_core *core, int index)
+{
+	struct drvmgr_dev *newdev;
+	struct leon2_amba_dev_info *info;
+	union drvmgr_key_value *value;
+	char irq_name[8];
+	int i;
+
+	/* Allocate new device and businfo */
+	drvmgr_alloc_dev(&newdev, sizeof(struct leon2_amba_dev_info));
+	info = (struct leon2_amba_dev_info *)(newdev + 1);
+
+	/* Set Core ID */
+	info->core_id = core->id.core_id;
+
+	/* Get information from bus configuration */
+	value = drvmgr_key_val_get(core->keys, "REG0", KEY_TYPE_INT);
+	if ( !value ) {
+		printk("leon2_amba_dev_register: Failed getting resource REG0\n");
+		info->reg_base = 0x00000000;
+	} else {
+		DBG("leon2_amba_dev_register: REG0: 0x%08x\n", value->i);
+		info->reg_base = value->i;
+	}
+
+	strcpy(irq_name, "IRQ");
+	for(i=0; i<16; i++){
+		if ( i < 10 ){
+			irq_name[3] = '0' + i;
+			irq_name[4] = '\0';
+		} else {
+			irq_name[3] = '1';
+			irq_name[4] = '0' + (i-10);
+			irq_name[5] = '\0';
+		}
+
+		value = drvmgr_key_val_get(core->keys, irq_name, KEY_TYPE_INT);
+		if ( !value ) {
+			DBG("leon2_amba_dev_register: Failed getting resource IRQ%d for REG 0x%x\n", i, info->reg_base);
+			info->irqs[i] = 0;
+		} else {
+			DBG("leon2_amba_dev_register: IRQ%d: %d\n", i, value->i);
+			info->irqs[i] = value->i;
+		}
+	}
+
+	/* Init new device */
+	newdev->next = NULL;
+	newdev->parent = bus; /* Ourselfs */
+	newdev->minor_drv = 0;
+	newdev->minor_bus = 0;
+	newdev->businfo = (void *)info;
+	newdev->priv = NULL;
+	newdev->drv = NULL;
+	newdev->name = core->name;
+	newdev->next_in_drv = NULL;
+	newdev->bus = NULL;
+
+	/* Register new device */
+	drvmgr_dev_register(newdev);
+
+	return 0;
+}
+
+int leon2_amba_init1(struct drvmgr_dev *dev)
+{
+	/* Init our own device */
+	dev->priv = NULL;
+	dev->name = "LEON2 AMBA";
+
+	memset(leon2_isrs, 0, sizeof(leon2_isrs));
+
+	/* Init the bus */
+	drvmgr_alloc_bus(&dev->bus, 0);
+	dev->bus->bus_type = DRVMGR_BUS_TYPE_LEON2_AMBA;
+	dev->bus->next = NULL;
+	dev->bus->dev = dev;
+	dev->bus->priv = NULL;
+	dev->bus->children = NULL;
+	dev->bus->ops = &leon2_amba_bus_ops;
+	dev->bus->dev_cnt = 0;
+	dev->bus->reslist = NULL;
+	dev->bus->maps_up = leon2_bus_config->maps_up;
+	dev->bus->maps_down = leon2_bus_config->maps_down;
+	drvmgr_bus_register(dev->bus);
+
+	return DRVMGR_OK;
+}
+
+int leon2_amba_init2(struct drvmgr_dev *dev)
+{
+	return DRVMGR_OK;
+}
+
+int leon2_amba_remove(struct drvmgr_dev *dev)
+{
+	return DRVMGR_OK;
+}
+
+int leon2_amba_bus_init1(struct drvmgr_bus *bus)
+{
+	struct leon2_core *core;
+	int i;
+
+	if ( leon2_bus_res )
+		drvmgr_bus_res_add(bus, leon2_bus_res);
+
+	/**** REGISTER NEW DEVICES ****/
+	i=0;
+	core = leon2_bus_config->std_cores;
+	if ( core ) {
+		while ( core->id.core_id ) {
+			if ( leon2_amba_dev_register(bus, core, i) ) {
+				return RTEMS_UNSATISFIED;
+			}
+			i++;
+			core++;
+		}
+	}
+	core = leon2_bus_config->custom_cores;
+	if ( core ) {
+		while ( core->id.core_id ) {
+			if ( leon2_amba_dev_register(bus, core, i) ) {
+				return RTEMS_UNSATISFIED;
+			}
+			i++;
+			core++;
+		}
+	}
+
+	return 0;
+}
+
+int leon2_amba_unite(struct drvmgr_drv *drv, struct drvmgr_dev *dev)
+{
+	struct leon2_amba_dev_info *info;
+	struct leon2_amba_drv_info *adrv;
+	struct leon2_amba_dev_id *id;
+
+	if ( !drv || !dev || !dev->parent )
+		return 0;
+
+	if ( (drv->bus_type!=DRVMGR_BUS_TYPE_LEON2_AMBA) || (dev->parent->bus_type != DRVMGR_BUS_TYPE_LEON2_AMBA) ) {
+		return 0;
+	}
+
+	info = (struct leon2_amba_dev_info *)dev->businfo;
+	if ( !info ) 
+		return 0;
+
+	/* Get LEON2 AMBA driver info */
+	adrv = (struct leon2_amba_drv_info *)drv;
+	id = adrv->ids;
+	if ( !id )
+		return 0;
+
+	while ( id->core_id ) {
+		if ( id->core_id == info->core_id ) {
+			/* Driver is suitable for device, Unite them */
+			return 1;
+		}
+		id++;
+	}
+
+	return 0;
+}
+
+rtems_isr leon2_amba_isr(rtems_vector_number v)
+{
+	int irq = v - 0x10; /* Convert Vector number to Interrupt number */
+	struct leon2_isr_handler *isr;
+	
+	isr = &leon2_isrs[irq];
+	if ( isr->handler ) {
+		isr->handler(irq, isr->arg);
+	}
+}
+
+int leon2_amba_get_irq(struct drvmgr_dev *dev, int index)
+{
+	int irq;
+	struct leon2_amba_dev_info *info;
+
+	if ( !dev || (index > 15) )
+		return -1;
+
+	/* Relative (positive) or absolute (negative) IRQ number */
+	if ( index >= 0 ) {
+		/* IRQ Index relative to Cores base IRQ */
+
+		/* Get IRQ array configured by user */
+		info = (struct leon2_amba_dev_info *)dev->businfo;
+		irq = info->irqs[index];
+		if ( irq == 0 )
+			return -1;
+	} else {
+		/* Absolute IRQ number */
+		irq = -index;
+	}
+	return irq;
+}
+
+int leon2_amba_int_register
+	(
+	struct drvmgr_dev *dev,
+	int index,
+	const char *info,
+	drvmgr_isr isr,
+	void *arg
+	)
+{
+	int irq;
+
+	irq = leon2_amba_get_irq(dev, index);
+	if ( irq < 0 )
+		return -1;
+
+	DBG("Registering IRQ %d to func 0x%x arg 0x%x\n", irq, (unsigned int)isr, (unsigned int)arg);
+
+	return BSP_shared_interrupt_register(irq, info, isr, arg);
+}
+
+int leon2_amba_int_unregister
+	(
+	struct drvmgr_dev *dev,
+	int index,
+	drvmgr_isr isr,
+	void *arg
+	)
+{
+	int irq;
+
+	irq = leon2_amba_get_irq(dev, index);
+	if ( irq < 0 )
+		return -1;
+
+	DBG("Unregistering IRQ %d to func 0x%x arg 0x%x\n", irq, (unsigned int)handler, (unsigned int)arg);
+
+	return BSP_shared_interrupt_unregister(irq, isr, arg);
+}
+
+int leon2_amba_int_clear
+	(
+	struct drvmgr_dev *dev,
+	int index
+	)
+{
+	int irq;
+
+	irq = leon2_amba_get_irq(dev, index);
+	if ( irq < 0 )
+		return -1;
+
+	BSP_shared_interrupt_clear(irq);
+
+	return DRVMGR_OK;
+}
+
+int leon2_amba_int_mask
+	(
+	struct drvmgr_dev *dev,
+	int index
+	)
+{
+	int irq;
+
+	irq = leon2_amba_get_irq(dev, index);
+	if ( irq < 0 )
+		return -1;
+
+	BSP_shared_interrupt_mask(irq);
+
+	return DRVMGR_OK;
+}
+
+int leon2_amba_int_unmask
+	(
+	struct drvmgr_dev *dev,
+	int index
+	)
+{
+	int irq;
+
+	irq = leon2_amba_get_irq(dev, index);
+	if ( irq < 0 )
+		return -1;
+
+	BSP_shared_interrupt_unmask(irq);
+
+	return DRVMGR_OK;
+}
+
+struct drvmgr_drv_ops leon2_amba_ops = 
+{
+	.init = {leon2_amba_init1, leon2_amba_init2, NULL, NULL},
+	.remove = leon2_amba_remove,
+	.info = NULL
+};
+
+struct drvmgr_drv leon2_bus_drv =
+{
+	DRVMGR_OBJ_DRV,			/* Driver */
+	NULL,				/* Next driver */
+	NULL,				/* Device list */
+	DRIVER_LEON2_AMBA_ID,		/* Driver ID */
+	"LEON2_AMBA_DRV",		/* Must be placed at top bus */
+	DRVMGR_BUS_TYPE_ROOT,		/* Bus Type */
+	&leon2_amba_ops,		/* Bus Operations */
+	NULL,				/* Funcs */
+	0,				/* Device Count */
+	0,				/* Private structure size */
+};
diff --git a/c/src/lib/libbsp/sparc/shared/include/drvmgr/leon2_amba_bus.h b/c/src/lib/libbsp/sparc/shared/include/drvmgr/leon2_amba_bus.h
new file mode 100644
index 0000000..440e870
--- /dev/null
+++ b/c/src/lib/libbsp/sparc/shared/include/drvmgr/leon2_amba_bus.h
@@ -0,0 +1,95 @@
+/*  LEON2 Hardcoded bus driver interface.
+ *
+ *  COPYRIGHT (c) 2008.
+ *  Cobham Gaisler AB.
+ *
+ *  Bus driver for a hardcoded setup. LEON2 systems have some
+ *  cores always present, here called "Standard Cores". In 
+ *  addtion to the standard cores there are often extra cores
+ *  that can be defined using the "Custom Cores" mechanism.
+ *
+ *  A Core is described by assigning a base register and 
+ *  IRQ0..IRQ15 using the leon2_core structure.
+ *
+ *  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.
+ */
+
+#ifndef __LEON2_AMBA_BUS_H__
+#define __LEON2_AMBA_BUS_H__
+
+/*** Cores location and IRQs hardcoded ***/
+
+#include <drvmgr/drvmgr.h>
+#include <ambapp.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* LEON2 AMBA Driver ID generation */
+#define DRIVER_LEON2_AMBA(id)	DRIVER_ID(DRVMGR_BUS_TYPE_LEON2_AMBA, id)
+
+/* LEON2 Cores (any unique 48-bit number will do) */
+#define LEON2_AMBA_NONE_ID		0
+#define LEON2_AMBA_TIMER_ID		1
+#define LEON2_AMBA_UART_ID		2
+#define LEON2_AMBA_GPIO_ID		3
+#define LEON2_AMBA_IRQCTRL_ID		4
+
+#define LEON2_AMBA_AT697PCI_ID		100
+#define LEON2_AMBA_AMBAPP_ID		0xfff0
+
+/* LEON2 driver IDs */
+#define DRIVER_LEON2_AMBA_TIMER 	DRIVER_LEON2_AMBA(LEON2_AMBA_TIMER_ID)
+#define DRIVER_LEON2_AMBA_UART		DRIVER_LEON2_AMBA(LEON2_AMBA_UART_ID)
+#define DRIVER_LEON2_AMBA_AT697PCI	DRIVER_LEON2_AMBA(LEON2_AMBA_AT697PCI_ID)
+#define DRIVER_LEON2_AMBA_AMBAPP	DRIVER_LEON2_AMBA(LEON2_AMBA_AMBAPP_ID)
+
+struct leon2_amba_dev_id {
+	unsigned short		core_id;
+};
+
+#define EMPTY_LEON2_CORE {{LEON2_AMBA_NONE_ID}, NULL, NULL}
+struct leon2_core {
+	struct leon2_amba_dev_id	id;	/* Core ID */
+	char				*name;	/* Name of Core */
+	struct drvmgr_key		*keys;	/* Core setup (location, IRQs) */
+};
+
+struct leon2_bus {
+	struct leon2_core		*std_cores;	/* The LEON2 standard cores */
+	struct leon2_core		*custom_cores;	/* Custom cores on the same bus */
+	struct drvmgr_map_entry		*maps_up;	/* Memory map ip-stream */
+	struct drvmgr_map_entry		*maps_down;	/* Memory map down-stream */
+};
+
+extern struct leon2_core leon2_std_cores[];
+
+/* Data structure drivers can access */
+struct leon2_amba_dev_info {
+	unsigned short		core_id;	/* Core ID */
+	unsigned int		reg_base;	/* Register base */
+	char			irqs[16];	/* 16 irqs */
+};
+
+struct leon2_amba_drv_info {
+	struct drvmgr_drv	general;	/* General bus info */
+	/* AMBA specific bus information */
+	struct leon2_amba_dev_id	*ids;		/* Supported hardware */
+};
+
+/* Initialize LEON2 bus with a configuration 
+ *  bus_config   -   What cores, their location and irqs
+ *  resources    -   Driver configuration for the cores specified bus_config
+ */
+int leon2_root_register(
+	struct leon2_bus *bus_config,
+	struct drvmgr_bus_res *resources);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
-- 
1.7.0.4




More information about the devel mailing list