source: rtems/c/src/lib/libbsp/sparc/shared/mem/mctrl.c @ 4d3e70f4

4.115
Last change on this file since 4d3e70f4 was 4d3e70f4, checked in by Daniel Hellstrom <daniel@…>, on 04/13/15 at 09:26:52

DRVMGR: KEY_TYPE now a enum drvmgr_kt

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