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

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /or1k_soc_on_altera_embedded_dev_kit/trunk
    from Rev 13 to Rev 16
    Reverse comparison

Rev 13 → Rev 16

/linux-2.6/linux-2.6.24/arch/or32/drivers/sd_card.c
0,0 → 1,380
/*
*
* Block driver for spiMaster to drive SD card
*
* Copyright (c) 2008 by:
* Xianfeng Zeng <xianfeng.zeng@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the BSD Licence, GNU General Public License
* as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version
*
* ChangeLog:
* 2009-11-28 15:11:18 Xianfeng Zeng
* Init.
*
*/
 
#include <linux/version.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/genhd.h>
#include <linux/delay.h>
 
#include <linux/slab.h> /* kmalloc() */
#include <linux/errno.h> /* error codes */
#include <linux/timer.h>
#include <linux/types.h> /* size_t */
#include <linux/fcntl.h> /* O_ACCMODE */
#include <linux/hdreg.h> /* HDIO_GETGEO */
#include <linux/kdev_t.h>
#include <linux/vmalloc.h>
#include <linux/genhd.h>
#include <linux/blkdev.h>
#include <linux/buffer_head.h> /* invalidate_bdev */
#include <linux/bio.h>
 
 
#include "sd_card.h"
 
#define SDC_DEBUG 1
 
#ifdef SDC_DEBUG
# define SDC_PRINTK(fmt, args...) printk( KERN_WARNING "sd_card:" fmt, ## args)
#else
# define SDC_PRINTK(fmt, args...)
#endif
 
#define DRIVER_NAME "sd_card"
#define SD_CARD_MINORS 16
 
static int major = 8;
 
 
/**
* ============================================================
*
* ============================================================
*/
int spiMaster_init(void *vbase)
{
unsigned char data;
int i;
 
SDC_PRINTK("spiMaster_init begin\n");
 
REG8(vbase + SD_TX_FIFO_CONTROL_REG) = 0x10;
 
for (i = 0; i < 5; i++) {
REG8(vbase + SD_TRANS_TYPE_REG) = SD_INIT_SD;
REG8(vbase + SD_TRANS_CTRL_REG) = 1; // TRANS_START;
 
mdelay(1);
 
while (REG8(vbase + SD_TRANS_STS_REG) & 0x1) { // exit while !TRABS_BUSY
;
}
 
data = REG8(vbase + SD_TRANS_ERROR_REG) & 0x3;
 
if (data == 0) {
SDC_PRINTK("spiMaster_init done\n");
return 0;
}
}
 
SDC_PRINTK("spiMaster_init failed\n");
 
return data;
}
 
/**
* ============================================================
* Request Handling
* ============================================================
*/
 
static int read_sd_block(void *sd_vbase, unsigned long sector,
unsigned long nsect, char *buffer)
{
unsigned char data;
unsigned char transError;
int i;
unsigned int buffer_offset = 0;
unsigned int blockCnt;
 
SDC_PRINTK("read_sd_block begin: sector=%d, nsect=%d\n", sector, nsect);
 
for (blockCnt = 0; blockCnt < nsect; blockCnt++) {
REG8(sd_vbase + SD_ADDR_7_0_REG) = 0;
REG8(sd_vbase + SD_ADDR_15_8_REG) = (unsigned char) ((sector >> 8) & 0xff);
REG8(sd_vbase + SD_ADDR_23_16_REG) = (unsigned char) ((sector >> 16) & 0xff);
REG8(sd_vbase + SD_ADDR_31_24_REG) = (unsigned char) ((sector >> 24) & 0xff);
 
REG8(sd_vbase + SD_TRANS_TYPE_REG) = SD_RW_READ_SD_BLOCK;
REG8(sd_vbase + SD_RX_FIFO_CONTROL_REG) = 0x1; // Clean the RX FIFO
REG8(sd_vbase + SD_TRANS_CTRL_REG) = 0x1; //TRANS_START
while (REG8(sd_vbase + SD_TRANS_STS_REG) & 0x1) { // exit while !TRABS_BUSY
;
}
 
transError = REG8(sd_vbase + SD_TRANS_ERROR_REG) & 0xc;
if ( transError == SD_READ_NO_ERROR) {
for (i = 0; i < 512; i++) {
data = REG8(sd_vbase + SD_RX_FIFO_DATA_REG) ;
REG8(buffer + buffer_offset + i) = data ;
}
buffer_offset += 512;
sector += 512;
} else {
SDC_PRINTK("read_sd_block failed. Re-try\n");
spiMaster_init(sd_vbase); /* Init again and retry */
blockCnt--; /* read the same block again */
}
}
 
SDC_PRINTK("read_sd_block done\n");
 
return 0;
}
 
 
/*
* Handle an I/O request.
*/
static void sd_card_transfer(struct sd_card_dev *dev, unsigned long sector,
unsigned long nsect, char *buffer, int write)
{
unsigned long offset = sector*512;
unsigned long nbytes = nsect*512;
 
if ((offset + nbytes) > dev->size) {
printk (KERN_NOTICE "Beyond-end write (%ld %ld)\n", offset, nbytes);
return;
}
if (write)
printk(KERN_WARNING "Sorry, we are still working on sd block write\n");
else
read_sd_block(dev->vir_base, sector, nsect, buffer);
}
 
 
/*
* The simple form of the request function.
*/
static void sd_card_request(request_queue_t *q)
{
struct request *req;
 
while ((req = elv_next_request(q)) != NULL) {
struct sd_card_dev *dev = req->rq_disk->private_data;
if (! blk_fs_request(req)) {
printk (KERN_NOTICE "Skip non-fs request\n");
end_request(req, 0);
continue;
}
// printk (KERN_NOTICE "Req dev %d dir %ld sec %ld, nr %d f %lx\n",
// dev - Devices, rq_data_dir(req),
// req->sector, req->current_nr_sectors,
// req->flags);
sd_card_transfer(dev, req->sector, req->current_nr_sectors,
req->buffer, rq_data_dir(req));
end_request(req, 1);
}
}
 
