grlib: Move source files

Update #3678.
This commit is contained in:
Sebastian Huber
2018-12-22 18:31:04 +01:00
parent 3172092576
commit 7eb606d393
69 changed files with 71 additions and 202 deletions

View File

@@ -0,0 +1,239 @@
/* AHB Status register driver
*
* COPYRIGHT (c) 2009 - 2017.
* 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.org/license/LICENSE.
*/
#include <inttypes.h>
#include <string.h>
#include <rtems.h>
#include <rtems/bspIo.h>
#include <drvmgr/drvmgr.h>
#include <grlib/ambapp_bus.h>
#include <grlib/ahbstat.h>
#include <grlib/grlib_impl.h>
#define REG_WRITE(addr, val) (*(volatile uint32_t *)(addr) = (uint32_t)(val))
#define REG_READ(addr) (*(volatile uint32_t *)(addr))
void ahbstat_isr(void *arg);
/* AHB fail interrupt callback to user. This function is declared weak so that
* the user can define a function pointer variable containing the address
* responsible for handling errors
*
* minor Index of AHBSTAT hardware
* regs Register address of AHBSTAT
* status AHBSTAT status register at IRQ
* failing_address AHBSTAT Failing address register at IRQ
*
* * User return
* 0: print error onto terminal with printk and reenable AHBSTAT
* 1: just re-enable AHBSTAT
* 2: just print error
* 3: do nothing, let user do custom handling
*/
int (*ahbstat_error)(
int minor,
struct ahbstat_regs *regs,
uint32_t status,
uint32_t failing_address
) __attribute__((weak)) = NULL;
#define AHBSTAT_STS_CE_BIT 9
#define AHBSTAT_STS_NE_BIT 8
#define AHBSTAT_STS_HW_BIT 7
#define AHBSTAT_STS_HM_BIT 3
#define AHBSTAT_STS_HS_BIT 0
#define AHBSTAT_STS_CE (1 << AHBSTAT_STS_CE_BIT)
#define AHBSTAT_STS_NE (1 << AHBSTAT_STS_NE_BIT)
#define AHBSTAT_STS_HW (1 << AHBSTAT_STS_HW_BIT)
#define AHBSTAT_STS_HM (0xf << AHBSTAT_STS_HM_BIT)
#define AHBSTAT_STS_HS (0x7 << AHBSTAT_STS_HS_BIT)
enum { DEVNAME_LEN = 9 };
struct ahbstat_priv {
struct drvmgr_dev *dev;
struct ahbstat_regs *regs;
char devname[DEVNAME_LEN];
int minor;
/* Cached error */
uint32_t last_status;
uint32_t last_address;
/* Spin-lock ISR protection */
SPIN_DECLARE(devlock);
};
static int ahbstat_init2(struct drvmgr_dev *dev);
struct drvmgr_drv_ops ahbstat_ops =
{
.init = {NULL, ahbstat_init2, NULL, NULL},
.remove = NULL,
.info = NULL
};
struct amba_dev_id ahbstat_ids[] =
{
{VENDOR_GAISLER, GAISLER_AHBSTAT},
{0, 0} /* Mark end of table */
};
struct amba_drv_info ahbstat_drv_info =
{
{
DRVMGR_OBJ_DRV, /* Driver */
NULL, /* Next driver */
NULL, /* Device list */
DRIVER_AMBAPP_GAISLER_AHBSTAT_ID,/* Driver ID */
"AHBSTAT_DRV", /* Driver Name */
DRVMGR_BUS_TYPE_AMBAPP, /* Bus Type */
&ahbstat_ops,
NULL, /* Funcs */
0, /* No devices yet */
sizeof(struct ahbstat_priv),
},
&ahbstat_ids[0]
};
void ahbstat_register_drv (void)
{
drvmgr_drv_register(&ahbstat_drv_info.general);
}
static int ahbstat_init2(struct drvmgr_dev *dev)
{
struct ahbstat_priv *priv;
struct amba_dev_info *ambadev;
priv = dev->priv;
if (!priv)
return DRVMGR_NOMEM;
priv->dev = dev;
/* Get device information from AMBA PnP information */
ambadev = (struct amba_dev_info *)dev->businfo;
if (ambadev == NULL)
return DRVMGR_FAIL;
priv->regs = (struct ahbstat_regs *)ambadev->info.apb_slv->start;
priv->minor = dev->minor_drv;
strncpy(&priv->devname[0], "ahbstat0", DEVNAME_LEN);
priv->devname[7] += priv->minor;
/*
* Initialize spinlock for AHBSTAT Device. It is used to protect user
* API calls involivng priv structure from updates in ISR.
*/
SPIN_INIT(&priv->devlock, priv->devname);
/* Initialize hardware */
REG_WRITE(&priv->regs->status, 0);
/* Install IRQ handler */
drvmgr_interrupt_register(dev, 0, priv->devname, ahbstat_isr, priv);
return DRVMGR_OK;
}
void ahbstat_isr(void *arg)
{
struct ahbstat_priv *priv = arg;
uint32_t fadr, status;
int rc;
SPIN_ISR_IRQFLAGS(lock_context);
/* Get hardware status */
status = REG_READ(&priv->regs->status);
if ((status & AHBSTAT_STS_NE) == 0)
return;
/* IRQ generated by AHBSTAT core... handle it here */
/* Get Failing address */
fadr = REG_READ(&priv->regs->failing);
SPIN_LOCK(&priv->devlock, lock_context);
priv->last_status = status;
priv->last_address = fadr;
SPIN_UNLOCK(&priv->devlock, lock_context);
/* Let user handle error, default to print the error and reenable HW
*
* User return
* 0: print error and reenable AHBSTAT
* 1: just reenable AHBSTAT
* 2: just print error
* 3: do nothing
*/
rc = 0;
if (ahbstat_error != NULL)
rc = ahbstat_error(priv->minor, priv->regs, status, fadr);
if ((rc & 0x1) == 0) {
printk("\n### AHBSTAT: %s %s error of size %" PRId32
" by master %" PRId32 " at 0x%08" PRIx32 "\n",
status & AHBSTAT_STS_CE ? "single" : "non-correctable",
status & AHBSTAT_STS_HW ? "write" : "read",
(status & AHBSTAT_STS_HS) >> AHBSTAT_STS_HS_BIT,
(status & AHBSTAT_STS_HM) >> AHBSTAT_STS_HM_BIT,
fadr);
}
if ((rc & 0x2) == 0) {
/* Trigger new interrupts */
REG_WRITE(&priv->regs->status, 0);
}
}
/* Get Last received AHB Error
*
* Return
* 0: No error received
* 1: Error Received, last status and address stored into argument pointers
* -1: No such AHBSTAT device
*/
int ahbstat_last_error(int minor, uint32_t *status, uint32_t *address)
{
struct drvmgr_dev *dev;
struct ahbstat_priv *priv;
uint32_t last_status;
uint32_t last_address;
SPIN_IRQFLAGS(lock_context);
if (drvmgr_get_dev(&ahbstat_drv_info.general, minor, &dev)) {
return -1;
}
priv = (struct ahbstat_priv *)dev->priv;
/* Read information cached by ISR */
SPIN_LOCK_IRQ(&priv->devlock, lock_context);
last_status = REG_READ(&priv->last_status);
last_address = REG_READ(&priv->last_address);
SPIN_UNLOCK_IRQ(&priv->devlock, lock_context);
*status = last_status;
*address = last_address;
return (last_status & AHBSTAT_STS_NE) >> AHBSTAT_STS_NE_BIT;
}
/* Get AHBSTAT registers address from minor. NULL returned if no such device */
struct ahbstat_regs *ahbstat_get_regs(int minor)
{
struct drvmgr_dev *dev;
struct ahbstat_priv *priv;
if (drvmgr_get_dev(&ahbstat_drv_info.general, minor, &dev)) {
return NULL;
}
priv = (struct ahbstat_priv *)dev->priv;
return priv->regs;
}

