OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [mmc/] [host/] [mmc_ocores.c] - Blame information for rev 72

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 65 AlbertVeli
/* -*- linux-c -*-
2
 *
3
 * OpenCores MMC Controller driver
4
 *
5
 * Copyright (C) 2009 ORSoC, All Rights Reserved.
6
 *
7
 * This program is free software; you can redistribute it and/or modify it
8
 * under the terms of the GNU General Public License as published
9
 * by the Free Software Foundation; version 2 of the License.
10
 *
11
 * This program is distributed in the hope that it will be useful, but
12
 * WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License along
17
 * with this program; if not, write to the Free Software Foundation, Inc.,
18
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
 */
20
#include <linux/module.h>
21
#include <linux/init.h>
22
#include <linux/ioport.h>
23
#include <linux/platform_device.h>
24
#include <linux/delay.h>
25
#include <linux/interrupt.h>
26
#include <linux/err.h>
27
#include <linux/mmc/host.h>
28
 
29
#include <asm/board.h>
30
#include <asm/io.h>
31
#include <asm/mmc.h>
32 68 tac2
#include <asm/system.h>
33 65 AlbertVeli
#include "mmc_ocores.h"
34
 
35
#define DRIVER_NAME "mmc-ocores"
36
 
37
#define NR_SG   1
38
 
39 66 tac2
 
40 70 tac2
 
41 65 AlbertVeli
struct ocores_host {
42
        struct mmc_host         *mmc;
43
        spinlock_t              lock;
44
        struct resource         *res;
45
        void __iomem            *base;
46
        unsigned int            cmdat;
47
        unsigned int            power_mode;
48
        struct ocores_platform_data *pdata;
49 69 AlbertVeli
        unsigned int            word_cnt;
50 65 AlbertVeli
        struct mmc_request      *mrq;
51
        struct mmc_command      *cmd;
52
        struct mmc_data         *data;
53 66 tac2
        int irq_cmd;
54
        int irq_dat;
55
        unsigned int flags;
56
        struct tasklet_struct finish_cmd;
57 68 tac2
        struct {
58 69 AlbertVeli
                unsigned int normal_int_status;
59
                unsigned int error_int_status;
60
        } registers;
61 65 AlbertVeli
};
62
 
63 66 tac2
struct ocores_host *oc_host;
64
 
65
static void ocores_tasklet_finish_cmd(unsigned long param);
66
static inline void CMD_IRQ_ON(struct ocores_host *host, u32 mask)
67 65 AlbertVeli
{
68 66 tac2
        u32 val = readl(host->base  + SD_NOMAL_INT_SIGNAL_ENABLE);
69
        printk(KERN_ALERT "Int mask = %08x\n", val);
70
        val |= mask;
71
        writel (val, host->base  + SD_NOMAL_INT_SIGNAL_ENABLE);
72
        printk(KERN_ALERT "Int mask = %08x\n", val);
73
}
74
 
75
static inline void CMD_IRQ_OFF(struct ocores_host *host, u32 mask)
76 69 AlbertVeli
{
77 66 tac2
        u32 val = readl(host->base  + SD_NOMAL_INT_SIGNAL_ENABLE);
78
        val  &= ~mask;
79
        writel (val, host->base  + SD_NOMAL_INT_SIGNAL_ENABLE);
80
}
81 69 AlbertVeli
 
