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

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [linux-2.6/] [linux-2.6.24/] [arch/] [or32/] [drivers/] [sd_card.c] - Blame information for rev 16

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

Line No. Rev Author Line
1 16 xianfeng
/*
2
 *
3
 * Block driver for spiMaster to drive SD card
4
 *
5
 * Copyright (c) 2008 by:
6
 *      Xianfeng Zeng <xianfeng.zeng@gmail.com>
7
 *
8
 * This program is free software; you can redistribute it and/or modify
9
 * it under the terms of the BSD Licence, GNU General Public License
10
 * as published by the Free Software Foundation; either version 2 of the
11
 * License, or (at your option) any later version
12
 *
13
 * ChangeLog:
14
 *      2009-11-28 15:11:18   Xianfeng Zeng
15
 *          Init.
16
 *
17
 */
18
 
19
#include <linux/version.h>
20
#include <linux/module.h>
21
#include <linux/init.h>
22
#include <linux/kernel.h>
23
#include <linux/sched.h>
24
#include <linux/fs.h>
25
#include <linux/genhd.h>
26
#include <linux/delay.h>
27
 
28
#include <linux/slab.h>         /* kmalloc() */
29
#include <linux/errno.h>        /* error codes */
30
#include <linux/timer.h>
31
#include <linux/types.h>        /* size_t */
32
#include <linux/fcntl.h>        /* O_ACCMODE */
33
#include <linux/hdreg.h>        /* HDIO_GETGEO */
34
#include <linux/kdev_t.h>
35
#include <linux/vmalloc.h>
36
#include <linux/genhd.h>
37
#include <linux/blkdev.h>
38
#include <linux/buffer_head.h>  /* invalidate_bdev */
39
#include <linux/bio.h>
40
 
41
 
42
#include "sd_card.h"
43
 
44
#define SDC_DEBUG 1
45
 
46
#ifdef SDC_DEBUG
47
#       define SDC_PRINTK(fmt, args...) printk( KERN_WARNING "sd_card:" fmt, ## args)
48
#else
49
#       define SDC_PRINTK(fmt, args...)
50
#endif
51
 
52
#define DRIVER_NAME  "sd_card"
53
#define SD_CARD_MINORS 16
54
 
55
static int major = 8;
56
 
57
 
58
/**
59
 * ============================================================
60
 *
61
 * ============================================================
62
 */
63
int spiMaster_init(void *vbase)
64
{
65
        unsigned char data;
66
        int   i;
67
 
68
        SDC_PRINTK("spiMaster_init begin\n");
69
 
70
        REG8(vbase + SD_TX_FIFO_CONTROL_REG) = 0x10;
71
 
72
        for (i = 0; i < 5; i++) {
73
                REG8(vbase + SD_TRANS_TYPE_REG) = SD_INIT_SD;
74
                REG8(vbase + SD_TRANS_CTRL_REG) = 1; // TRANS_START;
75
 
76
                mdelay(1);
77
 
78
                while (REG8(vbase + SD_TRANS_STS_REG) & 0x1) { // exit while !TRABS_BUSY
79
                        ;
80
                }
81
 
82
                data = REG8(vbase + SD_TRANS_ERROR_REG) & 0x3;
83
 
84
                if (data == 0) {
85
                        SDC_PRINTK("spiMaster_init done\n");
86
                        return 0;
87
                }
88
        }
89
 
90
        SDC_PRINTK("spiMaster_init failed\n");
91
 
92
        return data;
93
}
94
 
95
/**
96
 * ============================================================
97
 *             Request Handling
98
 * ============================================================
99
 */
100
 
101
static int read_sd_block(void *sd_vbase, unsigned long sector,
102
                unsigned long nsect, char *buffer)
