source: trunk/hal/tsar_mips32/drivers/soclib_memc.c

Last change on this file was 679, checked in by alain, 6 years ago

Mainly cosmetic.

File size: 11.0 KB
Line 
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>
24#include <chdev.h>
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( __FUNCTION__,rq->file != NULL, "rq->file should'nt be NULL.\n");
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.