Line 48... |
Line 48... |
#else
|
#else
|
# define SDC_PRINTK(fmt, args...)
|
# define SDC_PRINTK(fmt, args...)
|
#endif
|
#endif
|
|
|
#define DRIVER_NAME "sd_card"
|
#define DRIVER_NAME "sd_card"
|
#define SD_CARD_MINORS 16
|
#define SD_CARD_MINORS 8
|
|
#define SD_CARD_SIZE 1995440128
|
|
|
static int major = 8;
|
static int major = 8;
|
|
|
|
|
/**
|
/**
|
Line 65... |
Line 66... |
unsigned char data;
|
unsigned char data;
|
int i;
|
int i;
|
|
|
SDC_PRINTK("spiMaster_init begin\n");
|
SDC_PRINTK("spiMaster_init begin\n");
|
|
|
REG8(vbase + SD_TX_FIFO_CONTROL_REG) = 0x10;
|
|
|
|
for (i = 0; i < 5; i++) {
|
for (i = 0; i < 5; i++) {
|
REG8(vbase + SD_TRANS_TYPE_REG) = SD_INIT_SD;
|
REG8(vbase + SD_TRANS_TYPE_REG) = SD_INIT_SD;
|
REG8(vbase + SD_TRANS_CTRL_REG) = 1; // TRANS_START;
|
REG8(vbase + SD_TRANS_CTRL_REG) = 1; // TRANS_START;
|
|
|
mdelay(1);
|
mdelay(1);
|
Line 114... |
Line 113... |
REG8(sd_vbase + SD_ADDR_15_8_REG) = (unsigned char) ((sector >> 8) & 0xff);
|
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_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_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_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_RX_FIFO_CONTROL_REG) = 0x1; /* Clean the RX FIFO */
|
REG8(sd_vbase + SD_TRANS_CTRL_REG) = 0x1; //TRANS_START
|
REG8(sd_vbase + SD_TRANS_CTRL_REG) = 0x1; /* TRANS_START */
|
while (REG8(sd_vbase + SD_TRANS_STS_REG) & 0x1) { // exit while !TRABS_BUSY
|
while (REG8(sd_vbase + SD_TRANS_STS_REG) & 0x1) { /* exit while !TRABS_BUSY */
|
;
|
;
|
}
|
}
|
|
|
transError = REG8(sd_vbase + SD_TRANS_ERROR_REG) & 0xc;
|
transError = REG8(sd_vbase + SD_TRANS_ERROR_REG) & 0xc;
|
if ( transError == SD_READ_NO_ERROR) {
|
if ( transError == SD_READ_NO_ERROR) {
|
Line 140... |
Line 139... |
SDC_PRINTK("read_sd_block done\n");
|
SDC_PRINTK("read_sd_block done\n");
|
|
|
return 0;
|
return 0;
|
}
|
}
|
|
|
|
static int write_sd_block(void *sd_vbase, unsigned long sector,
|
|
unsigned long nsect, char *buffer)
|
|
{
|
|
int i;
|
|
unsigned char data;
|
|
unsigned int blockCnt;
|
|
char *p = buffer;
|
|
|
|
SDC_PRINTK("write_sd_block begin: sector=%d, nsect=%d\n", sector, nsect);
|
|
|
|
for (blockCnt = 0; blockCnt < nsect; blockCnt++) {
|
|
|
|
/* Clean the TX FIFO */
|
|
REG8(sd_vbase + SD_TX_FIFO_CONTROL_REG) = 0x1;
|
|
|
|
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);
|
|
|
|
|
|
// Write data to TX_FIFO_DATA_REG
|
|
for (i = 0; i < 512; i++) {
|
|
REG8(sd_vbase + SD_TX_FIFO_DATA_REG) = p[i];
|
|
}
|
|
|
|
|
|
REG8(sd_vbase + SD_TRANS_TYPE_REG) = SD_RW_WRITE_SD_BLOCK;
|
|
REG8(sd_vbase + SD_TRANS_CTRL_REG) = 1; /* TRANS_START */
|
|
|
|
|
|
while (REG8(sd_vbase + SD_TRANS_STS_REG) & 0x1) { /* exit while !TRABS_BUSY */
|
|
;
|
|
}
|
|
|
|
data = REG8(sd_vbase + SD_TRANS_ERROR_REG) & 0x30;
|
|
if (data == 1) {
|
|
SDC_PRINTK("WRITE_CMD_ERROR\n\r");
|
|
} else if (data == 2) {
|
|
SDC_PRINTK("WRITE_DATA_ERROR\n\r");
|
|
} else if (data == 3) {
|
|
SDC_PRINTK("WRITE_BUSY_ERROR\n\r");
|
|
}
|
|
|
|
sector += 512;
|
|
p += 512;
|
|
}
|
|
|
|
SDC_PRINTK("write_sd_block done\n");
|
|
return 0;
|
|
}
|
|
|
/*
|
/*
|
* Handle an I/O request.
|
* Handle an I/O request.
|
*/
|
*/
|
static void sd_card_transfer(struct sd_card_dev *dev, unsigned long sector,
|
static void sd_card_transfer(struct sd_card_dev *dev, unsigned long sector,
|
Line 155... |
Line 205... |
if ((offset + nbytes) > dev->size) {
|
if ((offset + nbytes) > dev->size) {
|
printk (KERN_NOTICE "Beyond-end write (%ld %ld)\n", offset, nbytes);
|
printk (KERN_NOTICE "Beyond-end write (%ld %ld)\n", offset, nbytes);
|
return;
|
return;
|
}
|
}
|
if (write)
|
if (write)
|
printk(KERN_WARNING "Sorry, we are still working on sd block write\n");
|
write_sd_block(dev->vir_base, sector, nsect, buffer);
|
else
|
else
|
read_sd_block(dev->vir_base, sector, nsect, buffer);
|
read_sd_block(dev->vir_base, sector, nsect, buffer);
|
}
|
}
|
|
|
|
|
Line 274... |
Line 324... |
* up something plausible. So we claim 16 sectors, four heads,
|
* up something plausible. So we claim 16 sectors, four heads,
|
* and calculate the corresponding number of cylinders. We set the
|
* and calculate the corresponding number of cylinders. We set the
|
* start of data at sector four.
|
* start of data at sector four.
|
*/
|
*/
|
size = dev->size;
|
size = dev->size;
|
geo.cylinders = 1010; //984;
|
geo.cylinders = (size & ~0x3f) >> 6;
|
geo.heads = 8; //32;
|
geo.heads = 62; //32;
|
geo.sectors = 62; //63;
|
geo.sectors = 62; //63;
|
geo.start = 0;
|
geo.start = get_start_sect(inode->i_bdev);
|
if (copy_to_user((void __user *) arg, &geo, sizeof(geo)))
|
if (copy_to_user((void __user *) arg, &geo, sizeof(geo)))
|
return -EFAULT;
|
return -EFAULT;
|
return 0;
|
return 0;
|
}
|
}
|
|
|
Line 326... |
Line 376... |
printk(KERN_WARNING "sd_card: unable to get major number\n");
|
printk(KERN_WARNING "sd_card: unable to get major number\n");
|
kfree(dev);
|
kfree(dev);
|
return -EBUSY;
|
return -EBUSY;
|
}
|
}
|
|
|
dev->size = 256638976; //1015808000; /* 1GB */
|
dev->size = SD_CARD_SIZE; //1015808000; /* 1GB */
|
spin_lock_init(&dev->lock);
|
spin_lock_init(&dev->lock);
|
dev->queue = blk_init_queue(sd_card_request, &dev->lock);
|
dev->queue = blk_init_queue(sd_card_request, &dev->lock);
|
blk_queue_hardsect_size(dev->queue, 512);
|
blk_queue_hardsect_size(dev->queue, 512);
|
|
|
dev->vir_base = ioremap(SD_BASE_ADD, 0x2000);
|
dev->vir_base = ioremap(SD_BASE_ADD, 0x2000);
|
|
|
|
/* Reset spiMaster controller */
|
|
REG8(dev->vir_base + SD_TRANS_CTRL_REG) = 0x1; /* reset spiMaster */
|
|
mdelay(1);
|
|
REG8(dev->vir_base + SD_TRANS_CTRL_REG) = 0x0;
|
|
REG8(dev->vir_base + SD_CLK_DEL_REG) = 0x1;
|
|
|
/* allocate gendsik and init it */
|
/* allocate gendsik and init it */
|
dev->gd = alloc_disk(SD_CARD_MINORS);
|
dev->gd = alloc_disk(SD_CARD_MINORS);
|
if (!dev->gd) {
|
if (!dev->gd) {
|
printk(KERN_WARNING "alloc_disk failed\n");
|
printk(KERN_WARNING "alloc_disk failed\n");
|
kfree(dev);
|
kfree(dev);
|