View File

@@ -0,0 +1,457 @@
/*
* AMBA Plug & Play routines
*
* COPYRIGHT (c) 2011.
* Aeroflex Gaisler.
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*/
#include <string.h>
#include <stdlib.h>
#include <string.h>
#include <grlib/ambapp.h>
#include <bsp.h>
#include <grlib/grlib_impl.h>
#define AMBA_CONF_AREA 0xff000
#define AMBA_AHB_SLAVE_CONF_AREA (1 << 11)
#define AMBA_APB_SLAVES 16
/* Allocate one AMBA device */
static struct ambapp_dev *ambapp_alloc_dev_struct(int dev_type)
{
struct ambapp_dev *dev;
size_t size = sizeof(*dev);
if (dev_type == DEV_APB_SLV)
size += sizeof(struct ambapp_apb_info);
else
size += sizeof(struct ambapp_ahb_info); /* AHB */
dev = grlib_calloc(1, size);
if (dev != NULL)
dev->dev_type = dev_type;
return dev;
}
static unsigned int
ambapp_addr_from (struct ambapp_mmap *mmaps, unsigned int address)
{
/* no translation? */
if (!mmaps)
return address;
while (mmaps->size) {
if ((address >= mmaps->remote_adr) &&
(address <= (mmaps->remote_adr + (mmaps->size - 1)))) {
return (address - mmaps->remote_adr) + mmaps->local_adr;
}
mmaps++;
}
return 1;
}
static void ambapp_ahb_dev_init(
unsigned int ioarea,
struct ambapp_mmap *mmaps,
struct ambapp_pnp_ahb *ahb,
struct ambapp_dev *dev,
int ahbidx
)
{
int bar;
struct ambapp_ahb_info *ahb_info;
unsigned int addr, mask, mbar;
/* Setup device struct */
dev->vendor = ambapp_pnp_vendor(ahb->id);
dev->device = ambapp_pnp_device(ahb->id);
ahb_info = DEV_TO_AHB(dev);
ahb_info->ver = ambapp_pnp_ver(ahb->id);
ahb_info->irq = ambapp_pnp_irq(ahb->id);
ahb_info->ahbidx = ahbidx;
ahb_info->custom[0] = (unsigned int)ahb->custom[0];
ahb_info->custom[1] = (unsigned int)ahb->custom[1];
ahb_info->custom[2] = (unsigned int)ahb->custom[2];
/* Memory BARs */
for (bar=0; bar<4; bar++) {
mbar = ahb->mbar[bar];
if (mbar == 0) {
addr = 0;
mask = 0;
} else {
addr = ambapp_pnp_start(mbar);
if (ambapp_pnp_mbar_type(mbar) == AMBA_TYPE_AHBIO) {
/* AHB I/O area is releative IO_AREA */
addr = AMBA_TYPE_AHBIO_ADDR(addr, ioarea);
mask = (((unsigned int)(ambapp_pnp_mbar_mask(~mbar) << 8) | 0xff)) + 1;
} else {
/* AHB memory area, absolute address */
addr = ambapp_addr_from(mmaps, addr);
mask = (~((unsigned int)(ambapp_pnp_mbar_mask(mbar) << 20))) + 1;
}
}
ahb_info->start[bar] = addr;
ahb_info->mask[bar] = mask;
ahb_info->type[bar] = ambapp_pnp_mbar_type(mbar);
}
}
static void ambapp_apb_dev_init(
unsigned int base,
struct ambapp_mmap *mmaps,
struct ambapp_pnp_apb *apb,
struct ambapp_dev *dev,
int ahbidx
)
{
struct ambapp_apb_info *apb_info;
/* Setup device struct */
dev->vendor = ambapp_pnp_vendor(apb->id);
dev->device = ambapp_pnp_device(apb->id);
apb_info = DEV_TO_APB(dev);
apb_info->ver = ambapp_pnp_ver(apb->id);
apb_info->irq = ambapp_pnp_irq(apb->id);
apb_info->ahbidx = ahbidx;
apb_info->start = ambapp_pnp_apb_start(apb->iobar, base);
apb_info->mask = ambapp_pnp_apb_mask(apb->iobar);
}
static int ambapp_add_ahbbus(
struct ambapp_bus *abus,
unsigned int ioarea
)
{
int i;
for (i=0; i<AHB_BUS_MAX; i++) {
if (abus->ahbs[i].ioarea == 0) {
abus->ahbs[i].ioarea = ioarea;
return i;
} else if (abus->ahbs[i].ioarea == ioarea) {
/* Bus already added */
return -1;
}
}
return -1;
}
/* Internal AMBA Scanning Function */
static int ambapp_scan2(
struct ambapp_bus *abus,
unsigned int ioarea,
ambapp_memcpy_t memfunc,
struct ambapp_dev *parent,
struct ambapp_dev **root
)
{
struct ambapp_pnp_ahb *ahb, ahb_buf;
struct ambapp_pnp_apb *apb, apb_buf;
struct ambapp_dev *dev, *prev, *prevapb, *apbdev;
struct ambapp_ahb_info *ahb_info;
int maxloops = 64;
unsigned int apbbase, bridge_adr;
int i, j, ahbidx;
*root = NULL;
if (parent) {
/* scan first bus for 64 devices, rest for 16 devices */
maxloops = 16;
}
ahbidx = ambapp_add_ahbbus(abus, ioarea);
if (ahbidx < 0) {
/* Bus already scanned, stop */
return 0;
}
prev = parent;
/* AHB MASTERS */
ahb = (struct ambapp_pnp_ahb *) (ioarea | AMBA_CONF_AREA);
for (i = 0; i < maxloops; i++, ahb++) {
memfunc(&ahb_buf, ahb, sizeof(struct ambapp_pnp_ahb), abus);
if (ahb_buf.id == 0)
continue;
/* An AHB device present here */
dev = ambapp_alloc_dev_struct(DEV_AHB_MST);
if (!dev)
return -1;
ambapp_ahb_dev_init(ioarea, abus->mmaps, &ahb_buf, dev, ahbidx);
if (*root == NULL)
*root = dev;
if (prev != parent)
prev->next = dev;
dev->prev = prev;
prev = dev;
}
/* AHB SLAVES */
ahb = (struct ambapp_pnp_ahb *)
(ioarea | AMBA_CONF_AREA | AMBA_AHB_SLAVE_CONF_AREA);
for (i = 0; i < maxloops; i++, ahb++) {
memfunc(&ahb_buf, ahb, sizeof(struct ambapp_pnp_ahb), abus);
if (ahb_buf.id == 0)
continue;
/* An AHB device present here */
dev = ambapp_alloc_dev_struct(DEV_AHB_SLV);
if (!dev)
return -1;
ambapp_ahb_dev_init(ioarea, abus->mmaps, &ahb_buf, dev, ahbidx);
if (*root == NULL)
*root = dev;
if (prev != parent)
prev->next = dev;
dev->prev = prev;
prev = dev;
ahb_info = DEV_TO_AHB(dev);
/* Is it a AHB/AHB Bridge ? */
if (((dev->device == GAISLER_AHB2AHB) &&
(dev->vendor == VENDOR_GAISLER) && (ahb_info->ver > 0)) ||
((dev->device == GAISLER_L2CACHE) &&
(dev->vendor == VENDOR_GAISLER)) ||
((dev->device == GAISLER_GRIOMMU) &&
(dev->vendor == VENDOR_GAISLER))) {
/* AHB/AHB Bridge Found, recurse down the
* Bridge
*/
if (ahb_info->custom[1] != 0) {
bridge_adr = ambapp_addr_from(abus->mmaps,
ahb_info->custom[1]);
/* Scan next bus if not already scanned */
if (ambapp_scan2(abus, bridge_adr, memfunc, dev,
&dev->children))
return -1;
}
} else if ((dev->device == GAISLER_APBMST) &&
(dev->vendor == VENDOR_GAISLER)) {
/* AHB/APB Bridge Found, add the APB devices to this
* AHB Slave's children
*/
prevapb = dev;
apbbase = ahb_info->start[0];
/* APB SLAVES */
apb = (struct ambapp_pnp_apb *)
(apbbase | AMBA_CONF_AREA);
for (j=0; j<AMBA_APB_SLAVES; j++, apb++) {
memfunc(&apb_buf, apb, sizeof(*apb), abus);
if (apb_buf.id == 0)
continue;
apbdev = ambapp_alloc_dev_struct(DEV_APB_SLV);
if (!apbdev)
return -1;
ambapp_apb_dev_init(apbbase, abus->mmaps,
&apb_buf, apbdev, ahbidx);
if (prevapb != dev)
prevapb->next = apbdev;
else
dev->children = apbdev;
apbdev->prev = prevapb;
prevapb = apbdev;
}
}
}
/* Remember first AHB MST/SLV device on bus and Parent Bridge */
abus->ahbs[ahbidx].dev = *root;
abus->ahbs[ahbidx].bridge = parent;
return 0;
}
/* Build AMBA Plug & Play device graph */
int ambapp_scan(
struct ambapp_bus *abus,
unsigned int ioarea,
ambapp_memcpy_t memfunc,
struct ambapp_mmap *mmaps
)
{
memset(abus, 0, sizeof(*abus));
abus->mmaps = mmaps;
/* Default to memcpy() */
if (!memfunc)
memfunc = (ambapp_memcpy_t)memcpy;
return ambapp_scan2(abus, ioarea, memfunc, NULL, &abus->root);
}
/* Match search options againt device */
static int ambapp_dev_match_options(struct ambapp_dev *dev, unsigned int options, int vendor, int device)
{
if ((((options & (OPTIONS_ALL_DEVS)) == OPTIONS_ALL_DEVS) || /* TYPE */
((options & OPTIONS_AHB_MSTS) && (dev->dev_type == DEV_AHB_MST)) ||
((options & OPTIONS_AHB_SLVS) && (dev->dev_type == DEV_AHB_SLV)) ||
((options & OPTIONS_APB_SLVS) && (dev->dev_type == DEV_APB_SLV))) &&
((vendor == -1) || (vendor == dev->vendor)) && /* VENDOR/DEV ID */
((device == -1) || (device == dev->device)) &&
(((options & OPTIONS_ALL) == OPTIONS_ALL) || /* Allocated State */
((options & OPTIONS_FREE) && DEV_IS_FREE(dev)) ||
((options & OPTIONS_ALLOCATED) && DEV_IS_ALLOCATED(dev)))) {
return 1;
}
return 0;
}
/* If device is an APB bridge all devices on the APB bridge is processed */
static int ambapp_for_each_apb(
struct ambapp_dev *dev,
unsigned int options,
int vendor,
int device,
ambapp_func_t func,
void *arg)
{
int index, ret;
struct ambapp_dev *apbslv;
ret = 0;
if (dev->children && (dev->children->dev_type == DEV_APB_SLV)) {
/* Found a APB Bridge */
index = 0;
apbslv = dev->children;
while (apbslv) {
if (ambapp_dev_match_options(apbslv, options,
vendor, device) == 1) {
ret = func(apbslv, index, arg);
if (ret != 0)
break; /* Signalled stopped */
}
index++;
apbslv = apbslv->next;
}
}
return ret;
}
/* Traverse the prescanned device information */
static int ambapp_for_each_dev(
struct ambapp_dev *root,
unsigned int options,
int vendor,
int device,
ambapp_func_t func,
void *arg)
{
struct ambapp_dev *dev;
int ahb_slave = 0;
int index, ret;
/* Start at device 'root' and process downwards.
*
* Breadth first search, search order
* 1. AHB MSTS
* 2. AHB SLVS
* 3. APB SLVS on primary bus
* 4. AHB/AHB secondary... -> step to 1.
*/
/* AHB MST / AHB SLV */
if (options & (OPTIONS_AHB_MSTS|OPTIONS_AHB_SLVS|OPTIONS_DEPTH_FIRST)) {
index = 0;
dev = root;
while (dev) {
if ((dev->dev_type == DEV_AHB_SLV) && !ahb_slave) {
/* First AHB Slave */
ahb_slave = 1;
index = 0;
}
/* Conditions must be fullfilled for function to be
* called
*/
if (ambapp_dev_match_options(dev, options, vendor, device) == 1) {
/* Correct device and vendor ID */
ret = func(dev, index, arg);
if (ret != 0)
return ret; /* Signalled stopped */
}
if ((options & OPTIONS_DEPTH_FIRST) && (options & OPTIONS_APB_SLVS)) {
/* Check is APB bridge, and process all APB
* Slaves in that case
*/
ret = ambapp_for_each_apb(dev, options, vendor, device, func, arg);
if (ret != 0)
return ret; /* Signalled stopped */
}
if (options & OPTIONS_DEPTH_FIRST) {
if (dev->children && (dev->children->dev_type != DEV_APB_SLV)) {
/* Found AHB Bridge, recurse */
ret = ambapp_for_each_dev(dev->children, options, vendor, device,
func, arg);
if (ret != 0)
return ret;
}
}
index++;
dev = dev->next;
}
}
/* Find APB Bridges */
if ((options & OPTIONS_APB_SLVS) && !(options & OPTIONS_DEPTH_FIRST)) {
dev = root;
while (dev) {
/* Check is APB bridge, and process all APB Slaves in
* that case
*/
ret = ambapp_for_each_apb(dev, options, vendor, device, func, arg);
if (ret != 0)
return ret; /* Signalled stopped */
dev = dev->next;
}
}
/* Find AHB Bridges */
if (!(options & OPTIONS_DEPTH_FIRST)) {
dev = root;
while (dev) {
if (dev->children && (dev->children->dev_type != DEV_APB_SLV)) {
/* Found AHB Bridge, recurse */
ret = ambapp_for_each_dev(dev->children, options, vendor, device,
func, arg);
if (ret != 0)
return ret;
}
dev = dev->next;
}
}
return 0;
}
int ambapp_for_each(
struct ambapp_bus *abus,
unsigned int options,
int vendor,
int device,
ambapp_func_t func,
void *arg)
{
return ambapp_for_each_dev(abus->root, options, vendor, device, func, arg);
}