103
{
104
        unsigned char data;
105
        unsigned char transError;
106
        int i;
107
        unsigned int buffer_offset = 0;
108
        unsigned int blockCnt;
109
 
110
        SDC_PRINTK("read_sd_block begin: sector=%d, nsect=%d\n", sector, nsect);
111
 
112
        for (blockCnt = 0; blockCnt < nsect; blockCnt++) {
113
                REG8(sd_vbase + SD_ADDR_7_0_REG)   = 0;
114
                REG8(sd_vbase + SD_ADDR_15_8_REG)  = (unsigned char) ((sector >> 8) & 0xff);
115
                REG8(sd_vbase + SD_ADDR_23_16_REG) = (unsigned char) ((sector >> 16) & 0xff);
116
                REG8(sd_vbase + SD_ADDR_31_24_REG) = (unsigned char) ((sector >> 24) & 0xff);
117
 
118
                REG8(sd_vbase + SD_TRANS_TYPE_REG) = SD_RW_READ_SD_BLOCK;
119
                REG8(sd_vbase + SD_RX_FIFO_CONTROL_REG) = 0x1; // Clean the RX FIFO
120
                REG8(sd_vbase + SD_TRANS_CTRL_REG) = 0x1; //TRANS_START
121
                while (REG8(sd_vbase + SD_TRANS_STS_REG) & 0x1) { // exit while !TRABS_BUSY
122
                        ;
123
                }
124
 
125
                transError = REG8(sd_vbase + SD_TRANS_ERROR_REG) & 0xc;
126
                if ( transError == SD_READ_NO_ERROR) {
127
                        for (i = 0; i < 512; i++) {
128
                                data = REG8(sd_vbase + SD_RX_FIFO_DATA_REG) ;
129
                                REG8(buffer + buffer_offset + i) = data ;
130
                        }
131
                        buffer_offset += 512;
132
                        sector += 512;
133
                } else {
134
                        SDC_PRINTK("read_sd_block failed. Re-try\n");
135
                        spiMaster_init(sd_vbase); /* Init again and retry */
136
                        blockCnt--; /* read the same block again */
137
                }
138
        }
139
 
140
        SDC_PRINTK("read_sd_block done\n");
141
 
142
        return 0;
143
}
144
 
145
 
146
/*
147
 * Handle an I/O request.
148
 */
149
static void sd_card_transfer(struct sd_card_dev *dev, unsigned long sector,
150
                unsigned long nsect, char *buffer, int write)
151
{
152
        unsigned long offset = sector*512;
153
        unsigned long nbytes = nsect*512;
154
 
155
        if ((offset + nbytes) > dev->size) {
156
                printk (KERN_NOTICE "Beyond-end write (%ld %ld)\n", offset, nbytes);
157
                return;
158
        }
159
        if (write)
160
                printk(KERN_WARNING "Sorry, we are still working on sd block write\n");
161
        else
162
                read_sd_block(dev->vir_base, sector, nsect, buffer);
163
}
164
 
165
 
166
/*
167
 * The simple form of the request function.
168
 */
169
static void sd_card_request(request_queue_t *q)
170
{
171
        struct request *req;
172
 
173
        while ((req = elv_next_request(q)) != NULL) {
174
                struct sd_card_dev *dev = req->rq_disk->private_data;
175
                if (! blk_fs_request(req)) {
176
                        printk (KERN_NOTICE "Skip non-fs request\n");
177
                        end_request(req, 0);
178
                        continue;
179
                }
180
    //          printk (KERN_NOTICE "Req dev %d dir %ld sec %ld, nr %d f %lx\n",
181
    //                          dev - Devices, rq_data_dir(req),
182
    //                          req->sector, req->current_nr_sectors,
183
    //                          req->flags);
184
                sd_card_transfer(dev, req->sector, req->current_nr_sectors,
185
                                req->buffer, rq_data_dir(req));
186
                end_request(req, 1);
187
        }
188
}
189
 
190
/**
191
 * ============================================================
192
 *             Block device operations
193
 * ============================================================
194
 */
195
static int sd_card_open(struct inode *inode, struct file *filp)
196
{
197
        struct sd_card_dev *dev = inode->i_bdev->bd_disk->private_data;
198
 
199
        SDC_PRINTK("sd_card_open beging\n");
200
 
201
        filp->private_data = dev;
202
        spin_lock(&dev->lock);
203
        if (! dev->users)
204
                check_disk_change(inode->i_bdev);
205
 
206
        /* Init SD card controller */
207
        spiMaster_init(dev->vir_base);
208
 
209
        dev->users++;
210
        spin_unlock(&dev->lock);
211
 
212
        SDC_PRINTK("sd_card_open done\n");
213
 
214
        return 0;
215
}
216
 
217
static int sd_card_release(struct inode *inode, struct file *filp)
218
{
219
        struct sd_card_dev *dev = inode->i_bdev->bd_disk->private_data;
220
 
221
        SDC_PRINTK("sd_card_release beging\n");
222
 
223
        spin_lock(&dev->lock);
224
        dev->users--;
225
 
226
        spin_unlock(&dev->lock);
227
 
228
        SDC_PRINTK("sd_card_release done\n");
229
 
230
        return 0;
231
}
232
 
233
/*
234
 * Look for a (simulated) media change.
235
 */
236
int sd_card_media_changed(struct gendisk *gd)
237
{
238
        //struct sd_card_dev *dev = gd->private_data;
239
 
240
        return 0; //dev->media_change;
241
}
242
 
243
/*
244
 * Revalidate.  WE DO NOT TAKE THE LOCK HERE, for fear of deadlocking
245
 * with open.  That needs to be reevaluated.
246
 */