82 66 tac2
static void ocores_start_cmd(struct ocores_host *host, struct mmc_command *cmd)
83
{
84 69 AlbertVeli
        unsigned int cmd_arg, cmd_command=0;
85 66 tac2
 
86 69 AlbertVeli
        //struct mmc_data *data = cmd->data;
87 68 tac2
        //WARN_ON(host->cmd != NULL);
88 65 AlbertVeli
        host->cmd = cmd;
89 69 AlbertVeli
 
90
        //Set up command
91 66 tac2
        cmd_arg = cmd->arg;
92
        cmd_command |= cmd->opcode << 8;
93 71 AlbertVeli
        cmd_command |= host->word_cnt << 6;
94
 
95
        if ( mmc_resp_type(cmd) == MMC_RSP_CRC  )
96 70 tac2
                cmd_command |= CRCE;
97
        if ( mmc_resp_type(cmd) == MMC_RSP_OPCODE  )
98
                cmd_command |= CICE;
99 71 AlbertVeli
 
100 66 tac2
        switch (mmc_resp_type(cmd)) {
101 71 AlbertVeli
        case MMC_RSP_NONE:
102
                cmd_command |= MMCOC_RSP_NONE;
103 66 tac2
                break;
104 71 AlbertVeli
        case MMC_RSP_R1:
105
                cmd_command |= MMCOC_RSP_48;
106 66 tac2
                break;
107 71 AlbertVeli
        case MMC_RSP_R1B:
108
                cmd_command |= MMCOC_RSP_48;
109 66 tac2
                break;
110 71 AlbertVeli
        case MMC_RSP_R2:
111
                cmd_command |= MMCOC_RSP_136;
112 66 tac2
                break;
113 71 AlbertVeli
        case MMC_RSP_R3:
114
                cmd_command |= MMCOC_RSP_48;
115 66 tac2
                break;
116 71 AlbertVeli
        default:
117 66 tac2
                printk(KERN_INFO "mmc_ocores: unhandled response type %02x\n",
118 71 AlbertVeli
                       mmc_resp_type(cmd));
119 66 tac2
        }
120 72 tac2
 
121
     /*If data
122
    //  if ( data->blksz & 0x3 ) {
123
                        pr_debug("Unsupported block size\n");
124
                        cmd->error = -EINVAL;
125
                        mmc_request_done(host->mmc, host->request);
126
                        return;
127
                } */
128
 
129 68 tac2
        printk(KERN_ALERT "%s: cmd_arg = %08x\n", __FUNCTION__, cmd_arg);
130 66 tac2
        printk(KERN_ALERT "%s: cmd_command   = %08x\n", __FUNCTION__, cmd_command);
131 71 AlbertVeli
        oc_host=host;
132 72 tac2
 
133
        //XXX:Remove after uppdated bitfil with Timeout
134
        if (cmd->opcode == 8  || cmd->opcode ==  5 )
135
        {
136
                host->mrq->cmd->error = -ETIMEDOUT;
137
                mmc_request_done(host->mmc, host->mrq);
138
        }
139
        else
140
        {
141
                CMD_IRQ_ON (host,(ECC|EEI));
142
                writel(cmd_command, host->base + SD_COMMAND);
143
                wmb();
144
                writel(cmd_arg, host->base + SD_ARG);
145
        }
146 65 AlbertVeli
}
147 69 AlbertVeli
 
148 66 tac2
static void ocores_process_next(struct ocores_host *host)
149 71 AlbertVeli
{
150
        host->word_cnt=0;
151 66 tac2
        if (!(host->flags & FL_SENT_COMMAND)) {
152
                host->flags |= FL_SENT_COMMAND;
153 69 AlbertVeli
                ocores_start_cmd(host, host->mrq->cmd);
154 66 tac2
        }
155
        else if ((!(host->flags & FL_SENT_STOP)) && host->mrq->stop) {
156
                host->flags |= FL_SENT_STOP;
157
                ocores_start_cmd(host, host->mrq->stop);
158
        }
159
}
160 69 AlbertVeli
 
161 65 AlbertVeli
static void ocores_request(struct mmc_host *mmc, struct mmc_request *mrq)
162
{
163
        struct ocores_host *host = mmc_priv(mmc);
164 69 AlbertVeli
 
165
        //unsigned int cmdr, mr;
166
 
167 65 AlbertVeli
        printk(KERN_ALERT "%s: mrq->cmd->opcode = %08x\n", __FUNCTION__, mrq->cmd->opcode);
168
        printk(KERN_ALERT "%s: mrq->cmd->arg    = %08x\n", __FUNCTION__, mrq->cmd->arg);
169
 
170 66 tac2
        //WARN_ON(host->mrq != NULL);
171 65 AlbertVeli
 
172
        host->mrq = mrq;
173 66 tac2
        host->flags = 0;
174 65 AlbertVeli
 
175 69 AlbertVeli
        ocores_process_next(host);
176
 
177
 
178 66 tac2
        printk(KERN_ALERT "%s: exit\n", __FUNCTION__);
179
}
180 65 AlbertVeli
 
