Back to home page

LXR

 
 

    


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

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*  Memory Controller driver (FTMTRL, MCTRL)
0004  * 
0005  *  COPYRIGHT (c) 2008.
0006  *  Cobham Gaisler AB.
0007  *
0008  *  This file contains the driver for the MCTRL memory controller.
0009  *  The driver sets the memory configuration registers (MCFG1, MCFG2, MCFG3)
0010  *  during driver initialization
0011  *
0012  * Redistribution and use in source and binary forms, with or without
0013  * modification, are permitted provided that the following conditions
0014  * are met:
0015  * 1. Redistributions of source code must retain the above copyright
0016  *    notice, this list of conditions and the following disclaimer.
0017  * 2. Redistributions in binary form must reproduce the above copyright
0018  *    notice, this list of conditions and the following disclaimer in the
0019  *    documentation and/or other materials provided with the distribution.
0020  *
0021  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0022  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0023  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0024  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0025  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0026  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0027  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0028  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0029  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0030  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0031  * POSSIBILITY OF SUCH DAMAGE.
0032  */
0033 
0034 /******************* Driver manager interface ***********************/
0035 #include <stdlib.h>
0036 #include <string.h>
0037 #include <stdio.h>
0038 
0039 #include <drvmgr/drvmgr.h>
0040 #include <grlib/ambapp_bus.h>
0041 
0042 #include <grlib/mctrl.h>
0043 
0044 #include <grlib/grlib_impl.h>
0045 
0046 #define MEMSET(priv, start, c, length) memset((void *)start, c, length)
0047 
0048 #define DBG(args...)
0049 /*#define DBG(args...) printk(args)*/
0050 
0051 struct mctrl_regs {
0052     unsigned int    mcfg[8];
0053 };
0054 
0055 struct mctrl_priv;
0056 
0057 struct mctrl_ops {
0058     void (*mcfg_set)(struct mctrl_priv *priv, int index, void *regs, unsigned int regval);
0059 };
0060 
0061 struct mctrl_priv {
0062     struct drvmgr_dev   *dev;
0063     void            *regs;
0064     unsigned int        mcfg[8];    /* The wanted memory configuration */
0065     unsigned int        configured; /* Determines what mcfgs was configured by user */
0066     struct mctrl_ops    *ops;       /* Operation may depend on hardware */
0067 };
0068 
0069 static int mctrl_init1(struct drvmgr_dev *dev);
0070 static int mctrl_remove(struct drvmgr_dev *dev);
0071 
0072 /* Standard MCFG registers */
0073 static void mctrl_set_std(struct mctrl_priv *priv, int index, void *regs, unsigned int regval);
0074 
0075 struct mctrl_ops std_mctrl_ops = 
0076 {
0077     mctrl_set_std
0078 };
0079 
0080 struct drvmgr_drv_ops mctrl_ops = 
0081 {
0082     .init = {mctrl_init1, NULL, NULL, NULL},
0083     .remove = mctrl_remove,
0084     .info = NULL
0085 };
0086 
0087 struct amba_dev_id mctrl_ids[] = 
0088 {
0089     {VENDOR_ESA, ESA_MCTRL},
0090     {VENDOR_GAISLER, GAISLER_FTMCTRL},
0091     {VENDOR_GAISLER, GAISLER_FTSRCTRL},
0092     {0, 0}      /* Mark end of table */
0093 };
0094 
0095 struct amba_drv_info mctrl_drv_info =
0096 {
0097     {
0098         DRVMGR_OBJ_DRV,         /* Driver */
0099         NULL,               /* Next driver */
0100         NULL,               /* Device list */
0101         DRIVER_AMBAPP_MCTRL_ID,     /* Driver ID */
0102         "MCTRL_DRV",            /* Driver Name */
0103         DRVMGR_BUS_TYPE_AMBAPP,     /* Bus Type */
0104         &mctrl_ops,
0105         NULL,               /* Funcs */
0106         0,              /* No devices yet */
0107         0,
0108     },
0109     &mctrl_ids[0]
0110 };
0111 
0112 void mctrl_register_drv (void)
0113 {
0114     DBG("Registering MCTRL driver\n");
0115     drvmgr_drv_register(&mctrl_drv_info.general);
0116 }
0117 
0118 static int mctrl_init1(struct drvmgr_dev *dev)
0119 {
0120     struct mctrl_priv *priv;
0121     struct amba_dev_info *ambadev;
0122     struct ambapp_core *pnpinfo;
0123     int i;
0124     char res_name[16];
0125     union drvmgr_key_value *value;
0126     unsigned int start, length;
0127 
0128     DBG("MCTRL[%d] on bus %s\n", dev->minor_drv, dev->parent->dev->name);
0129     priv = dev->priv = grlib_calloc(1, sizeof(*priv));
0130     if ( !priv )
0131         return DRVMGR_NOMEM;
0132     priv->dev = dev;
0133 
0134     /* Get device information from AMBA PnP information */
0135     ambadev = (struct amba_dev_info *)priv->dev->businfo;
0136     if ( ambadev == NULL ) {
0137         return DRVMGR_FAIL;
0138     }
0139     pnpinfo = &ambadev->info;
0140     if ( pnpinfo->apb_slv == NULL ) {
0141         /* LEON2 PnP systems are missing the APB interface */
0142         priv->regs = (void *)0x80000000;
0143     } else {
0144         priv->regs = (void *)pnpinfo->apb_slv->start;
0145     }
0146 
0147     /* Depending on Hardware selection write/read routines */
0148     switch ( pnpinfo->vendor ) {
0149         case VENDOR_ESA:
0150         switch ( pnpinfo->device ) {
0151             case ESA_MCTRL:
0152             default:
0153                 priv->ops = &std_mctrl_ops;
0154         }
0155         break;
0156 
0157         case VENDOR_GAISLER:
0158         switch ( pnpinfo->device ) {
0159             case GAISLER_FTMCTRL:
0160             case GAISLER_FTSRCTRL:
0161             default:
0162                 priv->ops = &std_mctrl_ops;
0163         }
0164         break;
0165 
0166         default:
0167         priv->ops = &std_mctrl_ops;
0168         break;
0169     }
0170 
0171     /* Find user configuration from bus resources */
0172     priv->configured = 0;
0173     strcpy(res_name, "mcfgX");
0174     for(i=0; i<8; i++) {
0175         res_name[4] = '1' + i;
0176         value = drvmgr_dev_key_get(priv->dev, res_name, DRVMGR_KT_INT);
0177         if ( value ) {
0178             priv->mcfg[i] = value->i;
0179             priv->configured |= (1<<i);
0180         }
0181     }
0182 
0183     /* Init hardware registers right away, other devices may depend on it in init2(), also
0184      * the washing depend on it.
0185      */
0186     for ( i=0; i<8; i++) {
0187         if ( priv->configured & (1<<i) ) {
0188             DBG("Setting MCFG%d to 0x%08x\n", i+1, priv->mcfg[i]);
0189             priv->ops->mcfg_set(priv, i, priv->regs, priv->mcfg[i]);
0190         }
0191     }
0192 
0193     /* Wash memory partitions if user wants */
0194     for (i=0; i<9; i++) {
0195         strcpy(res_name, "washXStart");
0196         res_name[4] = '0' + i;
0197         value = drvmgr_dev_key_get(priv->dev, res_name, DRVMGR_KT_INT);
0198         if ( value ) {
0199             start = value->i;
0200             strcpy(res_name, "washXLength");
0201             res_name[4] = '0' + i;
0202             value = drvmgr_dev_key_get(priv->dev, res_name, DRVMGR_KT_INT);
0203             if ( value ) {
0204                 length = value->i;
0205 
0206                 if ( length > 0 ) {
0207                     DBG("MCTRL: Washing 0x%08x-0x%08x\n", start, start+length-1);
0208 
0209                     MEMSET(priv, (void *)start, 0, length);
0210                 }
0211             }
0212         }
0213     }
0214 
0215     return DRVMGR_OK;
0216 }
0217 
0218 static int mctrl_remove(struct drvmgr_dev *dev)
0219 {
0220     /* Nothing to be done */
0221     DBG("Removing %s\n", dev->name);
0222     return DRVMGR_OK;
0223 }
0224 
0225 /* Standard Operations */
0226 static void mctrl_set_std(struct mctrl_priv *priv, int index, void *regs, unsigned int regval)
0227 {
0228     struct mctrl_regs *pregs = regs;
0229 
0230     /* Store new value */
0231     pregs->mcfg[index] = regval;
0232 }