diff options
author | Daniel Hellstrom <daniel@gaisler.com> | 2015-02-23 13:02:39 +0100 |
---|---|---|
committer | Daniel Hellstrom <daniel@gaisler.com> | 2015-04-17 01:10:17 +0200 |
commit | 3bb41226e0941b86d58ecb97f7d292677de573c8 (patch) | |
tree | 907aa270343f7c6d1bc08bf73288fb9b10da6197 /c/src/lib/libbsp/sparc/shared/1553/gr1553b.c | |
parent | LEON: added network device configuration helper function (diff) | |
download | rtems-3bb41226e0941b86d58ecb97f7d292677de573c8.tar.bz2 |
LEON: added new drivers to the LEON2/LEON3 BSPs
Most drivers use the Driver Manager for device probing, they
work on AMBA-over-PCI systems if PCI is big-endian.
New APIs:
* GPIO Library, interfaced to GRGPIO
* GENIRQ, Generic interrupt service implementation helper
New GRLIB Drivers:
* ACTEL 1553 RT, user interface is similar to 1553 BRM driver
* GR1553 (1553 BC, RT and BM core)
* AHBSTAT (AHB error status core)
* GRADCDAC (Core interfacing to ADC/DAC hardware)
* GRGPIO (GPIO port accessed from GPIO Library)
* MCTRL (Memory controller settings configuration)
* GRETH (10/100/1000 Ethernet driver using Driver manager)
* GRPWM (Pulse Width Modulation core)
* SPICTRL (SPI master interface)
* GRSPW_ROUTER (SpaceWire Router AMBA configuration interface)
* GRCTM (SpaceCraft on-board Time Management core)
* SPWCUC (Time distribution over SpaceWire)
* GRTC (SpaceCraft up-link Tele core)
* GRTM (SpaceCraft down-link Tele Metry core)
GR712RC ASIC specific interfaces:
* GRASCS
* CANMUX (select between OCCAN and SATCAN)
* SATCAN
* SLINK
Diffstat (limited to 'c/src/lib/libbsp/sparc/shared/1553/gr1553b.c')
-rw-r--r-- | c/src/lib/libbsp/sparc/shared/1553/gr1553b.c | 305 |
1 files changed, 305 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/sparc/shared/1553/gr1553b.c b/c/src/lib/libbsp/sparc/shared/1553/gr1553b.c new file mode 100644 index 0000000000..26d7b400c3 --- /dev/null +++ b/c/src/lib/libbsp/sparc/shared/1553/gr1553b.c @@ -0,0 +1,305 @@ +/* GR1553B driver, used by BC, RT and/or BM driver + * + * COPYRIGHT (c) 2010. + * 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. + */ + +#include <stdlib.h> +#include <drvmgr/ambapp_bus.h> + +#include <gr1553b.h> + +/* Driver Manager interface for BC, RT, BM, BRM, BC-BM and RT-BM */ + +#define GR1553B_WRITE_REG(adr, val) *(volatile uint32_t *)(adr) = (val) +#define GR1553B_READ_REG(adr) (*(volatile uint32_t *)(adr)) + +#define FEAT_BC 0x1 +#define FEAT_RT 0x2 +#define FEAT_BM 0x4 + +#define ALLOC_BC 0x1 +#define ALLOC_RT 0x2 +#define ALLOC_BM 0x4 + +struct gr1553_device { + struct drvmgr_dev *dev; + int features; + int alloc; +}; + +struct gr1553_device_feature { + struct gr1553_device_feature *next; + struct gr1553_device *dev; + int minor; +}; + +/* Device lists */ +struct gr1553_device_feature *gr1553_bm_root = NULL; +struct gr1553_device_feature *gr1553_rt_root = NULL; +struct gr1553_device_feature *gr1553_bc_root = NULL; + +/* Driver registered */ +int gr1553_driver_registerd = 0; + +/* Add 'feat' to linked list pointed to by 'root'. A minor is also assigned. */ +void gr1553_list_add + ( + struct gr1553_device_feature **root, + struct gr1553_device_feature *feat + ) +{ + int minor; + struct gr1553_device_feature *curr; + + if ( *root == NULL ) { + *root = feat; + feat->next = NULL; + feat->minor = 0; + return; + } + + minor = 0; +retry_new_minor: + curr = *root; + while ( curr->next ) { + if ( curr->minor == minor ) { + minor++; + goto retry_new_minor; + } + curr = curr->next; + } + + feat->next = NULL; + feat->minor = minor; + curr->next = feat; +} + +struct gr1553_device_feature *gr1553_list_find + ( + struct gr1553_device_feature *root, + int minor + ) +{ + struct gr1553_device_feature *curr = root; + while ( curr ) { + if ( curr->minor == minor ) { + return curr; + } + curr = curr->next; + } + return NULL; +} + +struct drvmgr_dev **gr1553_bc_open(int minor) +{ + struct gr1553_device_feature *feat; + + feat = gr1553_list_find(gr1553_bc_root, minor); + if ( feat == NULL ) + return NULL; + + /* Only possible to allocate is RT and BC is free, + * this is beacuse it is not possible to use the + * RT and the BC at the same time. + */ + if ( feat->dev->alloc & (ALLOC_BC|ALLOC_RT) ) + return NULL; + + /* Alloc BC device */ + feat->dev->alloc |= ALLOC_BC; + + return &feat->dev->dev; +} + +void gr1553_bc_close(struct drvmgr_dev **dev) +{ + struct gr1553_device *d = (struct gr1553_device *)dev; + + d->alloc &= ~ALLOC_BC; +} + +struct drvmgr_dev **gr1553_rt_open(int minor) +{ + struct gr1553_device_feature *feat; + + feat = gr1553_list_find(gr1553_rt_root, minor); + if ( feat == NULL ) + return NULL; + + /* Only possible to allocate is RT and BC is free, + * this is beacuse it is not possible to use the + * RT and the BC at the same time. + */ + if ( feat->dev->alloc & (ALLOC_BC|ALLOC_RT) ) + return NULL; + + /* Alloc RT device */ + feat->dev->alloc |= ALLOC_RT; + + return &feat->dev->dev; +} + +void gr1553_rt_close(struct drvmgr_dev **dev) +{ + struct gr1553_device *d = (struct gr1553_device *)dev; + + d->alloc &= ~ALLOC_RT; +} + +struct drvmgr_dev **gr1553_bm_open(int minor) +{ + struct gr1553_device_feature *feat; + + feat = gr1553_list_find(gr1553_bm_root, minor); + if ( feat == NULL ) + return NULL; + + /* Only possible to allocate is RT and BC is free, + * this is beacuse it is not possible to use the + * RT and the BC at the same time. + */ + if ( feat->dev->alloc & ALLOC_BM ) + return NULL; + + /* Alloc BM device */ + feat->dev->alloc |= ALLOC_BM; + + return &feat->dev->dev; +} + +void gr1553_bm_close(struct drvmgr_dev **dev) +{ + struct gr1553_device *d = (struct gr1553_device *)dev; + + d->alloc &= ~ALLOC_BM; +} + +int gr1553_init2(struct drvmgr_dev *dev) +{ + struct amba_dev_info *ambadev; + struct ambapp_core *pnpinfo; + struct gr1553b_regs *regs; + + /* Get device information from AMBA PnP information */ + ambadev = (struct amba_dev_info *)dev->businfo; + if ( ambadev == NULL ) { + return DRVMGR_FAIL; + } + pnpinfo = &ambadev->info; + regs = (struct gr1553b_regs *)pnpinfo->apb_slv->start; + + /* Stop IRQ */ + GR1553B_WRITE_REG(®s->imask, 0); + GR1553B_WRITE_REG(®s->irq, 0xffffffff); + /* Stop BC if not already stopped (just in case) */ + GR1553B_WRITE_REG(®s->bc_ctrl, 0x15520204); + /* Stop RT rx (just in case) */ + GR1553B_WRITE_REG(®s->rt_cfg, 0x15530000); + /* Stop BM logging (just in case) */ + GR1553B_WRITE_REG(®s->bm_ctrl, 0); + + return DRVMGR_OK; +} + +/* Register the different functionalities that the + * core supports. + */ +int gr1553_init3(struct drvmgr_dev *dev) +{ + struct amba_dev_info *ambadev; + struct ambapp_core *pnpinfo; + struct gr1553_device *priv; + struct gr1553_device_feature *feat; + struct gr1553b_regs *regs; + + priv = malloc(sizeof(struct gr1553_device)); + if ( priv == NULL ) + return DRVMGR_NOMEM; + priv->dev = dev; + priv->alloc = 0; + priv->features = 0; + dev->priv = NULL; /* Let higher level driver handle this */ + + /* Get device information from AMBA PnP information */ + ambadev = (struct amba_dev_info *)dev->businfo; + if ( ambadev == NULL ) { + return DRVMGR_FAIL; + } + pnpinfo = &ambadev->info; + regs = (struct gr1553b_regs *)pnpinfo->apb_slv->start; + + if ( GR1553B_READ_REG(®s->bm_stat) & GR1553B_BM_STAT_BMSUP ) { + priv->features |= FEAT_BM; + feat = malloc(sizeof(struct gr1553_device_feature)); + feat->dev = priv; + /* Init Minor and Next */ + gr1553_list_add(&gr1553_bm_root, feat); + } + + if ( GR1553B_READ_REG(®s->bc_stat) & GR1553B_BC_STAT_BCSUP ) { + priv->features |= FEAT_BC; + feat = malloc(sizeof(struct gr1553_device_feature)); + feat->dev = priv; + /* Init Minor and Next */ + gr1553_list_add(&gr1553_bc_root, feat); + } + + if ( GR1553B_READ_REG(®s->rt_stat) & GR1553B_RT_STAT_RTSUP ) { + priv->features |= FEAT_RT; + feat = malloc(sizeof(struct gr1553_device_feature)); + feat->dev = priv; + /* Init Minor and Next */ + gr1553_list_add(&gr1553_rt_root, feat); + } + + return DRVMGR_OK; +} + +struct drvmgr_drv_ops gr1553_ops = +{ + {NULL, gr1553_init2, gr1553_init3, NULL}, + NULL, + NULL +}; + +struct amba_dev_id gr1553_ids[] = +{ + {VENDOR_GAISLER, GAISLER_GR1553B}, + {0, 0} /* Mark end of table */ +}; + +struct amba_drv_info gr1553_drv_info = +{ + { + DRVMGR_OBJ_DRV, /* Driver */ + NULL, /* Next driver */ + NULL, /* Device list */ + DRIVER_AMBAPP_GAISLER_GR1553B_ID,/* Driver ID */ + "GR1553_DRV", /* Driver Name */ + DRVMGR_BUS_TYPE_AMBAPP, /* Bus Type */ + &gr1553_ops, + NULL, /* Funcs */ + 0, /* No devices yet */ + 0, + }, + &gr1553_ids[0] +}; + +/* Multiple drivers may call this function. The drivers that depends on + * this driver: + * - BM driver + * - BC driver + * - RT driver + */ +void gr1553_register(void) +{ + if ( gr1553_driver_registerd == 0 ) { + gr1553_driver_registerd = 1; + drvmgr_drv_register(&gr1553_drv_info.general); + } +} |