247
int sd_card_revalidate(struct gendisk *gd)
248
{
249
        struct sd_card_dev *dev = gd->private_data;
250
 
251
        if (dev->media_change) {
252
                dev->media_change = 0;
253
//              memset (dev->data, 0, dev->size);
254
        }
255
        return 0;
256
}
257
 
258
 
259
/*
260
 * The ioctl() implementation
261
 */
262
 
263
int sd_card_ioctl (struct inode *inode, struct file *filp,
264
                 unsigned int cmd, unsigned long arg)
265
{
266
        long size;
267
        struct hd_geometry geo;
268
        struct sd_card_dev *dev = filp->private_data;
269
 
270
        switch(cmd) {
271
            case HDIO_GETGEO:
272
                /*
273
                 * Get geometry: since we are a virtual device, we have to make
274
                 * up something plausible.  So we claim 16 sectors, four heads,
275
                 * and calculate the corresponding number of cylinders.  We set the
276
                 * start of data at sector four.
277
                 */
278
                size = dev->size;
279
                geo.cylinders = 1010; //984;
280
                geo.heads = 8; //32;
281
                geo.sectors = 62; //63;
282
                geo.start = 0;
283
                if (copy_to_user((void __user *) arg, &geo, sizeof(geo)))
284
                        return -EFAULT;
285
                return 0;
286
        }
287
 
288
        return -ENOTTY; /* unknown command */
289
}
290
 
291
 
292
/*
293
 * The device operations structure.
294
 */
295
static struct block_device_operations sd_card_ops = {
296
        .owner           = THIS_MODULE,
297
        .open            = sd_card_open,
298
        .release         = sd_card_release,
299
        .media_changed   = sd_card_media_changed,
300
        .revalidate_disk = sd_card_revalidate,
301
        .ioctl           = sd_card_ioctl
302
};
303
 
304
/**
305
 * ============================================================
306
 *                 Driver Entry and clean up
307
 * ============================================================
308
 */
309
static int __init sd_card_init(void)
310
{
311
        int ret;
312
        struct sd_card_dev  *dev;
313
 
314
        /* Put the init code here */
315
        printk(KERN_INFO "SD Card Driver Enter.\n");
316
 
317
        dev = (struct sd_card_dev *)kmalloc(sizeof(struct sd_card_dev), GFP_KERNEL);
318
        if (dev < 0) {
319
                printk(KERN_WARNING "lack of memory\n");
320
                return -1;
321
        }
322
        memset(dev, 0, sizeof(struct sd_card_dev));
323
 
324
        ret = register_blkdev(major, DRIVER_NAME);
325
        if (ret <0) {
326
                printk(KERN_WARNING "sd_card: unable to get major number\n");
327
                kfree(dev);
328
                return -EBUSY;
329
        }
330
 
331
        dev->size = 256638976; //1015808000; /* 1GB */
332
        spin_lock_init(&dev->lock);
333
        dev->queue = blk_init_queue(sd_card_request, &dev->lock);
334
        blk_queue_hardsect_size(dev->queue, 512);
335
 
336
        dev->vir_base = ioremap(SD_BASE_ADD, 0x2000);
337
 
338
        /* allocate gendsik and init it */
339
        dev->gd = alloc_disk(SD_CARD_MINORS);
340
        if (!dev->gd) {
341
                printk(KERN_WARNING "alloc_disk failed\n");
342
                kfree(dev);
343
                unregister_blkdev(major, DRIVER_NAME);
344
                return -1;
345
        }
346
        dev->gd->major          = major;
347
        dev->gd->first_minor    = 0;
348
        dev->gd->fops           = &sd_card_ops;
349
        dev->gd->queue          = dev->queue;
350
        dev->gd->private_data   = dev;
351
        snprintf(dev->gd->disk_name, 32, "sd%c", 'a');
352
 
353
        set_capacity(dev->gd, dev->size/512);
354
 
355
        add_disk(dev->gd);
356
 
357
        SDC_PRINTK("sd_card_init done\n");
358
 
359
        return 0;
360
}
361
 
362
 
363
static void __exit sd_card_exit(void)
364
{
365
        /* Put the driver clean up code here */
366
 
367
        unregister_blkdev(major, DRIVER_NAME);
368
 
369
        printk(KERN_INFO "SD Card Driver Exit.\n");
370
}
371
 
372
//module_init(sd_card_init);
373
late_initcall(sd_card_init);
374
module_exit(sd_card_exit);
375
 
376
MODULE_LICENSE("Dual BSD/GPL");
377
MODULE_AUTHOR("Xianfeng Zeng - Xianfeng.zeng@SierraAtlantic.com, http://www.LinuxExperts.cn");
378
MODULE_DESCRIPTION("spiMaster driver");
379
MODULE_VERSION("0.1");
380
 

powered by: WebSVN 2.1.0

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