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 69

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

powered by: WebSVN 2.1.0

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