181
 
182
 
183
static int ocores_get_ro(struct mmc_host *mmc)
184
{
185
        /* struct ocores_host *host = mmc_priv(mmc); */
186
 
187
        printk(KERN_ALERT "%s: enter\n", __FUNCTION__);
188
 
189
        /* if (host->pdata && host->pdata->get_ro) */
190
        /*      return host->pdata->get_ro(mmc_dev(mmc)); */
191
        /* /\* Host doesn't support read only detection so assume writeable *\/ */
192
        return 0;
193
}
194
 
195
static void ocores_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
196 69 AlbertVeli
{
197
        struct ocores_host *host = mmc_priv(mmc);
198 66 tac2
        int clk_div, cmd_timeout;
199 65 AlbertVeli
        /* struct ocores_host *host = mmc_priv(mmc); */
200 69 AlbertVeli
 
201 65 AlbertVeli
        printk(KERN_ALERT "%s: clock = 0x%08x\n", __FUNCTION__, ios->clock);
202
        printk(KERN_ALERT "%s: vdd = 0x%04x\n", __FUNCTION__, ios->vdd);
203
        printk(KERN_ALERT "%s: bus_mode = 0x%02x\n", __FUNCTION__, ios->bus_mode);
204
        printk(KERN_ALERT "%s: power_mode = 0x%02x\n", __FUNCTION__, ios->power_mode);
205
        printk(KERN_ALERT "%s: bus_width = 0x%02x\n", __FUNCTION__, ios->bus_width);
206
        printk(KERN_ALERT "%s: timing = 0x%02x\n", __FUNCTION__, ios->timing);
207 69 AlbertVeli
 
208 66 tac2
        //Set clock divider and timeout registers
209 69 AlbertVeli
        printk(KERN_ALERT "%s: host->base = %p\n", __FUNCTION__, host->base);
210 66 tac2
        if (ios->clock == 0) {
211 69 AlbertVeli
                //ocores_mci_write (host, SD_SOFTWARE_RST, SD_DISABLE);
212 66 tac2
        }
213
        else
214 69 AlbertVeli
        {
215 66 tac2
                writel(SD_DISABLE, host->base + SD_SOFTWARE_RST);
216
                clk_div = ((SYS_CLK / ios->clock)-2 )/ 2;
217 68 tac2
                cmd_timeout = ((SYS_CLK/ios->clock) * 512);
218 69 AlbertVeli
 
219 66 tac2
                printk(KERN_ALERT " clk_div = 0x%02x\n", clk_div);
220
                printk(KERN_ALERT " cmd_timeout = 0x%02x\n", cmd_timeout);
221 69 AlbertVeli
 
222 66 tac2
                writel (clk_div, host->base  + SD_CLOCK_DIVIDER);
223
                writel (cmd_timeout, host->base  + SD_TIMEOUT);
224 69 AlbertVeli
 
225
 
226 66 tac2
                writel(SD_ENABLE, host->base + SD_SOFTWARE_RST);
227
        }
228
 
229 65 AlbertVeli
}
230
 
231 66 tac2
 
232
 
233
static irqreturn_t ocores_irq_cmd(int irq, void *devid)
234
{
235 70 tac2
         struct ocores_host *host = oc_host;
236 71 AlbertVeli
 
237 70 tac2
         disable_irq(host->irq_cmd);
238 71 AlbertVeli
 
239 70 tac2
                //printk(KERN_ALERT "%s: IRQ START***** Normal In  = %08x\n", __FUNCTION__, readl(host->base + SD_NORMAL_INT_STATUS));
240 71 AlbertVeli
 
241 70 tac2
         host->registers.normal_int_status  = readl(host->base + SD_NORMAL_INT_STATUS);
242
         rmb();
243
         host->registers.error_int_status  = readl(host->base + SD_ERROR_INT_STATUS);
244 71 AlbertVeli
 
245 70 tac2
         writel(0,host->base + SD_NORMAL_INT_STATUS);
246
         writel(0,host->base + SD_ERROR_INT_STATUS);
247 71 AlbertVeli
 
248
         //printk(KERN_ALERT "%s: IRQ END***** Error In  = %08x\n", __FUNCTION__, readl(host->base + SD_ERROR_INT_STATUS));
249
         tasklet_schedule(&host->finish_cmd);
250
         CMD_IRQ_OFF (host,(ECC|EEI));
251
         enable_irq(host->irq_cmd);
252
 
253
         return IRQ_HANDLED;
254 66 tac2
}
255
 
