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 76

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

powered by: WebSVN 2.1.0

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