View File

@@ -0,0 +1,25 @@
/*
* AMBA Plug & Play routines
*
* COPYRIGHT (c) 2011
* Aeroflex Gaisler
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*/
#include <grlib/ambapp.h>
int ambapp_alloc_dev(struct ambapp_dev *dev, void *owner)
{
if (dev->owner)
return -1;
dev->owner = owner;
return 0;
}
void ambapp_free_dev(struct ambapp_dev *dev)
{
dev->owner = 0;
}

View File

@@ -0,0 +1,23 @@
/*
* AMBA Plug & Play routines
*
* COPYRIGHT (c) 2011
* Aeroflex Gaisler
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*/
#include <grlib/ambapp.h>
/* Get number of devices matching search options */
int ambapp_dev_count(struct ambapp_bus *abus, unsigned int options,
int vendor, int device)
{
int count = 10000;
ambapp_for_each(abus, options, vendor, device, ambapp_find_by_idx, &count);
return 10000 - count;
}

View File

@@ -0,0 +1,25 @@
/*
* AMBA Plug & Play routines
*
* COPYRIGHT (c) 2011
* Aeroflex Gaisler
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*/
#include <grlib/ambapp.h>
/* Get bus depth a device is located at */
int ambapp_depth(struct ambapp_dev *dev)
{
int depth = 0;
do {
dev = ambapp_find_parent(dev);
depth++;
} while (dev);
return depth - 1;
}

