Back to home page

LXR

 
 

    


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

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*  LEON2 GRLIB AMBA Plug & Play bus driver.
0004  *
0005  *  COPYRIGHT (c) 2008.
0006  *  Cobham Gaisler AB.
0007  *
0008  *  This is driver is a wrapper for the general AMBA Plug & Play bus
0009  *  driver. This is a bus driver for LEON2-GRLIB systems providing a
0010  *  AMBA Plug & Play bus, the parent bus must be a LEON2 hardcoded
0011  *  Bus. All IRQs must be routed to this bus driver in order for IRQs
0012  *  to work. The PnP information is used to extract IRQs and base
0013  *  register addresses.
0014  *
0015  * Redistribution and use in source and binary forms, with or without
0016  * modification, are permitted provided that the following conditions
0017  * are met:
0018  * 1. Redistributions of source code must retain the above copyright
0019  *    notice, this list of conditions and the following disclaimer.
0020  * 2. Redistributions in binary form must reproduce the above copyright
0021  *    notice, this list of conditions and the following disclaimer in the
0022  *    documentation and/or other materials provided with the distribution.
0023  *
0024  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0025  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0026  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0027  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0028  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0029  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0030  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0031  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0032  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0033  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0034  * POSSIBILITY OF SUCH DAMAGE.
0035  */
0036 
0037 #include <bsp.h>
0038 
0039 #ifdef LEON2
0040 #include <stdlib.h>
0041 #include <stdio.h>
0042 #include <string.h>
0043 #include <libcpu/access.h>
0044 #include <drvmgr/drvmgr.h>
0045 #include <grlib/ambapp_bus.h>
0046 #include <drvmgr/leon2_amba_bus.h>
0047 
0048 #define DBG(args...)
0049 
0050 int ambapp_leon2_int_register(
0051     struct drvmgr_dev *dev,
0052     int index,
0053     const char *info,
0054     drvmgr_isr isr,
0055     void *arg);
0056 int ambapp_leon2_int_unregister(
0057     struct drvmgr_dev *dev,
0058     int index,
0059     drvmgr_isr isr,
0060     void *arg);
0061 int ambapp_leon2_int_clear(
0062     struct drvmgr_dev *dev,
0063     int index);
0064 int ambapp_leon2_int_mask(
0065     struct drvmgr_dev *dev,
0066     int irq);
0067 int ambapp_leon2_int_unmask(
0068     struct drvmgr_dev *dev,
0069     int irq);
0070 int ambapp_leon2_get_params(
0071     struct drvmgr_dev *dev,
0072     struct drvmgr_bus_params *params);
0073 
0074 int ambapp_leon2_init1(struct drvmgr_dev *dev);
0075 int ambapp_leon2_init2(struct drvmgr_dev *dev);
0076 int ambapp_leon2_remove(struct drvmgr_dev *dev);
0077 void ambapp_leon2_register(void);
0078 
0079 /* READ/WRITE access to SpaceWire target over RMAP */
0080 void *ambapp_leon2_rw_arg(struct drvmgr_dev *dev);
0081 
0082 struct ambappl2_priv {
0083     struct ambapp_bus abus;
0084     struct ambapp_config config;
0085 };
0086 
0087 struct ambapp_ops ambapp_leon2_ops = {
0088     .int_register = ambapp_leon2_int_register,
0089     .int_unregister = ambapp_leon2_int_unregister,
0090     .int_clear = ambapp_leon2_int_clear,
0091     .int_mask = ambapp_leon2_int_mask,
0092     .int_unmask = ambapp_leon2_int_unmask,
0093     .get_params = ambapp_leon2_get_params
0094 };
0095 
0096 struct drvmgr_func ambapp_leon2_funcs[] = {
0097     DRVMGR_FUNC(AMBAPP_RW_ARG, ambapp_leon2_rw_arg),
0098 
0099     DRVMGR_FUNC(AMBAPP_R8,  _ld8),
0100     DRVMGR_FUNC(AMBAPP_R16, _ld16),
0101     DRVMGR_FUNC(AMBAPP_R32, _ld32),
0102     DRVMGR_FUNC(AMBAPP_R64, _ld64),
0103 
0104     DRVMGR_FUNC(AMBAPP_W8,  _st8),
0105     DRVMGR_FUNC(AMBAPP_W16, _st16),
0106     DRVMGR_FUNC(AMBAPP_W32, _st32),
0107     DRVMGR_FUNC(AMBAPP_W64, _st64),
0108 
0109     DRVMGR_FUNC(AMBAPP_RMEM, memcpy),
0110     DRVMGR_FUNC(AMBAPP_WMEM, memcpy),
0111 
0112     DRVMGR_FUNC_END
0113 };
0114 
0115 struct drvmgr_drv_ops ambapp_ops = {
0116     .init = {ambapp_leon2_init1, ambapp_leon2_init2, NULL, NULL},
0117     .remove = ambapp_leon2_remove,
0118     .info = NULL,
0119 };
0120 
0121 struct leon2_amba_dev_id ambapp_leon2_ids[] = {
0122     {LEON2_AMBA_AMBAPP_ID},
0123     {0}
0124 };
0125 
0126 struct leon2_amba_drv_info ambapp_bus_drv_leon2 = {
0127     {
0128         DRVMGR_OBJ_DRV,         /* Driver */
0129         NULL,               /* Next driver */
0130         NULL,               /* Device list */
0131         DRIVER_LEON2_AMBA_AMBAPP,   /* Driver ID */
0132         "AMBAPP_LEON2_DRV",     /* Driver Name */
0133         DRVMGR_BUS_TYPE_LEON2_AMBA, /* Bus Type */
0134         &ambapp_ops,
0135         NULL,               /* Funcs */
0136         0,
0137         sizeof(struct ambappl2_priv),   /* Let DrvMgr allocate priv */
0138     },
0139     &ambapp_leon2_ids[0]
0140 };
0141 
0142 void ambapp_leon2_register(void)
0143 {
0144     drvmgr_drv_register(&ambapp_bus_drv_leon2.general);
0145 }
0146 
0147 /* Function called from a hard configuration */
0148 int ambapp_leon2_init1(struct drvmgr_dev *dev)
0149 {
0150     union drvmgr_key_value *value;
0151     struct ambappl2_priv *priv = dev->priv;
0152     struct leon2_amba_dev_info *devinfo;
0153     struct ambapp_config *config;
0154     unsigned int ioarea;
0155     unsigned int freq_hz;
0156     LEON_Register_Map *regs;
0157 
0158     dev->name = "LEON2 AMBA PnP";
0159 
0160     if (!priv)
0161         return DRVMGR_NOMEM;
0162 
0163     config = &priv->config;
0164     config->abus = &priv->abus;
0165     config->ops = &ambapp_leon2_ops;
0166     config->maps_up = DRVMGR_TRANSLATE_ONE2ONE;
0167     config->maps_down = DRVMGR_TRANSLATE_ONE2ONE;
0168     config->funcs = ambapp_leon2_funcs;
0169     config->bus_type = DRVMGR_BUS_TYPE_LEON2_AMBA;
0170 
0171     /* Get AMBA PnP Area from REG0 */
0172     devinfo = (struct leon2_amba_dev_info *)dev->businfo;
0173     ioarea = devinfo->reg_base;
0174 
0175     /* Scan AMBA PnP Bus. ABUS has already been cleared with memset() */
0176     ambapp_scan(&priv->abus, ioarea, NULL, NULL);
0177 
0178     /* Try to get Configuration from resource configuration */
0179 
0180     value = drvmgr_dev_key_get(dev, "busFreq", DRVMGR_KT_INT);
0181     if (value) {
0182         /* Set frequency of AMBA bus if specified by user. The frequency
0183          * must be for AHB bus which IOAREA matches (AHB bus 0).
0184          */
0185         freq_hz = value->i;
0186     } else {
0187         /* Get Bus/LEON2 Frequency from timer prescaler,
0188          * the hardcoded address is used to get to timer
0189          */
0190         regs = (LEON_Register_Map *) 0x80000000;
0191         freq_hz = (regs->Scaler_Reload + 1) * 1000 * 1000;
0192     }
0193     /* Note that this can be overrided by a driver on the AMBA PnP bus.*/
0194     ambapp_freq_init(&priv->abus, NULL, freq_hz);
0195 
0196     value = drvmgr_dev_key_get(dev, "drvRes", DRVMGR_KT_POINTER);
0197     if (!value) {
0198         DBG("ambapp_leon2_init1: Failed getting resource drvRes\n");
0199         config->resources = NULL;
0200     } else {
0201         DBG("ambapp_leon2_init1: drvRes: 0x%08x\n", (unsigned int)value->ptr);
0202         config->resources = (struct drvmgr_bus_res *)value->ptr;
0203     }
0204 
0205     /* Initialize the AMBA Bus */
0206     return ambapp_bus_register(dev, config);
0207 }
0208 
0209 int ambapp_leon2_init2(struct drvmgr_dev *dev)
0210 {
0211     return 0;
0212 }
0213 
0214 int ambapp_leon2_remove(struct drvmgr_dev *dev)
0215 {
0216     return 0;
0217 }
0218 
0219 void *ambapp_leon2_rw_arg(struct drvmgr_dev *dev)
0220 {
0221     return dev; /* No argument really needed, by for debug */
0222 }
0223 
0224 int ambapp_leon2_int_register
0225     (
0226     struct drvmgr_dev *dev,
0227     int index,
0228     const char *info,
0229     drvmgr_isr isr,
0230     void *arg
0231     )
0232 {
0233     /* Let LEON2 bus handle interrupt requests */
0234     return drvmgr_interrupt_register(dev->parent->dev, index, info, isr, arg);
0235 }
0236 
0237 int ambapp_leon2_int_unregister
0238     (
0239     struct drvmgr_dev *dev,
0240     int index,
0241     drvmgr_isr isr,
0242     void *arg
0243     )
0244 {
0245     /* Let LEON2 bus handle interrupt requests */
0246     return drvmgr_interrupt_unregister(dev->parent->dev, index, isr, arg);
0247 }
0248 
0249 int ambapp_leon2_int_clear
0250     (
0251     struct drvmgr_dev *dev,
0252     int index
0253     )
0254 {
0255     /* Let LEON2 bus handle interrupt requests */
0256     return drvmgr_interrupt_clear(dev->parent->dev, index);
0257 }
0258 
0259 int ambapp_leon2_int_mask
0260     (
0261     struct drvmgr_dev *dev,
0262     int index
0263     )
0264 {
0265     /* Let LEON2 bus handle interrupt requests */
0266     return drvmgr_interrupt_mask(dev->parent->dev, index);
0267 }
0268 
0269 int ambapp_leon2_int_unmask
0270     (
0271     struct drvmgr_dev *dev,
0272     int index
0273     )
0274 {
0275     /* Let LEON2 bus handle interrupt requests */
0276     return drvmgr_interrupt_unmask(dev->parent->dev, index);
0277 }
0278 
0279 int ambapp_leon2_get_params(struct drvmgr_dev *dev, struct drvmgr_bus_params *params)
0280 {
0281     params->dev_prefix = "";
0282     return 0;
0283 }
0284 
0285 #endif