/**
* ============================================================
* Block device operations
* ============================================================
*/
static int sd_card_open(struct inode *inode, struct file *filp)
{
struct sd_card_dev *dev = inode->i_bdev->bd_disk->private_data;
 
SDC_PRINTK("sd_card_open beging\n");
 
filp->private_data = dev;
spin_lock(&dev->lock);
if (! dev->users)
check_disk_change(inode->i_bdev);
 
/* Init SD card controller */
spiMaster_init(dev->vir_base);
 
dev->users++;
spin_unlock(&dev->lock);
 
SDC_PRINTK("sd_card_open done\n");
 
return 0;
}
 
static int sd_card_release(struct inode *inode, struct file *filp)
{
struct sd_card_dev *dev = inode->i_bdev->bd_disk->private_data;
 
SDC_PRINTK("sd_card_release beging\n");
 
spin_lock(&dev->lock);
dev->users--;
 
spin_unlock(&dev->lock);
 
SDC_PRINTK("sd_card_release done\n");
 
return 0;
}
 
/*
* Look for a (simulated) media change.
*/
int sd_card_media_changed(struct gendisk *gd)
{
//struct sd_card_dev *dev = gd->private_data;
return 0; //dev->media_change;
}
 
/*
* Revalidate. WE DO NOT TAKE THE LOCK HERE, for fear of deadlocking
* with open. That needs to be reevaluated.
*/
int sd_card_revalidate(struct gendisk *gd)
{
struct sd_card_dev *dev = gd->private_data;
if (dev->media_change) {
dev->media_change = 0;
// memset (dev->data, 0, dev->size);
}
return 0;
}
 
 
/*
* The ioctl() implementation
*/
 
int sd_card_ioctl (struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
long size;
struct hd_geometry geo;
struct sd_card_dev *dev = filp->private_data;
 
switch(cmd) {
case HDIO_GETGEO:
/*
* Get geometry: since we are a virtual device, we have to make
* up something plausible. So we claim 16 sectors, four heads,
* and calculate the corresponding number of cylinders. We set the
* start of data at sector four.
*/
size = dev->size;
geo.cylinders = 1010; //984;
geo.heads = 8; //32;
geo.sectors = 62; //63;
geo.start = 0;
if (copy_to_user((void __user *) arg, &geo, sizeof(geo)))
return -EFAULT;
return 0;
}
 
return -ENOTTY; /* unknown command */
}
 
 
/*
* The device operations structure.
*/
static struct block_device_operations sd_card_ops = {
.owner = THIS_MODULE,
.open = sd_card_open,
.release = sd_card_release,
.media_changed = sd_card_media_changed,
.revalidate_disk = sd_card_revalidate,
.ioctl = sd_card_ioctl
};
 