View File

@@ -0,0 +1,39 @@
/*
* AMBA Plug & Play routines
*
* COPYRIGHT (c) 2011
* Aeroflex Gaisler
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*/
#include <grlib/ambapp.h>
/* AMBAPP helper routine to find a device by index. The function is given to
* ambapp_for_each, the argument may be NULL (find first device) or a pointer
* to a index which is downcounted until 0 is reached. If the int-pointer
* points to a value of:
* 0 - first device is returned
* 1 - second device is returned
* ...
*
* The matching device is returned, which will stop the ambapp_for_each search.
* If zero is returned from ambapp_for_each no device matching the index was
* found
*/
int ambapp_find_by_idx(struct ambapp_dev *dev, int index, void *pcount)
{
int *pi = pcount;
if (pi) {
if ((*pi)-- == 0)
return (int)dev;
else
return 0;
} else {
/* Satisfied with first matching device, stop search */
return (int)dev;
}
}

View File

@@ -0,0 +1,109 @@
/*
* AMBA Plug & Play routines
*
* COPYRIGHT (c) 2011
* Aeroflex Gaisler
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*/
#include <grlib/ambapp.h>
/* Calculate AHB Bus frequency of
* - Bus[0] (inverse=1), relative to the frequency of Bus[ahbidx]
* NOTE: set freq_hz to frequency of Bus[ahbidx].
* or
* - Bus[ahbidx] (inverse=0), relative to the frequency of Bus[0]
* NOTE: set freq_hz to frequency of Bus[0].
*
* If a unsupported bridge is found the invalid frequncy of 0Hz is
* returned.
*/
static unsigned int ambapp_freq_calc(
struct ambapp_bus *abus,
int ahbidx,
unsigned int freq_hz,
int inverse)
{
struct ambapp_ahb_info *ahb;
struct ambapp_dev *bridge;
unsigned char ffact;
int dir;
/* Found Bus0? */
bridge = abus->ahbs[ahbidx].bridge;
if (!bridge)
return freq_hz;
/* Find this bus frequency relative to freq_hz */
if ((bridge->vendor == VENDOR_GAISLER) &&
((bridge->device == GAISLER_AHB2AHB) ||
(bridge->device == GAISLER_L2CACHE))) {
ahb = DEV_TO_AHB(bridge);
ffact = (ahb->custom[0] & AMBAPP_FLAG_FFACT) >> 4;
if (ffact != 0) {
dir = ahb->custom[0] & AMBAPP_FLAG_FFACT_DIR;
/* Calculate frequency by dividing or
* multiplying system frequency
*/
if ((dir && !inverse) || (!dir && inverse))
freq_hz = freq_hz * ffact;
else
freq_hz = freq_hz / ffact;
}
return ambapp_freq_calc(abus, ahb->ahbidx, freq_hz, inverse);
} else {
/* Unknown bridge, impossible to calc frequency */
return 0;
}
}
/* Find the frequency of all AHB Buses from knowing the frequency of one
* particular APB/AHB Device.
*/
void ambapp_freq_init(
struct ambapp_bus *abus,
struct ambapp_dev *dev,
unsigned int freq_hz)
{
struct ambapp_common_info *info;
int i;
for (i=0; i<AHB_BUS_MAX; i++)
abus->ahbs[i].freq_hz = 0;
/* Register Frequency at the AHB bus that the device the user gave us
* is located at.
*/
if (dev) {
info = DEV_TO_COMMON(dev);
abus->ahbs[info->ahbidx].freq_hz = freq_hz;
/* Find Frequency of Bus 0 */
abus->ahbs[0].freq_hz = ambapp_freq_calc(abus, info->ahbidx, freq_hz, 1);
} else {
abus->ahbs[0].freq_hz = freq_hz;
}
/* Find Frequency of all except for Bus0 and the bus which frequency
* was reported at
*/
for (i=1; i<AHB_BUS_MAX; i++) {
if (abus->ahbs[i].ioarea == 0)
break;
if (abus->ahbs[i].freq_hz != 0)
continue;
abus->ahbs[i].freq_hz = ambapp_freq_calc(abus, i, abus->ahbs[0].freq_hz, 0);
}
}
/* Assign a AMBA Bus a frequency but reporting the frequency of a
* particular AHB/APB device */
unsigned int ambapp_freq_get(struct ambapp_bus *abus, struct ambapp_dev *dev)
{
struct ambapp_common_info *info = DEV_TO_COMMON(dev);
return abus->ahbs[info->ahbidx].freq_hz;
}

