forked from Imagelibrary/rtems
LEON3: implemented AMBA PnP Bus Driver for Driver Manager
This commit is contained in:
@@ -73,5 +73,12 @@ EXTRA_DIST += shared/include/b1553brm_rasta.h
|
||||
EXTRA_DIST += shared/i2c/i2cmst.c
|
||||
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/include/drvmgr/ambapp_bus_grlib.h
|
||||
EXTRA_DIST += shared/include/drvmgr/ambapp_bus.h
|
||||
|
||||
include $(top_srcdir)/../../../automake/subdirs.am
|
||||
include $(top_srcdir)/../../../automake/local.am
|
||||
|
||||
@@ -133,6 +133,13 @@ libbsp_a_SOURCES += ../../../libcpu/shared/src/cache_manager.c
|
||||
libbsp_a_SOURCES += include/cache_.h
|
||||
libbsp_a_CPPFLAGS = -I$(srcdir)/include
|
||||
|
||||
# Driver Manager
|
||||
include_drvmgrdir = $(includedir)/drvmgr
|
||||
include_drvmgr_HEADERS = ../../sparc/shared/include/drvmgr/ambapp_bus_grlib.h
|
||||
include_drvmgr_HEADERS += ../../sparc/shared/include/drvmgr/ambapp_bus.h
|
||||
libbsp_a_SOURCES += ../../sparc/shared/drvmgr/ambapp_bus.c
|
||||
libbsp_a_SOURCES += ../../sparc/shared/drvmgr/ambapp_bus_grlib.c
|
||||
|
||||
if HAS_SMP
|
||||
libbsp_a_SOURCES += startup/bspsmp.c
|
||||
endif
|
||||
|
||||
@@ -249,6 +249,13 @@ extern const unsigned char LEON3_irq_to_cpu[32];
|
||||
#define BSP_PCI_shared_interrupt_mask BSP_shared_interrupt_mask
|
||||
#define BSP_PCI_shared_interrupt_clear BSP_shared_interrupt_clear
|
||||
|
||||
/* 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
|
||||
|
||||
@@ -169,3 +169,15 @@ $(PROJECT_INCLUDE)/watchdog.h: include/watchdog.h $(PROJECT_INCLUDE)/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/watchdog.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/watchdog.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_grlib.h: ../../sparc/shared/include/drvmgr/ambapp_bus_grlib.h $(PROJECT_INCLUDE)/drvmgr/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/drvmgr/ambapp_bus_grlib.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/drvmgr/ambapp_bus_grlib.h
|
||||
|
||||
$(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
|
||||
|
||||
754
c/src/lib/libbsp/sparc/shared/drvmgr/ambapp_bus.c
Normal file
754
c/src/lib/libbsp/sparc/shared/drvmgr/ambapp_bus.c
Normal file
@@ -0,0 +1,754 @@
|
||||
/* General part of a AMBA Plug & Play bus driver.
|
||||
*
|
||||
* COPYRIGHT (c) 2008.
|
||||
* Cobham Gaisler AB.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This is the general part of the different AMBA Plug & Play
|
||||
* drivers. The drivers are wrappers around this driver, making
|
||||
* the code size smaller for systems with multiple AMBA Plug &
|
||||
* Play buses.
|
||||
*
|
||||
* The BSP define APBUART_INFO_AVAIL in order to add the info routine
|
||||
* used for debugging.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <drvmgr/drvmgr.h>
|
||||
#include <drvmgr/ambapp_bus.h>
|
||||
|
||||
#include <bsp.h>
|
||||
#include <ambapp.h>
|
||||
|
||||
/*#define DEBUG 1*/
|
||||
#define DBG(args...)
|
||||
/*#define DBG(args...) printk(args)*/
|
||||
|
||||
struct grlib_gptimer_regs {
|
||||
volatile unsigned int scaler_value; /* common timer registers */
|
||||
volatile unsigned int scaler_reload;
|
||||
volatile unsigned int status;
|
||||
volatile unsigned int notused;
|
||||
};
|
||||
|
||||
/* AMBA IMPLEMENTATION */
|
||||
|
||||
int ambapp_bus_init1(struct drvmgr_bus *bus);
|
||||
int ambapp_bus_remove(struct drvmgr_bus *bus);
|
||||
int ambapp_unite(struct drvmgr_drv *drv, struct drvmgr_dev *dev);
|
||||
int ambapp_int_register(struct drvmgr_dev *dev, int index, const char *info, drvmgr_isr isr, void *arg);
|
||||
int ambapp_int_unregister(struct drvmgr_dev *dev, int index, drvmgr_isr isr, void *arg);
|
||||
int ambapp_int_clear(struct drvmgr_dev *dev, int index);
|
||||
int ambapp_int_mask(struct drvmgr_dev *dev, int index);
|
||||
int ambapp_int_unmask(struct drvmgr_dev *dev, int index);
|
||||
int ambapp_get_params(struct drvmgr_dev *dev, struct drvmgr_bus_params *params);
|
||||
int ambapp_bus_freq_get(
|
||||
struct drvmgr_dev *dev,
|
||||
int options,
|
||||
unsigned int *freq_hz);
|
||||
void ambapp_dev_info(struct drvmgr_dev *, void (*print)(void *p, char *str), void *p);
|
||||
|
||||
struct drvmgr_bus_ops ambapp_bus_ops =
|
||||
{
|
||||
.init =
|
||||
{
|
||||
/* init1 */ ambapp_bus_init1,
|
||||
/* init2 */ NULL,
|
||||
/* init3 */ NULL,
|
||||
/* init4 */ NULL
|
||||
},
|
||||
.remove = ambapp_bus_remove,
|
||||
.unite = ambapp_unite,
|
||||
.int_register = ambapp_int_register,
|
||||
.int_unregister = ambapp_int_unregister,
|
||||
.int_clear = ambapp_int_clear,
|
||||
.int_mask = ambapp_int_mask,
|
||||
.int_unmask = ambapp_int_unmask,
|
||||
.get_params = ambapp_get_params,
|
||||
.freq_get = ambapp_bus_freq_get,
|
||||
#ifdef AMBAPPBUS_INFO_AVAIL
|
||||
.info_dev = ambapp_dev_info,
|
||||
#endif
|
||||
};
|
||||
|
||||
struct ambapp_priv {
|
||||
struct ambapp_config *config;
|
||||
};
|
||||
|
||||
int ambapp_unite(struct drvmgr_drv *drv, struct drvmgr_dev *dev)
|
||||
{
|
||||
struct amba_drv_info *adrv;
|
||||
struct amba_dev_id *id;
|
||||
struct amba_dev_info *amba;
|
||||
|
||||
if ( !drv || !dev || !dev->parent )
|
||||
return 0;
|
||||
|
||||
if ( ! (((drv->bus_type == DRVMGR_BUS_TYPE_AMBAPP) && (dev->parent->bus_type == DRVMGR_BUS_TYPE_AMBAPP)) ||
|
||||
((drv->bus_type == DRVMGR_BUS_TYPE_AMBAPP_RMAP) && (dev->parent->bus_type == DRVMGR_BUS_TYPE_AMBAPP_RMAP)) ||
|
||||
((drv->bus_type == DRVMGR_BUS_TYPE_AMBAPP_DIST) && (dev->parent->bus_type == DRVMGR_BUS_TYPE_AMBAPP_DIST)))
|
||||
) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
amba = (struct amba_dev_info *)dev->businfo;
|
||||
if ( !amba )
|
||||
return 0;
|
||||
|
||||
adrv = (struct amba_drv_info *)drv;
|
||||
id = adrv->ids;
|
||||
if ( !id )
|
||||
return 0;
|
||||
while( id->vendor != 0 ) {
|
||||
if ( (id->vendor == amba->id.vendor) &&
|
||||
(id->device == amba->id.device) ) {
|
||||
/* Unite device and driver */
|
||||
DBG("DRV 0x%x and DEV 0x%x united\n", (unsigned int)drv, (unsigned int)dev);
|
||||
return 1;
|
||||
}
|
||||
id++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ambapp_int_get(struct drvmgr_dev *dev, int index)
|
||||
{
|
||||
int irq;
|
||||
|
||||
/* Relative (positive) or absolute (negative) IRQ number */
|
||||
if ( index >= 0 ) {
|
||||
/* IRQ Index relative to Cores base IRQ */
|
||||
|
||||
/* Get Base IRQ */
|
||||
irq = ((struct amba_dev_info *)dev->businfo)->info.irq;
|
||||
if ( irq < 0 )
|
||||
return -1;
|
||||
irq += index;
|
||||
} else {
|
||||
/* Absolute IRQ number */
|
||||
irq = -index;
|
||||
}
|
||||
return irq;
|
||||
}
|
||||
|
||||
int ambapp_int_register(
|
||||
struct drvmgr_dev *dev,
|
||||
int index,
|
||||
const char *info,
|
||||
drvmgr_isr isr,
|
||||
void *arg)
|
||||
{
|
||||
struct drvmgr_dev *busdev;
|
||||
struct ambapp_priv *priv;
|
||||
int irq;
|
||||
|
||||
busdev = dev->parent->dev;
|
||||
priv = dev->parent->priv;
|
||||
|
||||
/* Get IRQ number from index and device information */
|
||||
irq = ambapp_int_get(dev, index);
|
||||
if ( irq < 0 )
|
||||
return DRVMGR_EINVAL;
|
||||
|
||||
DBG("Register interrupt on 0x%x for dev 0x%x (IRQ: %d)\n", (unsigned int)busdev, (unsigned int)dev, irq);
|
||||
|
||||
if ( priv->config->ops->int_register ) {
|
||||
/* Let device override driver default */
|
||||
return priv->config->ops->int_register(dev, irq, info, isr, arg);
|
||||
} else {
|
||||
return DRVMGR_ENOSYS;
|
||||
}
|
||||
}
|
||||
|
||||
int ambapp_int_unregister(
|
||||
struct drvmgr_dev *dev,
|
||||
int index,
|
||||
drvmgr_isr isr,
|
||||
void *arg)
|
||||
{
|
||||
struct drvmgr_dev *busdev;
|
||||
struct ambapp_priv *priv;
|
||||
int irq;
|
||||
|
||||
busdev = dev->parent->dev;
|
||||
priv = dev->parent->priv;
|
||||
|
||||
/* Get IRQ number from index and device information */
|
||||
irq = ambapp_int_get(dev, index);
|
||||
if ( irq < 0 )
|
||||
return DRVMGR_EINVAL;
|
||||
|
||||
DBG("Unregister interrupt on 0x%x for dev 0x%x (IRQ: %d)\n", (unsigned int)busdev, (unsigned int)dev, irq);
|
||||
|
||||
if ( priv->config->ops->int_unregister ) {
|
||||
/* Let device override driver default */
|
||||
return priv->config->ops->int_unregister(dev, irq, isr, arg);
|
||||
} else {
|
||||
return DRVMGR_ENOSYS;
|
||||
}
|
||||
}
|
||||
|
||||
int ambapp_int_clear(
|
||||
struct drvmgr_dev *dev,
|
||||
int index)
|
||||
{
|
||||
struct drvmgr_dev *busdev;
|
||||
struct ambapp_priv *priv;
|
||||
int irq;
|
||||
|
||||
busdev = dev->parent->dev;
|
||||
priv = dev->parent->priv;
|
||||
|
||||
/* Get IRQ number from index and device information */
|
||||
irq = ambapp_int_get(dev, index);
|
||||
if ( irq < 0 )
|
||||
return -1;
|
||||
|
||||
DBG("Clear interrupt on 0x%x for dev 0x%x (IRQ: %d)\n", (unsigned int)busdev, (unsigned int)dev, irq);
|
||||
|
||||
if ( priv->config->ops->int_clear ) {
|
||||
/* Let device override driver default */
|
||||
return priv->config->ops->int_clear(dev, irq);
|
||||
} else {
|
||||
return DRVMGR_ENOSYS;
|
||||
}
|
||||
}
|
||||
|
||||
int ambapp_int_mask(
|
||||
struct drvmgr_dev *dev,
|
||||
int index)
|
||||
{
|
||||
struct drvmgr_dev *busdev;
|
||||
struct ambapp_priv *priv;
|
||||
int irq;
|
||||
|
||||
busdev = dev->parent->dev;
|
||||
priv = dev->parent->priv;
|
||||
|
||||
/* Get IRQ number from index and device information */
|
||||
irq = ambapp_int_get(dev, index);
|
||||
if ( irq < 0 )
|
||||
return -1;
|
||||
|
||||
DBG("MASK interrupt on 0x%x for dev 0x%x (IRQ: %d)\n", (unsigned int)busdev, (unsigned int)dev, irq);
|
||||
|
||||
if ( priv->config->ops->int_mask ) {
|
||||
/* Let device override driver default */
|
||||
return priv->config->ops->int_mask(dev, irq);
|
||||
} else {
|
||||
return DRVMGR_ENOSYS;
|
||||
}
|
||||
}
|
||||
|
||||
int ambapp_int_unmask(
|
||||
struct drvmgr_dev *dev,
|
||||
int index)
|
||||
{
|
||||
struct drvmgr_dev *busdev;
|
||||
struct ambapp_priv *priv;
|
||||
int irq;
|
||||
|
||||
busdev = dev->parent->dev;
|
||||
priv = dev->parent->priv;
|
||||
|
||||
/* Get IRQ number from index and device information */
|
||||
irq = ambapp_int_get(dev, index);
|
||||
if ( irq < 0 )
|
||||
return DRVMGR_EINVAL;
|
||||
|
||||
DBG("UNMASK interrupt on 0x%x for dev 0x%x (IRQ: %d)\n", (unsigned int)busdev, (unsigned int)dev, irq);
|
||||
|
||||
if ( priv->config->ops->int_unmask ) {
|
||||
/* Let device override driver default */
|
||||
return priv->config->ops->int_unmask(dev, irq);
|
||||
} else {
|
||||
return DRVMGR_ENOSYS;
|
||||
}
|
||||
}
|
||||
|
||||
/* Assign frequency to an AMBA Bus */
|
||||
void ambapp_bus_freq_register(
|
||||
struct drvmgr_dev *dev,
|
||||
int amba_interface,
|
||||
unsigned int freq_hz
|
||||
)
|
||||
{
|
||||
struct ambapp_priv *priv = (struct ambapp_priv *)dev->parent->priv;
|
||||
struct ambapp_dev *adev;
|
||||
struct amba_dev_info *pnp = dev->businfo;
|
||||
|
||||
if ( freq_hz == 0 )
|
||||
return;
|
||||
|
||||
if ( amba_interface == DEV_AHB_MST ) {
|
||||
adev = (struct ambapp_dev *)
|
||||
((unsigned int)pnp->info.ahb_mst -
|
||||
sizeof(struct ambapp_dev));
|
||||
} else if ( amba_interface == DEV_AHB_SLV ) {
|
||||
adev = (struct ambapp_dev *)
|
||||
((unsigned int)pnp->info.ahb_slv -
|
||||
sizeof(struct ambapp_dev));
|
||||
} else if ( amba_interface == DEV_APB_SLV ) {
|
||||
adev = (struct ambapp_dev *)
|
||||
((unsigned int)pnp->info.apb_slv -
|
||||
sizeof(struct ambapp_dev));
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Calculate Top bus frequency from lower part. The frequency comes
|
||||
* from some kind of hardware able to report local bus frequency.
|
||||
*/
|
||||
ambapp_freq_init(priv->config->abus, adev, freq_hz);
|
||||
}
|
||||
|
||||
int ambapp_bus_freq_get(
|
||||
struct drvmgr_dev *dev,
|
||||
int options,
|
||||
unsigned int *freq_hz)
|
||||
{
|
||||
struct ambapp_priv *priv = (struct ambapp_priv *)dev->parent->priv;
|
||||
struct ambapp_dev *adev;
|
||||
struct amba_dev_info *pnp = dev->businfo;
|
||||
|
||||
if ( options == DEV_AHB_MST ) {
|
||||
adev = (struct ambapp_dev *)
|
||||
((unsigned int)pnp->info.ahb_mst -
|
||||
sizeof(struct ambapp_dev));
|
||||
} else if ( options == DEV_AHB_SLV ) {
|
||||
adev = (struct ambapp_dev *)
|
||||
((unsigned int)pnp->info.ahb_slv -
|
||||
sizeof(struct ambapp_dev));
|
||||
} else if ( options == DEV_APB_SLV ) {
|
||||
adev = (struct ambapp_dev *)
|
||||
((unsigned int)pnp->info.apb_slv -
|
||||
sizeof(struct ambapp_dev));
|
||||
} else {
|
||||
*freq_hz = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Calculate core/bus frequency from top most bus frequency. */
|
||||
*freq_hz = ambapp_freq_get(priv->config->abus, adev);
|
||||
if ( *freq_hz == 0 )
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ambapp_get_params(struct drvmgr_dev *dev, struct drvmgr_bus_params *params)
|
||||
{
|
||||
struct ambapp_priv *priv = dev->parent->priv;
|
||||
|
||||
if ( priv->config->ops->get_params ) {
|
||||
/* Let device override driver default */
|
||||
return priv->config->ops->get_params(dev, params);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef AMBAPPBUS_INFO_AVAIL
|
||||
void ambapp_dev_info(
|
||||
struct drvmgr_dev *dev,
|
||||
void (*print_line)(void *p, char *str),
|
||||
void *p)
|
||||
{
|
||||
struct amba_dev_info *devinfo;
|
||||
struct ambapp_core *core;
|
||||
char buf[64];
|
||||
int ver, i;
|
||||
char *str1, *str2, *str3;
|
||||
unsigned int ahbmst_freq, ahbslv_freq, apbslv_freq;
|
||||
|
||||
if (!dev)
|
||||
return;
|
||||
|
||||
devinfo = (struct amba_dev_info *)dev->businfo;
|
||||
if (!devinfo)
|
||||
return;
|
||||
core = &devinfo->info;
|
||||
|
||||
print_line(p, "AMBA PnP DEVICE");
|
||||
|
||||
str1 = ambapp_vendor_id2str(devinfo->id.vendor);
|
||||
if (str1 == NULL)
|
||||
str1 = "unknown";
|
||||
sprintf(buf, "VENDOR ID: 0x%04x (%s)", devinfo->id.vendor, str1);
|
||||
print_line(p, buf);
|
||||
|
||||
str1 = ambapp_device_id2str(devinfo->id.vendor, devinfo->id.device);
|
||||
if (str1 == NULL)
|
||||
str1 = "unknown";
|
||||
sprintf(buf, "DEVICE ID: 0x%04x (%s)", devinfo->id.device, str1);
|
||||
print_line(p, buf);
|
||||
|
||||
ahbmst_freq = ahbslv_freq = apbslv_freq = 0;
|
||||
ver = 0;
|
||||
str1 = str2 = str3 = "";
|
||||
if (core->ahb_mst) {
|
||||
str1 = "AHBMST ";
|
||||
ver = core->ahb_mst->ver;
|
||||
ambapp_bus_freq_get(dev, DEV_AHB_MST, &ahbmst_freq);
|
||||
}
|
||||
if (core->ahb_slv) {
|
||||
str2 = "AHBSLV ";
|
||||
ver = core->ahb_slv->ver;
|
||||
ambapp_bus_freq_get(dev, DEV_AHB_SLV, &ahbslv_freq);
|
||||
}
|
||||
if (core->apb_slv) {
|
||||
str3 = "APBSLV";
|
||||
ver = core->apb_slv->ver;
|
||||
ambapp_bus_freq_get(dev, DEV_APB_SLV, &apbslv_freq);
|
||||
}
|
||||
|
||||
sprintf(buf, "IRQ: %d", ambapp_int_get(dev, 0));
|
||||
print_line(p, buf);
|
||||
|
||||
sprintf(buf, "VERSION: 0x%x", ver);
|
||||
print_line(p, buf);
|
||||
|
||||
sprintf(buf, "ambapp_core: %p", core);
|
||||
print_line(p, buf);
|
||||
|
||||
sprintf(buf, "interfaces: %s%s%s", str1, str2, str3);
|
||||
print_line(p, buf);
|
||||
|
||||
if (ahbmst_freq != 0) {
|
||||
sprintf(buf, "AHBMST FREQ: %dkHz", ahbmst_freq/1000);
|
||||
print_line(p, buf);
|
||||
}
|
||||
|
||||
if (ahbslv_freq != 0) {
|
||||
sprintf(buf, "AHBSLV FREQ: %dkHz", ahbslv_freq/1000);
|
||||
print_line(p, buf);
|
||||
}
|
||||
|
||||
if (apbslv_freq != 0) {
|
||||
sprintf(buf, "APBSLV FREQ: %dkHz", apbslv_freq/1000);
|
||||
print_line(p, buf);
|
||||
}
|
||||
|
||||
if (core->ahb_slv) {
|
||||
for(i=0; i<4; i++) {
|
||||
if (core->ahb_slv->type[i] == AMBA_TYPE_AHBIO)
|
||||
str1 = " ahbio";
|
||||
else if (core->ahb_slv->type[i] == AMBA_TYPE_MEM)
|
||||
str1 = "ahbmem";
|
||||
else
|
||||
continue;
|
||||
sprintf(buf, " %s[%d]: 0x%08x-0x%08x", str1, i,
|
||||
core->ahb_slv->start[i],
|
||||
core->ahb_slv->start[i]+core->ahb_slv->mask[i]-1);
|
||||
print_line(p, buf);
|
||||
}
|
||||
}
|
||||
if (core->apb_slv) {
|
||||
sprintf(buf, " apb: 0x%08x-0x%08x",
|
||||
core->apb_slv->start,
|
||||
core->apb_slv->start + core->apb_slv->mask - 1);
|
||||
print_line(p, buf);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Fix device in last stage */
|
||||
int ambapp_dev_fixup(struct drvmgr_dev *dev, struct amba_dev_info *pnp)
|
||||
{
|
||||
/* OCCAN speciality:
|
||||
* Mulitple cores are supported through the same amba AHB interface.
|
||||
* The number of "sub cores" can be detected by decoding the AMBA
|
||||
* Plug&Play version information. verion = ncores. A maximum of 8
|
||||
* sub cores are supported, each separeated with 0x100 inbetween.
|
||||
*
|
||||
* Now, lets detect sub cores.
|
||||
*/
|
||||
if ( (pnp->info.device == GAISLER_CANAHB) && (pnp->info.vendor == VENDOR_GAISLER) ) {
|
||||
struct drvmgr_dev *newdev;
|
||||
struct amba_dev_info *pnpinfo;
|
||||
int subcores;
|
||||
int core;
|
||||
|
||||
subcores = (pnp->info.ahb_slv->ver & 0x7) + 1;
|
||||
for(core = 1; core < subcores; core++) {
|
||||
drvmgr_alloc_dev(&newdev, sizeof(*pnpinfo));
|
||||
memcpy(newdev, dev, sizeof(*newdev));
|
||||
pnpinfo = (struct amba_dev_info *)(newdev+1);
|
||||
memcpy(pnpinfo, pnp, sizeof(*pnp));
|
||||
pnpinfo->info.index = core;
|
||||
pnpinfo->info.irq += core;
|
||||
newdev->businfo = (void *)pnpinfo;
|
||||
|
||||
/* Register device */
|
||||
drvmgr_dev_register(newdev);
|
||||
}
|
||||
} else if ( (pnp->info.device == GAISLER_GPIO) && (pnp->info.vendor == VENDOR_GAISLER) ) {
|
||||
/* PIO[N] is connected to IRQ[N]. */
|
||||
pnp->info.irq = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct ambapp_dev_reg_struct {
|
||||
struct ambapp_bus *abus;
|
||||
struct drvmgr_bus *bus;
|
||||
struct ambapp_dev *ahb_mst;
|
||||
struct ambapp_dev *ahb_slv;
|
||||
struct ambapp_dev *apb_slv;
|
||||
};
|
||||
|
||||
void ambapp_core_register(
|
||||
struct ambapp_dev *ahb_mst,
|
||||
struct ambapp_dev *ahb_slv,
|
||||
struct ambapp_dev *apb_slv,
|
||||
struct ambapp_dev_reg_struct *arg
|
||||
)
|
||||
{
|
||||
struct drvmgr_dev *newdev;
|
||||
struct amba_dev_info *pnpinfo;
|
||||
unsigned short device;
|
||||
unsigned char vendor;
|
||||
int namelen;
|
||||
char buf[64];
|
||||
|
||||
if ( ahb_mst ) {
|
||||
device = ahb_mst->device;
|
||||
vendor = ahb_mst->vendor;
|
||||
}else if ( ahb_slv ) {
|
||||
device = ahb_slv->device;
|
||||
vendor = ahb_slv->vendor;
|
||||
}else if( apb_slv ) {
|
||||
device = apb_slv->device;
|
||||
vendor = apb_slv->vendor;
|
||||
} else {
|
||||
DBG("NO DEV!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
DBG("CORE REGISTER DEV [%x:%x] MST: 0x%x, SLV: 0x%x, APB: 0x%x\n", vendor, device, (unsigned int)ahb_mst, (unsigned int)ahb_slv, (unsigned int)apb_slv);
|
||||
|
||||
/* Get unique device name from AMBA data base by combining VENDOR and
|
||||
* DEVICE short names
|
||||
*/
|
||||
namelen = ambapp_vendev_id2str(vendor, device, buf);
|
||||
|
||||
/* Allocate a device */
|
||||
drvmgr_alloc_dev(&newdev, sizeof(struct amba_dev_info) + namelen);
|
||||
pnpinfo = (struct amba_dev_info *)(newdev + 1);
|
||||
newdev->parent = arg->bus; /* Ourselfs */
|
||||
newdev->minor_drv = 0;
|
||||
newdev->minor_bus = 0;
|
||||
newdev->priv = NULL;
|
||||
newdev->drv = NULL;
|
||||
if (namelen > 0) {
|
||||
newdev->name = (char *)(pnpinfo + 1);
|
||||
strcpy(newdev->name, buf);
|
||||
} else {
|
||||
newdev->name = NULL;
|
||||
}
|
||||
newdev->next_in_drv = NULL;
|
||||
newdev->bus = NULL;
|
||||
|
||||
/* Init PnP information, Assign Core interfaces with this device */
|
||||
pnpinfo->id.vendor = vendor;
|
||||
pnpinfo->id.device = device;
|
||||
pnpinfo->info.vendor = vendor;
|
||||
pnpinfo->info.device = device;
|
||||
pnpinfo->info.index = 0;
|
||||
if ( ahb_mst ) {
|
||||
pnpinfo->info.ahb_mst = (struct ambapp_ahb_info *)
|
||||
ahb_mst->devinfo;
|
||||
ambapp_alloc_dev(ahb_mst, (void *)newdev);
|
||||
if ( pnpinfo->info.ahb_mst->irq )
|
||||
pnpinfo->info.irq = pnpinfo->info.ahb_mst->irq;
|
||||
}
|
||||
if ( ahb_slv ) {
|
||||
pnpinfo->info.ahb_slv = (struct ambapp_ahb_info *)
|
||||
ahb_slv->devinfo;
|
||||
ambapp_alloc_dev(ahb_slv, (void *)newdev);
|
||||
if ( pnpinfo->info.ahb_slv->irq )
|
||||
pnpinfo->info.irq = pnpinfo->info.ahb_slv->irq;
|
||||
}
|
||||
if ( apb_slv ) {
|
||||
pnpinfo->info.apb_slv = (struct ambapp_apb_info *)
|
||||
apb_slv->devinfo;
|
||||
ambapp_alloc_dev(apb_slv, (void *)newdev);
|
||||
if ( pnpinfo->info.apb_slv->irq )
|
||||
pnpinfo->info.irq = pnpinfo->info.apb_slv->irq;
|
||||
}
|
||||
if ( pnpinfo->info.irq == 0 )
|
||||
pnpinfo->info.irq = -1; /* indicate no IRQ */
|
||||
|
||||
/* Connect device with PnP information */
|
||||
newdev->businfo = (void *)pnpinfo;
|
||||
|
||||
ambapp_dev_fixup(newdev, pnpinfo);
|
||||
|
||||
/* Register New Device */
|
||||
drvmgr_dev_register(newdev);
|
||||
}
|
||||
|
||||
/* Register one AMBA device */
|
||||
int ambapp_dev_register(struct ambapp_dev *dev, int index, void *arg)
|
||||
{
|
||||
struct ambapp_dev_reg_struct *p = arg;
|
||||
|
||||
#ifdef DEBUG
|
||||
char *type;
|
||||
|
||||
if ( dev->dev_type == DEV_AHB_MST )
|
||||
type = "AHB MST";
|
||||
else if ( dev->dev_type == DEV_AHB_SLV )
|
||||
type = "AHB SLV";
|
||||
else if ( dev->dev_type == DEV_APB_SLV )
|
||||
type = "APB SLV";
|
||||
|
||||
DBG("Found [%d:%x:%x], %s\n", index, dev->vendor, dev->device, type);
|
||||
#endif
|
||||
|
||||
if ( dev->dev_type == DEV_AHB_MST ) {
|
||||
if ( p->ahb_mst ) {
|
||||
/* This should not happen */
|
||||
printk("ambapp_dev_register: ahb_mst not NULL!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Remember AHB Master */
|
||||
p->ahb_mst = dev;
|
||||
|
||||
/* Find AHB Slave and APB slave for this Core */
|
||||
ambapp_for_each(p->abus, (OPTIONS_AHB_SLVS|OPTIONS_APB_SLVS|OPTIONS_FREE), dev->vendor, dev->device, ambapp_dev_register, p);
|
||||
|
||||
ambapp_core_register(p->ahb_mst, p->ahb_slv, p->apb_slv, p);
|
||||
p->ahb_mst = p->ahb_slv = p->apb_slv = NULL;
|
||||
return 0;
|
||||
|
||||
} else if ( dev->dev_type == DEV_AHB_SLV ) {
|
||||
if ( p->ahb_slv ) {
|
||||
/* Already got our AHB Slave interface */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Remember AHB Slave */
|
||||
p->ahb_slv = dev;
|
||||
|
||||
if ( p->ahb_mst ) {
|
||||
/* Continue searching for APB Slave */
|
||||
return 0;
|
||||
} else {
|
||||
/* Find APB Slave interface for this Core */
|
||||
ambapp_for_each(p->abus, (OPTIONS_APB_SLVS|OPTIONS_FREE), dev->vendor, dev->device, ambapp_dev_register, p);
|
||||
|
||||
ambapp_core_register(p->ahb_mst, p->ahb_slv, p->apb_slv, p);
|
||||
p->ahb_mst = p->ahb_slv = p->apb_slv = NULL;
|
||||
return 0;
|
||||
}
|
||||
} else if ( dev->dev_type == DEV_APB_SLV ) {
|
||||
if ( p->apb_slv ) {
|
||||
/* This should not happen */
|
||||
printk("ambapp_dev_register: apb_slv not NULL!\n");
|
||||
exit(1);
|
||||
}
|
||||
/* Remember APB Slave */
|
||||
p->apb_slv = dev;
|
||||
|
||||
if ( p->ahb_mst || p->ahb_slv ) {
|
||||
/* Stop scanning */
|
||||
return 1;
|
||||
} else {
|
||||
ambapp_core_register(p->ahb_mst, p->ahb_slv, p->apb_slv, p);
|
||||
p->ahb_mst = p->ahb_slv = p->apb_slv = NULL;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Register all AMBA devices available on the AMBAPP bus */
|
||||
int ambapp_ids_register(struct drvmgr_bus *bus)
|
||||
{
|
||||
struct ambapp_priv *priv = bus->priv;
|
||||
struct ambapp_bus *abus;
|
||||
struct ambapp_dev_reg_struct arg;
|
||||
|
||||
DBG("ambapp_ids_register:\n");
|
||||
|
||||
memset(&arg, 0, sizeof(arg));
|
||||
|
||||
abus = priv->config->abus;
|
||||
arg.abus = abus;
|
||||
arg.bus = bus;
|
||||
|
||||
/* Combine the AHB MST, AHB SLV and APB SLV interfaces of a core. A core has often more than
|
||||
* one interface. A core can not have more than one interface of the same type.
|
||||
*/
|
||||
ambapp_for_each(abus, (OPTIONS_ALL_DEVS|OPTIONS_FREE), -1, -1, ambapp_dev_register, &arg);
|
||||
|
||||
#ifdef DEBUG
|
||||
ambapp_print(abus->root, 1);
|
||||
#endif
|
||||
|
||||
return DRVMGR_OK;
|
||||
}
|
||||
|
||||
/*** DEVICE FUNCTIONS ***/
|
||||
|
||||
int ambapp_bus_register(struct drvmgr_dev *dev, struct ambapp_config *config)
|
||||
{
|
||||
struct ambapp_priv *priv;
|
||||
|
||||
if ( !config || !config->ops )
|
||||
return DRVMGR_OK;
|
||||
|
||||
DBG("AMBAPP BUS: initializing\n");
|
||||
|
||||
/* Register BUS */
|
||||
drvmgr_alloc_bus(&dev->bus, sizeof(struct ambapp_priv));
|
||||
priv = (struct ambapp_priv *)(dev->bus + 1);
|
||||
priv->config = config;
|
||||
if ( priv->config->bus_type == DRVMGR_BUS_TYPE_AMBAPP_DIST )
|
||||
dev->bus->bus_type = DRVMGR_BUS_TYPE_AMBAPP_DIST;
|
||||
else if ( priv->config->bus_type == DRVMGR_BUS_TYPE_AMBAPP_RMAP )
|
||||
dev->bus->bus_type = DRVMGR_BUS_TYPE_AMBAPP_RMAP;
|
||||
else
|
||||
dev->bus->bus_type = DRVMGR_BUS_TYPE_AMBAPP;
|
||||
dev->bus->next = NULL;
|
||||
dev->bus->dev = dev;
|
||||
dev->bus->priv = priv;
|
||||
dev->bus->children = NULL;
|
||||
dev->bus->ops = &ambapp_bus_ops;
|
||||
dev->bus->funcs = config->funcs;
|
||||
dev->bus->dev_cnt = 0;
|
||||
dev->bus->reslist = NULL;
|
||||
dev->bus->maps_up = config->maps_up;
|
||||
dev->bus->maps_down = config->maps_down;
|
||||
|
||||
/* Add resource configuration */
|
||||
if ( priv->config->resources )
|
||||
drvmgr_bus_res_add(dev->bus, priv->config->resources);
|
||||
|
||||
drvmgr_bus_register(dev->bus);
|
||||
|
||||
return DRVMGR_OK;
|
||||
}
|
||||
|
||||
/*** BUS INITIALIZE FUNCTIONS ***/
|
||||
|
||||
/* Initialize the bus, register devices on this bus */
|
||||
int ambapp_bus_init1(struct drvmgr_bus *bus)
|
||||
{
|
||||
/* Initialize the bus, register devices on this bus */
|
||||
return ambapp_ids_register(bus);
|
||||
}
|
||||
|
||||
int ambapp_bus_remove(struct drvmgr_bus *bus)
|
||||
{
|
||||
return DRVMGR_OK;
|
||||
}
|
||||
227
c/src/lib/libbsp/sparc/shared/drvmgr/ambapp_bus_grlib.c
Normal file
227
c/src/lib/libbsp/sparc/shared/drvmgr/ambapp_bus_grlib.c
Normal file
@@ -0,0 +1,227 @@
|
||||
/* LEON3 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 the root bus driver for GRLIB systems.
|
||||
*
|
||||
* 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 <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <libcpu/access.h>
|
||||
|
||||
#include <drvmgr/ambapp_bus.h>
|
||||
#include <drvmgr/ambapp_bus_grlib.h>
|
||||
#include <genirq.h>
|
||||
|
||||
#include <bsp.h>
|
||||
|
||||
#define DBG(args...)
|
||||
/*#define DBG(args...) printk(args)*/
|
||||
|
||||
int ambapp_grlib_int_register(
|
||||
struct drvmgr_dev *dev,
|
||||
int irq,
|
||||
const char *info,
|
||||
drvmgr_isr isr,
|
||||
void *arg);
|
||||
int ambapp_grlib_int_unregister(
|
||||
struct drvmgr_dev *dev,
|
||||
int irq,
|
||||
drvmgr_isr isr,
|
||||
void *arg);
|
||||
int ambapp_grlib_int_clear(
|
||||
struct drvmgr_dev *dev,
|
||||
int irq);
|
||||
int ambapp_grlib_int_mask(
|
||||
struct drvmgr_dev *dev,
|
||||
int irq);
|
||||
int ambapp_grlib_int_unmask(
|
||||
struct drvmgr_dev *dev,
|
||||
int irq);
|
||||
int ambapp_grlib_get_params(
|
||||
struct drvmgr_dev *dev,
|
||||
struct drvmgr_bus_params *params);
|
||||
|
||||
int ambapp_grlib_init1(struct drvmgr_dev *dev);
|
||||
int ambapp_grlib_init2(struct drvmgr_dev *dev);
|
||||
int ambapp_grlib_remove(struct drvmgr_dev *dev);
|
||||
|
||||
/* READ/WRITE access to SpaceWire target over RMAP */
|
||||
void *ambapp_grlib_rw_arg(struct drvmgr_dev *dev);
|
||||
|
||||
struct ambapp_ops ambapp_grlib_ops = {
|
||||
.int_register = ambapp_grlib_int_register,
|
||||
.int_unregister = ambapp_grlib_int_unregister,
|
||||
.int_clear = ambapp_grlib_int_clear,
|
||||
.int_mask = ambapp_grlib_int_mask,
|
||||
.int_unmask = ambapp_grlib_int_unmask,
|
||||
.get_params = ambapp_grlib_get_params
|
||||
};
|
||||
|
||||
void *ambapp_grlib_rw_arg(struct drvmgr_dev *dev)
|
||||
{
|
||||
return dev; /* No argument really needed, but for debug? */
|
||||
}
|
||||
|
||||
struct drvmgr_func ambapp_grlib_funcs[] =
|
||||
{
|
||||
DRVMGR_FUNC(AMBAPP_RW_ARG, ambapp_grlib_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_grlib_drv_ops =
|
||||
{
|
||||
.init = {ambapp_grlib_init1, ambapp_grlib_init2, NULL, NULL},
|
||||
.remove = ambapp_grlib_remove,
|
||||
.info = NULL,
|
||||
};
|
||||
|
||||
struct drvmgr_drv ambapp_bus_drv_grlib =
|
||||
{
|
||||
DRVMGR_OBJ_DRV, /* Driver */
|
||||
NULL, /* Next driver */
|
||||
NULL, /* Device list */
|
||||
DRIVER_GRLIB_AMBAPP_ID, /* Driver ID */
|
||||
"AMBAPP_GRLIB_DRV", /* Driver Name */
|
||||
DRVMGR_BUS_TYPE_ROOT, /* Bus Type */
|
||||
&ambapp_grlib_drv_ops,
|
||||
NULL, /* Funcs */
|
||||
0,
|
||||
0,
|
||||
};
|
||||
|
||||
static struct grlib_config *drv_mgr_grlib_config = NULL;
|
||||
|
||||
void ambapp_grlib_register(void)
|
||||
{
|
||||
drvmgr_drv_register(&ambapp_bus_drv_grlib);
|
||||
}
|
||||
|
||||
int ambapp_grlib_root_register(struct grlib_config *config)
|
||||
{
|
||||
|
||||
/* Save the configuration for later */
|
||||
drv_mgr_grlib_config = config;
|
||||
|
||||
/* Register root device driver */
|
||||
drvmgr_root_drv_register(&ambapp_bus_drv_grlib);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Function called from Driver Manager Initialization Stage 1 */
|
||||
int ambapp_grlib_init1(struct drvmgr_dev *dev)
|
||||
{
|
||||
struct ambapp_config *config;
|
||||
|
||||
dev->priv = NULL;
|
||||
dev->name = "GRLIB AMBA PnP";
|
||||
|
||||
DBG("AMBAPP GRLIB: intializing\n");
|
||||
|
||||
config = malloc(sizeof(struct ambapp_config));
|
||||
if ( !config )
|
||||
return RTEMS_NO_MEMORY;
|
||||
|
||||
config->ops = &ambapp_grlib_ops;
|
||||
config->maps_up = DRVMGR_TRANSLATE_ONE2ONE;
|
||||
config->maps_down = DRVMGR_TRANSLATE_ONE2ONE;
|
||||
config->abus = drv_mgr_grlib_config->abus;
|
||||
config->resources = drv_mgr_grlib_config->resources;
|
||||
config->funcs = ambapp_grlib_funcs;
|
||||
config->bus_type = DRVMGR_BUS_TYPE_AMBAPP;
|
||||
|
||||
/* Initialize the generic part of the AMBA Bus */
|
||||
return ambapp_bus_register(dev, config);
|
||||
}
|
||||
|
||||
int ambapp_grlib_init2(struct drvmgr_dev *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ambapp_grlib_remove(struct drvmgr_dev *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ambapp_grlib_int_register
|
||||
(
|
||||
struct drvmgr_dev *dev,
|
||||
int irq,
|
||||
const char *info,
|
||||
drvmgr_isr isr,
|
||||
void *arg
|
||||
)
|
||||
{
|
||||
return BSP_shared_interrupt_register(irq, info, isr, arg);
|
||||
}
|
||||
|
||||
int ambapp_grlib_int_unregister
|
||||
(
|
||||
struct drvmgr_dev *dev,
|
||||
int irq,
|
||||
drvmgr_isr isr,
|
||||
void *arg
|
||||
)
|
||||
{
|
||||
return BSP_shared_interrupt_unregister(irq, isr, arg);
|
||||
}
|
||||
|
||||
int ambapp_grlib_int_clear
|
||||
(
|
||||
struct drvmgr_dev *dev,
|
||||
int irq)
|
||||
{
|
||||
BSP_shared_interrupt_clear(irq);
|
||||
return DRVMGR_OK;
|
||||
}
|
||||
|
||||
int ambapp_grlib_int_mask
|
||||
(
|
||||
struct drvmgr_dev *dev,
|
||||
int irq
|
||||
)
|
||||
{
|
||||
BSP_shared_interrupt_mask(irq);
|
||||
return DRVMGR_OK;
|
||||
}
|
||||
|
||||
int ambapp_grlib_int_unmask
|
||||
(
|
||||
struct drvmgr_dev *dev,
|
||||
int irq
|
||||
)
|
||||
{
|
||||
BSP_shared_interrupt_unmask(irq);
|
||||
return DRVMGR_OK;
|
||||
}
|
||||
|
||||
int ambapp_grlib_get_params(struct drvmgr_dev *dev, struct drvmgr_bus_params *params)
|
||||
{
|
||||
/* Leave params->freq_hz untouched for default */
|
||||
params->dev_prefix = "";
|
||||
return 0;
|
||||
}
|
||||
101
c/src/lib/libbsp/sparc/shared/include/drvmgr/ambapp_bus.h
Normal file
101
c/src/lib/libbsp/sparc/shared/include/drvmgr/ambapp_bus.h
Normal file
@@ -0,0 +1,101 @@
|
||||
/* General part of a AMBA Plug & Play bus driver.
|
||||
*
|
||||
* COPYRIGHT (c) 2008.
|
||||
* Cobham Gaisler AB
|
||||
*
|
||||
* This is the general part of the different AMBA Plug & Play
|
||||
* drivers. The drivers are wrappers around this driver, making
|
||||
* the code size smaller for systems with multiple AMBA Plug &
|
||||
* Play buses.
|
||||
*
|
||||
* 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 __AMBAPP_BUS_H__
|
||||
#define __AMBAPP_BUS_H__
|
||||
|
||||
#include <drvmgr/drvmgr.h>
|
||||
#include <ambapp.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* GRLIB AMBA Plug&Play Driver ID generation */
|
||||
#define DRIVER_AMBAPP_ID(vendor, device) \
|
||||
DRIVER_ID(DRVMGR_BUS_TYPE_AMBAPP, ((((vendor) & 0xff) << 16) | ((device) & 0xfff)))
|
||||
|
||||
struct amba_dev_id {
|
||||
unsigned short vendor;
|
||||
unsigned short device;
|
||||
/* Version ? */
|
||||
};
|
||||
|
||||
struct amba_drv_info {
|
||||
struct drvmgr_drv general; /* General bus info */
|
||||
/* AMBA specific bus information */
|
||||
struct amba_dev_id *ids; /* Supported hardware */
|
||||
};
|
||||
|
||||
struct amba_dev_info {
|
||||
struct amba_dev_id id;
|
||||
struct ambapp_core info;
|
||||
};
|
||||
|
||||
struct ambapp_ops {
|
||||
int (*int_register)
|
||||
(struct drvmgr_dev *dev, int index, const char *info, drvmgr_isr isr, void *arg);
|
||||
int (*int_unregister)
|
||||
(struct drvmgr_dev *dev, int index, drvmgr_isr isr, void *arg);
|
||||
int (*int_clear)(struct drvmgr_dev *dev, int index);
|
||||
int (*int_mask)(struct drvmgr_dev *dev, int index);
|
||||
int (*int_unmask)(struct drvmgr_dev *dev, int index);
|
||||
int (*get_params)
|
||||
(struct drvmgr_dev *, struct drvmgr_bus_params *);
|
||||
};
|
||||
|
||||
struct ambapp_config {
|
||||
struct ambapp_bus *abus; /* Prescanned AMBA PnP bus */
|
||||
struct ambapp_ops *ops; /* AMBA bus operations */
|
||||
struct drvmgr_map_entry *maps_up; /* Bus memory map up-stream towards CPU */
|
||||
struct drvmgr_map_entry *maps_down; /* Bus memory map down-stream towards HW */
|
||||
struct drvmgr_bus_res *resources; /* Driver Resources */
|
||||
int bus_type; /* Set DRVMGR_BUS_TYPE_AMBAPP_DIST if distributed AMBA Bus */
|
||||
struct drvmgr_func *funcs; /* Custom functions */
|
||||
};
|
||||
|
||||
/*** Bus operations with READ/WRITE access operations ***
|
||||
*
|
||||
* The functions are implemented using the standard drvmgr RW interface
|
||||
*/
|
||||
#define AMBAPP_R8 DRVMGR_RWFUNC(RW_SIZE_1|RW_READ|RW_REG)
|
||||
#define AMBAPP_R16 DRVMGR_RWFUNC(RW_SIZE_2|RW_READ|RW_REG)
|
||||
#define AMBAPP_R32 DRVMGR_RWFUNC(RW_SIZE_4|RW_READ|RW_REG)
|
||||
#define AMBAPP_R64 DRVMGR_RWFUNC(RW_SIZE_8|RW_READ|RW_REG)
|
||||
#define AMBAPP_W8 DRVMGR_RWFUNC(RW_SIZE_1|RW_WRITE|RW_REG)
|
||||
#define AMBAPP_W16 DRVMGR_RWFUNC(RW_SIZE_2|RW_WRITE|RW_REG)
|
||||
#define AMBAPP_W32 DRVMGR_RWFUNC(RW_SIZE_4|RW_WRITE|RW_REG)
|
||||
#define AMBAPP_W64 DRVMGR_RWFUNC(RW_SIZE_8|RW_WRITE|RW_REG)
|
||||
#define AMBAPP_RMEM DRVMGR_RWFUNC(RW_SIZE_ANY|RW_READ|RW_MEM)
|
||||
#define AMBAPP_WMEM DRVMGR_RWFUNC(RW_SIZE_ANY|RW_WRITE|RW_MEM)
|
||||
#define AMBAPP_MEMSET DRVMGR_RWFUNC(RW_SIZE_ANY|RW_SET|RW_MEM)
|
||||
#define AMBAPP_RW_ARG DRVMGR_RWFUNC(RW_ARG)
|
||||
|
||||
/* Register an ambapp bus on-top of a device */
|
||||
extern int ambapp_bus_register(
|
||||
struct drvmgr_dev *dev,
|
||||
struct ambapp_config *config
|
||||
);
|
||||
|
||||
extern void ambapp_bus_freq_register(
|
||||
struct drvmgr_dev *dev,
|
||||
int amba_interface,
|
||||
unsigned int freq_hz);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,33 @@
|
||||
/* LEON3 GRLIB AMBA Plug & Play bus driver interface.
|
||||
*
|
||||
* COPYRIGHT (c) 2008.
|
||||
* Cobham Gaisler AB.
|
||||
*
|
||||
* This is driver is a wrapper for the general AMBA Plug & Play bus
|
||||
* driver. This is the root bus driver for GRLIB systems.
|
||||
*
|
||||
* 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 __AMBAPP_BUS_GRLIB_H__
|
||||
#define __AMBAPP_BUS_GRLIB_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct grlib_config {
|
||||
struct ambapp_bus *abus;
|
||||
struct drvmgr_bus_res *resources;
|
||||
};
|
||||
|
||||
/* Register GRLIB AMBA PnP Bus as root bus at driver manager */
|
||||
extern int ambapp_grlib_root_register(struct grlib_config *config);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user