256
static irqreturn_t ocores_irq_dat(int irq, void *dev_id)
257
{
258
 
259
}
260 69 AlbertVeli
 
261 65 AlbertVeli
static const struct mmc_host_ops ocores_ops = {
262
        .request                = ocores_request,
263
        .get_ro                 = ocores_get_ro,
264
        .set_ios                = ocores_set_ios,
265
        /* .enable_sdio_irq     = ocores_enable_sdio_irq, */
266
};
267
 
268
static int ocores_probe(struct platform_device *pdev)
269
{
270
        struct mmc_host *mmc;
271
        struct ocores_host *host = NULL;
272
        struct resource *r;
273
        int ret;
274
 
275
        printk(KERN_ALERT "%s: enter\n", __FUNCTION__);
276
 
277
        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
278
 
279
        printk(KERN_ALERT "%s: resource %x, %x\n", __FUNCTION__, r->start, r->end);
280
 
281
        r = request_mem_region(r->start, r->end - r->start, DRIVER_NAME);
282
        if (!r) {
283
                return -EBUSY;
284
        }
285
 
286
        mmc = mmc_alloc_host(sizeof(struct ocores_host), &pdev->dev);
287
        if (!mmc) {
288
                ret = -ENOMEM;
289
                goto out;
290
        }
291
 
292 69 AlbertVeli
 
293 65 AlbertVeli
        mmc->ops = &ocores_ops;
294 69 AlbertVeli
 
295 65 AlbertVeli
        mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
296
        mmc->caps = MMC_CAP_4_BIT_DATA;
297 66 tac2
        mmc->f_min = 700000;  //SYS_CLK  60; 0.7 Mhz
298 69 AlbertVeli
        mmc->f_max = 4166666;  //SYS_CLK;   4.166 666 mhz
299 65 AlbertVeli
 
300
        mmc->max_blk_count = 8;
301
        mmc->max_hw_segs = mmc->max_blk_count;
302
        mmc->max_blk_size = MMCOC_MAX_BLOCK_SIZE;
303
        mmc->max_seg_size = mmc->max_blk_count * mmc->max_blk_size;
304
        mmc->max_req_size = mmc->max_seg_size;
305
        mmc->max_phys_segs = mmc->max_hw_segs;
306
 
307
        host = mmc_priv(mmc);
308
        host->mmc = mmc;
309
        host->cmdat = 0;
310 69 AlbertVeli
        host->registers.normal_int_status =0;
311 65 AlbertVeli
 
312 66 tac2
 
313 69 AlbertVeli
        tasklet_init(&host->finish_cmd, ocores_tasklet_finish_cmd,
314
                     (unsigned long) host);
315
 
316 65 AlbertVeli
        spin_lock_init(&host->lock);
317
        host->res = r;
318
 
319 66 tac2
        host->base = ioremap(r->start, r->end - r->start +1);
320 65 AlbertVeli
        /* host->base = (void *)r->start; */
321
        if (!host->base) {
322
                ret = -ENOMEM;
323
                goto out;
324
        }
325
        host->pdata = pdev->dev.platform_data;
326
        mmc->ocr_avail = host->pdata->ocr_mask;
327 69 AlbertVeli
 
328
        host->irq_cmd = platform_get_irq_byname(pdev, "cmd_irq");
329 66 tac2
        ret = request_irq(host->irq_cmd, ocores_irq_cmd, IRQF_DISABLED, DRIVER_NAME, host);
330 69 AlbertVeli
        printk(KERN_ALERT "%s: IRQ dat resource  %x\n", __FUNCTION__, host->irq_cmd );
331
        printk(KERN_ALERT "%s: RET cmd irq %x\n", __FUNCTION__, ret);
332
        if (ret)
333 66 tac2
                goto out;
334
        disable_irq(host->irq_cmd);
335 69 AlbertVeli
 
336 66 tac2
        host->irq_dat = platform_get_irq_byname(pdev, "dat_irq");
337
        ret = request_irq(host->irq_dat, ocores_irq_dat, IRQF_DISABLED, DRIVER_NAME, host);
338 69 AlbertVeli
        printk(KERN_ALERT "%s: IRQ dat resource  %x\n", __FUNCTION__, host->irq_dat );
339
        printk(KERN_ALERT "%s: RET Dat irq  %x\n", __FUNCTION__, ret);
340
        if (ret)
341 66 tac2
                goto out;
342 69 AlbertVeli
        disable_irq(host->irq_dat);
343 65 AlbertVeli
 
344 66 tac2
 
345
 
346 69 AlbertVeli
        enable_irq(host->irq_cmd);
347 66 tac2
        enable_irq(host->irq_dat);
348 65 AlbertVeli
        printk(KERN_ALERT "%s: host->base = %p\n", __FUNCTION__, host->base);
349
        printk(KERN_ALERT "%s: SD_BLOCK = %08x\n", __FUNCTION__, readl(host->base + SD_BLOCK));
350
        printk(KERN_ALERT "%s: host->pdata->ocr_mask = %08x\n", __FUNCTION__, host->pdata->ocr_mask);
351 69 AlbertVeli
        oc_host=host;
352 65 AlbertVeli
        mmc_add_host(mmc);
353
 
354
        printk(KERN_ALERT "%s: exit\n", __FUNCTION__);
355
 
356
        return 0;
357
 
358
 out:
359 66 tac2
        printk(KERN_ALERT "%s: ERROR REQUESTINING RESOURCES\n", __FUNCTION__);
360 65 AlbertVeli
        if (mmc) {
361
                mmc_free_host(mmc);
362
        }
363
        release_resource(r);
364
 
365
        return ret;
366
}
367
 