View File

@@ -0,0 +1,447 @@
/*
* AMBA Plug & Play Device and Vendor name database: Created from GRLIB 3386.
*
* COPYRIGHT (c) 2009.
* Aeroflex Gaisler.
*
* The device and vendor definitions are extracted with a script from
* GRLIB.
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*/
#include <grlib/ambapp.h>
#include <grlib/ambapp_ids.h>
#include <string.h>
#ifndef NULL
#define NULL 0
#endif
typedef struct {
int device_id;
char *name;
} ambapp_device_name;
typedef struct {
unsigned int vendor_id;
char *name;
ambapp_device_name *devices;
} ambapp_vendor_devnames;
/**************** AUTO GENERATED FROM devices.vhd ****************/
static ambapp_device_name GAISLER_devices[] =
{
{GAISLER_LEON2DSU, "LEON2DSU"},
{GAISLER_LEON3, "LEON3"},
{GAISLER_LEON3DSU, "LEON3DSU"},
{GAISLER_ETHAHB, "ETHAHB"},
{GAISLER_APBMST, "APBMST"},
{GAISLER_AHBUART, "AHBUART"},
{GAISLER_SRCTRL, "SRCTRL"},
{GAISLER_SDCTRL, "SDCTRL"},
{GAISLER_SSRCTRL, "SSRCTRL"},
{GAISLER_I2C2AHB, "I2C2AHB"},
{GAISLER_APBUART, "APBUART"},
{GAISLER_IRQMP, "IRQMP"},
{GAISLER_AHBRAM, "AHBRAM"},
{GAISLER_AHBDPRAM, "AHBDPRAM"},
{GAISLER_GRIOMMU2, "GRIOMMU2"},
{GAISLER_GPTIMER, "GPTIMER"},
{GAISLER_PCITRG, "PCITRG"},
{GAISLER_PCISBRG, "PCISBRG"},
{GAISLER_PCIFBRG, "PCIFBRG"},
{GAISLER_PCITRACE, "PCITRACE"},
{GAISLER_DMACTRL, "DMACTRL"},
{GAISLER_AHBTRACE, "AHBTRACE"},
{GAISLER_DSUCTRL, "DSUCTRL"},
{GAISLER_CANAHB, "CANAHB"},
{GAISLER_GPIO, "GPIO"},
{GAISLER_AHBROM, "AHBROM"},
{GAISLER_AHBJTAG, "AHBJTAG"},
{GAISLER_ETHMAC, "ETHMAC"},
{GAISLER_SWNODE, "SWNODE"},
{GAISLER_SPW, "SPW"},
{GAISLER_AHB2AHB, "AHB2AHB"},
{GAISLER_USBDC, "USBDC"},
{GAISLER_USB_DCL, "USB_DCL"},
{GAISLER_DDRMP, "DDRMP"},
{GAISLER_ATACTRL, "ATACTRL"},
{GAISLER_DDRSP, "DDRSP"},
{GAISLER_EHCI, "EHCI"},
{GAISLER_UHCI, "UHCI"},
{GAISLER_I2CMST, "I2CMST"},
{GAISLER_SPW2, "SPW2"},
{GAISLER_AHBDMA, "AHBDMA"},
{GAISLER_NUHOSP3, "NUHOSP3"},
{GAISLER_CLKGATE, "CLKGATE"},
{GAISLER_SPICTRL, "SPICTRL"},
{GAISLER_DDR2SP, "DDR2SP"},
{GAISLER_SLINK, "SLINK"},
{GAISLER_GRTM, "GRTM"},
{GAISLER_GRTC, "GRTC"},
{GAISLER_GRPW, "GRPW"},
{GAISLER_GRCTM, "GRCTM"},
{GAISLER_GRHCAN, "GRHCAN"},
{GAISLER_GRFIFO, "GRFIFO"},
{GAISLER_GRADCDAC, "GRADCDAC"},
{GAISLER_GRPULSE, "GRPULSE"},
{GAISLER_GRTIMER, "GRTIMER"},
{GAISLER_AHB2PP, "AHB2PP"},
{GAISLER_GRVERSION, "GRVERSION"},
{GAISLER_APB2PW, "APB2PW"},
{GAISLER_PW2APB, "PW2APB"},
{GAISLER_GRCAN, "GRCAN"},
{GAISLER_I2CSLV, "I2CSLV"},
{GAISLER_U16550, "U16550"},
{GAISLER_AHBMST_EM, "AHBMST_EM"},
{GAISLER_AHBSLV_EM, "AHBSLV_EM"},
{GAISLER_GRTESTMOD, "GRTESTMOD"},
{GAISLER_ASCS, "ASCS"},
{GAISLER_IPMVBCTRL, "IPMVBCTRL"},
{GAISLER_SPIMCTRL, "SPIMCTRL"},
{GAISLER_L4STAT, "L4STAT"},
{GAISLER_LEON4, "LEON4"},
{GAISLER_LEON4DSU, "LEON4DSU"},
{GAISLER_PWM, "PWM"},
{GAISLER_L2CACHE, "L2CACHE"},
{GAISLER_SDCTRL64, "SDCTRL64"},
{GAISLER_GR1553B, "GR1553B"},
{GAISLER_1553TST, "1553TST"},
{GAISLER_GRIOMMU, "GRIOMMU"},
{GAISLER_FTAHBRAM, "FTAHBRAM"},
{GAISLER_FTSRCTRL, "FTSRCTRL"},
{GAISLER_AHBSTAT, "AHBSTAT"},
{GAISLER_LEON3FT, "LEON3FT"},
{GAISLER_FTMCTRL, "FTMCTRL"},
{GAISLER_FTSDCTRL, "FTSDCTRL"},
{GAISLER_FTSRCTRL8, "FTSRCTRL8"},
{GAISLER_MEMSCRUB, "MEMSCRUB"},
{GAISLER_FTSDCTRL64, "FTSDCTRL64"},
{GAISLER_NANDFCTRL, "NANDFCTRL"},
{GAISLER_N2DLLCTRL, "N2DLLCTRL"},
{GAISLER_N2PLLCTRL, "N2PLLCTRL"},
{GAISLER_SPI2AHB, "SPI2AHB"},
{GAISLER_DDRSDMUX, "DDRSDMUX"},
{GAISLER_AHBFROM, "AHBFROM"},
{GAISLER_PCIEXP, "PCIEXP"},
{GAISLER_APBPS2, "APBPS2"},
{GAISLER_VGACTRL, "VGACTRL"},
{GAISLER_LOGAN, "LOGAN"},
{GAISLER_SVGACTRL, "SVGACTRL"},
{GAISLER_T1AHB, "T1AHB"},
{GAISLER_MP7WRAP, "MP7WRAP"},
{GAISLER_GRSYSMON, "GRSYSMON"},
{GAISLER_GRACECTRL, "GRACECTRL"},
{GAISLER_ATAHBSLV, "ATAHBSLV"},
{GAISLER_ATAHBMST, "ATAHBMST"},
{GAISLER_ATAPBSLV, "ATAPBSLV"},
{GAISLER_MIGDDR2, "MIGDDR2"},
{GAISLER_LCDCTRL, "LCDCTRL"},
{GAISLER_SWITCHOVER, "SWITCHOVER"},
{GAISLER_FIFOUART, "FIFOUART"},
{GAISLER_MUXCTRL, "MUXCTRL"},
{GAISLER_B1553BC, "B1553BC"},
{GAISLER_B1553RT, "B1553RT"},
{GAISLER_B1553BRM, "B1553BRM"},
{GAISLER_AES, "AES"},
{GAISLER_ECC, "ECC"},
{GAISLER_PCIF, "PCIF"},
{GAISLER_CLKMOD, "CLKMOD"},
{GAISLER_HAPSTRAK, "HAPSTRAK"},
{GAISLER_TEST_1X2, "TEST_1X2"},
{GAISLER_WILD2AHB, "WILD2AHB"},
{GAISLER_BIO1, "BIO1"},
{GAISLER_AESDMA, "AESDMA"},
{GAISLER_GRPCI2, "GRPCI2"},
{GAISLER_GRPCI2_DMA, "GRPCI2_DMA"},
{GAISLER_GRPCI2_TB, "GRPCI2_TB"},
{GAISLER_MMA, "MMA"},
{GAISLER_SATCAN, "SATCAN"},
{GAISLER_CANMUX, "CANMUX"},
{GAISLER_GRTMRX, "GRTMRX"},
{GAISLER_GRTCTX, "GRTCTX"},
{GAISLER_GRTMDESC, "GRTMDESC"},
{GAISLER_GRTMVC, "GRTMVC"},
{GAISLER_GEFFE, "GEFFE"},
{GAISLER_GPREG, "GPREG"},
{GAISLER_GRTMPAHB, "GRTMPAHB"},
{GAISLER_SPWCUC, "SPWCUC"},
{GAISLER_SPW2_DMA, "SPW2_DMA"},
{GAISLER_SPWROUTER, "SPWROUTER"},
{GAISLER_EDCLMST, "EDCLMST"},
{GAISLER_GRPWTX, "GRPWTX"},
{GAISLER_GRPWRX, "GRPWRX"},
{GAISLER_GPREGBANK, "GPREGBANK"},
{GAISLER_MIG_7SERIES, "MIG_7SERIES"},
{GAISLER_GRSPW2_SIST, "GRSPW2_SIST"},
{GAISLER_SGMII, "SGMII"},
{GAISLER_RGMII, "RGMII"},
{GAISLER_IRQGEN, "IRQGEN"},
{GAISLER_GRDMAC, "GRDMAC"},
{GAISLER_AHB2AVLA, "AHB2AVLA"},
{GAISLER_SPWTDP, "SPWTDP"},
{GAISLER_L3STAT, "L3STAT"},
{GAISLER_GR740THS, "GR740THS"},
{GAISLER_GRRM, "GRRM"},
{GAISLER_CMAP, "CMAP"},
{GAISLER_CPGEN, "CPGEN"},
{GAISLER_AMBAPROT, "AMBAPROT"},
{GAISLER_IGLOO2_BRIDGE, "IGLOO2_BRIDGE"},
{GAISLER_AHB2AXI, "AHB2AXI"},
{GAISLER_AXI2AHB, "AXI2AHB"},
{GAISLER_FDIR_RSTCTRL, "FDIR_RSTCTRL"},
{GAISLER_APB3MST, "APB3MST"},
{GAISLER_LRAM, "LRAM"},
{GAISLER_BOOTSEQ, "BOOTSEQ"},
{GAISLER_TCCOP, "TCCOP"},
{GAISLER_SPIMASTER, "SPIMASTER"},
{GAISLER_SPISLAVE, "SPISLAVE"},
{GAISLER_GRSRIO, "GRSRIO"},
{0, NULL}
};
static ambapp_device_name PENDER_devices[] =
{
{0, NULL}
};
static ambapp_device_name ESA_devices[] =
{
{ESA_LEON2, "LEON2"},
{ESA_LEON2APB, "LEON2APB"},
{ESA_IRQ, "IRQ"},
{ESA_TIMER, "TIMER"},
{ESA_UART, "UART"},
{ESA_CFG, "CFG"},
{ESA_IO, "IO"},
{ESA_MCTRL, "MCTRL"},
{ESA_PCIARB, "PCIARB"},
{ESA_HURRICANE, "HURRICANE"},
{ESA_SPW_RMAP, "SPW_RMAP"},
{ESA_AHBUART, "AHBUART"},
{ESA_SPWA, "SPWA"},
{ESA_BOSCHCAN, "BOSCHCAN"},
{ESA_IRQ2, "IRQ2"},
{ESA_AHBSTAT, "AHBSTAT"},
{ESA_WPROT, "WPROT"},
{ESA_WPROT2, "WPROT2"},
{ESA_PDEC3AMBA, "PDEC3AMBA"},
{ESA_PTME3AMBA, "PTME3AMBA"},
{0, NULL}
};
static ambapp_device_name ASTRIUM_devices[] =
{
{0, NULL}
};
static ambapp_device_name OPENCHIP_devices[] =
{
{OPENCHIP_APBGPIO, "APBGPIO"},
{OPENCHIP_APBI2C, "APBI2C"},
{OPENCHIP_APBSPI, "APBSPI"},
{OPENCHIP_APBCHARLCD, "APBCHARLCD"},
{OPENCHIP_APBPWM, "APBPWM"},
{OPENCHIP_APBPS2, "APBPS2"},
{OPENCHIP_APBMMCSD, "APBMMCSD"},
{OPENCHIP_APBNAND, "APBNAND"},
{OPENCHIP_APBLPC, "APBLPC"},
{OPENCHIP_APBCF, "APBCF"},
{OPENCHIP_APBSYSACE, "APBSYSACE"},
{OPENCHIP_APB1WIRE, "APB1WIRE"},
{OPENCHIP_APBJTAG, "APBJTAG"},
{OPENCHIP_APBSUI, "APBSUI"},
{0, NULL}
};
static ambapp_device_name OPENCORES_devices[] =
{
{0, NULL}
};
static ambapp_device_name CONTRIB_devices[] =
{
{CONTRIB_CORE1, "CORE1"},
{CONTRIB_CORE2, "CORE2"},
{0, NULL}
};
static ambapp_device_name EONIC_devices[] =
{
{0, NULL}
};
static ambapp_device_name RADIONOR_devices[] =
{
{0, NULL}
};
static ambapp_device_name GLEICHMANN_devices[] =
{
{GLEICHMANN_CUSTOM, "CUSTOM"},
{GLEICHMANN_GEOLCD01, "GEOLCD01"},
{GLEICHMANN_DAC, "DAC"},
{GLEICHMANN_HPI, "HPI"},
{GLEICHMANN_SPI, "SPI"},
{GLEICHMANN_HIFC, "HIFC"},
{GLEICHMANN_ADCDAC, "ADCDAC"},
{GLEICHMANN_SPIOC, "SPIOC"},
{GLEICHMANN_AC97, "AC97"},
{0, NULL}
};
static ambapp_device_name MENTA_devices[] =
{
{0, NULL}
};
static ambapp_device_name SUN_devices[] =
{
{SUN_T1, "SUN_T1"},
{SUN_S1, "SUN_S1"},
{0, NULL}
};
static ambapp_device_name MOVIDIA_devices[] =
{
{0, NULL}
};
static ambapp_device_name ORBITA_devices[] =
{
{ORBITA_1553B, "1553B"},
{ORBITA_429, "429"},
{ORBITA_SPI, "SPI"},
{ORBITA_I2C, "I2C"},
{ORBITA_SMARTCARD, "SMARTCARD"},
{ORBITA_SDCARD, "SDCARD"},
{ORBITA_UART16550, "UART16550"},
{ORBITA_CRYPTO, "CRYPTO"},
{ORBITA_SYSIF, "SYSIF"},
{ORBITA_PIO, "PIO"},
{ORBITA_RTC, "RTC"},
{ORBITA_COLORLCD, "COLORLCD"},
{ORBITA_PCI, "PCI"},
{ORBITA_DSP, "DSP"},
{ORBITA_USBHOST, "USBHOST"},
{ORBITA_USBDEV, "USBDEV"},
{0, NULL}
};
static ambapp_device_name SYNOPSYS_devices[] =
{
{0, NULL}
};
static ambapp_device_name NASA_devices[] =
{
{NASA_EP32, "EP32"},
{0, NULL}
};
static ambapp_device_name CAL_devices[] =
{
{CAL_DDRCTRL, "DDRCTRL"},
{0, NULL}
};
static ambapp_device_name EMBEDDIT_devices[] =
{
{0, NULL}
};
static ambapp_device_name CETON_devices[] =
{
{0, NULL}
};
static ambapp_device_name ACTEL_devices[] =
{
{ACTEL_COREMP7, "COREMP7"},
{0, NULL}
};
static ambapp_vendor_devnames vendors[] =
{
{VENDOR_GAISLER, "GAISLER", GAISLER_devices},
{VENDOR_PENDER, "PENDER", PENDER_devices},
{VENDOR_ESA, "ESA", ESA_devices},
{VENDOR_ASTRIUM, "ASTRIUM", ASTRIUM_devices},
{VENDOR_OPENCHIP, "OPENCHIP", OPENCHIP_devices},
{VENDOR_OPENCORES, "OPENCORES", OPENCORES_devices},
{VENDOR_CONTRIB, "CONTRIB", CONTRIB_devices},
{VENDOR_EONIC, "EONIC", EONIC_devices},
{VENDOR_RADIONOR, "RADIONOR", RADIONOR_devices},
{VENDOR_GLEICHMANN, "GLEICHMANN", GLEICHMANN_devices},
{VENDOR_MENTA, "MENTA", MENTA_devices},
{VENDOR_SUN, "SUN", SUN_devices},
{VENDOR_MOVIDIA, "MOVIDIA", MOVIDIA_devices},
{VENDOR_ORBITA, "ORBITA", ORBITA_devices},
{VENDOR_SYNOPSYS, "SYNOPSYS", SYNOPSYS_devices},
{VENDOR_NASA, "NASA", NASA_devices},
{VENDOR_CAL, "CAL", CAL_devices},
{VENDOR_EMBEDDIT, "EMBEDDIT", EMBEDDIT_devices},
{VENDOR_CETON, "CETON", CETON_devices},
{VENDOR_ACTEL, "ACTEL", ACTEL_devices},
{0, NULL, NULL}
};
/*****************************************************************/
static char *ambapp_get_devname(ambapp_device_name *devs, int id)
{
while (devs->device_id > 0) {
if (devs->device_id == id)
return devs->name;
devs++;
}
return NULL;
}
char *ambapp_device_id2str(int vendor, int id)
{
ambapp_vendor_devnames *ven = &vendors[0];
while (ven->vendor_id > 0) {
if (ven->vendor_id == vendor)
return ambapp_get_devname(ven->devices, id);
ven++;
}
return NULL;
}
char *ambapp_vendor_id2str(int vendor)
{
ambapp_vendor_devnames *ven = &vendors[0];
while (ven->vendor_id > 0) {
if (ven->vendor_id == vendor)
return ven->name;
ven++;
}
return NULL;
}
int ambapp_vendev_id2str(int vendor, int id, char *buf)
{
char *dstr, *vstr;
*buf = '\0';
vstr = ambapp_vendor_id2str(vendor);
if (vstr == NULL)
return 0;
dstr = ambapp_device_id2str(vendor, id);
if (dstr == NULL)
return 0;
strcpy(buf, vstr);
strcat(buf, "_");
strcat(buf, dstr);
return strlen(buf);
}

