source: trunk/kernel/drivers/soclib/soclib_memc.c @ 8

Last change on this file since 8 was 4, checked in by alain, 8 years ago

Introduce the chdev_t structure in place of device_t.

File size: 11.0 KB
RevLine 
[1]1/*
2 * soclib_memc.c - soclib/tsar L2 Confugration Controller
3 *
4 * Copyright (c) 2008,2009,2010,2011,2012,2013 Ghassan Almaless
5 * Copyright (c) 2011,2012,2013 UPMC Sorbonne Universites
6 *
7 * This file is part of ALMOS-kernel.
8 *
9 * ALMOS-kernel is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; version 2.0 of the License.
12 *
13 * ALMOS-kernel is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with ALMOS-kernel; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23#include <bits.h>
[4]24#include <chdev.h>
[1]25#include <driver.h>
26#include <drvdb.h>
27#include <errno.h>
28#include <vfs.h>
29#include <string.h>
30#include <soclib_memc.h>
31#include <vmm.h>
32
33#define MEMC_CNF_FUNC         0x0
34#define MEMC_PRF_FUNC         0x1
35#define MEMC_ERR_FUNC         0x2
36
37#define MEMC_RD_MUPDT_SEL     0x0
38#define MEMC_WR_MINVL_SEL     0x1
39#define MEMC_LL_CLNUP_SEL     0x2
40#define MEMC_SC_MUPDTT_SEL    0x3
41#define MEMC_CS_MINVLT_SEL    0x4
42#define MEMC_XX_BINVLT_SEL    0x5
43
44#define MEMC_LOC_SEL          0x0
45#define MEMC_REM_SEL          0x1
46#define MEMC_OTH_SEL          0x2
47
48#define MEMC_DIRCT_SEL        0x0
49#define MEMC_COHER_SEL        0x1
50
51#define MEMC_LO_SEL           0x0
52#define MEMC_HI_SEL           0x1
53
54#define MEMC_REG_IDX(z,y,x,w)  (((z) << 6) | ((y) << 4) | ((x) << 1) | (w))
55#define MEMC_REG(func,idx)     (((func) << 9) | ((idx) << 2))
56
57/* ---------------------------------------- */
58/* PERFORMANCE REGISTERS FOR DIRECT TRAFFIC */
59/* ---------------------------------------- */
60
61#define MEMC_RD_LIDX      (MEMC_REG_IDX(MEMC_DIRCT_SEL, MEMC_LOC_SEL, MEMC_RD_MUPDT_SEL, MEMC_LO_SEL))
62#define MEMC_RD_RIDX      (MEMC_REG_IDX(MEMC_DIRCT_SEL, MEMC_REM_SEL, MEMC_RD_MUPDT_SEL, MEMC_LO_SEL))
63#define MEMC_RD_CIDX      (MEMC_REG_IDX(MEMC_DIRCT_SEL, MEMC_OTH_SEL, MEMC_RD_MUPDT_SEL, MEMC_LO_SEL))
64
65#define MEMC_WR_LIDX      (MEMC_REG_IDX(MEMC_DIRCT_SEL, MEMC_LOC_SEL, MEMC_WR_MINVL_SEL, MEMC_LO_SEL))
66#define MEMC_WR_RIDX      (MEMC_REG_IDX(MEMC_DIRCT_SEL, MEMC_REM_SEL, MEMC_WR_MINVL_SEL, MEMC_LO_SEL))
67#define MEMC_WR_CIDX      (MEMC_REG_IDX(MEMC_DIRCT_SEL, MEMC_OTH_SEL, MEMC_WR_MINVL_SEL, MEMC_LO_SEL))
68
69#define MEMC_LL_LIDX      (MEMC_REG_IDX(MEMC_DIRCT_SEL, MEMC_LOC_SEL, MEMC_LL_CLNUP_SEL, MEMC_LO_SEL))
70#define MEMC_LL_RIDX      (MEMC_REG_IDX(MEMC_DIRCT_SEL, MEMC_REM_SEL, MEMC_LL_CLNUP_SEL, MEMC_LO_SEL))
71#define MEMC_LL_CIDX      (MEMC_REG_IDX(MEMC_DIRCT_SEL, MEMC_OTH_SEL, MEMC_LL_CLNUP_SEL, MEMC_LO_SEL))
72
73#define MEMC_SC_LIDX      (MEMC_REG_IDX(MEMC_DIRCT_SEL, MEMC_LOC_SEL, MEMC_SC_MUPDTT_SEL, MEMC_LO_SEL))
74#define MEMC_SC_RIDX      (MEMC_REG_IDX(MEMC_DIRCT_SEL, MEMC_REM_SEL, MEMC_SC_MUPDTT_SEL, MEMC_LO_SEL))
75#define MEMC_SC_CIDX      (MEMC_REG_IDX(MEMC_DIRCT_SEL, MEMC_OTH_SEL, MEMC_SC_MUPDTT_SEL, MEMC_LO_SEL))
76
77#define MEMC_CS_LIDX      (MEMC_REG_IDX(MEMC_DIRCT_SEL, MEMC_LOC_SEL, MEMC_CS_MINVLT_SEL, MEMC_LO_SEL))
78#define MEMC_CS_RIDX      (MEMC_REG_IDX(MEMC_DIRCT_SEL, MEMC_REM_SEL, MEMC_CS_MINVLT_SEL, MEMC_LO_SEL))
79#define MEMC_CS_CIDX      (MEMC_REG_IDX(MEMC_DIRCT_SEL, MEMC_OTH_SEL, MEMC_CS_MINVLT_SEL, MEMC_LO_SEL))
80
81#define MEMC_RD_LOCAL      MEMC_REG(MEMC_PRF_FUNC, MEMC_RD_LIDX)
82#define MEMC_RD_REMOTE     MEMC_REG(MEMC_PRF_FUNC, MEMC_RD_RIDX)
83#define MEMC_RD_COST       MEMC_REG(MEMC_PRF_FUNC, MEMC_RD_CIDX)
84
85#define MEMC_WR_LOCAL      MEMC_REG(MEMC_PRF_FUNC, MEMC_WR_LIDX)
86#define MEMC_WR_REMOTE     MEMC_REG(MEMC_PRF_FUNC, MEMC_WR_RIDX)
87#define MEMC_WR_COST       MEMC_REG(MEMC_PRF_FUNC, MEMC_WR_CIDX)
88
89#define MEMC_LL_LOCAL      MEMC_REG(MEMC_PRF_FUNC, MEMC_LL_LIDX)
90#define MEMC_LL_REMOTE     MEMC_REG(MEMC_PRF_FUNC, MEMC_LL_RIDX)
91#define MEMC_LL_COST       MEMC_REG(MEMC_PRF_FUNC, MEMC_LL_CIDX)
92
93#define MEMC_SC_LOCAL      MEMC_REG(MEMC_PRF_FUNC, MEMC_SC_LIDX)
94#define MEMC_SC_REMOTE     MEMC_REG(MEMC_PRF_FUNC, MEMC_SC_RIDX)
95#define MEMC_SC_COST       MEMC_REG(MEMC_PRF_FUNC, MEMC_SC_CIDX)
96
97#define MEMC_CS_LOCAL      MEMC_REG(MEMC_PRF_FUNC, MEMC_CS_LIDX)
98#define MEMC_CS_REMOTE     MEMC_REG(MEMC_PRF_FUNC, MEMC_CS_RIDX)
99#define MEMC_CS_COST       MEMC_REG(MEMC_PRF_FUNC, MEMC_CS_CIDX)
100
101/* ------------------------------------------- */
102/* PERFORMANCE REGISTERS FOR COHERENCE TRAFFIC */
103/* ------------------------------------------- */
104
105#define MEMC_MUPDT_LIDX      (MEMC_REG_IDX(MEMC_COHER_SEL, MEMC_LOC_SEL, MEMC_RD_MUPDT_SEL, MEMC_LO_SEL))
106#define MEMC_MUPDT_RIDX      (MEMC_REG_IDX(MEMC_COHER_SEL, MEMC_REM_SEL, MEMC_RD_MUPDT_SEL, MEMC_LO_SEL))
107#define MEMC_MUPDT_CIDX      (MEMC_REG_IDX(MEMC_COHER_SEL, MEMC_OTH_SEL, MEMC_RD_MUPDT_SEL, MEMC_LO_SEL))
108
109#define MEMC_MINVL_LIDX      (MEMC_REG_IDX(MEMC_COHER_SEL, MEMC_LOC_SEL, MEMC_WR_MINVL_SEL, MEMC_LO_SEL))
110#define MEMC_MINVL_RIDX      (MEMC_REG_IDX(MEMC_COHER_SEL, MEMC_REM_SEL, MEMC_WR_MINVL_SEL, MEMC_LO_SEL))
111#define MEMC_MINVL_CIDX      (MEMC_REG_IDX(MEMC_COHER_SEL, MEMC_OTH_SEL, MEMC_WR_MINVL_SEL, MEMC_LO_SEL))
112
113#define MEMC_CLNUP_LIDX      (MEMC_REG_IDX(MEMC_COHER_SEL, MEMC_LOC_SEL, MEMC_LL_CLNUP_SEL, MEMC_LO_SEL))
114#define MEMC_CLNUP_RIDX      (MEMC_REG_IDX(MEMC_COHER_SEL, MEMC_REM_SEL, MEMC_LL_CLNUP_SEL, MEMC_LO_SEL))
115#define MEMC_CLNUP_CIDX      (MEMC_REG_IDX(MEMC_COHER_SEL, MEMC_OTH_SEL, MEMC_LL_CLNUP_SEL, MEMC_LO_SEL))
116
117#define MEMC_MUPDTT_TIDX     (MEMC_REG_IDX(MEMC_COHER_SEL, MEMC_OTH_SEL, MEMC_SC_MUPDTT_SEL, MEMC_LO_SEL))
118#define MEMC_MINVLT_TIDX     (MEMC_REG_IDX(MEMC_COHER_SEL, MEMC_OTH_SEL, MEMC_CS_MINVLT_SEL, MEMC_LO_SEL))
119#define MEMC_BINVLT_TIDX     (MEMC_REG_IDX(MEMC_COHER_SEL, MEMC_OTH_SEL, MEMC_XX_BINVLT_SEL, MEMC_LO_SEL))
120
121#define MEMC_MUPDT_LOCAL     MEMC_REG(MEMC_PRF_FUNC, MEMC_MUPDT_LIDX)
122#define MEMC_MUPDT_REMOTE    MEMC_REG(MEMC_PRF_FUNC, MEMC_MUPDT_RIDX)
123#define MEMC_MUPDT_COST      MEMC_REG(MEMC_PRF_FUNC, MEMC_MUPDT_CIDX)
124
125#define MEMC_MINVL_LOCAL     MEMC_REG(MEMC_PRF_FUNC, MEMC_MINVL_LIDX)
126#define MEMC_MINVL_REMOTE    MEMC_REG(MEMC_PRF_FUNC, MEMC_MINVL_RIDX)
127#define MEMC_MINVL_COST      MEMC_REG(MEMC_PRF_FUNC, MEMC_MINVL_CIDX)
128
129#define MEMC_CLNUP_LOCAL     MEMC_REG(MEMC_PRF_FUNC, MEMC_CLNUP_LIDX)
130#define MEMC_CLNUP_REMOTE    MEMC_REG(MEMC_PRF_FUNC, MEMC_CLNUP_RIDX)
131#define MEMC_CLNUP_COST      MEMC_REG(MEMC_PRF_FUNC, MEMC_CLNUP_CIDX)
132
133#define MEMC_MUPDT_TOTAL     MEMC_REG(MEMC_PRF_FUNC, MEMC_MUPDTT_TIDX)
134#define MEMC_MINVL_TOTAL     MEMC_REG(MEMC_PRF_FUNC, MEMC_MINVLT_TIDX)
135#define MEMC_BINVL_TOTAL     MEMC_REG(MEMC_PRF_FUNC, MEMC_BINVLT_TIDX)
136
137#define MEMC_REG_NR 27
138
139static const uint16_t reg_tbl[MEMC_REG_NR] = {
140                MEMC_RD_LOCAL,
141                MEMC_RD_REMOTE,
142                MEMC_RD_COST,
143                MEMC_WR_LOCAL,
144                MEMC_WR_REMOTE,
145                MEMC_WR_COST,
146                MEMC_LL_LOCAL,
147                MEMC_LL_REMOTE,
148                MEMC_LL_COST,
149                MEMC_SC_LOCAL,
150                MEMC_SC_REMOTE,
151                MEMC_SC_COST,
152                MEMC_CS_LOCAL,
153                MEMC_CS_REMOTE,
154                MEMC_CS_COST,
155                MEMC_MUPDT_LOCAL,
156                MEMC_MUPDT_REMOTE,
157                MEMC_MUPDT_COST,
158                MEMC_MINVL_LOCAL,
159                MEMC_MINVL_REMOTE,
160                MEMC_MINVL_COST,
161                MEMC_CLNUP_LOCAL,
162                MEMC_CLNUP_REMOTE,
163                MEMC_CLNUP_COST,
164                MEMC_MUPDT_TOTAL,
165                MEMC_MINVL_TOTAL,
166                MEMC_BINVL_TOTAL};
167
168static sint_t memc_read(struct device_s *memc, dev_request_t *rq)
169{       
170        register size_t count;
171        register uint_t i;
172        uint_t *dst;
173                     
174        assert(rq->file != NULL);
175 
176        count = rq->count >> 2; /* 32 bits registers */
177        dst   = rq->dst;
178
179        count = (count > MEMC_REG_NR) ? MEMC_REG_NR : count;
180
181        for(i = 0; i < count; i++)
182        {
183                memcpy((void*)&dst[i], (void *)((uint_t)memc->base + reg_tbl[i]), 4);
184        }
185        return (count << 2);
186}
187
188static sint_t memc_write(struct device_s *memc, dev_request_t *rq)
189{
190        return -ENOTSUPPORTED;
191}
192
193static error_t memc_lseek(struct device_s *memc, dev_request_t *rq)
194{
195        return ENOTSUPPORTED;
196}
197
198static sint_t memc_get_params(struct device_s *memc, dev_params_t *params)
199{
200        params->size = MEMC_REG_NR * 4; /* 32 bits registers */
201        return 0;
202}
203
204static sint_t memc_open(struct device_s *memc, dev_request_t *rq)
205{
206        return 0;
207}
208
209static VM_REGION_PAGE_FAULT(memc_pagefault)
210{
211        return EFAULT;
212}
213
214static struct vm_region_op_s memc_vm_region_op = 
215{
216        .page_in     = NULL,
217        .page_out    = NULL,
218        .page_lookup = NULL,
219        .page_fault  = memc_pagefault
220};
221
222static error_t memc_mmap(struct device_s *memc, dev_request_t *rq)
223{
224        struct vfs_file_s *file;
225        struct vm_region_s *region;
226        struct pmm_s *pmm;
227        uint_t size;
228        pmm_page_info_t info;
229        vma_t current_vma;
230        error_t err;
231
232        file   = rq->file;
233        region = rq->region;
234        pmm    = &region->vmm->pmm;
235        size   = (uint_t) memc->data;
236 
237        if(size < (region->vm_limit - region->vm_start))
238        {
239                printk(WARNING, "WARNING: %s: asked size (%d) exceed real one (%d)\n", 
240                       __FUNCTION__, region->vm_limit - region->vm_start, size);
241                return ERANGE;
242        }
243
244        printk(INFO, "INFO: %s: started, file inode %p, region <0x%x - 0x%x>\n",
245               __FUNCTION__, 
246               file->f_inode, 
247               region->vm_start, 
248               region->vm_limit);
249
250        if((err = pmm_get_page(pmm, (vma_t)memc->base, &info)))
251                return err;
252
253        region->vm_flags |= VM_REG_DEV;
254        current_vma       = region->vm_start;
255        info.attr         = region->vm_pgprot & ~(PMM_CACHED);
256        info.cluster      = NULL;
257        size              = region->vm_limit - region->vm_start; 
258        size              = ARROUND_UP(size, PMM_PAGE_SIZE);
259
260        while(size)
261        {
262                if((err = pmm_set_page(pmm, current_vma, &info)))
263                        return err;
264
265                info.ppn ++;
266                current_vma += PMM_PAGE_SIZE;
267                size -= PMM_PAGE_SIZE;
268        }
269 
270        region->vm_file = *file;
271        //region->vm_mapper = NULL;
272
273        region->vm_op = &memc_vm_region_op;
274        return 0;
275}
276
277static error_t memc_munmap(struct device_s *memc, dev_request_t *rq)
278{
279        struct vfs_file_s *file;
280        struct vm_region_s *region;
281        struct pmm_s *pmm;
282        uint_t size;
283        pmm_page_info_t info;
284        vma_t current_vma;
285        error_t err;
286
287        file   = rq->file;
288        region = rq->region;
289        pmm    = &region->vmm->pmm;
290        size   = (uint_t) memc->data;
291
292        if(size < (region->vm_limit - region->vm_start))
293        {
294                printk(ERROR, "ERROR: %s: asked size (%d) exceed real one (%d)\n", 
295                       __FUNCTION__, region->vm_limit - region->vm_start, size);
296                return ERANGE;
297        }
298
299        current_vma = region->vm_start;
300        info.attr   = 0;
301        info.ppn    = 0;
302        size        = region->vm_limit - region->vm_start;
303
304        while(size)
305        {   
306                if((err = pmm_set_page(pmm, current_vma, &info)))
307                        return err;
308
309                current_vma += PMM_PAGE_SIZE;
310                size -= PMM_PAGE_SIZE;
311        }
312 
313        return 0;
314}
315
316static uint_t memc_count = 0;
317
318error_t soclib_memc_init(struct device_s *memc)
319{ 
320        memc->type = DEV_CHR;
321
322        memc->op.dev.open       = &memc_open;
323        memc->op.dev.read       = &memc_read;
324        memc->op.dev.write      = &memc_write;
325        memc->op.dev.close      = NULL;
326        memc->op.dev.lseek      = &memc_lseek;
327        memc->op.dev.mmap       = &memc_mmap;
328        memc->op.dev.munmap     = &memc_munmap;
329        memc->op.dev.set_params = NULL;
330        memc->op.dev.get_params = &memc_get_params;
331        memc->op.drvid          = SOCLIB_MEMC_ID;
332
333        memc->data = (void*)memc->size;
334
335        sprintk(memc->name, 
336#if CONFIG_ROOTFS_IS_VFAT
337                "MEMC%d"
338#else
339                "memc%d"
340#endif
341                , memc_count++);
342
343        metafs_init(&memc->node, memc->name);
344        return 0;
345}
346
347
348driver_t soclib_memc_driver = { .init = &soclib_memc_init };
Note: See TracBrowser for help on using the repository browser.