368 69 AlbertVeli
static void ocores_tasklet_finish_cmd(unsigned long param)
369
{
370
        struct ocores_host *host = (struct ocores_host *) param;
371
 
372
        printk(KERN_ALERT " TASKLET RUNNS************\n");
373
 
374
        printk(KERN_ALERT "%s: TASKLET RUNNS****** Normal INT = %08x\n", __FUNCTION__,  host->registers.normal_int_status);
375
        printk(KERN_ALERT "%s: TASKLET RUNNS****** Error INT = %08x\n", __FUNCTION__,  host->registers.error_int_status);
376
 
377
        //Check For Transmissions errors
378
        if ((host->registers.normal_int_status & EI) == EI)
379
        {
380
                printk(KERN_ALERT "TRANSMISSION ERROR DETECTED");
381
                switch ( host->registers.error_int_status )
382
                {
383
                case (CTE):
384
                        pr_debug("Card took too long to respond\n");
385
                        host->mrq->cmd->error = -ETIMEDOUT ;
386
                        break;
387
                case (CCRC  ):
388
                        pr_debug(" CRC  problem with the received or sent data\n");
389
                        host->mrq->cmd->error = -EILSEQ;
390
                        break;
391
                case (CIE  ):
392
                        pr_debug("Index problem with the received or sent data\n");
393
                        host->mrq->cmd->error = -EILSEQ;
394
                        break;
395
                }
396
        }
397
        else
398 71 AlbertVeli
        {
399 70 tac2
                if ( mmc_resp_type(host->mrq->cmd) == MMCOC_RSP_136      )   //Long response
400 71 AlbertVeli
                {
401
                        printk(KERN_ALERT "Long Response, Word Cnt  * = %08x\n ",host->word_cnt);
402
                        host->word_cnt+=1;
403
                        switch(host->word_cnt-1)
404
                        {
405 70 tac2
                        case (0):
406
                                host->mrq->cmd->resp[3]  =  readl(host->base + SD_RESP1);
407 71 AlbertVeli
                                ocores_start_cmd(host, host->mrq->cmd);
408
                                break;
409 70 tac2
                        case (1):
410
                                host->mrq->cmd->resp[2]  =  readl(host->base + SD_RESP1);
411
                                ocores_start_cmd(host, host->mrq->cmd);
412 71 AlbertVeli
                                break;
413 70 tac2
                        case (2):
414
                                host->mrq->cmd->resp[1]  =  readl(host->base + SD_RESP1);
415
                                ocores_start_cmd(host, host->mrq->cmd);
416 71 AlbertVeli
                                break;
417 70 tac2
                        case (3):
418
                                host->mrq->cmd->resp[0]  =  readl(host->base + SD_RESP1);
419
                                mmc_request_done(host->mmc, host->mrq);
420 71 AlbertVeli
                                break;
421 70 tac2
                        }
422 71 AlbertVeli
                }
423
                else  //Short response
424
                {
425
                        host->mrq->cmd->error = 0 ;
426
                        host->mrq->cmd->resp[0] = readl(host->base + SD_RESP1);
427
                        printk(KERN_ALERT "Short Response CMD RSP * = %08x\n", host->mrq->cmd->resp[0]);
428
                        mmc_request_done(host->mmc, host->mrq);
429
                }
430 69 AlbertVeli
        }
431 72 tac2
 
432 69 AlbertVeli
}
433
 