View File

@@ -0,0 +1,112 @@
/*
* Old AMBA scanning Interface provided for backwards compability
*
* COPYRIGHT (c) 2011
* Aeroflex Gaisler
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*/
#include <grlib/ambapp.h>
struct ambapp_dev_find_match_arg {
int index;
int count;
int type;
void *dev;
};
/* AMBA PP find routines */
static int ambapp_dev_find_match(struct ambapp_dev *dev, int index, void *arg)
{
struct ambapp_dev_find_match_arg *p = arg;
if (p->index == 0) {
/* Found controller, stop */
if (p->type == DEV_APB_SLV) {
*(struct ambapp_apb_info *)p->dev = *DEV_TO_APB(dev);
p->dev = ((struct ambapp_apb_info *)p->dev)+1;
} else {
*(struct ambapp_ahb_info *)p->dev = *DEV_TO_AHB(dev);
p->dev = ((struct ambapp_ahb_info *)p->dev)+1;
}
p->count--;
if (p->count < 1)
return 1;
} else {
p->index--;
}
return 0;
}
int ambapp_find_apbslvs_next(struct ambapp_bus *abus, int vendor, int device, struct ambapp_apb_info *dev, int index, int maxno)
{
struct ambapp_dev_find_match_arg arg;
arg.index = index;
arg.count = maxno;
arg.type = DEV_APB_SLV; /* APB */
arg.dev = dev;
ambapp_for_each(abus, (OPTIONS_ALL|OPTIONS_APB_SLVS), vendor, device,
ambapp_dev_find_match, &arg);
return maxno - arg.count;
}
int ambapp_find_apbslv(struct ambapp_bus *abus, int vendor, int device, struct ambapp_apb_info *dev)
{
return ambapp_find_apbslvs_next(abus, vendor, device, dev, 0, 1);
}
int ambapp_find_apbslv_next(struct ambapp_bus *abus, int vendor, int device, struct ambapp_apb_info *dev, int index)
{
return ambapp_find_apbslvs_next(abus, vendor, device, dev, index, 1);
}
int ambapp_find_apbslvs(struct ambapp_bus *abus, int vendor, int device, struct ambapp_apb_info *dev, int maxno)
{
return ambapp_find_apbslvs_next(abus, vendor, device, dev, 0, maxno);
}
int ambapp_get_number_apbslv_devices(struct ambapp_bus *abus, int vendor, int device)
{
return ambapp_dev_count(abus, (OPTIONS_ALL|OPTIONS_APB_SLVS), vendor, device);
}
int ambapp_find_ahbslvs_next(struct ambapp_bus *abus, int vendor, int device, struct ambapp_ahb_info *dev, int index, int maxno)
{
struct ambapp_dev_find_match_arg arg;
arg.index = index;
arg.count = maxno;
arg.type = DEV_AHB_SLV; /* AHB SLV */
arg.dev = dev;
ambapp_for_each(abus, (OPTIONS_ALL|OPTIONS_AHB_SLVS), vendor, device,
ambapp_dev_find_match, &arg);
return maxno - arg.count;
}
int ambapp_find_ahbslv_next(struct ambapp_bus *abus, int vendor, int device, struct ambapp_ahb_info *dev, int index)
{
return ambapp_find_ahbslvs_next(abus, vendor, device, dev, index, 1);
}
int ambapp_find_ahbslv(struct ambapp_bus *abus, int vendor, int device, struct ambapp_ahb_info *dev)
{
return ambapp_find_ahbslvs_next(abus, vendor, device, dev, 0, 1);
}
int ambapp_find_ahbslvs(struct ambapp_bus *abus, int vendor, int device, struct ambapp_ahb_info *dev, int maxno)
{
return ambapp_find_ahbslvs_next(abus, vendor, device, dev, 0, maxno);
}
int ambapp_get_number_ahbslv_devices(struct ambapp_bus *abus, int vendor, int device)
{
return ambapp_dev_count(abus, (OPTIONS_ALL|OPTIONS_AHB_SLVS), vendor, device);
}

