source: rtems/bsps/shared/grlib/mem/mctrl.c @ 7eb606d3

Last change on this file since 7eb606d3 was 7eb606d3, checked in by Sebastian Huber <sebastian.huber@…>, on Dec 22, 2018 at 5:31:04 PM

grlib: Move source files

Update #3678.

  • Property mode set to 100644
File size: 4.9 KB
Line 
1/*  Memory Controller driver (FTMTRL, MCTRL)
2 *
3 *  COPYRIGHT (c) 2008.
4 *  Cobham Gaisler AB.
5 *
6 *  This file contains the driver for the MCTRL memory controller.
7 *  The driver sets the memory configuration registers (MCFG1, MCFG2, MCFG3)
8 *  during driver initialization
9 *
10 *  The license and distribution terms for this file may be
11 *  found in found in the file LICENSE in this distribution or at
12 *  http://www.rtems.org/license/LICENSE.
13 */
14
15/******************* Driver manager interface ***********************/
16#include <stdlib.h>
17#include <string.h>
18#include <stdio.h>
19
20#include <drvmgr/drvmgr.h>
21#include <grlib/ambapp_bus.h>
22
23#include <grlib/mctrl.h>
24
25#include <grlib/grlib_impl.h>
26
27#define MEMSET(priv, start, c, length) memset((void *)start, c, length)
28
29#define DBG(args...)
30/*#define DBG(args...) printk(args)*/
31
32struct mctrl_regs {
33        unsigned int    mcfg[8];
34};
35
36struct mctrl_priv;
37
38struct mctrl_ops {
39        void (*mcfg_set)(struct mctrl_priv *priv, int index, void *regs, unsigned int regval);
40};
41
42struct mctrl_priv {
43        struct drvmgr_dev       *dev;
44        void                    *regs;
45        unsigned int            mcfg[8];        /* The wanted memory configuration */
46        unsigned int            configured;     /* Determines what mcfgs was configured by user */
47        struct mctrl_ops        *ops;           /* Operation may depend on hardware */
48};
49
50static int mctrl_init1(struct drvmgr_dev *dev);
51static int mctrl_remove(struct drvmgr_dev *dev);
52
53/* Standard MCFG registers */
54static void mctrl_set_std(struct mctrl_priv *priv, int index, void *regs, unsigned int regval);
55
56struct mctrl_ops std_mctrl_ops = 
57{
58        mctrl_set_std
59};
60
61struct drvmgr_drv_ops mctrl_ops = 
62{
63        .init = {mctrl_init1, NULL, NULL, NULL},
64        .remove = mctrl_remove,
65        .info = NULL
66};
67
68struct amba_dev_id mctrl_ids[] = 
69{
70        {VENDOR_ESA, ESA_MCTRL},
71        {VENDOR_GAISLER, GAISLER_FTMCTRL},
72        {VENDOR_GAISLER, GAISLER_FTSRCTRL},
73        {0, 0}          /* Mark end of table */
74};
75
76struct amba_drv_info mctrl_drv_info =
77{
78        {
79                DRVMGR_OBJ_DRV,                 /* Driver */
80                NULL,                           /* Next driver */
81                NULL,                           /* Device list */
82                DRIVER_AMBAPP_MCTRL_ID,         /* Driver ID */
83                "MCTRL_DRV",                    /* Driver Name */
84                DRVMGR_BUS_TYPE_AMBAPP,         /* Bus Type */
85                &mctrl_ops,
86                NULL,                           /* Funcs */
87                0,                              /* No devices yet */
88                0,
89        },
90        &mctrl_ids[0]
91};
92
93void mctrl_register_drv (void)
94{
95        DBG("Registering MCTRL driver\n");
96        drvmgr_drv_register(&mctrl_drv_info.general);
97}
98
99static int mctrl_init1(struct drvmgr_dev *dev)
100{
101        struct mctrl_priv *priv;
102        struct amba_dev_info *ambadev;
103        struct ambapp_core *pnpinfo;
104        int i;
105        char res_name[16];
106        union drvmgr_key_value *value;
107        unsigned int start, length;
108
109        DBG("MCTRL[%d] on bus %s\n", dev->minor_drv, dev->parent->dev->name);
110        priv = dev->priv = grlib_calloc(1, sizeof(*priv));
111        if ( !priv )
112                return DRVMGR_NOMEM;
113        priv->dev = dev;
114
115        /* Get device information from AMBA PnP information */
116        ambadev = (struct amba_dev_info *)priv->dev->businfo;
117        if ( ambadev == NULL ) {
118                return DRVMGR_FAIL;
119        }
120        pnpinfo = &ambadev->info;
121        if ( pnpinfo->apb_slv == NULL ) {
122                /* LEON2 PnP systems are missing the APB interface */
123                priv->regs = (void *)0x80000000;
124        } else {
125                priv->regs = (void *)pnpinfo->apb_slv->start;
126        }
127
128        /* Depending on Hardware selection write/read routines */
129        switch ( pnpinfo->vendor ) {
130                case VENDOR_ESA:
131                switch ( pnpinfo->device ) {
132                        case ESA_MCTRL:
133                        default:
134                                priv->ops = &std_mctrl_ops;
135                }
136                break;
137
138                case VENDOR_GAISLER:
139                switch ( pnpinfo->device ) {
140                        case GAISLER_FTMCTRL:
141                        case GAISLER_FTSRCTRL:
142                        default:
143                                priv->ops = &std_mctrl_ops;
144                }
145                break;
146
147                default:
148                priv->ops = &std_mctrl_ops;
149                break;
150        }
151
152        /* Find user configuration from bus resources */
153        priv->configured = 0;
154        strcpy(res_name, "mcfgX");
155        for(i=0; i<8; i++) {
156                res_name[4] = '1' + i;
157                value = drvmgr_dev_key_get(priv->dev, res_name, DRVMGR_KT_INT);
158                if ( value ) {
159                        priv->mcfg[i] = value->i;
160                        priv->configured |= (1<<i);
161                }
162        }
163
164        /* Init hardware registers right away, other devices may depend on it in init2(), also
165         * the washing depend on it.
166         */
167        for ( i=0; i<8; i++) {
168                if ( priv->configured & (1<<i) ) {
169                        DBG("Setting MCFG%d to 0x%08x\n", i+1, priv->mcfg[i]);
170                        priv->ops->mcfg_set(priv, i, priv->regs, priv->mcfg[i]);
171                }
172        }
173
174        /* Wash memory partitions if user wants */
175        for (i=0; i<9; i++) {
176                strcpy(res_name, "washXStart");
177                res_name[4] = '0' + i;
178                value = drvmgr_dev_key_get(priv->dev, res_name, DRVMGR_KT_INT);
179                if ( value ) {
180                        start = value->i;
181                        strcpy(res_name, "washXLength");
182                        res_name[4] = '0' + i;
183                        value = drvmgr_dev_key_get(priv->dev, res_name, DRVMGR_KT_INT);
184                        if ( value ) {
185                                length = value->i;
186
187                                if ( length > 0 ) {
188                                        DBG("MCTRL: Washing 0x%08x-0x%08x\n", start, start+length-1);
189
190                                        MEMSET(priv, (void *)start, 0, length);
191                                }
192                        }
193                }
194        }
195
196        return DRVMGR_OK;
197}
198
199static int mctrl_remove(struct drvmgr_dev *dev)
200{
201        /* Nothing to be done */
202        DBG("Removing %s\n", dev->name);
203        return DRVMGR_OK;
204}
205
206/* Standard Operations */
207static void mctrl_set_std(struct mctrl_priv *priv, int index, void *regs, unsigned int regval)
208{
209        struct mctrl_regs *pregs = regs;
210
211        /* Store new value */
212        pregs->mcfg[index] = regval;
213}
Note: See TracBrowser for help on using the repository browser.