/**
* ============================================================
* Driver Entry and clean up
* ============================================================
*/
static int __init sd_card_init(void)
{
int ret;
struct sd_card_dev *dev;
 
/* Put the init code here */
printk(KERN_INFO "SD Card Driver Enter.\n");
 
dev = (struct sd_card_dev *)kmalloc(sizeof(struct sd_card_dev), GFP_KERNEL);
if (dev < 0) {
printk(KERN_WARNING "lack of memory\n");
return -1;
}
memset(dev, 0, sizeof(struct sd_card_dev));
 
ret = register_blkdev(major, DRIVER_NAME);
if (ret <0) {
printk(KERN_WARNING "sd_card: unable to get major number\n");
kfree(dev);
return -EBUSY;
}
 
dev->size = 256638976; //1015808000; /* 1GB */
spin_lock_init(&dev->lock);
dev->queue = blk_init_queue(sd_card_request, &dev->lock);
blk_queue_hardsect_size(dev->queue, 512);
 
dev->vir_base = ioremap(SD_BASE_ADD, 0x2000);
 
/* allocate gendsik and init it */
dev->gd = alloc_disk(SD_CARD_MINORS);
if (!dev->gd) {
printk(KERN_WARNING "alloc_disk failed\n");
kfree(dev);
unregister_blkdev(major, DRIVER_NAME);
return -1;
}
dev->gd->major = major;
dev->gd->first_minor = 0;
dev->gd->fops = &sd_card_ops;
dev->gd->queue = dev->queue;
dev->gd->private_data = dev;
snprintf(dev->gd->disk_name, 32, "sd%c", 'a');
 
set_capacity(dev->gd, dev->size/512);
 
add_disk(dev->gd);
 
SDC_PRINTK("sd_card_init done\n");
 
return 0;
}
 
 
static void __exit sd_card_exit(void)
{
/* Put the driver clean up code here */
 
unregister_blkdev(major, DRIVER_NAME);
 
printk(KERN_INFO "SD Card Driver Exit.\n");
}
 
//module_init(sd_card_init);
late_initcall(sd_card_init);
module_exit(sd_card_exit);
 
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Xianfeng Zeng - Xianfeng.zeng@SierraAtlantic.com, http://www.LinuxExperts.cn");
MODULE_DESCRIPTION("spiMaster driver");
MODULE_VERSION("0.1");
 
/linux-2.6/linux-2.6.24/arch/or32/drivers/sd_card.h
0,0 → 1,59
#ifndef __SD_CARD_H__
#define __SD_CARD_H__
 
 
#define SD_BASE_ADD 0x50000000
 
#define SD_TRANS_TYPE_REG 0x2
#define SD_TRANS_CTRL_REG 0x3
#define SD_TRANS_STS_REG 0x4
#define SD_TRANS_ERROR_REG 0x5
#define SD_DIRECT_ACCESS_DATA_REG 0x6
#define SD_ADDR_7_0_REG 0x7
#define SD_ADDR_15_8_REG 0x8
#define SD_ADDR_23_16_REG 0x9
#define SD_ADDR_31_24_REG 0xa
#define SD_CLK_DEL_REG 0xb
#define SD_RX_FIFO_DATA_REG 0x10
#define SD_RX_FIFO_DATA_COUNT_MSB 0x12
#define SD_RX_FIFO_DATA_COUNT_LSB 0x13
#define SD_RX_FIFO_CONTROL_REG 0x14
#define SD_TX_FIFO_DATA_REG 0x20
#define SD_TX_FIFO_CONTROL_REG 0x24
 
#define SD_DIRECT_ACCESS 0
#define SD_INIT_SD 1
#define SD_RW_READ_SD_BLOCK 2
#define SD_RW_WRITE_SD_BLOCK 3
 
#define SD_WRITE_NO_ERROR 0
#define SD_WRITE_CMD_ERROR 1
#define SD_WRITE_DATA_ERROR 2
#define SD_WRITE_BUSY_ERROR 3
 
#define SD_READ_NO_ERROR 0
#define SD_READ_CMD_ERROR 1
#define SD_READ_TOKEN_ERROR 2
 
#define SD_INIT_NO_ERROR 0
#define SD_INIT_CMD0_ERROR 1
#define SD_INIT_CMD1_ERROR 2
 
#define REG8(add) *((volatile unsigned char *) (add))
#define REG16(add) *((volatile unsigned short *) (add))
#define REG32(add) *((volatile unsigned long *) (add))
 
struct sd_card_dev {
void *vir_base; /* Virtual address for spiMaster */
int size; /* the size of the SD Card */
short users; /* How many users are using me */
short media_change; /* a flag to save the media change */
spinlock_t lock; /* lock for request queue */
struct request_queue *queue; /* request queue */
struct gendisk *gd; /* gendisk */
};
 
 
 
#endif /* __SD_CARD_H__ */
 
/linux-2.6/linux-2.6.24/arch/or32/drivers/Makefile
3,4 → 3,5
#
 
obj-$(CONFIG_OETH) += open_eth.o
#obj-y += sd_card.o
 

powered by: WebSVN 2.1.0

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