434 65 AlbertVeli
static int ocores_remove(struct platform_device *pdev)
435
{
436
        struct mmc_host *mmc = platform_get_drvdata(pdev);
437
 
438
        printk(KERN_ALERT "%s: enter\n", __FUNCTION__);
439
 
440
        platform_set_drvdata(pdev, NULL);
441
 
442
        if (mmc) {
443
                struct ocores_host *host = mmc_priv(mmc);
444
 
445
                mmc_remove_host(mmc);
446
 
447
                release_resource(host->res);
448
 
449
                mmc_free_host(mmc);
450
        }
451
 
452
        printk(KERN_ALERT "%s: exit\n", __FUNCTION__);
453
 
454
        return 0;
455
}
456
 
457
#ifdef CONFIG_PM
458
static int ocores_suspend(struct platform_device *dev, pm_message_t state)
459
{
460
        struct mmc_host *mmc = platform_get_drvdata(dev);
461
        int ret = 0;
462
 
463
        printk(KERN_ALERT "%s: enter\n", __FUNCTION__);
464
 
465
        if (mmc) {
466
                ret = mmc_suspend_host(mmc, state);
467
        }
468
 
469
        printk(KERN_ALERT "%s: exit\n", __FUNCTION__);
470
 
471
        return ret;
472
}
473
 
474
static int ocores_resume(struct platform_device *dev)
475
{
476
        struct mmc_host *mmc = platform_get_drvdata(dev);
477
        int ret = 0;
478
 
479
        printk(KERN_ALERT "%s: enter\n", __FUNCTION__);
480
 
481
        if (mmc) {
482
                ret = mmc_resume_host(mmc);
483
        }
484
 
485
        printk(KERN_ALERT "%s: exit\n", __FUNCTION__);
486
 
487
        return ret;
488
}
489
#else
490
#define ocores_suspend  NULL
491
#define ocores_resume   NULL
492
#endif
493
 
494
static struct platform_driver ocores_driver = {
495
        .probe          = ocores_probe,
496
        .remove         = ocores_remove,
497
        .suspend        = ocores_suspend,
498
        .resume         = ocores_resume,
499
        .driver         = {
500
                .name   = DRIVER_NAME,
501
        },
502
};
503
 
504
static int __init ocores_init(void)
505
{
506
        printk(KERN_ALERT "%s: registering ocores platform_driver\n", __FUNCTION__);
507
 
508
        return platform_driver_register(&ocores_driver);
509
}
510
 
511
static void __exit ocores_exit(void)
512
{
513
        printk(KERN_ALERT "%s: unregistering ocores platform_driver\n", __FUNCTION__);
514
 
515
        platform_driver_unregister(&ocores_driver);
516
}
517
 
518
module_init(ocores_init);
519
module_exit(ocores_exit);
520
 
521
MODULE_DESCRIPTION("OpenCores Multimedia Card Interface Driver");
522
MODULE_LICENSE("GPL");

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.