View File

@@ -0,0 +1,23 @@
/*
* AMBA Plug & Play routines
*
* COPYRIGHT (c) 2011
* Aeroflex Gaisler
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*/
#include <stdlib.h>
#include <grlib/ambapp.h>
struct ambapp_dev *ambapp_find_parent(struct ambapp_dev *dev)
{
while (dev->prev) {
if (dev == dev->prev->children)
return dev->prev;
dev = dev->prev;
}
return NULL;
}

View File

@@ -0,0 +1,68 @@
/*
* AMBA Plug & Play routines: device information printing.
*
* COPYRIGHT (c) 2009.
* Aeroflex Gaisler.
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*/
#include <stdio.h>
#include <grlib/ambapp.h>
struct ambapp_dev_print_arg {
int show_depth;
};
static char *unknown = "unknown";
static int ambapp_dev_print(struct ambapp_dev *dev, int index, void *arg)
{
char *dev_str, *ven_str, *type_str;
struct ambapp_dev_print_arg *p = arg;
char dp[32];
int i=0;
unsigned int basereg;
if (p->show_depth) {
for (i=0; i<ambapp_depth(dev)*2; i+=2) {
dp[i] = ' ';
dp[i+1] = ' ';
}
}
dp[i] = '\0';
ven_str = ambapp_vendor_id2str(dev->vendor);
if (!ven_str) {
ven_str = unknown;
dev_str = unknown;
} else {
dev_str = ambapp_device_id2str(dev->vendor, dev->device);
if (!dev_str)
dev_str = unknown;
}
if (dev->dev_type == DEV_APB_SLV) {
/* APB */
basereg = DEV_TO_APB(dev)->start;
type_str = "apb";
} else {
/* AHB */
basereg = DEV_TO_AHB(dev)->start[0];
type_str = "ahb";
}
printf("%s |-> 0x%x:0x%x:0x%x: %s_%s, %s: 0x%x, 0x%x (OWNER: 0x%x)\n",
dp, index, dev->vendor, dev->device, ven_str, dev_str, type_str,
basereg, (unsigned int)dev, (unsigned int)dev->owner);
return 0;
}
void ambapp_print(struct ambapp_bus *abus, int show_depth)
{
struct ambapp_dev_print_arg arg;
arg.show_depth = show_depth;
ambapp_for_each(abus, (OPTIONS_ALL_DEVS|OPTIONS_ALL|OPTIONS_DEPTH_FIRST), -1,
-1, ambapp_dev_print, &arg);
}