Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:05

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*  GR1553B driver, used by BC, RT and/or BM driver
0004  *
0005  *  COPYRIGHT (c) 2010.
0006  *  Cobham Gaisler AB.
0007  *
0008  * Redistribution and use in source and binary forms, with or without
0009  * modification, are permitted provided that the following conditions
0010  * are met:
0011  * 1. Redistributions of source code must retain the above copyright
0012  *    notice, this list of conditions and the following disclaimer.
0013  * 2. Redistributions in binary form must reproduce the above copyright
0014  *    notice, this list of conditions and the following disclaimer in the
0015  *    documentation and/or other materials provided with the distribution.
0016  *
0017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0018  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0020  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0021  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0022  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0023  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0026  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0027  * POSSIBILITY OF SUCH DAMAGE.
0028  */
0029 
0030 #include <stdlib.h>
0031 #include <grlib/ambapp_bus.h>
0032 
0033 #include <grlib/gr1553b.h>
0034 
0035 #include <grlib/grlib_impl.h>
0036 
0037 /* Driver Manager interface for BC, RT, BM, BRM, BC-BM and RT-BM */
0038 
0039 #define GR1553B_WRITE_REG(adr, val) *(volatile uint32_t *)(adr) = (val)
0040 #define GR1553B_READ_REG(adr) (*(volatile uint32_t *)(adr))
0041 
0042 #define FEAT_BC 0x1
0043 #define FEAT_RT 0x2
0044 #define FEAT_BM 0x4
0045 
0046 #define ALLOC_BC 0x1
0047 #define ALLOC_RT 0x2
0048 #define ALLOC_BM 0x4
0049 
0050 struct gr1553_device {
0051     struct drvmgr_dev *dev;
0052     int features;
0053     int alloc;
0054 };
0055 
0056 struct gr1553_device_feature {
0057     struct gr1553_device_feature *next;
0058     struct gr1553_device *dev;
0059     int minor;
0060 };
0061 
0062 /* Device lists */
0063 static struct gr1553_device_feature *gr1553_bm_root = NULL;
0064 static struct gr1553_device_feature *gr1553_rt_root = NULL;
0065 static struct gr1553_device_feature *gr1553_bc_root = NULL;
0066 
0067 /* Driver registered */
0068 static int gr1553_driver_registerd = 0;
0069 
0070 /* Add 'feat' to linked list pointed to by 'root'. A minor is also assigned. */
0071 static void gr1553_list_add
0072     (
0073     struct gr1553_device_feature **root,
0074     struct gr1553_device_feature *feat
0075     )
0076 {
0077     int minor;
0078     struct gr1553_device_feature *curr;
0079 
0080     if ( *root == NULL ) {
0081         *root = feat;
0082         feat->next = NULL;
0083         feat->minor = 0;
0084         return;
0085     }
0086 
0087     minor = 0;
0088 retry_new_minor:
0089     curr = *root;
0090     while ( curr->next ) {
0091         if ( curr->minor == minor ) {
0092             minor++;
0093             goto retry_new_minor;
0094         }
0095         curr = curr->next;
0096     }
0097 
0098     feat->next = NULL;
0099     feat->minor = minor;
0100     curr->next = feat;
0101 }
0102 
0103 static struct gr1553_device_feature *gr1553_list_find
0104     (
0105     struct gr1553_device_feature *root,
0106     int minor
0107     )
0108 {
0109     struct gr1553_device_feature *curr = root;
0110     while ( curr ) {
0111         if ( curr->minor == minor ) {
0112             return curr;
0113         }
0114         curr = curr->next;
0115     }
0116     return NULL;
0117 }
0118 
0119 struct drvmgr_dev **gr1553_bc_open(int minor)
0120 {
0121     struct gr1553_device_feature *feat;
0122     
0123     feat = gr1553_list_find(gr1553_bc_root, minor);
0124     if ( feat == NULL )
0125         return NULL;
0126 
0127     /* Only possible to allocate is RT and BC is free,
0128      * this is beacuse it is not possible to use the
0129      * RT and the BC at the same time.
0130      */
0131     if ( feat->dev->alloc & (ALLOC_BC|ALLOC_RT) )
0132         return NULL;
0133 
0134     /* Alloc BC device */
0135     feat->dev->alloc |= ALLOC_BC;
0136 
0137     return &feat->dev->dev;
0138 }
0139 
0140 void gr1553_bc_close(struct drvmgr_dev **dev)
0141 {
0142     struct gr1553_device *d = (struct gr1553_device *)dev;
0143 
0144     d->alloc &= ~ALLOC_BC;
0145 }
0146 
0147 struct drvmgr_dev **gr1553_rt_open(int minor)
0148 {
0149     struct gr1553_device_feature *feat;
0150 
0151     feat = gr1553_list_find(gr1553_rt_root, minor);
0152     if ( feat == NULL )
0153         return NULL;
0154 
0155     /* Only possible to allocate is RT and BC is free,
0156      * this is beacuse it is not possible to use the
0157      * RT and the BC at the same time.
0158      */
0159     if ( feat->dev->alloc & (ALLOC_BC|ALLOC_RT) )
0160         return NULL;
0161 
0162     /* Alloc RT device */
0163     feat->dev->alloc |= ALLOC_RT;
0164 
0165     return &feat->dev->dev;
0166 }
0167 
0168 void gr1553_rt_close(struct drvmgr_dev **dev)
0169 {
0170     struct gr1553_device *d = (struct gr1553_device *)dev;
0171 
0172     d->alloc &= ~ALLOC_RT;
0173 }
0174 
0175 struct drvmgr_dev **gr1553_bm_open(int minor)
0176 {
0177     struct gr1553_device_feature *feat;
0178     
0179     feat = gr1553_list_find(gr1553_bm_root, minor);
0180     if ( feat == NULL )
0181         return NULL;
0182 
0183     /* Only possible to allocate is RT and BC is free,
0184      * this is beacuse it is not possible to use the
0185      * RT and the BC at the same time.
0186      */
0187     if ( feat->dev->alloc & ALLOC_BM )
0188         return NULL;
0189 
0190     /* Alloc BM device */
0191     feat->dev->alloc |= ALLOC_BM;
0192 
0193     return &feat->dev->dev;
0194 }
0195 
0196 void gr1553_bm_close(struct drvmgr_dev **dev)
0197 {
0198     struct gr1553_device *d = (struct gr1553_device *)dev;
0199 
0200     d->alloc &= ~ALLOC_BM;
0201 }
0202 
0203 static int gr1553_init2(struct drvmgr_dev *dev)
0204 {
0205     struct amba_dev_info *ambadev;
0206     struct ambapp_core *pnpinfo;
0207     struct gr1553b_regs *regs;
0208 
0209     /* Get device information from AMBA PnP information */
0210     ambadev = (struct amba_dev_info *)dev->businfo;
0211     if ( ambadev == NULL ) {
0212         return DRVMGR_FAIL;
0213     }
0214     pnpinfo = &ambadev->info;
0215     if ( pnpinfo->apb_slv == NULL )
0216         return DRVMGR_EIO;
0217     regs = (struct gr1553b_regs *)pnpinfo->apb_slv->start;
0218 
0219     /* Stop IRQ */
0220     GR1553B_WRITE_REG(&regs->imask, 0);
0221     GR1553B_WRITE_REG(&regs->irq, 0xffffffff);
0222     /* Stop BC if not already stopped (just in case) */
0223     GR1553B_WRITE_REG(&regs->bc_ctrl, 0x15520204);
0224     /* Stop RT rx (just in case) */
0225     GR1553B_WRITE_REG(&regs->rt_cfg, 0x15530000);
0226     /* Stop BM logging (just in case) */
0227     GR1553B_WRITE_REG(&regs->bm_ctrl, 0);
0228     /* Set codec version. This is only supported by some devices, i.e. GR740.
0229      * It will not have any effect on devices that does not support this bit. 
0230      */
0231     GR1553B_WRITE_REG(&regs->hwcfg, 1<<12);
0232 
0233     return DRVMGR_OK;
0234 }
0235 
0236 /* Register the different functionalities that the
0237  * core supports.
0238  */
0239 static int gr1553_init3(struct drvmgr_dev *dev)
0240 {
0241     struct amba_dev_info *ambadev;
0242     struct ambapp_core *pnpinfo;
0243     struct gr1553_device *priv;
0244     struct gr1553_device_feature *feat;
0245     struct gr1553b_regs *regs;
0246 
0247     priv = grlib_malloc(sizeof(*priv));
0248     if ( priv == NULL )
0249         return DRVMGR_NOMEM;
0250     priv->dev = dev;
0251     priv->alloc = 0;
0252     priv->features = 0;
0253     dev->priv = NULL; /* Let higher level driver handle this */
0254 
0255     /* Get device information from AMBA PnP information */
0256     ambadev = (struct amba_dev_info *)dev->businfo;
0257     pnpinfo = &ambadev->info;
0258     regs = (struct gr1553b_regs *)pnpinfo->apb_slv->start;
0259 
0260     if ( GR1553B_READ_REG(&regs->bm_stat) & GR1553B_BM_STAT_BMSUP ) {
0261         priv->features |= FEAT_BM;
0262         feat = grlib_malloc(sizeof(*feat));
0263         feat->dev = priv;
0264         /* Init Minor and Next */
0265         gr1553_list_add(&gr1553_bm_root, feat);
0266     }
0267 
0268     if ( GR1553B_READ_REG(&regs->bc_stat) & GR1553B_BC_STAT_BCSUP ) {
0269         priv->features |= FEAT_BC;
0270         feat = grlib_malloc(sizeof(*feat));
0271         feat->dev = priv;
0272         /* Init Minor and Next */
0273         gr1553_list_add(&gr1553_bc_root, feat);
0274     }
0275 
0276     if ( GR1553B_READ_REG(&regs->rt_stat) & GR1553B_RT_STAT_RTSUP ) {
0277         priv->features |= FEAT_RT;
0278         feat = grlib_malloc(sizeof(*feat));
0279         feat->dev = priv;
0280         /* Init Minor and Next */
0281         gr1553_list_add(&gr1553_rt_root, feat);
0282     }
0283 
0284     if ( priv->features == 0 ) {
0285         /* no features in HW should never happen.. an I/O error? */
0286         free(priv);
0287         return DRVMGR_EIO;
0288     }
0289 
0290     return DRVMGR_OK;
0291 }
0292 
0293 struct drvmgr_drv_ops gr1553_ops =
0294 {
0295     {NULL, gr1553_init2, gr1553_init3, NULL},
0296     NULL,
0297     NULL
0298 };
0299 
0300 struct amba_dev_id gr1553_ids[] =
0301 {
0302     {VENDOR_GAISLER, GAISLER_GR1553B},
0303     {0, 0}  /* Mark end of table */
0304 };
0305 
0306 struct amba_drv_info gr1553_drv_info =
0307 {
0308     {
0309         DRVMGR_OBJ_DRV,         /* Driver */
0310         NULL,               /* Next driver */
0311         NULL,               /* Device list */
0312         DRIVER_AMBAPP_GAISLER_GR1553B_ID,/* Driver ID */
0313         "GR1553_DRV",           /* Driver Name */
0314         DRVMGR_BUS_TYPE_AMBAPP,     /* Bus Type */
0315         &gr1553_ops,
0316         NULL,               /* Funcs */
0317         0,              /* No devices yet */
0318         0,
0319     },
0320     &gr1553_ids[0]
0321 };
0322 
0323 /* Multiple drivers may call this function. The drivers that depends on
0324  * this driver:
0325  *  - BM driver
0326  *  - BC driver
0327  *  - RT driver
0328  */
0329 void gr1553_register(void)
0330 {
0331     if ( gr1553_driver_registerd == 0 ) {
0332         gr1553_driver_registerd = 1;
0333             drvmgr_drv_register(&gr1553_drv_info.general);
0334     }
0335 }